SoundPool stops playing - android

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;
}

Related

How to set a value for Bluetooth media volume

I`m trying to make an android app that can control Bluetooth volume.
till now i managed to change Bluetooth volume value for calls. using this piece of code :
audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
int streamMaxVolume = audioManager.getStreamMaxVolume(6);
int lVol = ((volumeValue / 100) * streamMaxVolume);
audioManager.setStreamVolume(6, lVol, 0);
now the problem that I have is I cannot find the int value for streamType which is allocated for Bluetooth Media volume.
well I found the answer.
looks like after a bluetooth device connect to the phone. in order to change the bluetooth media volume the app should wait for some amount of time. I`ve set my method to run its codes after 10sec. here it is :
public void strat(BtDevice btDevice){
new Timer().schedule(
new TimerTask() {
#Override
public void run() {
AudioManager audioManager = (AudioManager) myContex.getSystemService(Context.AUDIO_SERVICE);
int volumeValue = btDevice.getMusicVolume();
int streamMaxVolume = audioManager.getStreamMaxVolume(3);
int lVol = ((volumeValue / 100) * streamMaxVolume);
audioManager.setStreamVolume(3, lVol, AudioManager.FLAG_SHOW_UI);
}
},
10000
);

Android volume of a beep generated by ToneGenerator

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

Playing Audio in Android via AudioManager?

I play a sound using:
public class NotificationFunction implements FREFunction {
public FREObject call(FREContext context, FREObject[] args) {
Context appContext = context.getActivity().getApplicationContext();
AudioManager mAudioManager = (AudioManager)
appContext.getSystemService(Context.AUDIO_SERVICE);
mAudioManager.loadSoundEffects();
mAudioManager.playSoundEffect(0);
It plays a default sound effect, how can I get it to play a custom sound effect.
Also I have tried to implement sound pool but it doesnt work, I implemented it the standard way but it doesnt work. Any ideas why? Or if I can use the audio manager for sounds instead?
Check with following code
using (AudioManager am= (AudioManager)WebViewActivity.Instance.GetSystemService(Context.AudioService))
{
int maxVol = am.GetStreamMaxVolume(Stream.Music);
float myVol= maxVol * volume;
am.SetStreamVolume(Stream.Music, (int)(myVol), 0);
using (SoundPool soundPool = new SoundPool(1, Stream.Music, 0))
{
int soundFileId = soundPool.Load(soundFilePath, 1);
soundPool.LoadComplete += (sender, eventArgs) =>
{
using (SoundPool soundPoolLoaded = sender as SoundPool)
{
soundPoolLoaded.Play(soundFileId, myVol,
myVol, 0, 0, 1.0f);
}
};
}
}

Dynamically re-reading a midi file

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.

Android - Getting audio to play through earpiece

I currently have code that reads a recording in from the devices mic using the AudioRecord class and then playing it back out using the AudioTrack class.
My problem is that when I play it out it plays via the speaker phone.
I want it to play out via the ear piece on the device.
Here is my code:
public class LoopProg extends Activity {
boolean isRecording; //currently not used
AudioManager am;
int count = 0;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
am.setMicrophoneMute(true);
while(count <= 1000000){
Record record = new Record();
record.run();
count ++;
Log.d("COUNT", "Count is : " + count);
}
}
public class Record extends Thread{
static final int bufferSize = 200000;
final short[] buffer = new short[bufferSize];
short[] readBuffer = new short[bufferSize];
public void run() {
isRecording = true;
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);
int buffersize = AudioRecord.getMinBufferSize(11025, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT);
AudioRecord arec = new AudioRecord(MediaRecorder.AudioSource.MIC, 11025, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT, buffersize);
AudioTrack atrack = new AudioTrack(AudioManager.STREAM_MUSIC, 11025, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT, buffersize, AudioTrack.MODE_STREAM);
am.setRouting(AudioManager.MODE_NORMAL,1, AudioManager.STREAM_MUSIC);
int ok = am.getRouting(AudioManager.ROUTE_EARPIECE);
Log.d("ROUTING", "getRouting = " + ok);
setVolumeControlStream(AudioManager.STREAM_VOICE_CALL);
//am.setSpeakerphoneOn(true);
Log.d("SPEAKERPHONE", "Is speakerphone on? : " + am.isSpeakerphoneOn());
am.setSpeakerphoneOn(false);
Log.d("SPEAKERPHONE", "Is speakerphone on? : " + am.isSpeakerphoneOn());
atrack.setPlaybackRate(11025);
byte[] buffer = new byte[buffersize];
arec.startRecording();
atrack.play();
while(isRecording) {
arec.read(buffer, 0, buffersize);
atrack.write(buffer, 0, buffer.length);
}
arec.stop();
atrack.stop();
isRecording = false;
}
}
}
As you can see if the code I have tried using the AudioManager class and its methods including the deprecated setRouting method and nothing works, the setSpeakerphoneOn method seems to have no effect at all, neither does the routing method.
Has anyone got any ideas on how to get it to play via the earpiece instead of the spaker phone?
Just got it to work on 2.2. I still needed the In_Call setup which I don't really like but I'll deal with it for now. I was able to ditch the call routing stuff which is deprecated now. I found you definitely need the Modify_Audio_Settings permission, no error without it but it the setSpeakerPhone method just does nothing. Here is the mock up of the code I used.
private AudioManager m_amAudioManager;
m_amAudioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
m_amAudioManager.setMode(AudioManager.MODE_IN_CALL);
m_amAudioManager.setSpeakerphoneOn(false);
Please use this code, works well:
//PLAY ON EARPIECE
mPlayer.setAudioStreamType(AudioManager.STREAM_VOICE_CALL);
audioManager.setMode(AudioManager.MODE_IN_CALL);
audioManager.setSpeakerphoneOn(false);
//PLAY ON SPEAKER
mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
audioManager.setMode(AudioManager.MODE_IN_CALL);
audioManager.setSpeakerphoneOn(true);
There was some related discussion in this recent question:
Android - can I mute currently playing audio applications?
Based on the AudioManager source code, it seems that you must be in "call mode" before the setSpeakerphoneOn method has any effect.
However, I recently saw an application that could seamlessly switch between earpiece and speakerphone while still showing the current stream as the "media" stream, so I would be interested in any further answers.
Misleaded by some answers here for quite a lot of time. I'm using Android 2.2. "audioManager.setSpeakerphoneOn(false);" is working.
audioManager.setSpeakerphoneOn(false);
...
mediaPlayer.setDataSource(..);
mediaPlayer.setAudioStreamType(AudioManager.STREAM_VOICE_CALL);
mediaPlayer.prepare();
public MediaPlayer m_mpSpeakerPlayer;
private AudioManager m_amAudioManager;
m_amAudioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
// 從Receiver Earpiece發音
m_amAudioManager.setSpeakerphoneOn(false);
m_amAudioManager.setRouting(AudioManager.MODE_NORMAL, AudioManager.ROUTE_EARPIECE, AudioManager.ROUTE_ALL);
Log.i(TAG, String.valueOf(m_amAudioManager.getRouting(AudioManager.ROUTE_EARPIECE)));
setVolumeControlStream(AudioManager.STREAM_VOICE_CALL);
// 把聲音設定成從Earpiece出來
// 重點在這行,要把它設定為正在通話中
m_amAudioManager.setMode(AudioManager.MODE_IN_CALL);
// 開始放音樂
m_mpSpeakerPlayer.reset();
m_mpSpeakerPlayer.setDataSource("sdcard/receiver.mp3");
m_mpSpeakerPlayer.prepare();
m_mpSpeakerPlayer.start();
//最後再把它設定從Speaker放音,達成!
m_amAudioManager.setMode(AudioManager.MODE_NORMAL);
I appear to have got it working on 1.6.
So I said I'd post here how I done it.
To get it working in 1.6 I:
Used the AudioManager class to set setSpeakerphoneOn(false), I then used the Voice_Call_Stream and add volume control to the Voice_Call_Stream.
The setSpeakerphoneOn(false) method is used in onCreate() of the activity and this appears to route to the headset, I then used a button and used the setSpeakerphoneOn(true) method and the audio gets routed to the speaker.
The method only appears to work when it is used in onCreate() for me and I haven't tested it extensively but for the moment it allows me to switch between headset and speaker on a 1.6 device
now in 2022 in Android S (12, API31) setSpeakerphoneOn(false) isn't working reliablie, it is in fact deprecated! instead we can use new API and setCommunicationDevice(AudioDeviceInfo) method. (works with AudioManager.STREAM_VOICE_CALL)
some sample
Boolean result = null;
ArrayList<Integer> targetTypes = new ArrayList<>();
if (earpieceMode) {
targetTypes.add(AudioDeviceInfo.TYPE_BUILTIN_EARPIECE);
} else { // play out loud
targetTypes.add(AudioDeviceInfo.TYPE_BUILTIN_SPEAKER);
}
AudioDeviceInfo currentDevice = audioManager.getCommunicationDevice();
if (currentDevice!=null) {
for (Integer targetType : targetTypes) {
if (targetType == currentDevice.getType()) {
Log.i("AUDIO_MANAGER", "setCommunicationDevice targetType ALREADY SET UP!!");
result = true;
break;
}
}
}
if (result == null) {
List<AudioDeviceInfo> devices = audioManager.getAvailableCommunicationDevices();
outer:
for (Integer targetType : targetTypes) {
for (AudioDeviceInfo device : devices) {
if (device.getType() == targetType) {
result = audioManager.setCommunicationDevice(device);
Log.i("AUDIO_MANAGER", "setCommunicationDevice type:" + targetType + " result:" + result);
if (result) break outer;
}
}
}
}
if (result == null) {
Log.i("AUDIO_MANAGER", "setCommunicationDevice targetType NOT FOUND!!");
}
else if (!result) {
Log.i("AUDIO_MANAGER", "setCommunicationDevice targetType FAILED TO SET!!");
}
If the ear piece is connected to the phone with bluetooth (which I assume it is), have you tried calling AudioManager.setBluetoothScoOn(true)?
I've been through the Android reference and this is the only thing I could find that you didn't mention trying.

Categories

Resources