【问题标题】:AudioRecord - how to get data in to buffer?AudioRecord - 如何将数据放入缓冲区?
【发布时间】:2012-11-09 16:02:18
【问题描述】:

我在使用 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(...) 函数缓冲区是否已满?我需要测量时间并复制缓冲区内容还是有其他方法可以实现?我还需要为整个录制操作创建一个线程吗?

很抱歉在一个主题中问了这么多问题:)

【问题讨论】:

    标签: android buffer


    【解决方案1】:

    回答您的问题 ::

    recorder.read(...) 根本不需要读取任何数据。您可能应该重写该循环以在读取调用之间暂停一小段时间(例如,50 毫秒)。在缓冲区有数据之前,它也不应该对缓冲区进行排队。此外,由于缓冲区可能未满,您可能需要使用维护字节数计数的数据结构。一个 ByteBuffer 被认为是一个很好的候选者。您可以在读取循环中将字节填充到其中,当它足够满时,将其排队等待传输并开始另一个。

    当然你需要创建一个线程来循环它。如下代码所示。

    这是一个经过修改的录制循环版本,可以进行正确的错误检查。它使用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

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-07-21
    • 2012-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多