iPhone - 如何测量PCM编码信号的振幅

8

我手头的问题如下:

  1. 我需要实时分析音频数据以查找信号的振幅。
  2. 我不能使用AudioQueue计量功能,因为它检测峰值的延迟太大。
  3. 我已经研究了aurioTouch示例...但是...

我根本不理解PCM编码的缓冲区是如何转换回示波器视图中显示的波形的。而我正是想分析这个波形的振幅。

在我的回调函数中,当我分析缓冲区时,它只包含0和-1——当使用NSLog(@"%d")时。我想这是有道理的,因为它是PCM。

我找不到在aurioTouch中将0 / -1流转换成波形的地方:-((

此外,一旦我在内存中拥有波形,我该如何分析振幅并将此读数转换为dB?

我不想使用FFT,因为我对频率不感兴趣,希望还有其他方法。

谢谢

Mat

2个回答

11

如果您已经将波形的一部分存储到内存中,那么计算dB幅度值相对容易(尽管您需要决定0 dB参考幅度是什么)。通常,如果您想要类似于VU表上显示的短期幅度,则需要对波形的瞬时值进行整流(可以使用abs函数),然后通过具有100ms左右时间常数的简单低通滤波器将这些整流值传递。要将值转换为dB,可以使用以下公式:

amplitude_dB = 20 * log10(amplitude) + calibration_dB;

其中,幅度是经过整流和滤波处理的幅度,而calibration_dB是一个偏移量,可为您特定应用程序中0 dB的正确幅度提供参考(例如,相对于满幅度的dB、校准的dBV或dBm值等)。

可以按以下方式实现简单但有效的低通滤波器。这将是一个单极IIR(递归)滤波器。每个输出都依赖于先前的输出值和当前的输入值。我们有一个恒定因子alpha,它实际上确定了此低通滤波器的时间常数或截止频率。

y = alpha * x + (1.0 - alpha) * y_old;
y_old = y;
  • x = 当前输入值
  • y = 新的输出值
  • y_old = 上一个输出值
  • alpha = 决定滤波器响应的常数 - 一个小正数 - 建议从0.001开始尝试并进行实验

我不是 DSP 专家,所以如果您能贴出一个低通滤波器的代码,我将不胜感激。Mat - Matthias Schorer
1
我已经在答案中添加了一个简单的低通滤波器实现。 - Paul R
非常感谢,这让我有了开始的动力。同时,我也成功地从rioBuffer中提取了数据 :-)) - Matthias Schorer
只是为了理解而问一个问题。我从我拥有的各种合成器中了解到LP滤波器。1极滤波器意味着6dB/Oct,4极滤波器则为24 dB/Oct。如果我正确理解上述滤波器,那么我需要将我的数据通过它运行四次才能获得24dB/Oct - 是这样吗? - Matthias Schorer
只是为了澄清 - 我们在这里过滤的是 矫正 信号,以便在短时间间隔内获得信号幅度的平滑估计,因此低通滤波器的响应并不特别重要。但在一般情况下,是的,如果您级联 N 个具有 6 dB/octave 级联衰减的相同滤波器,则会得到 6N dB/octave。 - Paul R

1
AurioTouch是一个很好的例子。不幸的是,代码非常糟糕。请确保只使用它来了解与RemoteIO音频单元一起工作的概念。
波形的实际绘制发生在renderProc回调中,当PCM数据可用时,CoreAudio会调用该回调。请查看aurioTouchAppDelegate.mm中的PerformThru():197行...更进一步,在第237行。
SInt8 *data_ptr = (SInt8 *)(ioData->mBuffers[0].mData);

... 那就是实际访问 PCM 数据的地方。这是您需要分析以获取信号的峰值/平均功率的数据。


我原以为这是正确的地方,但同时也觉得看起来太简单了...... 谢谢您的反馈! - Matthias Schorer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接