00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "MFCC.h"
00020
00021
00022 using std::ostringstream;
00023
00024
00025 using namespace Marsyas;
00026
00027 MFCC::MFCC(mrs_string name):MarSystem("MFCC",name)
00028 {
00029 addControls();
00030 pfftSize_ = 0;
00031 psamplingRate_ = 0;
00032 mfcc_offsets_ = NULL;
00033 pcepstralCoefs_ = 0;
00034 cepstralCoefs_ = MFCC::cepstralCoefs_default;
00035 }
00036
00037 MFCC::MFCC(const MFCC& a) : MarSystem(a)
00038 {
00039 ctrl_cepstralCoefs_ = getctrl("mrs_natural/coefficients");
00040 pfftSize_ = 0;
00041 psamplingRate_ = 0;
00042 mfcc_offsets_ = NULL;
00043 pcepstralCoefs_ = 0;
00044 cepstralCoefs_ = MFCC::cepstralCoefs_default;
00045 }
00046
00047 MFCC::~MFCC()
00048 {
00049 if (mfcc_offsets_!=NULL)
00050 delete [] mfcc_offsets_;
00051 }
00052
00053 MarSystem*
00054 MFCC::clone() const
00055 {
00056 return new MFCC(*this);
00057 }
00058
00059
00060 void
00061 MFCC::addControls() {
00063 addControl("mrs_natural/coefficients", MFCC::cepstralCoefs_default, ctrl_cepstralCoefs_);
00064 setControlState("mrs_natural/coefficients", true);
00065 }
00066
00067 void
00068 MFCC::myUpdate(MarControlPtr sender)
00069 {
00070 (void) sender;
00071
00072
00073 cepstralCoefs_ = ctrl_cepstralCoefs_->to<mrs_natural>();
00074
00075 ctrl_onSamples_->setValue((mrs_natural)1, NOUPDATE);
00076 ctrl_onObservations_->setValue((mrs_natural)cepstralCoefs_, NOUPDATE);
00077 ctrl_osrate_->setValue(ctrl_israte_, NOUPDATE);
00078
00079
00080 mrs_natural i,j;
00081 fftSize_ = 2 * (ctrl_inObservations_->to<mrs_natural>()-1);
00082 if (fftSize_ == 0) return;
00083
00084 samplingRate_ = (mrs_natural) (ctrl_israte_->to<mrs_real>() * fftSize_);
00085
00086
00087
00088 mrs_string inObsName = stringSplit(ctrl_inObsNames_->to<mrs_string>(), ",")[0];
00089 ostringstream oss;
00090 for (i=0; i < cepstralCoefs_; ++i)
00091 {
00092 oss << "MFCC" << i << "_" << inObsName << ",";
00093 }
00094 ctrl_onObsNames_->setValue(oss.str(), NOUPDATE);
00095
00096 if ((pfftSize_ != fftSize_) || (psamplingRate_ != samplingRate_) || (pcepstralCoefs_ != cepstralCoefs_))
00097 {
00098
00099 freqs_.create(42);
00100 lowestFrequency_ = 133.3333f;
00101 linearFilters_ = 13;
00102 linearSpacing_ = 66.66666f;
00103 logFilters_ = 27;
00104 logSpacing_ = 1.0711703f;
00105
00106 totalFilters_ = linearFilters_ + logFilters_;
00107 lower_.create(totalFilters_);
00108 center_.create(totalFilters_);
00109 upper_.create(totalFilters_);
00110 triangle_heights_.create(totalFilters_);
00111
00112
00113 for (i=0; i< linearFilters_; ++i)
00114 {
00115 freqs_(i) = lowestFrequency_ + i * linearSpacing_;
00116 }
00117
00118
00119 mrs_real first_log = freqs_(linearFilters_-1);
00120 for (i=1; i<=logFilters_+2; ++i)
00121 {
00122 freqs_(linearFilters_-1+i) = first_log * pow(logSpacing_, (mrs_real)i);
00123 }
00124
00125
00126 for (i=0; i<totalFilters_; ++i)
00127 {
00128 lower_(i) = freqs_(i);
00129 }
00130
00131 for (i=1; i<= totalFilters_; ++i)
00132 {
00133 center_(i-1) = freqs_(i);
00134 }
00135
00136 for (i=2; i<= totalFilters_+1; ++i)
00137 {
00138 upper_(i-2) = freqs_(i);
00139 }
00140
00141 for (i=0; i<totalFilters_; ++i)
00142 {
00143 triangle_heights_(i) = (mrs_real)(2.0 / (upper_(i) - lower_(i)));
00144 }
00145
00146 fftFreqs_.stretch(fftSize_);
00147
00148 for (i=0; i< fftSize_; ++i)
00149 {
00150 fftFreqs_(i) = (float)i / (float)fftSize_ * (float)samplingRate_;
00151 }
00152
00153 mfccFilterWeights_.create(totalFilters_, fftSize_);
00154 mfccDCT_.create(cepstralCoefs_, totalFilters_);
00155
00156 mrs_natural chan;
00157
00158
00159 if (pfftSize_!=fftSize_)
00160 {
00161 if (mfcc_offsets_!=NULL)
00162 {
00163 delete [] mfcc_offsets_;
00164 }
00165 mfcc_offsets_ = new int[totalFilters_*fftSize_*2];
00166 }
00167
00168 for (chan = 0; chan < totalFilters_; chan++)
00169 {
00170
00171 int len=0;
00172 int pos=0;
00173 for (i=0; i< fftSize_; ++i)
00174 {
00175 if ((fftFreqs_(i) > lower_(chan))&& (fftFreqs_(i) <= center_(chan)))
00176 {
00177 mfccFilterWeights_(chan, i) = triangle_heights_(chan) *
00178 ((fftFreqs_(i) - lower_(chan))/(center_(chan) - lower_(chan)));
00179
00180 if (len==-1)
00181 {
00182 pos=i;
00183 }
00184 len=i;
00185 }
00186 if ((fftFreqs_(i) > center_(chan)) && (fftFreqs_(i) <= upper_(chan)))
00187 {
00188 mfccFilterWeights_(chan, i) = triangle_heights_(chan) *
00189 ((upper_(chan) - fftFreqs_(i))/(upper_(chan) - center_(chan)));
00190
00191 if (len==-1)
00192 {
00193 pos=i;
00194 }
00195 len=i;
00196 }
00197 }
00198
00199 mfcc_offsets_[chan] = pos;
00200 mfcc_offsets_[chan+totalFilters_] = len;
00201 }
00202
00203
00204 mrs_real scale_fac = (mrs_real)(1.0/ sqrt((mrs_real)(totalFilters_/2)));
00205 for (j = 0; j<cepstralCoefs_; j++)
00206 {
00207 for (i=0; i< totalFilters_; ++i)
00208 {
00209 mfccDCT_(j, i) = scale_fac * cos(j * (2*i +1) * PI/2/totalFilters_);
00210 if (j == 0)
00211 {
00212 mfccDCT_(j,i) *= (mrs_real)(sqrt(2.0)/2.0);
00213 }
00214 }
00215 }
00216 }
00217
00218
00219 pfftSize_ = fftSize_;
00220 psamplingRate_ = samplingRate_;
00221
00222 fmagnitude_.stretch(ctrl_inObservations_->to<mrs_natural>() * 2);
00223 earMagnitude_.stretch(totalFilters_);
00224 }
00225
00226 void
00227 MFCC::myProcess(realvec& in, realvec& out)
00228 {
00229 mrs_natural i,k,o;
00230
00231
00232 for (o=0; o < inObservations_; o++)
00233 {
00234 fmagnitude_(o) = in(o,0);
00235 }
00236
00237 for (o=0; o< inObservations_; o++)
00238 {
00239 fmagnitude_(o + inObservations_) = fmagnitude_(inObservations_ - o -1);
00240 }
00241
00242 mrs_real sum =0.0;
00243
00244 for (i=0; i<totalFilters_; ++i)
00245 {
00246 sum = 0.0;
00247
00248 for (k=mfcc_offsets_[i]; k<=mfcc_offsets_[i+totalFilters_]; k++)
00249 {
00250 sum += (mfccFilterWeights_(i, k) * fmagnitude_(k));
00251 }
00252 if (sum != 0.0)
00253 {
00254 earMagnitude_(i) = log10(sum);
00255 }
00256 else
00257 {
00258 earMagnitude_(i) = 0.0;
00259 }
00260 }
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275 for (o=0; o < cepstralCoefs_; o++)
00276 {
00277 sum =0.0;
00278 for (k=0; k < totalFilters_; k++)
00279 {
00280 sum += (mfccDCT_(o,k) * earMagnitude_(k));
00281 }
00282 out(o,0) = sum;
00283 }
00284 }