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
Related
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();
}
When i click button plays sound on my app, but keep clicking for a while doesn`t play anymore. Maybe it is memory issue? Could you solve me my issue? Here is implemented play sound via SoundPool: when i click button i called play method: and play method works background thread
private void play(int resId) {
soundPool = buildBeforeAPI21();//TODO: refactor with deprecated constructor
soundPool.load(activity, Integer.parseInt(resId), 1);
}
public SoundPool buildBeforeAPI21() {
if (soundPool == null) {
soundPool = new SoundPool(2, AudioManager.STREAM_MUSIC, 0);
soundPool.setOnLoadCompleteListener(new SoundPool.OnLoadCompleteListener() {
#Override
public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
if (status == 0) {
soundPool.play(sampleId, 1.0f, 1.0f, 1, 0, 1.0f);
}
}
});
}
return soundPool;
}
Don't create a new SoundPool with each click. That is extremely wasteful. Do this instead:
1) Create the SoundPool just once
2) Load it with all the sounds you want to play, just once
3) Wait for all the sounds to load
4) Just call soundPool.play() with each click.
Maybe this answer cames too late; but here we go. The problem is in the line
soundPool = new SoundPool(2, AudioManager.STREAM_MUSIC, 0);
That '2' number is the int maxStreams, following the documentation "the maximum number of simultaneous streams for this SoundPool object" (you can go deep on this here). Now change it and set it to 10, for example, and try again. And after that, you cand adjust it as your wishes. So:
soundPool = new SoundPool(10, AudioManager.STREAM_MUSIC, 0);
Hope this helps (if it is still necessary).
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
The music either doesn't even start playing sometimes, but when it does, it stops after a few seconds. The file is 2 minutes long. I really don't know what's the problem.
#Override
public void onCreate(Bundle savedInstanceState) {
music = soundPoolVar.load(this, R.raw.music11, 1);
}
then
public void soundPlay(int i, MySurface pl, float volume) {
if (soundOn == true) {
switch (i) {
case 11:
soundPoolVar.play(music, 1, 1, 0, 0, 1);
break;
}}}
SoundPool designed to play short sound effects. To play music (big audio files) you need to use MediaPlayer
// R.raw.audio_file - res/raw/audio_file.mp3
mediaPlayer = MediaPlayer.create(this, R.raw.audio_file);
mediaPlayer.start();
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);
}
}