Mar*_*mić 7 c# algorithm fft naudio
我有一个使用NAudio的音频播放器,我想为每个频段显示实时强度.
我为每个1024个样本块触发了一个事件:
public void Update(Complex[] fftResults)
{
// ??
}
Run Code Online (Sandbox Code Playgroud)
我想要的是一组数字,表示每个频段的强度.让我们说我想将窗口划分为16个波段.
例如,当有更多低音频率时,它可能如下所示:
????????????????
????????????????
????????????????
????????????????
????????????????
????????????????
Run Code Online (Sandbox Code Playgroud)
如果可以使用该数据,我应该将什么放入该事件处理程序?
来自(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)((double)n / (fftResults.Length / 2) * bandIntensity.Length);
bandIntensity[band] += Math.Sqrt(fftResults[n].X * fftResults[n].X + fftResults[n].Y * fftResults[n].Y);
bandIntensity[band] /= 2;
}
}
Run Code Online (Sandbox Code Playgroud)
以上是做了一些事情,但我认为前两个乐队太多了,我正在演奏没有那么多低音的夏奇拉.
谢谢!
您可能希望在此处解决两个不同的问题:
(1)窗口功能
您需要在FFT之前对数据应用窗口函数,否则会出现频谱泄漏,从而导致光谱非常模糊.频谱泄漏的一个令人不快的副作用是,如果您有任何类型的重要DC(0 Hz)分量,那么这将导致您在条形图上看到的那种1/f形状.
(2)记录幅度/频率轴
人类听力在强度和频率轴上基本上都是对数的.不仅如此,语音和音乐往往在频谱的低频部分拥有更多的能量.为了获得更加令人愉悦和有意义的强度与频率的显示,我们通常使幅度轴和频率轴都成对数.在幅度轴的情况下,通常通过绘制dB re full scale来表示,即
magnitude_dB = 10 * log10(magnitude);
Run Code Online (Sandbox Code Playgroud)
在频率轴的情况下,您可能希望将频段分组为频段,每个频段可能是一个八度音程(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
Run Code Online (Sandbox Code Playgroud)
(假设您的采样率为44.1 kHz,音频输入硬件的上限为20 kHz).
请注意,虽然对于这种应用来说,具有幅度(dB)强度标度几乎是必需的,但是对数频率轴不那么重要,因此您现在可以尝试使用现有的线性分级,并看看您从应用中获得的效果时域中的窗口函数(假设您还没有)并将幅度比例转换为dB.