I'm looking to do a very simple piece of code that plays a sound effect. So far I have this code:
SoundManager snd;
int combo;
private void soundSetup() {
// Create an instance of the sound manger
snd = new SoundManager(getApplicationContext());
// Set volume rocker mode to media volume
this.setVolumeControlStream(AudioManager.STREAM_MUSIC);
// Load the samples from res/raw
combo = snd.load(R.raw.combo);
}
private void playSound() {
soundSetup();
snd.play(combo);
}
However, for some reason when I use the playSound() method, nothing happens. The audio file is in the correct location.
Is there a specific reason you are using SoundManager? I would use MediaPlayer instead, here is a link to the Android Docs
http://developer.android.com/reference/android/media/MediaPlayer.html
then it's as simple as
MediaPlayer mp = MediaPlayer.create(getApplicationContext(), R.raw.combo);
mp.start();
Make a directory called "raw/" under the "res/" directory. Drag wav or mp3 files into the raw/ directory. Play them from anywhere as above.
i have also attempted using the top answer, yet it resulted in NullPointerExceptions from the MediaPlayer when i tried playing a sound many times in a row, so I extended the code a bit.
FXPlayer is my global MediaPlayer.
public void playSound(int _id)
{
if(FXPlayer != null)
{
FXPlayer.stop();
FXPlayer.release();
}
FXPlayer = MediaPlayer.create(this, _id);
if(FXPlayer != null)
FXPlayer.start();
}
Related
I'm trying to write a function to play a short sound (in /res/raw) in my program, called at effectively random times throughout the program. So far I have this function:
public void playSound() {
MediaPlayer mp = new MediaPlayer();
mp = MediaPlayer.create(this, R.raw.ShortBeep);
mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
mp.setLooping(false);
mp.start();
}
It works fine for awhile, but after exactly 30 plays of the sound, it stops making sound.
According to the Docs
... failure to call release() may cause subsequent instances of MediaPlayer objects to fallback to software implementations or fail altogether.
When you are done with it call mp.release() so that it can release the resources. I don't know what the limit is and I'm sure it depends on many factors. Either way you should be calling this function on your MediaPlayer object, especially if it will be used more than once.
I've just solved the exact same problem, but I'm using Xamarin. I ended up changing from holding on to a MediaPlayer instance for the lifetime of the activity to creating an instance each time I want to play a sound. I also implemented the IOnPreparedListener and IOnCompletionListener.
Hopefully you can get the idea despite it being C# code
public class ScanBarcodeView :
MvxActivity,
MediaPlayer.IOnPreparedListener,
MediaPlayer.IOnCompletionListener
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.ScanBarcodeView);
((ScanBarcodeViewModel) ViewModel).BarcodeScanFailed += (sender, args) => PlaySound(Resource.Raw.fail);
((ScanBarcodeViewModel) ViewModel).DuplicateScan += (sender, args) => PlaySound(Resource.Raw.tryagain);
}
private void PlaySound(int resource)
{
var mp = new MediaPlayer();
mp.SetDataSource(ApplicationContext, Android.Net.Uri.Parse($"android.resource://com.company.appname/{resource}"));
mp.SetOnPreparedListener(this);
mp.SetOnCompletionListener(this);
mp.PrepareAsync();
}
public void OnPrepared(MediaPlayer mp)
{
mp.Start();
}
public void OnCompletion(MediaPlayer mp)
{
mp.Release();
}
}
So, each time I want a sound to be played I create a MediaPlayer instance, so the data source, tell it that my Activity is the listener to Prepared and Completion events and prepare it. Since I'm using PrepareAsync I don't block the UI thread. When the media player is prepared the Start method on the MediaPlayer is called, and when the sound has finished playing the MediaPlayer object is released.
Before I made these changes I would get to 30 sounds played and it would all stop working. Now I've gone way past 30, also multiple sounds can be played simultaneously.
Hope that helps.
I am trying to play two sound items, one after the other
MediaPlayer mp = null;
protected void produceErrorSound(int index) {
if (mp != null) {
mp.reset();
mp.release();
}
mp = MediaPlayer.create(this, index);
mp.start();
}
public void correctAnswerAndNext(){
produceErrorSound(R.raw.right1) ;
produceErrorSound(R.raw.right1) ;
}
but only second sound is produced.
is there any alternative approach?
I can't see any wait mechanism in your code.
You can use an onCompletionListener to receive a callback when your first MediaPlayer has finished playback. At that point you can start the second MediaPlayer.
An alternative way in Jellybean (and later versions) is to use the audio chaining functionality (i.e. setNextMediaPlayer) to automatically start another MediaPlayer as soon as the current one has finished playing. Something like this (I've omitted the calls to setDataSource etc for brevity):
mediaPlayer1.prepare();
mediaPlayer2.prepare();
mediaPlayer1.start();
mediaPlayer1.setNextMediaPlayer(mediaPlayer2);
I have a game in which a sound plays when a level is completed. Everything works fine to start with but after repeating a level 10 or 20 times the logcat suddenly reports:
"MediaPlayer error (-19,0)" and/or "MediaPlayer start called in state 0" and the sounds are no longer made.
I originally had the all sounds in mp3 format but, after reading that ogg may be more reliable, I converted them all to ogg, but the errors appeared just the same.
Any idea how I can fix this problem?
I was getting the same problem, I solved it by adding the following code to release the player:
mp1 = MediaPlayer.create(sound.this, R.raw.pan1);
mp1.start();
mp1.setOnCompletionListener(new OnCompletionListener() {
public void onCompletion(MediaPlayer mp) {
mp.release();
};
});
I think you are not releasing the mediaplayers you are using to play the sound..
You need to release() the media players otherwise the resources are not released , and you soon get out of memory (since you allocate them again next time). so,I think you can play twice or even thrice... but not many times without releasing the resources
MediaPlayer is not a good option when you are playing small sound effects as the user can click on multiple buttons very soon and you will have to create a MP object for all of them which doesnt happen synchronously. That is why you are not hearing sounds for every click. Go for the SoundPool Class which allows you to keep smaller sounds loaded in memory and you can play them any time you want without any lag which you would feel in a mediaplayer. http://developer.android.com/reference/android/media/SoundPool.html Here is a nice tutorial : http://www.anddev.org/using_soundpool_instead_of_mediaplayer-t3115.html
I solved both the errors (-19,0) and (-38,0) , by creating a new object of MediaPlayer every time before playing and releasing it after that.
Before :
void play(int resourceID) {
if (getActivity() != null) {
//Using the same object - Problem persists
player = MediaPlayer.create(getActivity(), resourceID);
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
player.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
player.release();
}
});
player.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
mp.start();
}
});
}
}
After:
void play(int resourceID) {
if (getActivity() != null) {
//Problem Solved
//Creating new MediaPlayer object every time and releasing it after completion
final MediaPlayer player = MediaPlayer.create(getActivity(), resourceID);
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
player.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
player.release();
}
});
player.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
mp.start();
}
});
}
}
This is a very old question, But this came up first in my search results So other people with the same issue will probably come upon this page eventually.
Unlike what some others have said, you can in fact use MediaPlayer for small sounds without using a lot of memory. I'll put in a little modified snippit from my soundboard app to show you what I'm getting at.
private MediaPlayer mp;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.your_layout);
mp = new MediaPlayer();
}
private void playSound(int soundID){
mp.reset();
AssetFileDescriptor sound = getResources().openRawResourceFd(soundID);
try {
mp.setDataSource(sound.getFileDescriptor(),sound.getStartOffset(),sound.getLength());
mp.prepare();
} catch (IOException e) {
e.printStackTrace();
}
mp.start();
}
with the way I set it up, you create on MediaPlayer object that you reuse everytime you play a sound so that you don't use up too much space.
You call .reset() instead of .release() because .release() is only used if you are disposing of an object, however you want to keep your MediaPlayer Object.
You use an assetfiledescriptor to set a new soundfile for your mediaplayer to play instead of setting a new object to your mediaplayer address because that way you are creating new objects within the method that aren't being handled properly and you will eventually run into the same error as you described.
This is only one of many ways to use MediaPlayer but I personally think it is the most efficient if you are only using it for small sound applications. The only issue with it is that it is relatively restrictive in what you can accomplish, but that shouldn't be much of an issue if you are indeed using it for small sound applications.
i try delete emulator and new create emulator for remove error of (-19,0) media player.
I'm trying to make an app that can play different midi files at the same time. The files would not be streaming and I would like to include them in the apk.
A maximum of 12 would be played at the same time... Mp3 or a combination of both would also be a suitable substitute but for now midi would be ideal.
Is this at all possible? Thanks in advance to the stack-overflow geniuses! :)
-EltMrx
One easy way to play a single sound is to use MediaPlayer. Put your sound files in the /res/raw folder, then call the below method using R constants, e.g. playSound(R.raw.sound_file_name) where playSound looks something like this:
private void playSound(int soundResId) {
MediaPlayer mp = MediaPlayer.create(context, soundResId);
if (mp == null) {
Log.warn("playSound", "Error creating MediaPlayer object to play sound.");
return;
}
mp.setOnErrorListener(new MediaPlayer.OnErrorListener() {
public boolean onError(MediaPlayer mp, int what, int extra) {
Log.e("playSound", "Found an error playing media. Error code: " + what);
mp.release();
return true;
}
});
mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
public void onCompletion(MediaPlayer mp) {
mp.release();
}
});
mp.start();
}
Now, playing multiple sounds at the same time is a bit more complex, but there is a good solution here.
As #uncheck noted, you can use the standard Android MediaPlayer class for MP3, though playing multiple channels at once is a bit tricky.
Android does not have a built-in synthesizer, so if you want to play pure MIDI files through some type of instrument, your best bet would be to use libpd for Android. After that, you can probably find a PD patch with a synth that would fit your needs for the given sound that you're after.
I've created an app that uses MediaPlayer to play a random (short) sound when a button is clicked. The sounds are played correctly on android devices < 2.2. This is the code responsible for playing sounds.
r = new Random();
sounds = new ArrayList<MediaPlayer>();
sounds.add(MediaPlayer.create(this, R.raw.sound1));
sounds.add(MediaPlayer.create(this, R.raw.sound2));
sounds.add(MediaPlayer.create(this, R.raw.sound3));
sounds.add(MediaPlayer.create(this, R.raw.sound4));
sounds.add(MediaPlayer.create(this, R.raw.sound5));
theButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
playSound();
}
});
private void playSound() {
Thread thread = new Thread() {
public void run() {
MediaPlayer soundPlayer = sounds.get(r.nextInt(sounds.size()));
while (soundPlayer.isPlaying())
{
soundPlayer = sounds.get(r.nextInt(sounds.size()));
}
soundPlayer.seekTo(0);
soundPlayer.start();
}
};
thread.start();
}
The sounds are all .wav files. I tried converting them to .mp3, but then they wouldn't play at all. Am I doing something extremely wrong, or is the MediaPlayer in 2.2 buggy? Anyone else had this problem and know of a fix? Keep in mind that the sounds are played normally on all other devices with an android version below 2.2.
I think you shouldn't create a ArrayList for MediaPlayer. Instead that, you use only a MediaPlayer object and a ArrayList to contain all music resources.
When you next other song, you update only the info of MediaPlayer. For example,
Release the previous MediaPlayer object.
Create other MediaPlayer object
Finally, start this song
Seems there was a problem with the sampling rate of the mp3's that the 2.2 Framework frowned upon. I fixed it by opening up the sounds in a sound editor, resampling them and adding silence to the first and last second of the sounds.