我正在尝试为我的应用制作一个体积计,它将在录制视频时显示。我已经为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,然后坐在这里列出一个(或多个?)audioBuffer列表。据我了解,实际数据表示为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
附近的值,而在某些噪音下获得7.773492
。感觉像是正确的“范围”,但处在“错误的位置”。我不能简单地从数字中减去7并假设我介于-1
和+1
之间。它应该如何工作背后应该有一些逻辑和科学,但是我对数字音频的工作原理还不够了解。
有人知道背后的逻辑吗?当-32,768
和32,767
是大声声音时,0是否总是静音?然后,我可以简单地将所有负值乘以-1
来始终得到正值,然后找出它们的百分比是多少(介于0和32767之间)吗?不知何故,我不认为这会奏效,因为我想这是负值的原因。.我不确定要尝试什么。
您问题中的代码在几种方面是错误的。这段代码试图从下面的文章中复制它,但是您没有正确地将其从文章中的基于浮点数的代码转换为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]范围。