2013-03-16 95 views
9

我正在尋找一種方法從歌曲中獲取高音和低音數據,以獲得一些時間增量(例如0.1秒)和0.0到1.0的範圍內的增量。我一直在搜索,但一直沒有找到任何東西遠遠接近我正在尋找。最終我希望能夠在歌曲播放時表現高音和低音水平。在iOS中從音頻中提取高音和低音

謝謝!

+0

查看該問題的接受答案:http://stackoverflow.com/questions/1794010/how-to-use-numpy-with-portaudio-to-extract-bass-mid-treble?rq=1 – 2013-03-17 03:38:44

+0

ok這是解釋過程,但不解釋如何在iOS上執行該過程 - 或者至少從何處開始。 – 2013-03-17 15:11:04

+0

iOS在音頻單元框架中內置了低通和高通濾波器。 – 2013-03-17 23:24:15

回答

10

其合理簡單。您需要執行FFT,然後總結您感興趣的箱。您選擇的很多方法取決於音頻的採樣率。

然後,您需要選擇合適的FFT順序,以便在返回的頻率點中獲得良好的信息。

所以,如果你做了8次FFT的訂單,你將需要256個樣本。這會返回128個複雜對。

接下來你需要將它們轉換成幅度。這其實很簡單。如果你正在使用std :: complex,你可以簡單地在複數上執行一個std :: abs,你將得到它的大小(sqrt(r^2 + i^2))。

有趣的是,在這一點上有一種叫做Parseval's theorem的東西。該定理指出,在執行傅立葉變換之後,返回的二進制數之和等於輸入信號均方的和。

這意味着要獲得特定組箱的振幅,您可以簡單地將它們加在一起除以它們的數量,然後sqrt以獲得那些箱的RMS振幅值。

那麼這會給你帶來什麼?

那麼從這裏你需要弄清楚你要加在一起的箱子。

  1. 高音定義爲2000Hz以上。
  2. 貝司音低於300Hz(如果我的記憶正確地爲我服務)。
  3. Mids介於300Hz和2kHz之間。

現在假設你的採樣率是8kHz。 Nyquist rate表示您可以在8kHz採樣中表示的最高頻率爲4kHz。每個箱體因此代表4000/128或31.25Hz。

所以如果前十個分檔(高達312.5Hz)用於低音頻率。箱10到箱63代表中號。最後bin 64到127是高音。

然後,您可以如上所述計算RMS值,並且您具有RMS值。

通過執行20.0f * log10f(rmsVal);可以將RMS值轉換爲dBFS值。這會返回一個從0dB(最大振幅)到-infinity dB(最小振幅)的值。注意幅度不要範圍從-1到1

沿幫助你,這裏是一個有點我的基於C++的FFT類iPhone(使用VDSP引擎蓋下)的:

MacOSFFT::MacOSFFT(unsigned int fftOrder) : 
    BaseFFT(fftOrder) 
{ 
    mFFTSetup = (void*)vDSP_create_fftsetup(mFFTOrder, 0); 
    mImagBuffer.resize(1 << mFFTOrder); 
    mRealBufferOut.resize(1 << mFFTOrder); 
    mImagBufferOut.resize(1 << mFFTOrder); 
} 

MacOSFFT::~MacOSFFT() 
{ 
    vDSP_destroy_fftsetup((FFTSetup)mFFTSetup); 
} 

bool MacOSFFT::ForwardFFT(std::vector< std::complex<float> >& outVec, const std::vector<float>& inVec) 
{ 
    return ForwardFFT(&outVec.front(), &inVec.front(), inVec.size()); 
} 

bool MacOSFFT::ForwardFFT(std::complex<float>* pOut, const float* pIn, unsigned int num) 
{ 
    // Bring in a pre-allocated imaginary buffer that is initialised to 0. 
    DSPSplitComplex dspscIn; 
    dspscIn.realp = (float*)pIn; 
    dspscIn.imagp = &mImagBuffer.front(); 

    DSPSplitComplex dspscOut; 
    dspscOut.realp = &mRealBufferOut.front(); 
    dspscOut.imagp = &mImagBufferOut.front(); 

    vDSP_fft_zop((FFTSetup)mFFTSetup, &dspscIn, 1, &dspscOut, 1, mFFTOrder, kFFTDirection_Forward); 

    vDSP_ztoc(&dspscOut, 1, (DSPComplex*)pOut, 1, num); 

    return true; 
} 
5

看來您正在尋找Fast Fourier Transform示例代碼。

這是一個相當大的話題要覆蓋在答案。

的工具,你將需要已經建立在iOS設備上:VDSP API

這會幫助你:vDSP Programming Guide

而且還有可用FFT Sample Code

你可能也想看看iPhoneFFT 。儘管這些代碼過時了,但它可以幫助你理解「引擎蓋下」的過程。

3

參考到auriotouch2來自Apple的例子 - 它具有從頻率分析到用戶界面表示的所有功能。