2014-11-20 121 views
0

我想看看在一段音頻中,某些頻率,特別是20 - 60Hz的低音。我有音頻作爲一個字節數組,我將它轉換爲短陣列,然後通過(short [i] /(double)short.MaxValue,0)轉換爲一個複數。然後我把它傳給Aforge的FFT。FFT哪些頻率在哪些分箱?

音頻是單聲道的,採樣率爲44100.據我所知,我只能在^ 2處通過FFT加載卡盤。例如4096。我不明白輸出箱中的頻率是多少。

如果我從44100採樣率的音頻採樣4096個採樣。這是否意味着我正在花費毫秒級的音頻?或只獲得一些將出現的頻率?

我將FFT的輸出添加到一個數組中,我的理解是當我取4096時,bin 0將包含0 * 44100/4096 = 0hz,bin 1將保存1 * 44100/4096 = 10.7666015625hz和等等。它是否正確?或者我在這裏做一些根本性錯誤?

我的目標是平均說20-60赫茲之間的頻率,所以對於低低重低音的歌曲,這個數字要比低音很少的軟鋼琴片要高。

這是我的代碼。

OpenFileDialog file = new OpenFileDialog(); 
file.ShowDialog(); 
WaveFileReader reader = new WaveFileReader(file.FileName); 

byte[] data = new byte[reader.Length]; 
reader.Read(data, 0, data.Length); 

samepleRate = reader.WaveFormat.SampleRate; 
bitDepth = reader.WaveFormat.BitsPerSample; 
channels = reader.WaveFormat.Channels; 

Console.WriteLine("audio has " + channels + " channels, a sample rate of " + samepleRate + " and bitdepth of " + bitDepth + "."); 


short[] shorts = data.Select(b => (short)b).ToArray(); 

int size = 4096; 
int window = 44100 * 10; 
int y = 0; 
Complex[] complexData = new Complex[size]; 
for (int i = window; i < window + size; i++) 
{ 
    Complex tmp = new Complex(shorts[i]/(double)short.MaxValue, 0); 

    complexData[y] = tmp; 
    y++; 

} 




FourierTransform.FFT(complexData, FourierTransform.Direction.Forward); 


double[] arr = new double[complexData.Length]; 
//print out sample of conversion 
for (int i = 0; i < complexData.Length; i++) 
{ 
    arr[i] = complexData[i].Magnitude; 

} 

Console.Write("complete, "); 


return arr; 

編輯:改到FFT來回DFT

+1

那麼你似乎在做一個DFT(它比FFT更精確),但是返回的數據是如何構造的,我不知道。應該在您正在使用的庫的文檔中。從根本上說,如果數據的結構是線性的,那麼它就是對的,但它也可以用對數結構。 – MrPaulch 2014-11-20 18:30:47

+0

感謝您指出了這一點,我的意思是運行fft,當我正在玩DFT時只是複製了代碼。 – 2014-11-20 18:47:14

+0

你基本上是在正確的軌道上 - 你的箱子在你計算的時候寬度大約爲10赫茲 - 見[這個答案](http://stackoverflow.com/questions/4364823/how-to-get-frequency-from-fft -result/4371627#4371627)以獲得更全面的解釋。 – 2014-11-20 20:07:25

回答

1

這是你的代碼的修改版本。注意以「***」開頭的註釋。

OpenFileDialog file = new OpenFileDialog(); 
file.ShowDialog(); 
WaveFileReader reader = new WaveFileReader(file.FileName); 

byte[] data = new byte[reader.Length]; 
reader.Read(data, 0, data.Length); 

samepleRate = reader.WaveFormat.SampleRate; 
bitDepth = reader.WaveFormat.BitsPerSample; 
channels = reader.WaveFormat.Channels; 

Console.WriteLine("audio has " + channels + " channels, a sample rate of " + samepleRate + " and bitdepth of " + bitDepth + "."); 

// *** NAudio "thinks" in floats 
float[] floats = new float[data.Length/sizeof(float)] 
Buffer.BlockCopy(data, 0, floats, 0, data.Length); 

int size = 4096; 
// *** You don't have to fill the FFT buffer to get valid results. More noisy & smaller "magnitudes", but better freq. res. 
int inputSamples = samepleRate/100; // 10ms... adjust as needed 
int offset = samepleRate * 10 * channels; 
int y = 0; 
Complex[] complexData = new Complex[size]; 
// *** get a "scaling" curve to make both ends of sample region 0 but still allow full amplitude in the middle of the region. 
float[] window = CalcWindowFunction(inputSamples); 
for (int i = 0; i < inputSamples; i++) 
{ 
    // *** "floats" is stored as LRLRLR interleaved data for stereo audio 
    complexData[y] = new Complex(floats[i * channels + offset] * window[i], 0); 
    y++; 
} 
// make sure the back portion of the buffer is set to all 0's 
while (y < size) 
{ 
    complexData[y] = new Complex(0, 0); 
    y++; 
} 


// *** Consider using a DCT here instead... It returns less "noisy" results 
FourierTransform.FFT(complexData, FourierTransform.Direction.Forward); 


double[] arr = new double[complexData.Length]; 
//print out sample of conversion 
for (int i = 0; i < complexData.Length; i++) 
{ 
    // *** I assume we don't care about phase??? 
    arr[i] = complexData[i].Magnitude; 
} 

Console.Write("complete, "); 


return arr; 

一旦獲得滿意的結果,並假設一個44100赫茲的採樣率和大小= 4096,元件2 - 4應該是你正在尋找的值。有一種方法可以將它們轉換爲dB,但我不記得它。

祝你好運!

+0

非常感謝。我不能讓你明白我的意思。這一直困擾着我一段時間。 – 2014-11-21 23:34:18

+0

你用什麼爲你的calcWindowsFunction(),有沒有一個包可用,或者我將不得不考慮實現這個自己。謝謝 – 2014-11-21 23:54:44

+0

你可以返回一個float數組(帶有「size」元素)和全部1。有更好的窗口,但你需要從http://en.wikipedia.org/wiki/Window_function找出正確的窗口。一般來說,只要實施Hamming或Blackman-Harris窗戶,你就應該有很好的形狀。這裏有很多示例代碼。 – ioctlLR 2014-11-23 02:55:56