2013-07-28 71 views
2

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

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反向正常工作。你能告诉我我的错误是什么。

+2

丹妮拉的答案是正确的。但是,如果您的目标是消除某些频率而不是其他频率,则不应使用FFT。您应该使用时域方法:http://blog.bjornroche.com/2012/08/why-eq-is-完成时间domain.html –

+0

@BjornRoche很高兴我找到了你的博客,最后有人可以从中学习:) –

回答

2

不幸的是,人的声音,即使在唱歌时,也不在“频率范围”。它通常具有一个主频率和多个谐波,取决于音素。

使用此https://play.google.com/store/apps/details?id=radonsoft.net.spectralview&hl=en或一些类似的应用程序来查看我的意思 - 然后重新定义您的策略。另外谷歌'卡拉OK'的影响。

NEXT:

这不是从你的例子很明显,但你应该扫描窗口整个文件(谷歌“FFT窗口”)来处理它的整体。

+0

对于低音和低音歌手在其音域的底部,基本音高频率几乎可以完全从FFT。由麦克风拾取的所有能量包括更高的泛音频率,一些远高于女高音范围,取决于正在唱的元音。 – hotpaw2