Playing multiple sounds using SoundManager - android

If I play a single sound, it runs fine.
Adding a second sound causes it to crash.
Anyone know what is causing the problem?
private SoundManager mSoundManager;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.sos);
mSoundManager = new SoundManager();
mSoundManager.initSounds(getBaseContext());
mSoundManager.addSound(1,R.raw.dit);
mSoundManager.addSound(1,R.raw.dah);
Button SoundButton = (Button)findViewById(R.id.SoundButton);
SoundButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
mSoundManager.playSound(1);
mSoundManager.playSound(2);
}
});
}

mSoundManager.addSound(1,R.raw.dit);
mSoundManager.addSound(1,R.raw.dah);
You need to change the second line to:
mSoundManager.addSound(2,R.raw.dah);
In order to play multiple sounds at once, first you need to let the SoundPool know that. In the declaration of SoundPool notice that I specified 20 streams. I have many guns and bad guys making noise in my game, and each has a very short sound loop, < 3000ms. Notice when I add a sound below I keep track of the specified index in a vector called, "mAvailibleSounds", this way my game can try and play sounds for items that dont exist and carry on without crashing. Each Index in this case corresponds to a sprite id. Just so you understand how I map particular sounds to specific sprites.
Next we queue up sounds, with playSound(). Each time this happens a soundId is dropped into a stack, which I then pop whenever my timeout occurs. This allows me to kill a stream after it has played, and reuse it again. I choose 20 streams because my game is very noisy. After that the sounds get washed out, so each application will require a magic number.
I found this source here, and added the runnable & kill queue myself.
private SoundPool mSoundPool;
private HashMap<Integer, Integer> mSoundPoolMap;
private AudioManager mAudioManager;
private Context mContext;
private Vector<Integer> mAvailibleSounds = new Vector<Integer>();
private Vector<Integer> mKillSoundQueue = new Vector<Integer>();
private Handler mHandler = new Handler();
public SoundManager(){}
public void initSounds(Context theContext) {
mContext = theContext;
mSoundPool = new SoundPool(20, AudioManager.STREAM_MUSIC, 0);
mSoundPoolMap = new HashMap<Integer, Integer>();
mAudioManager = (AudioManager)mContext.getSystemService(Context.AUDIO_SERVICE);
}
public void addSound(int Index, int SoundID)
{
mAvailibleSounds.add(Index);
mSoundPoolMap.put(Index, mSoundPool.load(mContext, SoundID, 1));
}
public void playSound(int index) {
// dont have a sound for this obj, return.
if(mAvailibleSounds.contains(index)){
int streamVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
int soundId = mSoundPool.play(mSoundPoolMap.get(index), streamVolume, streamVolume, 1, 0, 1f);
mKillSoundQueue.add(soundId);
// schedule the current sound to stop after set milliseconds
mHandler.postDelayed(new Runnable() {
public void run() {
if(!mKillSoundQueue.isEmpty()){
mSoundPool.stop(mKillSoundQueue.firstElement());
}
}
}, 3000);
}
}

Related

Playing multiple SoundPool at the same time

I have a activity that i'm using 12 button with different sound at them. Buttons should be play at the same time if user click both of them at once.
When i use MediaPlayer i couldn't manage to do this , then i learned about SoundPool and everything was fine.But with 12 different sounds I had to write so many row and i don't think that's the right way to do this.
Is this the right way to do this , when i write this for 12 sound it became to long ?
SoundPool sp1,sp2,sp3;
int id1,id2,id3;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.piano);
sp1 = new SoundPool(1, AudioManager.STREAM_MUSIC,1);
sp2 = new SoundPool(1, AudioManager.STREAM_MUSIC,1);
sp3 = new SoundPool(1, AudioManager.STREAM_MUSIC,1);
id1 = sp1.load(this,R.raw.p1,1);
id2 = sp2.load(this,R.raw.p2,1);
id3 = sp3.load(this,R.raw.p3,1);
}
public void p1Click(View v)
{
sp1.play(id1,1,1,1,0,1);
}
public void p2Click(View v)
{
sp2.play(id1,1,1,1,0,1);
}
public void p3Click(View v)
{
sp3.play(id1,1,1,1,0,1);
}
You only need one SoundPool (sp1):
sp1 = new SoundPool(12, AudioManager.STREAM_MUSIC,1);
id1 = sp1.load(this,R.raw.p1,1);
id2 = sp1.load(this,R.raw.p2,1);
...
sp1.play(id1,1,1,1,0,1);
sp1.play(id2,1,1,1,0,1);
...
(1) Note the 12 means you can play 12 sounds concurrently.
(2) Note keep track of your active sounds, it will be useful later. (sp1.play returns an integer):
int streamID = sp1.play(id1,1,1,1,0,1);

Set the volume of youtubeplayer api over time android

I have been integrating the YoutubePlayer API for with my Android project. The videos from the playlist are working well. What I am trying to do is have the audio start low and fade in over 30seconds.
What I have done so far, for some reason is doing somthing really weird. It set it to max volume and if you try to turn it down it turns it back up again really straight away.
The way I thought I could do it was to set the audio manager to a 0 volume and then on an ontick timer raise that by 1 until it got to the max volume.
The code below was my attempt, but like I said it is doing weird things.
Thanks for your help
youTubePlayer.loadPlaylist(playListTitle);
final AudioManager audioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
// Add listeners to YouTubePlayer instance
youTubePlayer.setPlayerStateChangeListener(new YouTubePlayer.PlayerStateChangeListener() {
#Override
public void onLoaded(String arg0) {
youTubePlayer.play();
audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, 0, 0);
Integer volumeRaisingTime = 30000;
new CountDownTimer(volumeRaisingTime, 1000) {
Integer deviceMaxVolume = 20;
Integer devicevolume = 0;
public void onTick(long millisUntilFinished) {
audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, 20, 0);
if (devicevolume > deviceMaxVolume){
devicevolume++;
Log.d("Device Volume:", ""+devicevolume);
}
}
public void onFinish() {
}
}.start();
}

Android sound latency using SoundPool

public class AndroidSound implements Sound {
int soundId;
SoundPool soundPool;
public AndroidSound(SoundPool soundPool, int soundId) {
this.soundId = soundId;
this.soundPool = soundPool;
}
#Override
public void play(float volume) {
soundPool.play(soundId, volume, volume, 0, 0, 1);
}
#Override
public void dispose() {
soundPool.unload(soundId);
}}
public class Assets{
public Music theme;
public static Sound sound;
public static void load(Game game) {
theme = game.getAudio().createMusic("theme.mp3");
theme.setLooping(true);
theme.setVolume(0.85f);
theme.play();
sound = game.getAudio().createSound("death.wav");
}
}
Then I play this sound in different class by calling play() on it, but it plays with really huge delay, something around 500ms. Why is that? I tried looking for solution, but there is tons of people with that problem and I haven't found any answer that actually worked. Most of topics was bit old tho, maybe there is a simple solution for this already, counting on your help.
public class AndroidAudio implements Audio {
AssetManager assets;
SoundPool soundPool;
public AndroidAudio(Activity activity) {
activity.setVolumeControlStream(AudioManager.STREAM_MUSIC);
this.assets = activity.getAssets();
this.soundPool = new SoundPool(20, AudioManager.STREAM_MUSIC, 0);
}
#Override
public Sound createSound(String filename) {
try {
AssetFileDescriptor assetDescriptor = assets.openFd(filename);
int soundId = soundPool.load(assetDescriptor, 0);
return new AndroidSound(soundPool, soundId);
} catch (IOException e) {
throw new RuntimeException("Couldn't load sound '" + filename + "'");
}
}
}
I don't know if this will be helpful now but also answering.
Use of SoundPool
1)First load your audio as required in the levels in the beginning of application initialization.Suppose you need 5 sound in the level load them in the beginning and keep the soundID's handy.
2) Now on any event just call play with the soundID.
3) This plays with a very less delay while I debugged from SoundPool play till HAL layer.Around 10-15 ms in my device.
For more info on SoundPool implementation follow my github thread:
https://github.com/sauravpradhan/Basic-Audio-Routing

Playing short .wav files - Android

I would like to play sound after touching the button. MediaPlayer works fine, but I read somewhere that this library is for long .wav (like music).
Is there any better way to play short .wav(2-3 sec.)?
The SoundPool is the correct class for this. The below code is an example of how to use it. It is also the code I use in several apps of mine to manage the sounds. You can have as may sounds as you like (or as memory permits).
public class SoundPoolPlayer {
private SoundPool mShortPlayer= null;
private HashMap mSounds = new HashMap();
public SoundPoolPlayer(Context pContext)
{
// setup Soundpool
this.mShortPlayer = new SoundPool(4, AudioManager.STREAM_MUSIC, 0);
mSounds.put(R.raw.<sound_1_name>, this.mShortPlayer.load(pContext, R.raw.<sound_1_name>, 1));
mSounds.put(R.raw.<sound_2_name>, this.mShortPlayer.load(pContext, R.raw.<sound_2_name>, 1));
}
public void playShortResource(int piResource) {
int iSoundId = (Integer) mSounds.get(piResource);
this.mShortPlayer.play(iSoundId, 0.99f, 0.99f, 0, 0, 1);
}
// Cleanup
public void release() {
// Cleanup
this.mShortPlayer.release();
this.mShortPlayer = null;
}
}
You would use this by calling:
SoundPoolPlayer sound = new SoundPoolPlayer(this);
in your Activity's onCreate() (or anytime after it). After that, to play a sound simple call:
sound.playShortResource(R.raw.<sound_name>);
Finally, once you're done with the sounds, call:
sound.release();
to free up resources.

Forever playing without pause in Android

I have a problem. When I try to play sound using Soundpool there is small pause between each playing.
For example, I have 2 sec-sound which I want to play when button is pressed.
I tried to start 2 threads with the same sound. Second started 0.5 sec after first. But there is no helpful.
AudioManager mAudioManager;
SoundPool mSoundPool;
Runnable thr1;
Runnable thr2;
public void playLoopedSound(int soundId) {
mSoundPool = new SoundPool(2, AudioManager.STREAM_MUSIC, 0);
mAudioManager = (AudioManager)mContext.getSystemService(Context.AUDIO_SERVICE);
int streamVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC)*2;
thr1 = new Runnable() {
public void run() {
mSoundPool.play(soundId, 0, streamVolume, 1, -1, 1f); //0 = no loop, -1 = loop forever
}
};
thr2 = new Runnable() {
public void run() {
mSoundPool.play(soundId, 0, streamVolume, 1, -1, 1f);
}
};
thr1.run();
try {
Thread.sleep(400);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
thr2.run();
}
It's hard to know without debugging, but I've had similar issues due to the performance of soundpool when it's loading sounds. To get around this, I implemented SoundPool.onLoadCompleteListener to ensure that I didn't start trying to play sounds until the soundpool was fully loaded.
Be aware that this is only available on API8 or above. See this answer for a nice implementation:
Knowing if the loading of a sound with SoundPool has been successful on Android 1.6/2.0/2.1

Categories

Resources