在iOS中从音频中提取高音和低音

时间:2013-03-16 22:55:25

标签: ios audio extract waveform

我正在寻找一种方法来获取歌曲中的高音和低音数据,增加时间(比如0.1秒),范围为0.0到1.0。我已经google了一下,但是找不到任何与我正在寻找的东西相近的东西。最终我希望能够在播放歌曲时表现高音和低音水平。

谢谢!

3 个答案:

答案 0 :(得分:11)

它相当容易。您需要执行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. 中频介于300Hz和2kHz之间。
  4. 现在假设你的采样率是8kHz。 Nyquist rate表示在8kHz采样中可以表示的最高频率是4kHz。因此每个箱代表4000/128或31.25Hz。

    因此,如果前5个音箱(最高312.5Hz)用于低音频率。 Bin 10到Bin 63代表中频。最后,bin 64到127是高音。

    然后,您可以如上所述计算RMS值,并获得RMS值。

    通过执行20.0f * log10f( rmsVal );可以将RMS值转换为dBFS值。这将返回从0dB(最大幅度)到-infinity dB(最小幅度)的值。请注意,振幅不在-1到1之间。

    为了帮助您,这里有一些基于C ++的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;
    }
    

答案 1 :(得分:5)

您似乎正在寻找Fast Fourier Transform示例代码。

这是一个很大的话题要在答案中介绍。

您需要的工具已经在iOS中构建:vDSP API

这可以帮助您:vDSP Programming Guide

还有一个FFT Sample Code可用

您可能还想查看iPhoneFFT。虽然这个代码很简单 过时它可以帮助你理解“引擎盖下”的过程。

答案 2 :(得分:3)

请参阅Apple的auriotouch2示例 - 它包含从频率分析到您想要的UI表示的所有内容。