FFT 是不是需要在音频文件上找到峰值和凹点
Posted
技术标签:
【中文标题】FFT 是不是需要在音频文件上找到峰值和凹点【英文标题】:Does FFT neccessary to find peaks and pits on audio filesFFT 是否需要在音频文件上找到峰值和凹点 【发布时间】:2012-07-03 14:07:55 【问题描述】:我能够读取 wav 文件及其值。我需要找到峰和坑的位置及其值。第一次,我尝试通过(i-1 + i + i +1) / 3
公式对其进行平滑处理,然后在数组上搜索array[i-1] > array[i] & direction == 'up' --> pits
样式的解决方案,但由于项目未来计算的噪声和其他原因,我正在寻找更好的工作区域。几天以来,我一直在研究 FFT。据我了解,fft 将音频文件转换为一系列正弦和余弦。在 fft 操作之后,给定的值是 a0
's 和 a1
's for a0 + ak * cos(k*x) + bk * sin(k*x) which k++ and x++
,如图所示
http://zone.ni.com/images/reference/en-XX/help/371361E-01/loc_eps_sigadd3freqcomp.gif
我的问题是,fft 是否有助于我找到音频的峰值和凹坑?有没有人有这种问题的经验?
【问题讨论】:
我建议在dsp.stackexchange.com上问这样的问题 【参考方案1】:这完全取决于你想要做什么,而你还没有真正说清楚。 “找峰找坑”是一回事,但由于这样做的原因可能有多种,因此可能有多种方法。您已经尝试过实际寻找局部最大值和最小值的简单方法,听起来像是。以下是一些提示:
-
您不需要 FFT。
音频数据通常在零上下波动(也有例外,包括 8 位 wav,它们是无符号的,但这些是例外),因此您必须注意正值和负值。不过,通常情况下,较大的正值和较大的负值会携带大量能量,因此您希望将它们视为相同的值。
由于#2,如果您想要平均,您可能想要取绝对值的平均值,或者更常见的是平方的平均值。一旦你找到平方的平均值,取那个值的平方根,这给出了RMS,它与信号的功率有关,所以你可能会做这样的事情,你试图指示信号响度,强度或近似模拟仪表。绝对值的平均值对于极端值可能更稳健,但不太常用。
另一种方法是在一定数量的样本上简单地寻找绝对值的峰值,这通常在绘制波形和数字“峰值”仪表时完成。查看最小绝对值是没有意义的。
完成上述操作后,是的,您可能需要计算找到的值的对数,以便以 dB 为单位显示信号,但请确保使用正确的公式。 10 * log_10(幅值) 不是它。经验法则:通常在从幅度计算日志时,您会看到 20,而不是 10。如果您想计算 dBFS(削波前的“净空”量,这是数字仪表的标准测量值),公式为 - 20 * log_10( |amplitude| ),其中幅度归一化为 +/- 1。注意幅度 = 0,这会以 dB 为单位提供无限余量。
【讨论】:
【参考方案2】:如果我理解正确,您只想估计音频数字样本在给定点的相对响度/安静度。
对于这种估计,您不需要使用 FFT。但是,您平均信号的方法也不会产生适当的图像。
数字信号是给定时刻音频波的值。您需要在给定时刻找到信号的整体幅度。您可以在某种程度上将其视为您要计算的那一刻给定间隔的局部最大值。您可能对信号有一个移动最大值并获得您的幅度估计。
在 16 位声音样本中,声音信号值可以从 0 到 32767。在 44.1 kHz 采样率下,您可以通过在给定值附近找到 441 个样本的最大值来找到大约 0.01 秒的峰值和凹坑时刻。
max=1;
for (i=0; i<441; i++) if (array[t*44100+i]>max) max=array[t*44100+i];
然后你用 0 到 1 的比例来表示它(不是真的 0,因为我们至少使用了 1)
amplitude = max / 32767;
或者你可以用相对的 dB 对数标度来表示它(在这里你明白为什么我们使用 1 作为最小值)
dB = 20 * log10(amplitude);
【讨论】:
dB = 10 * log_10(amplitude) 不是正确的公式。请参阅我的答案以获取正确的公式。【参考方案3】:您需要做的就是获取 dy/dx,只需扫描波形并从当前值中减去前一个值,然后查看它在哪里变为零或从正变为负,就可以得到近似值
在这段代码中,为了简洁起见,我让它变得非常简短和不智能,当然你可以更好地处理 dy 为零的情况,找到一个平坦峰的长部分的“中心”,诸如此类。但如果您只需要基本的波峰和波谷,这将找到它们。
lastY=0;
bool goingup=true;
for( i=0; i < wave.length; i++ )
y = wave[i];
dy = y - lastY;
bool stillgoingup = (dy>0);
if( goingup != direction )
// changed direction - note value of i(place) and 'y'(height)
stillgoingup = goingup;
【讨论】:
以上是关于FFT 是不是需要在音频文件上找到峰值和凹点的主要内容,如果未能解决你的问题,请参考以下文章