您的位置:首页 > 移动开发 > Android开发

AudioRecord 使用小结与注意事项

2017-08-10 09:40 976 查看
使用专门的线程读取数据,容易出现buffer overflow。
使用 setRecordPositionUpdateListener时,要注意两个问题:

一:
1.启动录音后,要先read buffer,才会通知激活 listener。
audioRecord.startRecording();
audioRecord.read(buffer, 0, buffer.length);

2.录音 通知周期 及 录音数据读取 buffer 的设定(重点:audioRecord.read()读取的大小最好是设定的缓冲区的一半,效果会好多)
audioRecord.setPositionNotificationPeriod(framePeriod);//也可以自己指定一个buffer大小,但是不能小于min buffer
bufferSize = AudioRecord.getMinBufferSize(sampleRate,channelConfig, audioFormat);

int framePeriod=framePeriod = bufferSize / (2 * bSamples * nChannels / 8);

//读取录音数据 的buffer 应该为bufferSize/2,否则会出现stop后,数据延时与混乱(数据未正确写入文件)
buffer = new byte[framePeriod * bSamples / 8 * nChannels];//buffer = new byte[bufferSize/2]

二:
避免录音阻塞主线程,利用反射,更改AudioRecord 对象中的 mInitializationLooper(Looper 对象) 属性,为我们指定的子线程的 looper,然后再设置setRecordPositionUpdateListener(这个方法中会用到mInitializationLooper
对象)


audioRecorder1=AudioRecorder1.getInstanse();

HandlerThread handlerThread=new HandlerThread("handlerThread");
handlerThread.start();
...
//利用反射,更改属性,为指定子线程的looper
field2.set(field.get(audioRecorder1), handlerThread.getLooper());

//设置监听
audioRecorder1.prepare();

//prepare 方法的实现
public void prepare() {
try {
if (state == State.INITIALIZING) {
audioRecorder.setRecordPositionUpdateListener(updateListener);
audioRecorder.setPositionNotificationPeriod(framePeriod);
if ((audioRecorder.getState() == AudioRecord.STATE_INITIALIZED)
& (filePath != null)) {
// write file header
OutputStream out = new FileOutputStream(filePath);
out.write(1);
out.close();
random = new RandomAccessFile(filePath, "rw");

random.setLength(0); // Set file length to

random.writeBytes("RIFF");
......

具体细节如下
audioRecorder1=AudioRecorder1.getInstanse();
HandlerThread handlerThread=new HandlerThread("handlerThread");
handlerThread.start();
try {
Field field=audioRecorder1.getClass().getDeclaredField("audioRecorder");
Field field2=field.getType().getDeclaredField("mInitializationLooper");
field.setAccessible(true);
field2.setAccessible(true);

System.out.println("--handlerThread-lp--"+handlerThread.getLooper());
System.out.println("--main-lp--"+Looper.getMainLooper());
field2.set(field.get(audioRecorder1), handlerThread.getLooper());

audioRecorder1.setOutputFile("/mnt/sdcard/audio11.wav");
audioRecorder1.prepare();
audioRecorder1.start();

} catch (NoSuchFieldException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息