9

我正在寻找一种方法来从歌曲中获取高音和低音数据,时间增加一些(比如 0.1 秒),范围在 0.0 到 1.0 之间。我已经四处搜索,但无法找到任何与我正在寻找的东西相近的东西。最终,我希望能够在播放歌曲时代表高音和低音级别。

谢谢!

4

3 回答 3

11

它相当容易。您需要执行 FFT,然后总结您感兴趣的 bin。您选择的很多方式将取决于音频的采样率。

然后,您需要选择适当的 FFT 顺序以在返回的频率区间中获得良好的信息。

因此,如果您订购 8 FFT,您将需要 256 个样本。这将返回 128 个复数对。

接下来,您需要将这些转换为幅度。这其实很简单。如果您使用的是 std::complex,您可以简单地对复数执行 std::abs 并且您将获得其大小 (sqrt(r^2 + i^2))。

有趣的是,此时有一个叫做Parseval 定理的东西。该定理指出,在执行傅立叶变换后,返回的 bin 之和等于输入信号的均方之和。

这意味着要获得一组特定 bin 的幅度,您只需将它们加在一起除以它们的数量,然后 sqrt 即可获得这些 bin 的 RMS 幅度值。

那么这会给你带来什么影响呢?

那么从这里你需要弄清楚你正在添加哪些垃圾箱。

  1. 高音定义为 2000Hz 以上。
  2. 低音低于 300Hz(如果我没记错的话)。
  3. 中频介于 300Hz 和 2kHz 之间。

现在假设您的采样率为 8kHz。奈奎斯特速率表示在 8kHz 采样中可以表示的最高频率是 4kHz 。因此,每个 bin 代表 4000/128 或 31.25Hz。

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

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

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

为了帮助您,这里是我的一些基于 C++ 的 iPhone FFT 类(它在后台使用 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;
}
于 2013-04-24T15:55:21.180 回答
5

您似乎正在寻找快速傅立叶变换示例代码。

这是一个相当大的话题,需要回答。

您需要的工具已经内置于 iOS:vDSP API

这应该对您有所帮助:vDSP 编程指南

还有一个FFT 示例代码可用

您可能还想查看iPhoneFFT。尽管该代码有些过时,但它可以帮助您了解“幕后”流程。

于 2013-04-23T13:51:37.733 回答
3

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

于 2013-04-25T15:58:15.280 回答