我在使用AudioRecord类时遇到了一些问题。我想将记录的数据存储在缓冲区中,但我不确定实现它的正确方法是什么。我经历了大量的例子,但大多数都是复杂的,代表了许多不同的方法。我正在寻找简单或简单的解释。
以下是我项目的音频设置:
int audioSource = AudioSource.MIC;
int sampleRateInHz = 8000;
int channelConfig = AudioFormat.CHANNEL_IN_MONO;
int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
int bufferSizeInBytes = AudioRecord.getMinBufferSize(sampleRateInHz, channelConfig, audioFormat);
short[] buffer = new short[bufferSizeInBytes];
AudioRecord audioRecorder = new AudioRecord(audioSource,
sampleRateInHz,
channelConfig,
audioFormat,
bufferSizeInBytes);
我正在尝试创建录制功能:
public void Recording() {
audioRecorder.startRecording();
...
audioRecorder.stop();
audioRecorder.release();
}
我知道我应该使用.read(short [] audioData,int offsetInShorts,int sizeInShorts)函数。在这里我的问题开始了。我不确定audioData缓冲区是如何工作的 - 我假设函数将记录的样本放入audioData中。如果它完全充满数据会发生什么?它从最早的位置开始重写?如果确实如此,我相信我必须将所有收集的样本复制到其他地方。它提出了另一个问题 - 如何检查.read(...)函数缓冲区是否已满?我是否需要测量时间和复制缓冲区内容,还是有另一种方法可以实现这一目标?我还需要为整个录制操作创建一个线程吗?
很抱歉在一个主题中提出这么多问题:)
答案 0 :(得分:4)
回答您的问题::
recorder.read(...)根本不一定读取任何数据。您可能应该重写该循环以在读取调用之间暂停一段时间(例如,50ms)。在缓冲区有数据之前,它也不应该对缓冲区进行排队。此外,由于缓冲区可能未满,您可能需要使用维持字节数计数的数据结构。作为一个好的候选人,我会想到一个ByteBuffer。您可以在读取循环中将字节填充到其中,当它足够满时,将其排队以进行传输并启动另一个。
offcourse你需要创建一个循环它的线程。如下面的代码所示。
这是录制循环的修改版本,可以进行正确的错误检查。它使用Queue<ByteBuffer>
代替Queue<byte[]>
:
private void startRecording() {
recorder.startRecording();
isRecording = true;
recordingThread = new Thread(new Runnable() {
@Override
public void run() {
bData = ByteBuffer.allocate(BufferElements);
bbarray = new byte[bData.remaining()];
bData.get(bbarray);
while (isRecording) {
int result = recorder.read(bbarray, 0, BufferElements);
System.out.println("READ DATA");
if (result > 0) {
qArray.add(bData);
--your stuffs--
bData = ByteBuffer.allocate(BufferElements);
} else if (result == AudioRecord.ERROR_INVALID_OPERATION) {
Log.e("Recording", "Invalid operation error");
break;
} else if (result == AudioRecord.ERROR_BAD_VALUE) {
Log.e("Recording", "Bad value error");
break;
} else if (result == AudioRecord.ERROR) {
Log.e("Recording", "Unknown error");
break;
}
try {
Thread.sleep(10);
} catch (InterruptedException e) {
break;
}
}
}
}, "AudioRecorder Thread");
recordingThread.start();
}
当然,在某个地方,您需要致电recorder.startRecording()
,否则您将无法获得任何数据。
查看工作样本at this example。