我正在尝试为我的应用制作音量表,这将在录制视频时显示。我已经为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,768
到32,767
。但是,如果我只是打印出这个收到的值,我会得到很多弹跳数字。在“沉默”时,我会在-200
和200
之间快速反弹,当有噪音时,我会从-4,000
到13,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之间)?不知何故,我不相信这会有效,因为我猜有负面价值的理由......我不完全确定要尝试什么。
答案 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]范围内。