抑制 FFT 中的频率

Posted

技术标签:

【中文标题】抑制 FFT 中的频率【英文标题】:Suppressing Frequencies From FFT 【发布时间】:2013-07-28 20:11:02 【问题描述】:

我要做的是从某些歌曲中检索频率并抑制所有未出现在人类声域或一般任何范围内的频率。这是我的抑制功能。

    public void SupressAndWrite(Func<FrequencyUnit, bool> func)
    
        this.WaveManipulated = true;
        while (this.mainWave.WAVFile.NumSamplesRemaining > 0)
        
            FrequencyUnit[] freqUnits = this.mainWave.NextFrequencyUnits();

            Complex[] compUnits = (from item
                                   in freqUnits
                                   select (func(item)
                                    ? new Complex(item.Frequency, 0) :Complex.Zero))    
                                   .ToArray();

            FourierTransform.FFT(compUnits, FourierTransform.Direction.Backward);

            short[] shorts = (from item
                              in compUnits
                              select (short)item.Real).ToArray();

            foreach (short item in shorts)
            
                this.ManipulatedFile.AddSample16bit(item);
            
        
        this.ManipulatedFile.Close();
    

这是我的波浪课。

public sealed class ComplexWave

    public readonly WAVFile WAVFile;
    public readonly Int32 SampleSize;

    private FourierTransform.Direction fourierDirection  get; set; 

    private long position;
    /// <param name="file"></param>
    /// <param name="sampleSize in BLOCKS"></param>
    public ComplexWave(WAVFile file, int sampleSize)
    
        file.NullReferenceExceptionCheck();

        this.WAVFile = file;
        this.SampleSize = sampleSize;

        if (this.SampleSize % 8 != 0)
        
            if (this.SampleSize % 16 != 0)
            
                throw new ArgumentException("Sample Size");
            
        
        if (!MathTools.IsPowerOf2(sampleSize))
        
            throw new ArgumentException("Sample Size");
        
        this.fourierDirection = FourierTransform.Direction.Forward;
    
    public Complex[] NextSampleFourierTransform()
    
        short[] newInput = this.GetNextSample();
        Complex[] data = newInput.CopyToComplex();

        if (newInput.Any((x) => x != 0))
        
            Debug.Write("done");
        
        FourierTransform.FFT(data, this.fourierDirection);

        return data;
    
    public FrequencyUnit[] NextFrequencyUnits()
    
        Complex[] cm = this.NextSampleFourierTransform();
        FrequencyUnit[] freqUn = new FrequencyUnit[(cm.Length / 2)];
        int max = (cm.Length / 2);
        for (int i = 0; i < max; i++)
        
            freqUn[i] = new FrequencyUnit(cm[i], this.WAVFile.SampleRateHz, i, cm.Length);
        
        Array.Sort(freqUn);
        return freqUn;
    
    private short[] GetNextSample()
    
        short[] retval = new short[this.SampleSize];

        for (int i = 0; i < this.SampleSize; i++)
        
            if (this.WAVFile.NumSamplesRemaining > 0)
            
                retval[i] = this.WAVFile.GetNextSampleAs16Bit();
                this.position++;
            
        
        return retval;
    

FFT 向前和 FFT 向后都可以正常工作。你能告诉我我的错误是什么吗?

【问题讨论】:

丹妮拉的回答是正确的。但是,当您的目标是消除某些频率而不是其他频率时,您不应该使用 FFT。相反,您应该使用时域方法:blog.bjornroche.com/2012/08/why-eq-is-done-in-time-domain.html @BjornRoche 很高兴我找到了你的博客,终于有人可以向我学习了 :) 【参考方案1】:

很遗憾,即使在唱歌时,人声也不在“频率范围”内。它通常有一个主频率和跟随它的大量谐波,具体取决于音素。

使用此https://play.google.com/store/apps/details?id=radonsoft.net.spectralview&hl=en 或类似的应用程序来了解我的意思 - 然后重新定义您的策略。还有谷歌“卡拉OK”效果。

下一个:

这在您的示例中并不明显,但您应该在 windows (google 'fft windowing') 中扫描整个文件以对其进行整体处理。

【讨论】:

对于低音和男中音歌手来说,FFT 几乎可以完全忽略基本音高频率。麦克风拾取的所有能量都包含高得多的泛音频率,有些远高于女高音范围,具体取决于所唱的元音。

以上是关于抑制 FFT 中的频率的主要内容,如果未能解决你的问题,请参考以下文章

MATLAB中的FFT的采样频率和采样点怎样确定

MATLAB中的FFT的采样频率和采样点怎样确定

MATLAB中fft的频率轴怎么计算

AMR 文件的 FFT 计算中的问题

Android:通过fft获取更精确的频率

使用许多紧凑频率时出现奇怪的 FFT 峰值