2013-03-16 146 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的例子 - 它具有从频率分析到用户界面表示的所有功能。