如何解释AudioBuffer并获得电源?

时间:2014-08-11 22:14:41

标签: ios objective-c audio avfoundation core-audio

我正在尝试为我的应用制作音量表,这将在录制视频时显示。我已经为iOS发现了很多这样的米的支持,但主要是AVAudioPlayer,这对我来说是没有选择的。我正在使用AVCaptureSession进行记录,最后将使用如下所示的委托方法:

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection
{
    CMFormatDescriptionRef formatDescription = CMSampleBufferGetFormatDescription(sampleBuffer);

    CFRetain(sampleBuffer);
    CFRetain(formatDescription);

    if(connection == audioConnection)
    {
        CMBlockBufferRef blockBuffer;
        AudioBufferList audioBufferList;

        CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer(sampleBuffer, 
            NULL, &audioBufferList, sizeof(AudioBufferList), NULL, NULL,
            kCMSampleBufferFlag_AudioBufferList_Assure16ByteAlignment,
            &blockBuffer);

        SInt16 *data = audioBufferList.mBuffers[0].mData;
    }
    //Releases etc..
}

(仅显示相关代码)

根据我的理解,我收到一个'样本缓冲区',包含音频或视频。一旦我确认连接确实是音频,那么我从缓冲区中提取'audioBufferList,我坐在这里留下一个(或更多?)audioBuffers的列表。据我所知,实际数据表示为SInt16或“16位有符号整数”,据我所知,其范围从-32,76832,767。但是,如果我只是打印出这个收到的值,我会得到很多弹跳数字。在“沉默”时,我会在-200200之间快速反弹,当有噪音时,我会从-4,00013,000获得值,完全无序。 正如我从阅读中理解的那样,价值0将代表沉默。但是,我不明白负值和正值之间的区别,以及我不知道是否能够一直向上/向下到+-32,768

我相信我需要一定百分比的“大声”,但一直找不到任何东西。

我已经阅读过关于此事的一些教程和参考资料,但对我来说没有任何意义。我按照一个指南执行此操作(附加到上面的代码,在if内):

float accumulator = 0;
for(int i = 0; i < audioBufferList.mBuffers[0].mDataByteSize; i++)
    accumulator += data[i] * data[i];
float power = accumulator / audioBufferList.mBuffers[0].mDataByteSize;
float decibels = log10f(power);
NSLog(@"%f", decibels);

显然,此代码应该从-1+1对齐,但这并没有发生。我现在在沉默时获得6.194681左右的值,而在{1}}时获得一些噪音。这感觉就像正确的'范围',但在'错误的地方'。我不能简单地从数字中减去7并假设我在7.773492-1之间。应该有一些逻辑和科学背后的方法,但我对数字音频的工作原理还不太了解。

有谁知道这背后的逻辑?当+1-32,768是大声的噪音时,0总是静音吗?然后我可以简单地将所有负值乘以32,767以获得正值,然后找出它们的百分比(0到32767之间)?不知何故,我不相信这会有效,因为我猜有负面价值的理由......我不完全确定要尝试什么。

1 个答案:

答案 0 :(得分:1)

您问题中的代码在几种方面是错误的。这段代码试图从下面的文章中复制它,但是您没有正确地将其从文章中的基于浮点数的代码转换为16位整数数学。您还会循环使用错误数量的值(max i),并且最终将拉入垃圾数据。所以这是各种各样的错误。

https://www.mikeash.com/pyblog/friday-qa-2012-10-12-obtaining-and-interpreting-audio-data.html

文章中的代码正确。这就是它,扩展了一下。这只是查看32位浮点缓冲区列表中的第一个缓冲区。

float accumulator = 0;
AudioBuffer buffer = bufferList->mBuffers[0];
float * data = (float *)buffer.mData;
UInt32 numSamples = buffer.mDataByteSize / sizeof(float);

for (UInt32 i = 0; i < numSamples; i++) {
    accumulator += data[i] * data[i];
}
float power = accumulator / (float)numSamples;
float decibels = 10 * log10f(power);

如文章所述,这里的结果是分贝使用0dB参考。例如,0.0是 maximum 值。例如,这与AVAudioPlayer的averagePowerForChannel返回相同。

要在16位整数上下文中使用此函数,您需要a)适当循环遍历每个16位样本,b)将data [i]值从16位整数转换为浮点值平方并添加到累加器之前,请在[-1.0,1.0]范围内。