My app currently uses a SoundPool to manage all the different sounds. When the user taps the button, a sound should play. Since he might push that button quite quickly, the sounds should be able to play on top of each other.
The SoundPool is not able to listen for a sound finishing nor can it get the length of a sound file. Therefore I am thinking about using the MediaPlayer.
I have no experience with the MediaPlayer, but it seems that it is not as straight forward to set up that ability to quickly play a sound. Unfortunately I have to check when a sound finished playing, so I will have to rewrite using the MediaPlayer.
How would you make the MediaPlayer able to play many short sounds?
an instance of a media player plays one sound at a time. it's better to use soundpool..
try this with soundpool...
1) create an int, don't leave it null. somewhere before the onCreate method.
2) in the onCreate method attach a resource to it
3) lastly, apply logic to a button..
int db1, db2, db3, db4, db5 = 0;
db1 = sp.load(this, R.raw.snd1, 1);
db2 = sp.load(this, R.raw.snd2, 1);
db3 = sp.load(this, R.raw.snd3, 1);
db4 = sp.load(this, R.raw.snd4, 1);
db5 = sp.load(this, R.raw.snd5, 1);
samplebutton5.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
if (db5 != 0)
sp.play(db5, 1, 1, 1, 0, 1);
}
});
To use soundpool if you like you can first get the sound length by using MediaPlayer by using the following method:
private long getSoundDuration(int rawId)
{
MediaPlayer player = MediaPlayer.create(activity, rawId);
int duration = player.getDuration();
player.release();
return duration;
}
And afterwards use an handler and write something like:
handler.postAtTime(this, SystemClock.uptimeMillis() + duration);
The handler will wait until sound is finished to do the next task whatever that may be.
Related
I want to play mp3 file from res/raw folder when user click on button
my code is below:
btn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
MediaPlayer mp = MediaPlayer.create(MainActivity.this,
R.raw.click);
mp.start();
}
});
Work well but take some time to play after button click. please, anyone, give me a solution.
Thanks
Loading time depends on the buffer size of the MediaPlayer (which is hardcoded in the firmware) and that there is nothing that can be done to change it. Read more here.
Option 1:
Instead of creating the media player and then calling start() method in the onClick of the button, you can initialize the mediaPlayer in onCreate() of activity.
As for the button click implementation, you need to call mediaPlayer.start() only.
Option 2:
You can use SoundPool API provided by Android. This has lower latency compared to MediaPlayer API. SoundPool are recommended mainly for playing short clips.
This is as a result of the buffer size of media player.
Try using SoundPool for a more responsive playback. You can see an implementation of it here.
SoundPool soundPool = new SoundPool(1, AudioManager.STREAM_MUSIC, 100);
HashMap<Integer, Integer> soundPoolMap soundPoolMap = new HashMap<Integer, Integer>();
soundPoolMap.put(soundID, soundPool.load(this, R.raw.click, 1));
Start the sound with soundPool.play(soundId, 1, 1, 1, 0, 0);
I am having a bit of difficulty with my SoundPool. I have an ArrayList<Integer> of my soundIDs located in my res/raw folder. I'm creating the SoundPool like so in my ViewHolder class for my RecyclerView:
//create the SoundPool
sp = new SoundPool(20, AudioManager.STREAM_MUSIC, 0);
//create the AudioManager for managing volume
audioManager = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
//store the streamVolume in an int
streamVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
//set the load listener for my soundfiles
sp.setOnLoadCompleteListener(new SoundPool.OnLoadCompleteListener() {
#Override
public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
loaded = true;
}
});
I am playing the sound on the click of an ImageView like so:
#Override
public void onClick(View v) {
if (v.equals(cardImg)) {
sp.load(context, cardData.getSoundId(), 1);
if (loaded) {
sp.play(cardData.getSoundId(), streamVolume, streamVolume, 1, 0, 1f);
}
}
}
And every time I click on the cardImg it gives me this error:
W/SoundPool﹕ sample 2130968609 not READY
Where the sample int changes depending on which card I click, like it should.
So I know that it's GETTING the proper soundID from my ArrayList (stored in CardData class), and it definitely sees that it's loaded, because it wouldn't try to play otherwise because loaded would never be true. My question is: Why are my sounds never ready?
My sounds are .m4a format which Android says is supported in the documentation. I've tried on an Android 5.0 device and an Android 4.4 device but nothing changes.
I have tried using a MediaPlayer but I am running into memory errors as I have many short clips that need to be able to be spammed and I read that a SoundPool was a much better way to manage this (?).
Any help would be appreciated! I am super vexxed here.
You're using the wrong id. SoundPool.load returns an id that is suppose to be passed in to SoundPool.play.
I have a class that extends Service, where i have a MediaPlayer that manages the background music of my app.
MediaPlayer player = MediaPlayer.create(this, R.raw.background_music);
player.setLooping(true);
The problem is that it doens't "loop" well: I mean, when the mp3 file ends, there's a second of silence before it starts again.
But, in the mp3 file, actually, there's not any second of silence.
How can i solve this problem?
You can't. This bug has been there for ages now, but they still didn't fix it and it does not look like they are going to do it in the close future!
http://code.google.com/p/android/issues/detail?id=18756
You can try to use SoundPool to play your audio file (it loops very well and without delay, however might be inappropriate for some audio resources).
Here is some kind of implementation (deprecation removal and appropriate closing of resource is left as a homework :))
SoundPool pool = new SoundPool(1, AudioManager.STREAM_MUSIC, 0);
afd = getResources().openRawResourceFd(audioResource);
pool.setOnLoadCompleteListener(new OnLoadCompleteListener() {
#Override
public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
if (0 == status) {
soundPool.play(sampleId, 1f, 1f, 10, -1 /* looping parameter */, 1f);
}
}
});
pool.load(afd, 10);
afd.close();
From other side if MediaPlayer is a must have you might look into method setNextMediaPlayer. So the idea is to initialize several MediaPlayers for the same file (what a mess) and set them in a smart way.
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.
I'm working on a project in which I have to load 6 different sounds in one activity and play all sound on button click.The sound file are not so big,but the problem is that maybe they will be more.So my question is which is the fastest way to load sound files in a single activity.For test purposes I used res/raw folder to store the sound files and tried with two different method to play the files,but the result did not satisfied me.Here is the two different types of code :
Method 1:
Button first = (Button) findViewById(R.id.one);
Button second = (Button) findViewById(R.id.two);
first.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
MediaPlayer mp = MediaPlayer.create(SoundFXActivity.this, R.raw.drumtwo);
mp.start();
mp.setOnCompletionListener(new OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
// TODO Auto-generated method stub
mp.release();
}
});
}
});
second.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
MediaPlayer mp = MediaPlayer.create(SoundFXActivity.this, R.raw.drumone);
mp.start();
mp.setOnCompletionListener(new OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
// TODO Auto-generated method stub
mp.release();
}
});
}
});
Method 2:
private SoundPool spool;
private int soundID,soundID2;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
this.setVolumeControlStream(AudioManager.STREAM_MUSIC);
spool = new SoundPool(10, AudioManager.STREAM_MUSIC, 0);
soundID = spool.load(this, R.raw.drumone, 1);
soundID2 = spool.load(this, R.raw.drumtwo, 1);
Button three = (Button) findViewById(R.id.three);
three.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Sound();
}
});
}
public void Sound(){
AudioManager audioManager = (AudioManager) getSystemService(AUDIO_SERVICE);
float volume = (float) audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
spool.play(soundID, volume, volume, 1, 0, 1f);
};
But the problem is that the both methods are slow..I need to find a way a faster way to play the sounds..but now there is like almost a second after I click the button to play the sound.
Can you give me some advice how to play the sounda faster.Should I load them into a cache when the application starts or save them in database or somewhere else (I don't think database is a good option as a matter of fact,but I want to hear some suggestions).Or maybe load them from assets folder,but I think it still going to be slow.
So any ideas or suggestions?
Thanks in advance!
You could create the media players in your onCreate and then the buttons will just make them play. That would be the easiest solution, I would say.
Alternatively, depending on how important it is to you and how much work you want to do, you could consider using JetPlayer:
here's android development page for media:
http://developer.android.com/guide/topics/media/index.html
The page on the JetPlayer class:
http://developer.android.com/reference/android/media/JetPlayer.html
and the page on creating the JET files:
http://developer.android.com/guide/topics/media/jet/jetcreator_manual.html
If you implemented this it would likely work best but would definitely be the most work.
JetPlayer basically lets you have one audio file (i think it's a MIDI file) with multiple tracks that you mute and unmute as you please. I have no personal experience with it and have just read the docs some, but it seems like it would be very useful for any situation with more than one sound.
Edit: Also, it's worth mentioning this mailing list and in case the link ever changes this google search in case anyone is interested in android audio topics.
If you want to have the less delay you must use OpenSL in c++, From jelly bean is the faster sound player
SoundPool is working fine, you can see an example with the Hexiano project. However, you must preload the sounds into SoundPool, because it takes a lot of time to decode the file and store them in-memory before being able to use them. But once the sounds are loaded, there's no noticeable delay between key press and sound output.