MelFilterBank.cxx
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "MelFilterBank.hxx"
00023 #include "ProcessingFactory.hxx"
00024
00025 namespace CLAM
00026 {
00027
00028 namespace Hidden
00029 {
00030 static const char * metadata[] = {
00031 "key", "MelFilterBank",
00032 "category", "Analysis",
00033 "description", "MelFilterBank",
00034 0
00035 };
00036 static FactoryRegistrator<ProcessingFactory, MelFilterBank> reg = metadata;
00037 }
00038
00039 void MelFilterBankConfig::DefaultInit()
00040 {
00041 AddAll();
00042 UpdateData();
00043 SetUsePower(false);
00044 SetSpectrumSize(513);
00045 SetNumBands(20);
00046 SetSpectralRange(22050);
00047 SetLowCutoff(0);
00048 SetHighCutoff(11025);
00049 }
00050
00051 MelFilterBank::MelFilterBank()
00052 : mIn("Spectrum", this)
00053 , mOut("Mel Spectrum", this)
00054 {
00055 Configure(MelFilterBankConfig());
00056 }
00057
00058 MelFilterBank::MelFilterBank( const MelFilterBankConfig& cfg )
00059 : mIn("Spectrum", this)
00060 , mOut("Mel Spectrum", this)
00061 {
00062 Configure( cfg );
00063 }
00064
00065 MelFilterBank::~MelFilterBank()
00066 {
00067 }
00068
00069 bool MelFilterBank::Do()
00070 {
00071 const Spectrum & spectrum = mIn.GetData();
00072 MelSpectrum & melSpectrum = mOut.GetData();
00073 bool ok = Do(spectrum,melSpectrum);
00074 mIn.Consume();
00075 mOut.Produce();
00076 return ok;
00077 }
00078
00079 bool MelFilterBank::Do( const Spectrum& spec, MelSpectrum& melSpec )
00080 {
00081 if ( !AbleToExecute() ) return false;
00082
00083 const DataArray& specMag = spec.GetMagBuffer();
00084
00085 CLAM_ASSERT( specMag.Size() == mConfig.GetSpectrumSize(),
00086 "Spectrum doesn't have the expected size!" );
00087 CLAM_ASSERT( spec.GetSpectralRange() == mConfig.GetSpectralRange(),
00088 "Spectrum doesn't have the expected frequency range!" );
00089 CLAM_ASSERT( spec.GetScale() == EScale::eLinear,
00090 "Spectrum is not in linear scale!" );
00091
00092 const TSize numBands = mConfig.GetNumBands();
00093
00094 melSpec.SetNumBands(numBands);
00095 melSpec.SetLowCutoff(mConfig.GetLowCutoff());
00096 melSpec.SetHighCutoff(mConfig.GetHighCutoff());
00097 melSpec.SetSpectralRange(spec.GetSpectralRange());
00098
00099 DataArray& melCoeffs = melSpec.GetCoefficients();
00100
00101 if ( melCoeffs.Size() != numBands ) {
00102 melCoeffs.Resize( numBands );
00103 melCoeffs.SetSize( numBands );
00104 }
00105 for( int i = 0; i < numBands; i++)
00106 melCoeffs[i] = 0;
00107
00108 const bool usePower = mConfig.GetUsePower();
00109
00110 for (TIndex i=mLowIdx; i<=mHighIdx; i++) {
00111
00112
00113 TData mag = specMag[i];
00114 if (usePower) mag *=mag;
00115
00116
00117 TIndex bandIdx = mMelBand[i];
00118
00119
00120 TData weightedMag = mFilterWeights[i] * mag;
00121
00122
00123 if (bandIdx >= 0) {
00124 melCoeffs[bandIdx] += weightedMag;
00125 }
00126
00127 if ((bandIdx+1) < numBands) {
00128 melCoeffs[bandIdx+1] += mag - weightedMag;
00129 }
00130 }
00131 return true;
00132 }
00133
00134 bool MelFilterBank::ConcreteConfigure( const ProcessingConfig& cfg )
00135 {
00136 CopyAsConcreteConfig( mConfig, cfg );
00137 InitializeTables();
00138 return true;
00139 }
00140
00141 TData MelFilterBank::Mel( TData linFreq )
00142 {
00143
00144
00145
00146
00147
00148
00149
00150 return 1127.0*log(1.0 + linFreq/700.0);
00151 }
00152
00153 void MelFilterBank::InitializeTables()
00154 {
00155
00156
00157 const TData lowCutoff = mConfig.GetLowCutoff();
00158 const TData highCutoff = mConfig.GetHighCutoff();
00159
00160
00161 const TData melLowCutoff = Mel(lowCutoff);
00162 const TData melHighCutoff = Mel(highCutoff);
00163 const TData melFreqRange = melHighCutoff - melLowCutoff;
00164
00165
00166 const TSize specSize = mConfig.GetSpectrumSize();
00167 const TData specRange = mConfig.GetSpectralRange();
00168
00169 const TData deltaFreq = specRange/specSize;
00170
00171
00172
00173
00174 mLowIdx = (TIndex)(lowCutoff/deltaFreq + 1.5);
00175
00176
00177 if (mLowIdx < 1) mLowIdx = 1;
00178
00179
00180
00181 mHighIdx = (TIndex)(highCutoff/deltaFreq - 0.5);
00182
00183 if (mHighIdx >= specSize) mHighIdx = specSize-1;
00184
00185
00186
00187 const TSize maxBands = mConfig.GetNumBands() + 1;
00188
00189 TData* centreFreq = new TData[maxBands];
00190
00191 for (TIndex i=0; i<maxBands; i++) {
00192 centreFreq[i] = ((i+1)/(TData)maxBands)*melFreqRange + melLowCutoff;
00193 }
00194
00195
00196
00197 mMelBand.Resize( specSize );
00198 mMelBand.SetSize( specSize );
00199
00200 TData melFreq = 0;
00201 TIndex bandIdx = 0;
00202 for (TIndex i=0; i<specSize; i++) {
00203
00204 if (i<mLowIdx || i>mHighIdx) {
00205
00206
00207 mMelBand[i] = -1;
00208 } else {
00209
00210 melFreq = Mel((TData)i*deltaFreq);
00211
00212
00213
00214
00215
00216
00217 while (centreFreq[bandIdx]<melFreq && bandIdx<maxBands) bandIdx++;
00218 mMelBand[i] = bandIdx-1;
00219 }
00220
00221 }
00222
00223
00224
00225 mFilterWeights.Resize( specSize );
00226 mFilterWeights.SetSize( specSize );
00227
00228 for (TIndex i=0; i<specSize; i++) {
00229 bandIdx = mMelBand[i];
00230
00231 if (i<mLowIdx || i>mHighIdx) {
00232 mFilterWeights[i] = 0.0;
00233 } else {
00234
00235 if (bandIdx >= 0) {
00236 mFilterWeights[i] = (centreFreq[bandIdx+1] - Mel((TData)i*deltaFreq))
00237 / (centreFreq[bandIdx+1] - centreFreq[bandIdx]);
00238
00239 } else {
00240 mFilterWeights[i] = (centreFreq[0] - Mel((TData)i*deltaFreq))
00241 / (centreFreq[0] - melLowCutoff);
00242
00243 }
00244 }
00245
00246 }
00247
00248 delete [] centreFreq;
00249 }
00250
00251 }
00252