In my Application I want to use the AudioTrack class to play back some sound I record. I record the audio via an AudioRecord object, read the object and then I want to play the recorded sound. However, the way I have it programmed now will result in an error in the AudioTrack-JNI which will say that “Buffer direct access is not supported, can’t record”.
The code looks like this:
public class RecorderThread extends Thread{
private static AudioRecord mAudioRecorder;
private final int USE_MIC = MediaRecorder.AudioSource.MIC;
private static final int FREQUENCY = 8000;
private int mBuffSize, mChannel, mEncoding;
private byte[] mBuffer;
private Context mContext;
private volatile boolean mContinueLoop = true,
mDataPresent = false,
mProcessData = false;
private BroadcastReceiver mActionListener = new BroadcastReceiver(){
@Override
public void onReceive(Context context, Intent intent){
if(intent.getAction().equals(mContext.getString(R.string.STOP_THREAD))){
mContinueLoop = false;
Thread.currentThread().interrupt();
} else if(intent.getAction().equals(mContext.getString(R.string.START_RECORDING))){
mAudioRecorder.startRecording();
} else if(intent.getAction().equals(mContext.getString(R.string.STOP_RECORDING))){
mAudioRecorder.stop();
mDataPresent = true;
} else if(intent.getAction().equals(mContext.getString(R.string.PROCESS_DATA))){
if(mDataPresent){
mProcessData = true;
mDataPresent = false;
}
}
}
};
public RecorderThread(Context context){
mContext = context;
mChannel = AudioFormat.CHANNEL_IN_MONO;
mEncoding = AudioFormat.ENCODING_PCM_16BIT;
mBuffSize = AudioRecord.getMinBufferSize(FREQUENCY, mChannel, mEncoding);
mBuffer = new byte[FREQUENCY * 10];
mAudioRecorder = new AudioRecord(USE_MIC, FREQUENCY, mChannel, mEncoding, mBuffer.length);
IntentFilter filter = new IntentFilter();
filter.addAction(mContext.getString(R.string.START_RECORDING));
filter.addAction(mContext.getString(R.string.STOP_RECORDING));
filter.addAction(mContext.getString(R.string.PROCESS_DATA));
filter.addAction(mContext.getString(R.string.STOP_THREAD));
mContext.registerReceiver(mActionListener, filter);
}
@Override
public void run(){
while(mContinueLoop){
if(mProcessData){
// Process data.
ByteBuffer sampledData = ByteBuffer.wrap(mBuffer);
int readSamples = mAudioRecorder.read(sampledData, sampledData.limit());
processData(sampledData, readSamples);
mProcessData = false;
}
try{
Thread.sleep(100);
} catch(InterruptedException e){
e.printStackTrace();
}
}
mAudioRecorder.release();
}
private void processData(ByteBuffer sampledData, int readSamples) {
byte[] data = sampledData.array();
AudioTrack track = new AudioTrack(AudioManager.STREAM_MUSIC,
FREQUENCY,
AudioFormat.CHANNEL_OUT_MONO,
mEncoding,
data.length,
AudioTrack.MODE_STATIC);
if(track != null){
track.write(data, 0, data.length);
track.play();
track.release();
}
}
}
I’ve looked through the native code that is makes the AudioTrack-JNI (http://www.netmite.com/android/mydroid/1.6/frameworks/base/core/jni/android_media_AudioRecord.cpp), but this doesn’t make it any clearer. The only times this error will pop up is when a buffer capacity <= 0 or when the address to this buffer is null.
So yeah, I’ve got no idea on why this doesn’t work… Anybody with a bit more experience might have… So please enlighten me? Thanks in advance…
I’ve done some more debugging and found that the Issue is not the
AudioTrack, but it is with theAudioRecord.read()method. Still haven’t got a solution on it though… Anybody?