SoundPool | Check stream whether it is playing or not - android

I am using soundpool to play short audio files . Once I click the button it should play audio and second time it should pause stream . I used function like this detectPlayPause(sound2, activity!!.applicationContext)
The problem is it is not pausing and it is playing that sound again as a two stream
fun detectPlayPause(sound: Int, context: Context) {
val audioManager = context.getSystemService(AUDIO_SERVICE) as AudioManager
if (audioManager.isStreamMute(sound)) {
soundPool.play(sound, 1F, 1F, 0, -1, 1F)
} else {
soundPool.pause(sound)
}}
**

You're mis-using audioManager.isStreamMute(). That function takes an AudioManager constant, like STREAM_MUSIC. That is a different thing than the sound ID returned from SoundPool.load().
isStreamMute() won't tell you whether or not your sound is playing. That's more for detecting the device's mute settings; whether the user has selected mute/vibrate/silent, etc.
Instead, just track your play state using a boolean variable.
if (!playing) {
playing = true
soundPool.play(sound, 1F, 1F, 0, -1, 1F)
} else {
playing = false
soundPool.pause(sound)
}

Related

SoundPool issue on Android 11

It seems that soundPool Api is not working correctly on android 11. I hear the sound like slow motion. Have anyone any related issue ?
My code
private SoundPool soundPool;
private int wonSound;
...
soundPool = new SoundPool.Builder().setMaxStreams(1).build();
wonSound = soundPool.load(this, R.raw.slot_win_1, 1);
...
soundPool.play(wonSound, 1, 1, 0, 0, 0);
According to the documentation:
https://developer.android.com/reference/android/media/SoundPool#play(int,%20float,%20float,%20int,%20int,%20float)?
SoundPool's function play() takes as its last parameter:
float: playback rate (1.0 = normal playback, range 0.5 to 2.0)
So, playback rates below 1 will sound slower than the original sound. To play your sound in its original playback rate, you should call play() like this:
soundPool.play(wonSound, 1, 1, 0, 0, 1);

SoundPool items randomly playing/not playing when triggered

I have some sounds in a SoundPool that I need to play. Sometimes when they should play, there's just a low pitched click sound instead of the sound that should play. Sometimes they play just fine.
Here's the code I use for the SoundPool:
open class PingSoundPool(context: Context) {
open var mAttributes = AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.setUsage(AudioAttributes.USAGE_GAME)
.build()
open var mSoundPool = SoundPool.Builder()
.setMaxStreams(9)
.setAudioAttributes(mAttributes)
.build()
open var babping = mSoundPool.load(context, R.raw.ab830ping, 1)
open var aaping = mSoundPool.load(context, R.raw.a220ping, 1)
open var abbping = mSoundPool.load(context, R.raw.bb233ping, 1)
open var abping = mSoundPool.load(context, R.raw.b247ping, 1)
[and others]
open fun loadPings(note: Int) {
println(note.toString())
if (note == 0) {}
if(note == 1)
mSoundPool.play(acping, 2.55f, 2.55f, 1, 0, 1f)
if(note == 2)
mSoundPool.play(adbping, 2.5f, 2.5f, 1, 0, 1f)
if(note == 3)
mSoundPool.play(adping, 2.45f, 2.45f, 1, 0, 1f)
if(note == 4)
mSoundPool.play(aebping, 2.4f, 2.4f, 1, 0, 1f)
[and so on]
}
Now I make this accessible within my activity:
companion object {
lateinit var pingSoundPool: PingSoundPool
}
And in onCreate I do pingSoundPool = PingSoundPool(this)
Like this, I should be able to play any of these sounds with FullscreenActivity.pingSoundPool.loadPings(note: Int) - as stated above, this sometimes works, sometimes it doesn't, even for repetitions of the same sound.
One observation is that println(note.toString()) prints the Int corresponding to the note that should be played, regardless of whether the note can actually be heard. However, every time the note is actually played, that number is followed by W/AudioTrack: AUDIO_OUTPUT_FLAG_FAST denied by client; transfer 4, track 44100 Hz, output 48000 Hz - All these come up in Android Studio's logcat.
This happens in the emulator as well as on real devices.
Any ideas?
The solution is this: the volume only accepts values from 0.0f to 1.0f. I tried setting them all to 1.0f and now it works fine.
if(note == 4) mSoundPool.play(aebping, 2.4f, 2.4f, 1, 0, 1f) // wrong
if(note == 4) mSoundPool.play(aebping, 1.0f, 1.0f, 1, 0, 1f) // right

Android play music in a random amount of time

Now I can play a music in android. But I want to play this sound in a random amount of time between 2 to 8 seconds.How Can I randomly play it that for example the first time, it plays for 2 seconds, the next time 7 sec and so on? Can anybody help me?
Go through these links:
Random number Generation
Media Player
Timer
you will get an idea.
Sound in android is played like this :
AudioManager audioManager = (AudioManager) getSystemService(AUDIO_SERVICE);
int mSoundID = mSoundPool.load(this, R.raw.sound1, 1);
float lActualVolume = (float) audioManager
.getStreamVolume(AudioManager.STREAM_MUSIC);
float lMaxVolume = (float) audioManager
.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
float lVolume = lActualVolume / lMaxVolume;
// Is the sound loaded already?
if (mSoundIsLoaded) {
mSoundPool.play(mSoundID, lVolume, lVolume, 1, 0, 1f);
I think you have been given plenty of help to figure the random number part out.
You will have to put the sound file in your assets/raw directory.
edit:
I forgot to mention where the mSoundIsLoaded parameter came from.
I set it when my sound has been loaded. I do this in my onCreate method. when the sound is loaded I set the boolean field called mSoundIsLoaded. I do this to prevent NullPointerExceptions when playing the sound
the loading of the sound looks like this:
mSoundPool = new SoundPool(10, AudioManager.STREAM_MUSIC, 0);
mSoundPool.setOnLoadCompleteListener(new OnLoadCompleteListener() {
#Override
public void onLoadComplete(SoundPool soundPool, int sampleId,
int status) {
mSoundIsLoaded = true;
}
});
mSoundID = mSoundPool.load(this, R.raw.sound1, 1);

How to Sync Sounds using SoundPool

I have been trying to get a few sounds to play at the same time; currently i'm using a shared instance of SoundPool. I would like 1, 2 or 3 sounds to be played at the exact same time with no lag.
When calling SoundPool.play(...) X number of times in succession, the sounds are played in that order as one might think. what is the proper what to achieve this where i can prepare all of the sounds to be played at the same time and then play them as one?
Sudo Code:
SoundPool _soundPool = new SoundPool(10, AudioManager.STREAM_MUSIC, 0);
_soundPool.load(_context, soundId1, 1);
_soundPool.load(_context, soundId2, 1);
_soundPool.load(_context, soundId3, 1);
_soundPool.play(soundId1, vol, vol, 1, 0, 1f);
_soundPool.play(soundId2, vol, vol, 1, 0, 1f);
_soundPool.play(soundId3, vol, vol, 1, 0, 1f);
i done the sound pool for one sound at time it might help you.
Android:sound pool and service
Thank you
You need to understand that SoundPool.load method is asyncronous, so when you call it 3 times in a row, and then call play, there is no garantee that this sounds actually loaded. So you need to wait until all sounds is loaded. For that use OnLoadCompleteListener:
fun loadAndPlay(soundPool: SoundPool, context: Context, resIds: IntArray) {
val soundIds = IntArray(resIds.size) {
soundPool.load(context, resIds[it], 1)
}
var numLoaded: Int = 0
soundPool.setOnLoadCompleteListener { sPool, sampleId, status ->
numLoaded++
if (numLoaded == resIds.size) {
soundPool.setOnLoadCompleteListener(null)
for (id in soundIds) {
soundPool.play(id, 1f, 1f, 1, 0, 1f)
}
}
}
}
To use:
loadAndPlay(soundPool, context, intArrayOf(R.raw.sound_1, R.raw.sound_2, R.raw.sound_3))

Complex sound handling (I.E. pitch change while looping)

After going through the lovely set of Java tutorials and a while spent buried in source code I'm beginning to get the feel for it. For my next step, I will dive in with a fully featured application with graphics, sound, sensor use, touch response and a full menu.
My grand idea was to make an animated screwdriver where sliding the controls up and down modulate the frequency and that frequency dictates the sensor data it returns.
Now I have a semi-working sound system but its pretty poor for what its designed to represent and I just wouldn't be happy producing a sub-par end product whether its my first or not.
the problem:
sound must begin looping when the user presses down on the control
the sound must stop when the user releases the control
when moving the control up or down the sound effect must change pitch accordingly
if the user doesn't remove there finger before backing out of the application it must plate the casing of there device with gold (Easter egg ;P)
now I'm aware of how monolithic the first 3 look and that's why I would really appreciate any help I can get.
sorry for how bad this code looks but my general plan is to create the functional components then refine the code later, no good painting the walls if the roofs not finished.
here's my user input, he set slide stuff is used in the graphics for the control
#Override
public boolean onTouchEvent(MotionEvent event)
{
//motion event for the screwdriver view
if(event.getAction() == MotionEvent.ACTION_DOWN)
{
//make sure the users at least trying to touch the slider
if (event.getY() > SonicSlideYTop && event.getY() < SonicSlideYBottom)
{
//power setup, im using 1.5 to help out the rate on soundpool since it likes 0.5 to 1.5
SonicPower = 1.5f - ((event.getY() - SonicSlideYTop) / SonicSlideLength);
//just goes into a method which sets a private variable in my sound pool class thing
mSonicAudio.setPower(1, SonicPower);
//this handles the slides graphics
setSlideY ( (int) event.getY() );
#Override
public boolean onTouchEvent(MotionEvent event)
{
//motion event for the screwdriver view
if(event.getAction() == MotionEvent.ACTION_DOWN)
{
//make sure the users at least trying to touch the slider
if (event.getY() > SonicSlideYTop && event.getY() < SonicSlideYBottom)
{
//power setup, im using 1.5 to help out the rate on soundpool since it likes 0.5 to 1.5
SonicPower = 1.5f - ((event.getY() - SonicSlideYTop) / SonicSlideLength);
//just goes into a method which sets a private variable in my sound pool class thing
mSonicAudio.setPower(1, SonicPower);
//this handles the slides graphics
setSlideY ( (int) event.getY() );
//this is from my latest attempt at loop pitch change, look for this in my soundPool class
mSonicAudio.startLoopedSound();
}
}
if(event.getAction() == MotionEvent.ACTION_MOVE)
{
if (event.getY() > SonicSlideYTop && event.getY() < SonicSlideYBottom)
{
SonicPower = 1.5f - ((event.getY() - SonicSlideYTop) / SonicSlideLength);
mSonicAudio.setPower(1, SonicPower);
setSlideY ( (int) event.getY() );
}
}
if(event.getAction() == MotionEvent.ACTION_UP)
{
mSonicAudio.stopLoopedSound();
SonicPower = 1.5f - ((event.getY() - SonicSlideYTop) / SonicSlideLength);
mSonicAudio.setPower(1, SonicPower);
}
return true;
}
and here's where those methods end up in my sound pool class its horribly messy but that's because I've been trying a ton of variants to get this to work, you will also notice that I begin to hard code the index, again I was trying to get the methods to work before making them work well.
package com.mattster.sonicscrewdriver;
import java.util.HashMap;
import android.content.Context;
import android.media.AudioManager;
import android.media.SoundPool;
public class SoundManager
{
private float mPowerLvl = 1f;
private SoundPool mSoundPool;
private HashMap<Integer, Integer> mSoundPoolMap;
private AudioManager mAudioManager;
private Context mContext;
private int streamVolume;
private int LoopState;
private long mLastTime;
public SoundManager()
{
}
public void initSounds(Context theContext)
{
mContext = theContext;
mSoundPool = new SoundPool(2, AudioManager.STREAM_MUSIC, 0);
mSoundPoolMap = new HashMap<Integer, Integer>();
mAudioManager = (AudioManager)mContext.getSystemService(Context.AUDIO_SERVICE);
streamVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
}
public void addSound(int index,int SoundID)
{
mSoundPoolMap.put(1, mSoundPool.load(mContext, SoundID, 1));
}
public void playUpdate(int index)
{
if( LoopState == 1)
{
long now = System.currentTimeMillis();
if (now > mLastTime)
{
mSoundPool.play(mSoundPoolMap.get(1), streamVolume, streamVolume, 1, 0, mPowerLvl);
mLastTime = System.currentTimeMillis() + 250;
}
}
}
public void stopLoopedSound()
{
LoopState = 0;
mSoundPool.setVolume(mSoundPoolMap.get(1), 0, 0);
mSoundPool.stop(mSoundPoolMap.get(1));
}
public void startLoopedSound()
{
LoopState = 1;
}
public void setPower(int index, float mPower)
{
mPowerLvl = mPower;
mSoundPool.setRate(mSoundPoolMap.get(1), mPowerLvl);
}
}
I almost forgot, that looks pretty ineffective but I omitted my thread which actuality updates it, nothing fancy it just calls:
mSonicAudio.playUpdate(1);
There are some confusing points in there which I think are just cut and paste issues trying to get the source into this page, but assuming you're not having problems with your onTouchEvent handling, my random comments are:
It looks like you are calling play() every 250 ms while the touch is held. I can't see the loop argument to the play() call but I assume it is -1. If so, then you are launching a brand new looped sound every 250 msc (play returns a unique streamId for every audio stream you create).
I think you wanted to modify the pitch and amplitude of a single existing stream. So I think you wanted something like this:
int mySoundStreamId = 0;
...
onDown()
if( mySoundStreamId == 0 ) {
// create the one true stream
mySoundStreamId = mySOundPool.play( initial power and freq modifiers, loop = -1 )
} else {
// resume the one true stream
mySoundPool.resume( mySoundStreamId ); // note: a STREAM id is NOT a SOUND id.
}
onUp()
if( mySoundStreamId != 0 ) {
// pause the one true stream
mySoundPool.pause( mySoundStreamId ) // stop() will release all the samples you held
}
onWiggle()
if( mySoundStreamId != 0 ) {
// modify parameters of the one true stream
mySoundPool.setPitch( mySoundStreamId, newPitch ); // too lazy to look up real soundPool command
}
onGameOver
if( mySoundStreamId != 0 ) {
// shut down and release the samples of the one true stream
mySoundPool.setLoop( mySountStreamId, 0 ); // otherwise some phones will keep looping after shutdown
mySoundPool.stop( mySoundStreamId ); // no resume possible after this, need to reload samples
mySOundStreamId = 0;
}
I omit the creation/destruction of the sound pool itself. It sounds like you were successfully loading the sound data into the sound pool ok.
Note that the LOAD returns a SOUND ID which you pass to the PLAY command
but that PLAY returns a STREAM ID which you use in most of the other soundPool methods
Of course, I have my own problems with 'resume' on a looped sound, so take what I say with a grain of salt :-)
Good Luck! I guess I should have checked the time stamp. My apologies if you posted thie 3 years ago :-)

Categories

Resources