【问题标题】:Extract Treble and Bass from audio in iOS在 iOS 中从音频中提取高音和低音
【发布时间】:2013-03-05 13:01:08
【问题描述】:

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

谢谢!

【问题讨论】:

  • 查看这个问题的公认答案:stackoverflow.com/questions/1794010/…
  • 好的,这说明了该过程,但不是如何在 iOS 上执行该过程 - 或者至少从哪里开始。
  • iOS 在音频单元框架中内置了低通和高通滤波器。
  • 你能提供一些示例代码吗?我不知道该采取什么方向。

标签: ios audio extract waveform


【解决方案1】:

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

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

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

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

有趣的是,此时有一个名为Parseval's theorem 的东西。该定理表明,在执行傅立叶变换后,返回的 bin 之和等于输入信号的均方之和。

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

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

从这里开始,您需要弄清楚要添加哪些垃圾箱。

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

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

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

然后,您可以按照上述方法计算 RMS 值,并获得 RMS 值。

可以通过执行20.0f * log10f( rmsVal ); 将RMS 值转换为dBFS 值。这将返回一个从 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;
}

【讨论】:

    【解决方案2】:

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

    这是一个相当大的话题。

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

    这应该对你有帮助:vDSP Programming Guide

    还有一个FFT Sample Code 可用

    您可能还想查看iPhoneFFT。虽然该代码是slighlty 过时的它可以帮助您了解“幕后”流程。

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-12-26
        • 1970-01-01
        • 1970-01-01
        • 2013-07-30
        • 1970-01-01
        相关资源
        最近更新 更多