AudioRecord - 如何让数据缓冲?数据、AudioRecord

2023-09-07 17:42:50 作者:泪泯烈酒

我是有使用AudioRecord类的一些问题。我想存储在缓冲区中记录的数据,但我不知道什么是实现这一正确的方法。我经历的例子大量去了,但大多数被comlicated和再presenting许多不同的方法。我在寻找简单的一个或简单的解释。

I' m having some issues using AudioRecord class. I want to store recorded data in a buffer, but I' m not sure what is the proper way to achieve that. I went through great number of examples, but most of them were comlicated and representing many different approaches. I' m looking for simple one or simple explanation.

下面是我的音频设置为我的项目:

Here are my audio settings for my project:

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);

我是想创建一个录音功能:

I' m trying to create a Recording function:

public void Recording() {
    audioRecorder.startRecording();
    ...
    audioRecorder.stop();
    audioRecorder.release();
}

我知道,我在应该使用.read(短[] audioData,INT offsetInShorts,诠释sizeInShorts)函数。在这里,我的问题开始。我不知道如何audioData缓冲工作 - 我认为函数将记录样本放入audioData。如果它完全填满数据会发生什么?它从最早的位置重写?如果确实如此,我相信我有somwhere别人复制所有收集到的样本。这引发了另一个问题 - 我怎么能检查是否.read(...)函数缓冲区已满?我是否需要测量的时间和复制缓冲区的内容或者有另一种方式来达到这个?还做我需要为整个记录操作线程?

I know that I' m supposed to use .read(short[] audioData, int offsetInShorts, int sizeInShorts) function. And here my problems start. I' m not sure how audioData buffer works - I assume function puts recorded samples into the audioData. What happens if it completely filled with data? It starts rewriting from the earliest position? If it does I believe I have to copy all collected samples somwhere else. It raises another question - how can I check if .read(...) function buffer is already full? Do I need to measure time and copy buffer content or there is another way to reach that? Also do I need to create a thread for whole recording operation?

对不起,问这么多问题之一主题:)

Sorry for asking so many questions in one topic :)

推荐答案

回答您的问题:

recorder.read(......)并不一定在所有读取任何数据。你或许应该重写循环暂停通话阅读之间的短一段时间(例如,50毫秒)。它应该也不会排队缓冲区,直到缓冲区有数据。另外,由于缓冲器可能不充分,可能需要使用该保持的字节数的计数的数据结构。到ByteBuffer想到作为一个很好的候选人。您可以填充字节到它在读取循环,当它得到足够充分,排队它的传输和启动另一个。

recorder.read(...) does not necessarily read any data at all. You should probably rewrite that loop to pause for a short while (e.g., 50ms) between calls to read. It should also not queue the buffer until the buffer has data. Also, since the buffer may not be full, you probably need to use a data structure that maintains a count of the number of bytes. A ByteBuffer comes to mind as a good candidate. You can stuff bytes into it in the read loop and when it gets full enough, queue it for transmission and start another one.

offcourse你需要创建一个线程循环吧。如下面code。

offcourse you need to create a thread for looping it. as shown in below code.

下面是录音循环,做适当的错误检查的修改版本。它采用了问答LT; ByteBuffer的>将代替问答LT;字节[]>

Here's a modified version of the recording loop that does proper error checking. It uses a Queue<ByteBuffer> instead of a 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()或你不会得到任何数据。

Of course, somewhere you'll need to call recorder.startRecording() or you won't get any data.

在这个例子中工作样品的外观。

for working sample look at this example.

 
精彩推荐
图片推荐