AudioRecord的getMinBufferSize函数的分析

AudioRecord的getMinBufferSize函数的分析
1.java用法示例 此方法是静态方法,可以直接调用,测试用例如下,测试此函数的取得的最小buffer:

  1. int size = AudioRecord.getMinBufferSize(44100, AudioFormat.CHANNEL_IN_DEFAULT, AudioFormat.ENCODING_PCM_16BIT); 
  2. Log.d("TEST", "size = " + size); 
    int size = AudioRecord.getMinBufferSize(44100, AudioFormat.CHANNEL_IN_DEFAULT, AudioFormat.ENCODING_PCM_16BIT);
    Log.d("TEST", "size = " + size);

2.调用路线图 (1)AudioRecord.java文件的getMinBufferSize函数 通过调用jni函数native_get_min_buff_size取得buffer大小。

(2)在android_media_AudioRecord.cpp文件的native_get_min_buff_size函数,对应jni的函数为android_media_AudioRecord_get_min_buff_size函数

通过调用AudioRecord::getMinFrameCount函数,取得frameCount,用于计算buffer大小。

取得frameCount后,再通过以下公式计算出最终的buffer大小。 frameCount * nbChannels * (audioFormat == javaAudioRecordFields.PCM16 ? 2 : 1); (3)AudioRecord.cpp文件的AudioRecord::getMinFrameCount函数,取得frameCount 然后再通过以下公式计算出最小buffer: frameCount * nbChannels * (audioFormat == javaAudioRecordFields.PCM16 ? 2 : 1); (4)AudioRecord::getMinFrameCount函数用又调用AudioSystem.cpp文件的AudioSystem::getInputBufferSize函数取得buffer size后, 通过以下公式计算最小buffer:

  1. // We double the size of input buffer for ping pong use of record buffer. 
  2. size <<= 1; 
  3.  
  4. if (audio_is_linear_pcm(format)) { 
  5.     size /= channelCount * audio_bytes_per_sample(format); 
  6.  
  7. *frameCount = size; 
    // We double the size of input buffer for ping pong use of record buffer.
    size <<= 1;

    if (audio_is_linear_pcm(format)) {
        size /= channelCount * audio_bytes_per_sample(format);
    }

    *frameCount = size;

(5)AudioSystem::getInputBufferSize函数又通过调用AudioFlinger的 gInBuffSize = af->getInputBufferSize(sampleRate, format, channelCount);
(6)继续调用AudioFlinger的getInputBufferSize方法,取得buffer大小

  1. size_t AudioFlinger::getInputBufferSize(uint32_t sampleRate, int format, int channelCount) 
  2.     return mAudioHardware->getInputBufferSize(sampleRate, format, channelCount); 
size_t AudioFlinger::getInputBufferSize(uint32_t sampleRate, int format, int channelCount)
{
    return mAudioHardware->getInputBufferSize(sampleRate, format, channelCount);
}

直接返回从硬件取得的缓冲值,没有做其他处理。 在AudioFlinger的getInputBufferSize方法中,需要根据具体硬件实现,调用实际的硬件buffer大小。 (7)调用AudioHardwareALSA类的getInputBufferSize取得buffer大小

AudioHardwareALSA类位于hardware目录下,根据不同的cpu厂商实现,此类位于不同的目录下,并且getInputBufferSize的实现也不同。需要根据不同的录音机硬件来实现。

下面是具体代码实现,根据采样率和声道数不同,返回不同的buffer大小。

  1. size_t AudioHardwareALSA::getInputBufferSize(uint32_t sampleRate, int format, int channelCount) 
  2.     size_t bufferSize; 
  3.     if (format != AudioSystem::PCM_16_BIT) { 
  4.         LOGW("getInputBufferSize bad format: %d", format); 
  5.         return 0; 
  6.     } 
  7.     if(sampleRate == 16000) { 
  8.         bufferSize = DEFAULT_IN_BUFFER_SIZE * 2 * channelCount; 
  9.     } elseif(sampleRate < 44100) { 
  10.         bufferSize = DEFAULT_IN_BUFFER_SIZE * channelCount; 
  11.     } else
  12.         bufferSize = DEFAULT_IN_BUFFER_SIZE * 12; 
  13.     } 
  14.     return bufferSize; 
size_t AudioHardwareALSA::getInputBufferSize(uint32_t sampleRate, int format, int channelCount)
{
    size_t bufferSize;
    if (format != AudioSystem::PCM_16_BIT) {
        LOGW("getInputBufferSize bad format: %d", format);
        return 0;
    }
    if(sampleRate == 16000) {
        bufferSize = DEFAULT_IN_BUFFER_SIZE * 2 * channelCount;
    } else if(sampleRate < 44100) {
        bufferSize = DEFAULT_IN_BUFFER_SIZE * channelCount;
    } else {
        bufferSize = DEFAULT_IN_BUFFER_SIZE * 12;
    }
    return bufferSize;
}

返回给上级调用者后,还需要根据具体情况再做调整,最终结果值才是应用层要取得的最小缓冲大小,单位为字节。

例如,在我的华为U8500 2.2版本上取得的值是4096字节。 整个函数调用流程图如下:

posted @ 2012-12-15 00:34  1小松  阅读(1215)  评论(0编辑  收藏  举报