I am making a game for android which needs to play a small beep whenever a user touches a certain object.
To do this I have this simple code to create the media player. beep is a small .ogg file of ~1.5 sec length.
MediaPlayer mp = MediaPlayer.create(getContext(), R.raw.beep);
mp.setVolume(0.5f, 0.5f);
and use it like this
mp.start();
The problem I am having is that my game uses the android canvas, and the thread which draws to the canvas also calls mp.start(). I have discovered that playing the sound is taking quite a lot of time, and it is very varied in how long it takes. Sometimes 1ms, sometimes 15ms. This appears to be causing my game to noticeably lag a little bit, as the android canvas is pretty slow anyway.
I've had a look at the logs and I don't appear to having garbage collection causing the delay. I'm wondering if anyone can give me some advice to reduce this delay
EDIT - I've just discovered that MediaPlayer is designed for longer sound files, and SoundPool is better for shorter audio files. However, I load the file into the mediaPlayer only once, so I don't see how it should make any difference. I will test it out though
sorry for my english
Use SoundPool instead of MediaPlayer cause MediaPlayer need releasing memory after each call or call method mp.release() after each call of player
SoundPool tutorial here
Related
I'm trying to loop a ~30 seconds audio track multiple times. I'm using a MediaPlayer to play the sounds, here is the code where its created:
mAnimalMediaPlayer = MediaPlayer.create(mContext, fish.getSound());
I then call:
mAnimalMediaPlayer.setLooping(true);
mAnimalMediaPlayer.start();
when a play button is clicked. When the track loops, there is a small but noticeable pause between the track ending and the new loop beginning. I am positive that the audio file im using does not contain any actual pause.
Here is an android bug report which has been up for some time: https://code.google.com/p/android/issues/detail?id=18756
I've tried a few workarounds (such as using .ogg files instead of .mp3) but the problem persists.
I'm looking for any possible workaround that will allow me to seamlessly loop the playback multiple times.
There is a very noticeable pause. However, I have just discovered through experimentation on an emulator running level 25 that if one prepares two identical players and alternately starts them one after the other when the other has finished then the gap becomes much more difficult to hear.
Whenever I call setDisplay() on a MediaPlayer while it is playing (i.e. setDisplay(null) when backgrounding a video to play audio in the background) the media player stutters and rewinds for some small amount of time. Once I comment out these lines, essentially restricting the application to only play audio, these stutters and consequent rewinds no longer occur. Any ideas what the issue may be?
EDIT:
So I think the cause of the problem might be android media player choosing the closest keyframe to resume from on each display change because it can''t render inbetween keyframes. Any ideas?
I have a game in which a "ding" sound is made for each point scored in a game. Sometimes you can score points in very quick succession. In this case I do not allow overlapping sounds so I wait for the mediaplayer's isPlaying() function to go to false before playing the next sound.
On every phone I've tried so far (admittedly all 2.2 or 2.3) the result is a pleasing rapid-fire succession of sounds.
But just now I've tried Samsung galaxy S II with 4.0.3. On this machine each "ding" is separated by a long gap. The isPlaying() state seems to last twice as long as the sound itself. According to Audacity the sound should last about 0.1 seconds, but isPlaying() is remaining true for .28 seconds.
The sound is saved from Audacity into Ogg Vorbis format.
Any idea what's gone wrong?
It's better to use SoundPool for playing rapid-fire samples in games as they're uncompressed once and kept in memory. MediaPlayer may be decoding on the fly, causing a delay as it gets ready. Not sure why there's such a difference between devices, but I'd give SoundPool a try and see if it improves things.
I recently added simple looping background music to my Android game. It uses Canvas to draw to the screen, so I am very careful about optimizing performance. I added music using the standard MediaPlayer which seems to be the most common and easiest way to handing looping music. Unfortunately, I'm having trouble with the music skipping occasionally and, far worse, sometimes causing significant lag in the game play.
My only phone to test on is a Droid Eris, which is a fairly old phone, so I suspect this would not be an issue on newer Android phones, but I would like my game to be playable on all Android devices. What can I do to add music while maintaining reasonable performance?
This is the code I added:
// in setup() method of game thread
mediaPlayer = MediaPlayer.create(context, R.raw.rl_theme);
mediaPlayer.setLooping(true);
mediaPlayer.start();
// in method called when the player looses
mediaPlayer.stop();
mediaPlayer.release();
I have not ever had this issue, so I am not positive, but I think SoundPool is what you're looking for.
http://developer.android.com/reference/android/media/SoundPool.html
It looks like there isn't much you can do. Yes, adding music does slow Android apps down some, but it doesn't seem to be a major issue on newer phones. I did change the format of the audio files from OGG to MP4 to fix what appears to be a bug in the Android MediaPlayer (still looking into it, but the media server was crashing on OGG and works perfectly with MP4) and the performance seems to have gotten better. I'm not sure if that's related, though.
Is there a reliable way to prevent truncating of sounds in soundpool? I have had some success with the sleep() function between sounds, but they still sometimes miss the last bit of sound before starting another sound. My app plays short sounds in sequence.
Jerry
Although this is an old question, I thought I would post something here since I couldn't find a solution to this problem online but did come up with something of a solution...
I get the duration of each sound (using MediaPlayer) when my app starts up, and store the R.id.sound_name value and the duration together. I can then play the sounds using the SoundPool.
Code to get duration:
private long getSoundDuration(int rawId){
MediaPlayer player = MediaPlayer.create(context, rawId);
int duration = player.getDuration();
return duration;
}
In my sound class, I then play the sound as usual then sleep for the duration. Pretty simple stuff.
Seems to work well. Gives me the advantages of low-latency from SoundPool, plus ability to chain things.
A couple things to note:
Don't get the duration each time, as creating a MediaPlayer has overhead.
Durations are taken from file metadata -- ogg's work great for me, but I can't vouch for anything else.
Make sure you have enough Streams.
in the SoundPool constructor, the first argument is MaxStreams.
Set that to whatever you seem fit. 8 or so should be enough i guess... but you might need more, depending on your sounds.