Playing short .wav files - Android - 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.

Related

Libgdx Sound | setPitch causes Sound object to stop playing/making noise

I have a Sound object that calls setPitch(id, 1.0f). For some reason, on most devices this seems to work and sound perfect (I realize that 1.0f is normal). But on the galaxy note 3, it makes an ugly deep sound, then the Sound object no longer makes any sounds after calling play method again (I play the Sound object every time player gets point). Setting pitch is necessary because I use the same Sound object for other parts of my game. I will link my code below, but I feel as though this may be a libgdx glitch/hardware problem. Thanks!
if (contact.getFixtureA().getFilterData().categoryBits == Config.CATEGORYBIT_BONUS) {
final BonusFixtureUserData userData = (BonusFixtureUserData) contact.getFixtureA().getUserData();
if (userData.bonus.scorable) {
long id = AudioManager.getAudioManager().playSound(AudioManager.getAudioManager().bonusSound);
AudioManager.getAudioManager().bonusSound.setPitch(id, Config.pointSoundPitch * 2);
}
}
AudioManager class (below)
public class AudioManager {
private static AudioManager audioManager;
public Sound jumpSound, deathSound, pointSound, bonusSound;
public static AudioManager getAudioManager() {
if (audioManager == null) {
audioManager = new AudioManager();
}
return audioManager;
}
private float sound_volume, music_volume;
private AudioManager() {
sound_volume = 1f;
}
public void setAudio() {
deathSound = (Sound) Game.assetManager.get("sound/death.mp3");
jumpSound = (Sound) Game.assetManager.get("sound/tap.mp3");
pointSound = (Sound) Game.assetManager.get("sound/point.mp3");
bonusSound = (Sound) Game.assetManager.get("sound/point.mp3");
}
public long playSound(Sound sound) { //Returns soundID (Sound can play multiple times, soundID refers to which instance is playing)
long id = sound.play();
sound.setLooping(id, false);
sound.setVolume(id, sound_volume);
return id;
}
public static void dispose() {
audioManager = null;
}
}
Config.pointPitchSound is actually equal to between 1.0f and 1.07f throughout the game. When it is 1.0f, then it does the glitch. I haven't tried the other values, but I would asume they'd do the same.
LibGDX audio implementation depends completely on Android. Sound.setPitch actually calls SoundPool.setRate Android documentation of setRate
Try to convert sounds to OGG format, it is known that SoundPool has issues with playing MP3 files on some devices.

SoundPool doesn`t play sound after clicking several times

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).

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

SoundPool is loading sounds but every time I play it it says "sample ___ is not ready"?

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.

Keeping multiple sound files ready in MediaPlayer (like in a SounPool)

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.

Categories

Resources