I got a problem in getting amplitude in my app.
My start method
public void start() {
if (mRecorder == null) {
try {
mRecorder = new MediaRecorder();
mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mRecorder.setOutputFormat(MediaRecorder.OutputFormat.AMR_WB);
mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_WB);
mRecorder.setOutputFile("/dev/null");
try {
mRecorder.prepare();
mRecorder.start();
} catch (IOException e) {
e.printStackTrace();
mRecorder = null;
} catch(IllegalStateException e ){
e.printStackTrace();
mRecorder = null;
}
} catch (RuntimeException e) {
e.printStackTrace();
}
}
}
And my stop method:
public void stop() {
if (mRecorder != null) {
try {
mRecorder.stop();
} catch (RuntimeException stopException) {
//handle cleanup here
} finally {
mRecorder.release();
}
mRecorder = null;
}
}
It throws IllegalStateException on
mRecorder.start();
I tried different OutputFormats and AudioEncoders but none of them was working. :/ Also tried it on different phones.
This is my stacktrace.
W/MediaRecorder: mediarecorder went away with unhandled events
E/MediaRecorder: start failed: -38
W/System.err: java.lang.IllegalStateException
W/System.err: at android.media.MediaRecorder.start(Native Method)
W/System.err: at com.oscarsenior.oscar.util.sensorHelpers.SoundMeter.start(SoundMeter.java:33)
W/System.err: at com.oscarsenior.oscar.util.service.SensorService.updateAmplitude(SensorService.java:616)
W/System.err: at com.oscarsenior.oscar.util.service.SensorService$6.onSensorChanged(SensorService.java:606)
I run this every 15 minutes for 3 seconds to measure max amplitude.
I finally find the solution to my problem.
The problem was lying in my service. I was using MediaRecorder twice at the same time using same MediaRecorder.AudioSource.
The solution for this is to use the same mRecorder for both cases.
So I created Singleton from my SoundMeter class.
protected SoundMeter(){
}
public static SoundMeter getInstance(){
if(instance == null){
instance = new SoundMeter();
}
if(!instance.isRecording || instance.mRecorder == null){
instance.start();
}
return instance;
}
So I get instance of SoundMeter and if the instance with mRecorder is not initialized, I will use same SoundMeter.start() method as in question.
I added mRecorder.reset() to stop() method, so release mRecorder will clear its state. Probably I could release MediaRecorder once finished not every time I stop listening for a while, but I rather free some memory on background when I do not need it.
if (mRecorder != null) {
try {
mRecorder.stop();
} catch (RuntimeException stopException) {
//handle cleanup here
} finally {
mRecorder.reset();
mRecorder.release();
}
mRecorder = null;
isRecording = false;
}