turtleboy turtleboy - 1 month ago 11
Android Question

AudioRecord object not initializing

In the below code my

audioRecord
object is not initializing. I tried moving it to the
onCreate
method and made it a global. I've logged the state and that returns a value of
1
which means ready to use. The debugger says that
startRecording
is being called on an uninitialized object. It is also saying that it could not get the audio source.

Why am I getting these errors?

package com.tecmark;

import java.io.BufferedOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import android.app.Activity;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.View;
import android.widget.TextView;

public class recorder extends Activity {

private Thread thread;
private boolean isRecording;
private AudioRecord recorder;
private FileOutputStream os;
private BufferedOutputStream bos;
private DataOutputStream dos;
private TextView text;
private int audioSource = MediaRecorder.AudioSource.MIC;
private int sampleRate = 22050;
private int channel = AudioFormat.CHANNEL_CONFIGURATION_MONO;
private int encoding = AudioFormat.ENCODING_PCM_16BIT;
private int result = 0;
private int bufferSize;
private byte[] buffer;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

Log.v("onCreate", "layout set, about to init audiorec obj");
text = (TextView)findViewById(R.id.TextView01);

bufferSize = AudioRecord.getMinBufferSize(sampleRate,channel,encoding);
buffer = new byte[bufferSize];

recorder = new AudioRecord(audioSource, sampleRate,channel,encoding,
AudioRecord.getMinBufferSize(sampleRate, channel,encoding));
Log.i("recorder obj state",""+recorder.getRecordingState());
}

public void onClickPlay(View v){

}


public void record(){
Log.i("inside record method", "******");
File path = Environment.getExternalStorageDirectory();
Log.v("file path", ""+path.getAbsolutePath());

File file = new File(path, "test.wav");

if(file.exists()){
file.delete();
}

path.mkdirs();
Log.v("file path", ""+file.getAbsolutePath());

try {
os = new FileOutputStream(file);
bos = new BufferedOutputStream(os);
dos = new DataOutputStream(bos);
} catch (Exception e1) {
e1.printStackTrace();
}

int bufferSize = AudioRecord.getMinBufferSize(sampleRate,channel,encoding);
byte[] buffer = new byte[bufferSize];
recorder.startRecording();
isRecording = true;
try{
while (isRecording){
result = recorder.read(buffer, 0, bufferSize);
for(int a=0; a<result;a++){
dos.write(buffer[a]);

if(!isRecording){
recorder.stop();
break;
}

}

}
dos.flush();
dos.close();
}catch(Exception e){
e.printStackTrace();
}

}// end of record method

public void onClickStop(View v){
Log.v("onClickStop", "stop clicked");
isRecording=false;
}
public void onClickReverse(View v){
Log.v("onClickReverse", "reverse clicked");
}
public void onClickRecord(View v){
Log.v("onClickRecourd", "record clicked, thread gona start");
text.setText("recording");
thread = new Thread(new Runnable() {
public void run() {
isRecording = true;
record();
}
});

thread.start();
isRecording = false;
}
}//end of class


Logcat

01-30 15:23:16.724: ERROR/AudioRecord(12817): Could not get audio input for record source 1 01-30 15:23:16.729:
ERROR/AudioRecord-JNI(12817): Error creating AudioRecord instance: initialization check failed. 01-30 15:23:16.729:
ERROR/AudioRecord-Java(12817): [ android.media.AudioRecord ] Error code
-20 when initializing native AudioRecord object. 01-30 15:23:16.729: INFO/recorder obj state(12817): 1 01-30 15:23:16.729:
WARN/dalvikvm(12817): threadid=13: thread exiting with uncaught exception (group=0x4001b180) 01-30 15:23:16.729:
ERROR/AndroidRuntime(12817): Uncaught handler: thread Thread-7 exiting due to uncaught exception 01-30 15:23:16.739:
ERROR/AndroidRuntime(12817): java.lang.IllegalStateException: startRecording() called on an uninitialized AudioRecord. 01-30 15:23:16.739:
ERROR/AndroidRuntime(12817): at android.media.AudioRecord.startRecording(AudioRecord.java:495) 01-30 15:23:16.739:
ERROR/AndroidRuntime(12817): at com.tecmark.recorder.record(recorder.java:114) 01-30 15:23:16.739:
ERROR/AndroidRuntime(12817): at com.tecmark.recorder$1.run(recorder.java:175) 01-30 15:23:16.739:
ERROR/AndroidRuntime(12817): at java.lang.Thread.run(Thread.java:1096)

Answer

The trick with using AudioRecord is that each device may have different initialization settings, so you will have to create a method that loops over all possible combinations of bit rates, encoding, etc.

private static int[] mSampleRates = new int[] { 8000, 11025, 22050, 44100 };
public AudioRecord findAudioRecord() {
    for (int rate : mSampleRates) {
        for (short audioFormat : new short[] { AudioFormat.ENCODING_PCM_8BIT, AudioFormat.ENCODING_PCM_16BIT }) {
            for (short channelConfig : new short[] { AudioFormat.CHANNEL_IN_MONO, AudioFormat.CHANNEL_IN_STEREO }) {
                try {
                    Log.d(C.TAG, "Attempting rate " + rate + "Hz, bits: " + audioFormat + ", channel: "
                            + channelConfig);
                    int bufferSize = AudioRecord.getMinBufferSize(rate, channelConfig, audioFormat);

                    if (bufferSize != AudioRecord.ERROR_BAD_VALUE) {
                        // check if we can instantiate and have a success
                        AudioRecord recorder = new AudioRecord(AudioSource.DEFAULT, rate, channelConfig, audioFormat, bufferSize);

                        if (recorder.getState() == AudioRecord.STATE_INITIALIZED)
                            return recorder;
                    }
                } catch (Exception e) {
                    Log.e(C.TAG, rate + "Exception, keep trying.",e);
                }
            }
        }
    }
    return null;
}

AudioRecord recorder = findAudioRecord();
recorder.release();