我正在尝试构建用于生成MFCC的三角形滤波器。我有基于IPP 6的现有代码,但是由于IPP 8正在发展中,我现在非常希望得到一个有效的实现,并且不依赖于旧的,现在不受支持的库。
我已经生成了相关的mel缩放中心频率(加上两端的2)。
然后我尝试按如下方式构建过滤器:
std::vector< std::vector< float > > ret;
int numFilters = freqPositions.size() - 2;
for( int f = 1; f < numFilters + 1; f++ )
{
float freqLow = freqPositions[f - 1];
float freqMid = freqPositions[f];
float freqHigh = freqPositions[f + 1];
float binLow = (freqLow / (sampleRate / 2)) * (numSamples + 1);
float binMid = (freqMid / (sampleRate / 2)) * (numSamples + 1);
float binHigh = (freqHigh / (sampleRate / 2)) * (numSamples + 1);
std::vector< float > fbank;
for( int s = 0; s < (numSamples + 1); s++ )
{
if ( s >= binLow && s < binMid )
{
const float fAmpl = (s - binLow) / (float)(binMid - binLow);
fbank.push_back( fAmpl );
}
else if ( s >= binMid && s <= binHigh )
{
const float fAmpl = 1.0f - ((s - binMid) / (float)(binHigh - binMid));
fbank.push_back( fAmpl );
}
else
{
fbank.push_back( 0.0f );
}
}
ret.push_back( fbank );
}
然后,我将上述向量与FFT结果(其中bin 0为0Hz或DC Offset bin)相加,然后将它们相加(基本上是点积)。
这个似乎工作得相当好,但我与IPP相比的结果有很大的不同,足以让我稍微担心。
我有什么问题吗?
整个过程包括FFT,计算返回的复矢量(std :: abs)的大小,然后应用如上计算的滤波器组。代码如下:
std::vector< float > ApplyFilterBanks( std::vector< std::vector< float > >& filterBanks, std::vector< float >& fftMags )
{
std::vector< float > ret;
for( int fb = 0; fb < (int)filterBanks.size(); fb++ )
{
float res = 0.0f;
Vec::Dot( res, &filterBanks[fb].front(), &fftMags.front(), filterBanks[fb].size() );
ret.push_back( res );
}
return ret;
}
{
const int kFFTSize = 1 << mFFT.GetFFTOrder();
const int kFFTSizeDiv2 = kFFTSize >> 1;
std::vector< float > audioToFFT;
audioToFFT.reserve( kFFTSize );
std::copy( pAudio, pAudio + numSamples, std::back_inserter( audioToFFT ) );
audioToFFT.resize( kFFTSize );
std::vector< float > hammingWindow( numSamples );
Vec::BuildHammingWindow( hammingWindow );
Vec::Multiply( &audioToFFT.front(), &audioToFFT.front(), &hammingWindow.front(), numSamples );
std::vector< std::complex< float > > fftResult( kFFTSize + 1 );
// FFT the incoming audio.
mFFT.ForwardFFT( &fftResult.front(), &audioToFFT.front(), kFFTSize );
// Calculate the magnitudes of the resulting FFT.
Vec::Magnitude( &audioToFFT.front(), &fftResult.front(), kFFTSizeDiv2 + 1 );
//Vec::Multiply( &audioToFFT.front(), &audioToFFT.front(), &audioToFFT.front(), kFFTSizeDiv2 + 1 );
// Apply the MFCC filter banks.
std::vector< float > filtered = ApplyFilterBanks( mFilterBanks, audioToFFT );
}
这是一个情节,其中系列1是我的MFCC,系列2是IPP:
在记录和提升阶段(我已经确认其工作方式与IPP相同)后,结果更加错误。
任何想法和指示都会受到大力赞赏!
编辑 :我应该指出这里有一些关于IPP功能的文档:
这似乎显示了数学。但是,我不确定yk和ck到底是什么......
答案 0 :(得分:1)
好的,我现在在这个问题上做得更好。
我发现了2个问题,首先是:
float binLow = (freqLow / (sampleRate / 2)) * (numSamples + 1);
float binMid = (freqMid / (sampleRate / 2)) * (numSamples + 1);
float binHigh = (freqHigh / (sampleRate / 2)) * (numSamples + 1);
应该是:
float binLow = (freqLow / (sampleRate / 2)) * (numSamples);
float binMid = (freqMid / (sampleRate / 2)) * (numSamples);
float binHigh = (freqHigh / (sampleRate / 2)) * (numSamples);
其次我正在通过梅尔空间错误地计算我的步数。我正在做以下事情:
const float melStep = melDiff / (numFilterBanks + 2);
当我应该这样做的时候:
const float melStep = melDiff / (numFilterBanks + 1);
现在我的结果虽然不完全相同,但现在显示出更好的对应关系:
最终的MFCC: