我正在寻找一种方法来从歌曲中获取高音和低音数据,时间增加一些(比如 0.1 秒),范围在 0.0 到 1.0 之间。我已经四处搜索,但无法找到任何与我正在寻找的东西相近的东西。最终,我希望能够在播放歌曲时代表高音和低音级别。
谢谢!
它相当容易。您需要执行 FFT,然后总结您感兴趣的 bin。您选择的很多方式将取决于音频的采样率。
然后,您需要选择适当的 FFT 顺序以在返回的频率区间中获得良好的信息。
因此,如果您订购 8 FFT,您将需要 256 个样本。这将返回 128 个复数对。
接下来,您需要将这些转换为幅度。这其实很简单。如果您使用的是 std::complex,您可以简单地对复数执行 std::abs 并且您将获得其大小 (sqrt(r^2 + i^2))。
有趣的是,此时有一个叫做Parseval 定理的东西。该定理指出,在执行傅立叶变换后,返回的 bin 之和等于输入信号的均方之和。
这意味着要获得一组特定 bin 的幅度,您只需将它们加在一起除以它们的数量,然后 sqrt 即可获得这些 bin 的 RMS 幅度值。
那么这会给你带来什么影响呢?
那么从这里你需要弄清楚你正在添加哪些垃圾箱。
现在假设您的采样率为 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;
}
请参阅 Apple 的auriotouch2示例 - 它包含从频率分析到您想要的 UI 表示的所有内容。