N音频频带强度
Posted
技术标签:
【中文标题】N音频频带强度【英文标题】:NAudio frequency band intensity 【发布时间】:2011-10-12 03:42:06 【问题描述】:我有一个使用 NAudio 的音频播放器,我想显示每个频段的实时强度。
我为每个 1024 个样本块触发了一个事件:
public void Update(Complex[] fftResults)
// ??
我想要的是一组数字,表示每个频段的强度。假设我想将窗口分成 16 个波段。
例如,当有更多的低音频率时,它可能看起来像这样:
░░░░░░░░░░░░░░░░
▓▓▓░░░░░░░░░░░░░
▓▓▓░░░░░░░░░░░░░
▓▓▓▓░░░░░░░░░░░░
▓▓▓▓▓░░░░░░░░░░░
▓▓▓▓▓▓▓▓░░░▓░░▓░
如果可以使用该数据,我应该在该事件处理程序中添加什么?
传入的数据 (Complex[]) 已经使用 FFT 进行了转换。 这是一个立体声流。
第一次尝试:
double[] bandIntensity = new double[16] 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ;
public void Update(Complex[] fftResults)
// using half fftResults because the others are just mirrored
int band = 0;
for (int n = 0; n < fftResults.Length/2; n++)
band = (int)(.5 * n / fftResults.Length * bandIntensity.Length);
bandIntensity[band] += Math.Sqrt(fftResults[n].X * fftResults[n].X + fftResults[n].Y * fftResults[n].Y);
bandIntensity[band] /= 2;
上面正在做一些事情,但我认为前两个乐队的内容太多了,我正在演奏没有那么多低音的夏奇拉。
谢谢!
【问题讨论】:
【参考方案1】:您可能想在这里解决两个不同的问题:
(1) 窗口函数
您需要在 FFT 之前将window function 应用于您的数据,否则您将获得spectral leakage,这将导致频谱非常拖尾。频谱泄漏的一个令人不快的副作用是,如果您有任何类型的显着 DC (0 Hz) 分量,那么这将导致您在条形图上看到的那种 1/f 形状。
(2) 对数幅度/频率轴
人类的听力在强度和频率轴上基本上都是对数的。不仅如此,语音和音乐在频谱的低频部分往往具有更多的能量。为了获得更令人愉悦和有意义的强度与频率显示,我们通常将幅度和频率轴都设为对数。在幅度轴的情况下,这通常通过绘制 dB re full scale 来处理,即
magnitude_dB = 10 * log10(magnitude);
在频率轴的情况下,您可能希望将您的 bin 分组为频段,每个频段可能是一个八度音阶(2:1 频率范围),或者更常见的是为了更高分辨率,第三个八度音程。因此,如果您只想要 10 个“小节”,那么您可以使用以下八度带:
25 - 50 Hz
50 - 100 Hz
100 - 200 Hz
200 - 400 Hz
400 - 800 Hz
800 - 1600 Hz
1600 - 3200 Hz
3200 - 6400 Hz
6400 - 12800 Hz
12800 - 20000 Hz
(假设您的采样率为 44.1 kHz,音频输入硬件的上限为 20 kHz)。
请注意,虽然对于此类应用来说,具有幅度 (dB) 强度标度是非常必要的,但对数频率轴不太重要,因此您现在可以尝试使用现有的线性分档,看看效果如何通过在时域中应用一个窗口函数(假设您还没有窗口函数)并将幅度比例转换为 dB。
【讨论】:
对于窗口,我看到使用了 BlackmannHarrisWindow。但是我还没有尝试 10xLog10(),我会看看它是如何改变图表的。我将移除 0Hz DC bin。 即使在对频段集合应用倍频程箱后,我仍然会得到奇怪的数字,左侧仍然太多...我已将 y 刻度数字转换为 dBs 好的 - 你确定正在应用一个窗口函数?也许您可以发布更多代码,也许在一个新问题中 - 最好看看您设置输入缓冲区的部分,然后调用窗口函数 + FFT。 可以,只需要拿到我的笔记本电脑上 我很想看看代码。在音频方面我有点新手,我想使用 MAKE 控制器将类似类型的数据输出到 LED 波段。只需要生成条形!以上是关于N音频频带强度的主要内容,如果未能解决你的问题,请参考以下文章