为了账号安全,请及时绑定邮箱和手机立即绑定

NAudio FFT 为所有频率返回小而相等的幅度值

NAudio FFT 为所有频率返回小而相等的幅度值

C#
手掌心 2022-12-04 10:55:22
我正在使用 NAudio 1.9 进行一个项目,我想计算整首歌曲的 fft,即将歌曲分成大小相等的块,然后为每个块计算 fft。问题是 NAudio FFT 函数对于频谱中的任何频率都返回非常小且相等的值。我搜索了以前的相关帖子,但似乎没有一个对我有帮助。使用 NAudio 计算 FFT 的代码:public IList<FrequencySpectrum> Fft(uint windowSize) {        IList<Complex[]> timeDomainChunks = this.SplitInChunks(this.audioContent, windowSize);        return timeDomainChunks.Select(this.ToFrequencySpectrum).ToList();}private IList<Complex[]> SplitInChunks(float[] audioContent, uint chunkSize) {        IList<Complex[]> splittedContent = new List<Complex[]>();        for (uint k = 0; k < audioContent.Length; k += chunkSize) {            long size = k + chunkSize < audioContent.Length ? chunkSize : audioContent.Length - k;            Complex[] chunk = new Complex[size];            for (int i = 0; i < chunk.Length; i++) {                //i've tried windowing here but didn't seem to help me                chunk[i].X = audioContent[k + i];                chunk[i].Y = 0;            }            splittedContent.Add(chunk);        }        return splittedContent;}private FrequencySpectrum ToFrequencySpectrum(Complex[] timeDomain) {        int m = (int) Math.Log(timeDomain.Length, 2);        //true = forward fft        FastFourierTransform.FFT(true, m, timeDomain);        return new FrequencySpectrum(timeDomain, 44100);}频谱:public struct FrequencySpectrum {    private readonly Complex[] frequencyDomain;    private readonly uint samplingFrequency;     public FrequencySpectrum(Complex[] frequencyDomain, uint samplingFrequency) {        if (frequencyDomain.Length == 0) {            throw new ArgumentException("Argument value must be greater than 0", nameof(frequencyDomain));        }        if (samplingFrequency == 0) {            throw new ArgumentException("Argument value must be greater than 0", nameof(samplingFrequency));        }        this.frequencyDomain = frequencyDomain;        this.samplingFrequency = samplingFrequency;    }对于包含 440Hz 正弦波的文件预期输出:freq=440 的值为 0.5,其他值为 0实际输出:频谱中任何频率的值如 0.000168153987f
查看完整描述

1 回答

?
函数式编程

TA贡献1807条经验 获得超9个赞

看来我犯了4个错误:


1) 在这里我假设采样频率是 44100。但这不是我的代码不工作的原因,虽然


return new FrequencySpectrum(timeDomain, 44100);

2)始终对输出数据进行可视化表示!我必须吸取这一课......似乎对于包含 440Hz 正弦波的文件我得到了正确的结果但是......


3) 由于这个原因,频谱与我的预期略有不同:


int m = (int) Math.Log(timeDomain.Length, 2);

FastFourierTransform.FFT(true, m, timeDomain);

timeDomain 是一个大小为 44100 的数组,因为它是 windowSize 的值(我用 windowSize = 44100 调用了该方法),但是 FFT 方法需要一个值为 2 的窗口大小。我说“这里,NAudio,计算我该数组的 fft 具有 44100 个元素,但只考虑前 32768"。我没有意识到这会对结果产生严重影响:


float k = freq / ((float) this.samplingFrequency / this.FftWindowSize);

这里 this.FftWindowSize 是一个基于数组大小的属性,而不是m。因此,在可视化结果后,我发现 440Hz 频率的幅度实际上对应于调用:


spectrum[371]

代替


spectrum[440]

所以,我的错误是 fft ( m ) 的窗口大小与数组的实际长度 ( FrequencySpectrum.FftWindowSize )不对应。


4) 我收到的幅度值较小是因为我测试代码的音频文件没有以足够的增益录制。


查看完整回答
反对 回复 2022-12-04
  • 1 回答
  • 0 关注
  • 138 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信