I am writing an app that dynamically creates a midi file which I then want to play. Each time I press a button in my app a new midi file is created and written to external storage. I then want the app to read that file and play it. I am using SoundPool to play the file. However, from the samples I have found, SoundPool is initialized during onCreate and therefore my file is only read once. Meaning the same file is played everytime I hit the button regardless of any changes I make to it. I have tried moving the SoundPool initialisation into my Audio1ButtonHandler method but then I get no sound or get a selection of “sample x not ready” errors. The relevant code from my app is here:
public void onCreate(Bundle savedInstanceState) {
…………
soundPool = new SoundPool(1, AudioManager.STREAM_MUSIC, 0);
soundPoolMap = new HashMap<Integer, Integer>();
soundPoolMap.put(SOUNDPOSITION, soundPool.load("/sdcard/test.mid", 1));
}
public void Audio1ButtonHandler(View target) {
ArrayList<Integer> chord = new ArrayList<Integer>();
chord = Chord.calculateChord(kSelection, cSelection);
for (int i = 0; i < chord.size(); i++) {
System.out.println("chord value is " + chord.get(i).toString());
}
Midi.createMidiFile(chord);
playSound();
releaseSound();
}
public void playSound() {
AudioManager mgr = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
float streamVolumeCurrent = mgr.getStreamVolume(AudioManager.STREAM_MUSIC);
float streamVolumeMax = mgr.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
float volume = streamVolumeCurrent / streamVolumeMax;
soundPool.play(soundPoolMap.get(SOUNDPOSITION), volume, volume, 1, 0, 1f);
}
public void releaseSound() {
soundPoolMap.clear();
soundPool.release();
}
As you can see I have tried to release the resources (within releaseSound) to try and force them to be re-read but to no avail.
Any pointers would be greatly received.
Thanks
First stop playing before you release! Then, after release, set soundPool to null.
Related
I found many questions regarding Soundpool but they all state that it is not working at all. for me the case is different.
i have declared a soundpool object and track ids as follow
public static SoundPool sp;
public static int comeCloseID, goFurtherID, blinkID, smileID, rotateLeftID, rotateRightID;
then i have created a initSounds function to initialize the sound pool
public static void initSounds()
{
sp = new SoundPool.Builder().build();
comeCloseID = sp.load(mContext, R.raw.comeclose,1);
goFurtherID = sp.load(mContext, R.raw.gofurther,1);
blinkID = sp.load(mContext, R.raw.blink, 1);
smileID = sp.load(mContext, R.raw.smile, 1);
rotateLeftID = sp.load(mContext, R.raw.rotateleft, 1);
rotateRightID = sp.load(mContext, R.raw.rotateright, 1);
sp.setOnLoadCompleteListener(new SoundPool.OnLoadCompleteListener() {
#Override
public void onLoadComplete(SoundPool soundPool, int sampleId,
int status) {
loaded = true;
}
});
}
then i paly the sounds as follows:
GlobalParams.sp.play(GlobalParams.comeCloseID, 1, 1, 1, 0, 1);
etc...
the audio files paly well using my samsung note5 device. but when i try them on a J1 device or a lenovo device the sounds wont play. (thogh i can log the value of loaded to be true).
what have i missed? and why the audio isn't playing?
Knowing that I tried using different formats for the audio (WAV, MP3....) but id didnt solve the case.
Try increasing setMaxStreams(5) to say 5, you have it set to default of 1:
AudioAttributes attributes = new AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.setFlags(AudioAttributes.FLAG_AUDIBILITY_ENFORCED)
.setUsage(AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_INSTANT)
.build();
sp = new SoundPool.Builder()
.setMaxStreams(5)
.setAudioAttributes(attributes)
.build();
What is the best way to play a sound and stop it?
I tried using RingtoneManager, MediaPlayer and SoundPool, but failed to stop the sound.
Is there a way to stop sound when using RingtoneManager TYPE_ALARM?
Please a simple snippet.
This is the last thing I tried:
SoundPool pool = new SoundPool(10, AudioManager.STREAM_MUSIC, 0);
List<Integer> streams = new ArrayList<Integer>();
int soundId = pool.load(getApplicationContext(), R.drawable.alarm, 1); //There are several versions of this, pick which fits your sound
try{
if(myWifiInfo.getRssi() < -55)
{
/*
Uri notification = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
Ringtone r = RingtoneManager.getRingtone(getApplicationContext(), notification);
r.play();*/
Thread.sleep(1000);
int streamId = -1;
streamId = pool.play(soundId, 1.0f, 1.0f, 1, 0, 1.0f);
streams.add(streamId);
textRssi.setText(String.valueOf(myWifiInfo.getRssi() + " WARNING"));
}
else {
Log.e("WIFI","Usao");
for (Integer stream : streams) {
pool.stop(stream);
}
streams.clear();
Log.e("WIFI","Izasao");
}
I'm assuming this function gets called many times? The problem is that you're adding the streamID to a local list. That list is getting recreated each time the function is called, so when you try to call stop the list will always be empty.
If its only being called once, then the problem is you're never calling stop, only play (they're in separate branches of that if).
I am using the ToneGenarator in order to play a continuous beep.
The problem is that the volume is far too low!
We can't hear anything when the volume is lower than 8.
And with the maximum volume, it is not loud at all...
Is it a limitation of the DTMF sound or am I doing something wrong?
Here is the code:
private final int TONE_TYPE = ToneGenerator.TONE_DTMF_5;
private final int STREAM = AudioManager.STREAM_MUSIC;
private final int DOT_TIME = 3;
public SoundManager(Activity anActivity) {
audio = (AudioManager) anActivity
.getSystemService(Context.AUDIO_SERVICE);
generator = new ToneGenerator(STREAM,
audio.getStreamMaxVolume(STREAM));
}
private void playBeep() {
generator.startTone(TONE_TYPE, DOT_TIME);
}
Use this one, For using Current System Volume.
ToneGenerator toneG = new ToneGenerator(AudioManager.STREAM_SYSTEM, 100);
I found where the problem was:
ToneGenerator takes a volume between 0 and 100, while the stream volume is between 0 and 15.
Thus, audio.getStreamMaxVolume(STREAM) gives 15 out of 100, it is low...
I have a button that when pressed sounds a short sound effect with SoundPool. the file is a 16k mp3.
The sound effect works for hundreds of button clicks, but at some point i get this error (and the sound isn't playing for clicks anymore):
E/AudioFlinger( 34): no more track names available
E/AudioTrack( 904): AudioFlinger could not create track, status: -12
E/SoundPool( 904): Error creating AudioTrack
W/AudioFlinger( 34): write blocked for 81 msecs, 4573 delayed writes, thread
xb3f0
onCreate:
setVolumeControlStream(AudioManager.STREAM_MUSIC);
soundpool = new SoundPool(10, AudioManager.STREAM_MUSIC, 0);
soundpool.setOnLoadCompleteListener(new OnLoadCompleteListener() {
#Override
public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
// TODO Auto-generated method stub
loaded = true;
}
});
//save the effect somewhere:
MyUtil.regularSound = soundpool.load(this, R.raw.regular_click,1);
onClick:
AudioManager audioManager = (AudioManager) getSystemService(AUDIO_SERVICE);
float actualVol = (float) audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
float maxVol = (float) audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
float vol = actualVol/maxVol;
if (loaded) {
soundpool.play(MyUtil.regularSound,vol,vol,1,0,1f);
}
before starting another intent:
Intent i = new Intent(con, EndScreen.class);
if (soundpool != null) {
soundpool.release();
soundpool = null;
}
startActivity(i);
I just spent hours with the same problem.
The -12 error means that sound allocated to the app is out of memory. using .finish() doesn't release the memory of SoundPool. You have to use .release().
In my app I have a soundPool.release() on the onclick method that starts the next activity,
Changing the sound formats didn't work for me either.
Im getting the same error. The thing I did was to try to resample the track, convert it to OGG format and change the quality to 0. I did all this with Audacity
You try code it: here
/*
private SoundPool mSoundPool;
private SparseArray<Integer> mSoundPoolMap;
private AudioManager mAudioManager;
*/
public static void clear() {
if (mSoundManager != null) {
mSoundManager.mSoundPool = null;
mSoundManager.mAudioManager = null;
mSoundManager.mSoundPoolMap = null;
}
mSoundManager = null;
}
I have searched StackOverflow and cannot find a situtation like mine. I am using four buttons with each button playing a sound file.
I am using SoundPool:
SoundPool sound = new SoundPool(4, AudioManager.STREAM_MUSIC, 0);
I am also using the OnLoadCompleteListener() which uses Log to create an I notification in LogCat.
When I launch the program in the emulator I see all four samples complete loading. During the program three of the sounds will play, however, one will always say:
WARN/SoundPool(4842): sample 0 not READY
Any Ideas.. cause i'm quite flabbergasted. The sound files are 16-bit pcm wave file playing squarewave tones.
Load Code:
sound.setOnLoadCompleteListener(new OnLoadCompleteListener(){
#Override
public void onLoadComplete(SoundPool sound, int sampleId, int status) {
if(status != 0)
Log.e("SOUND LOAD"," Sound ID: " + sampleId + " Failed to load.");
else
Log.i("SOUND LOAD"," Sound ID: " + sampleId + " loaded.");
}
});
soundID[0] = sound.load(this, R.raw.greennote, 1);
soundID[1] = sound.load(this, R.raw.rednote, 1);
soundID[2] = sound.load(this, R.raw.yellownote, 1);
soundID[3] = sound.load(this, R.raw.bluenote, 1);
Play Sound:
streamid.setStreamId(myActivity.sound.play(id, 0.5f, 0.5f, 0, 0, 1));
I'm having the same issues. From my experiments, it looks like there's something wrong with the ID handling. SoundPool just doesn't like sound IDs with the number 0.
So I have found a work-around. Start my sample IDs with 1, not 0. Hope this works.