Edinburgh Speech Tools  2.1-release
sigpr_frame.cc
Go to the documentation of this file.
1 /*************************************************************************/
2 /* */
3 /* Centre for Speech Technology Research */
4 /* University of Edinburgh, UK */
5 /* Copyright (c) 1996 */
6 /* All Rights Reserved. */
7 /* */
8 /* Permission is hereby granted, free of charge, to use and distribute */
9 /* this software and its documentation without restriction, including */
10 /* without limitation the rights to use, copy, modify, merge, publish, */
11 /* distribute, sublicense, and/or sell copies of this work, and to */
12 /* permit persons to whom this work is furnished to do so, subject to */
13 /* the following conditions: */
14 /* 1. The code must retain the above copyright notice, this list of */
15 /* conditions and the following disclaimer. */
16 /* 2. Any modifications must be clearly marked as such. */
17 /* 3. Original authors' names are not deleted. */
18 /* 4. The authors' names are not used to endorse or promote products */
19 /* derived from this software without specific prior written */
20 /* permission. */
21 /* */
22 /* THE UNIVERSITY OF EDINBURGH AND THE CONTRIBUTORS TO THIS WORK */
23 /* DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING */
24 /* ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT */
25 /* SHALL THE UNIVERSITY OF EDINBURGH NOR THE CONTRIBUTORS BE LIABLE */
26 /* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES */
27 /* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN */
28 /* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, */
29 /* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF */
30 /* THIS SOFTWARE. */
31 /* */
32 /*************************************************************************/
33 /* Authors: Paul Taylor and Simon King */
34 /* Date : March 1998 */
35 /*-----------------------------------------------------------------------*/
36 /* Functions operating on a single frame */
37 /* */
38 /*=======================================================================*/
39 
40 #include "sigpr/EST_sigpr_frame.h"
41 #include "sigpr/EST_fft.h"
42 #include "EST_inline_utils.h"
43 #include "EST_math.h"
44 #include "EST_error.h"
45 #include "EST_TBuffer.h"
46 
47 using namespace std;
48 
49 #define ALMOST1 0.99999
50 #define MAX_ABS_CEPS 4.0
51 
52 float Hz2Mel(float frequency_in_Hertz);
53 float Mel2Hz(float frequency_in_Mel);
54 
55 float lpredict(float *adc, int wsize,
56  float *acf, float *ref, float *lpc,
57  int order);
58 float ogi_lpc(float *adc, int wsize, int order,
59  float *acf, float *ref, float *lpc);
60 /*
61 void lpc2ref(float const *a, float *b, int c)
62 {
63  (void) a;
64  (void) b;
65  (void) c;
66 }
67 */
68 
69 void convert2lpc(const EST_FVector &in_frame, const EST_String &in_type,
70  EST_FVector &out_frame)
71 {
72  if (in_type == "sig")
73  sig2lpc(in_frame, out_frame);
74  else if (in_type == "lsf")
75  lsf2lpc(in_frame, out_frame);
76  else if (in_type == "ref")
77  ref2lpc(in_frame, out_frame);
78  else
79  EST_error("Cannot convert coefficient type %s to lpc\n",
80  (const char *) in_type);
81 }
82 
83 void convert2ref(const EST_FVector &in_frame, const EST_String &in_type,
84  EST_FVector &out_frame)
85 {
86  EST_FVector tmp;
87 
88  if (in_type == "lpc")
89  lpc2ref(in_frame, out_frame);
90  else if (in_type == "sig")
91  {
92  tmp.resize(out_frame.length());
93  sig2lpc(in_frame, tmp);
94  lpc2ref(tmp, out_frame);
95  }
96  else if (in_type == "lsf")
97  {
98  tmp.resize(out_frame.length());
99  lsf2lpc(in_frame, tmp);
100  lpc2ref(tmp, out_frame);
101  }
102  else
103  EST_error("Cannot convert coefficient type %s to reflection coefs\n",
104  (const char *) in_type);
105 }
106 
107 void convert2area(const EST_FVector &in_frame, const EST_String &in_type,
108  EST_FVector &out_frame)
109 {
110  EST_FVector tmp;
111 
112  if (in_type == "lpc")
113  lpc2ref(in_frame, out_frame);
114  else if (in_type == "sig")
115  {
116  tmp.resize(out_frame.length());
117  sig2lpc(in_frame, tmp);
118  lpc2ref(tmp, out_frame);
119  }
120  else if (in_type == "lsf")
121  {
122  tmp.resize(out_frame.length());
123  lsf2lpc(in_frame, tmp);
124  lpc2ref(tmp, out_frame);
125  }
126  else
127  EST_error("Cannot convert coefficient type %s to reflection coefs\n",
128  (const char *) in_type);
129 }
130 
131 void convert2cep(const EST_FVector &in_frame, const EST_String &in_type,
132  EST_FVector &out_frame)
133 {
134  EST_FVector tmp;
135 
136  if (in_type == "lpc")
137  lpc2cep(in_frame, out_frame);
138  else if (in_type == "sig")
139  {
140  tmp.resize(out_frame.length());
141  sig2lpc(in_frame, tmp);
142  lpc2cep(tmp, out_frame);
143  }
144  else if (in_type == "lsf")
145  {
146  tmp.resize(out_frame.length());
147  lsf2lpc(in_frame, tmp);
148  lpc2cep(tmp, out_frame);
149  }
150  else if (in_type == "ref")
151  {
152  tmp.resize(out_frame.length());
153  ref2lpc(in_frame, tmp);
154  lpc2cep(tmp, out_frame);
155  }
156  else
157  EST_error("Cannot convert coefficient type %s to cepstrum coefs\n",
158  (const char *) in_type);
159 }
160 
161 // void convert2melcep(const EST_FVector &in_frame, const EST_String &in_type,
162 // EST_FVector &out_frame, int num_mfccs, int fbank_order,
163 // float liftering_parameter)
164 // {
165 // EST_FVector tmp;
166 
167 // if (in_type == "fbank")
168 // // fbank2melcep(in_frame, out_frame);
169 // return;
170 // else if (in_type == "sig")
171 // {
172 // tmp.resize(out_frame.length());
173 // // incomplete !
174 // // sig2melcep(in_frame, outframe,num_mfccs,fbank_order,liftering_parameter);
175 // }
176 // else
177 // EST_error("Cannot convert coefficient type %s to Mel cepstrum coefs\n",
178 // (const char *) in_type);
179 // }
180 
181 
182 void convert2lsf(const EST_FVector &in_frame, const EST_String &in_type,
183  EST_FVector &out_frame)
184 {
185  EST_FVector tmp;
186 
187  if (in_type == "lpc")
188  lpc2lsf(in_frame, out_frame);
189  else if (in_type == "sig")
190  {
191  tmp.resize(out_frame.length());
192  sig2lpc(in_frame, tmp);
193  lpc2lsf(tmp, out_frame);
194  }
195  else if (in_type == "ref")
196  {
197  tmp.resize(out_frame.length());
198  ref2lpc(in_frame, tmp);
199  lpc2lsf(tmp, out_frame);
200  }
201  else
202  EST_error("Cannot convert coefficient type %s to reflection coefs\n",
203  (const char *) in_type);
204 }
205 
206 void frame_convert(const EST_FVector &in_frame, const EST_String &in_type,
207  EST_FVector &out_frame, const EST_String &out_type)
208 {
209  if (out_type == "lpc")
210  convert2lpc(in_frame, in_type, out_frame);
211  else if (out_type == "lsf")
212  convert2lsf(in_frame, in_type, out_frame);
213  else if (out_type == "ref")
214  convert2ref(in_frame, in_type, out_frame);
215  else if (out_type == "cep")
216  convert2cep(in_frame, in_type, out_frame);
217  else if (out_type == "area")
218  convert2area(in_frame, in_type, out_frame);
219  else
220  EST_error("Cannot convert coefficients to type %s\n",
221  (const char *) out_type);
222 }
223 
224 void sig2lpc(const EST_FVector &sig, EST_FVector &acf,
225  EST_FVector &ref, EST_FVector &xlpc);
226 
227 float lpredict2(EST_FVector &adc, int wsize,
228  EST_FVector &acf, float *ref, float *lpc,
229  int order);
230 
231 void sig2lpc(const EST_FVector &sig, EST_FVector &lpc)
232 {
233  EST_FVector acf(lpc.length()), ref(lpc.length());
234 
235 /* float *fadc, *facf, *fref, *flpc;
236 
237  fadc = new float[sig.length()];
238  facf = new float[lpc.length()];
239  fref = new float[lpc.length()];
240  flpc = new float[lpc.length()];
241 
242 // for (int i = 0; i < sig.length(); ++i)
243 // adc[i] = sig(i);
244 
245  lpredict2(sig, sig.length(), acf, fref, flpc, lpc.length()-1);
246 
247  for (int i = 0; i < lpc.length(); ++i)
248  lpc.a(i) = flpc[i];
249  */
250  sig2lpc(sig, acf, ref, lpc);
251 }
252 
253 void sig2ref(const EST_FVector &sig, EST_FVector &ref)
254 {
255  (void)sig;
256  EST_FVector acf(ref.length()), lpc(ref.length());
257 
258 // sig2lpc(sig, acf, ref, lpc);
259 }
260 
261 void ref2area(const EST_FVector &ref, EST_FVector &area)
262 {
263  for (int i = 1; i < ref.length(); i++)
264  area[i] = (1.0 - ref(i)) / (1.0 + ref(i));
265 }
266 
267 void ref2logarea(const EST_FVector &ref, EST_FVector &logarea)
268 {
269  int order = ref.length() -1;
270 
271  for(int i = 1; i <= order; i++)
272  {
273  if (ref(i) > ALMOST1)
274  logarea[i] = log((1.0 - ALMOST1) / (1.0 + ALMOST1));
275  else if (ref(i) < -ALMOST1)
276  logarea[i] = log((1.0 + ALMOST1)/(1.0 - ALMOST1));
277  else
278  logarea[i] = log((1.0 - ref(i)) / (1.0 + ref(i)));
279  }
280 }
281 
282 void ref2truearea(const EST_FVector &ref, EST_FVector &area)
283 {
284  int order = ref.length() -1;
285 
286  area[1] = (1.0 - ref(1)) / (1.0 + ref(1));
287  for(int i = 2; i <= order; i++)
288  area[i] = area[i - 1] * (1.0 - ref(i)) / (1.0 + ref(i));
289 }
290 
291 void lpc2cep(const EST_FVector &lpc, EST_FVector &cep)
292 {
293  int n, k;
294  float sum;
295  int order = lpc.length() - 1;
296 
297  for (n = 1; n <= order && n <= cep.length(); n++)
298  {
299  sum = 0.0;
300  for (k = 1; k < n; k++)
301  sum += k * cep(k-1) * lpc(n - k);
302  cep[n-1] = lpc(n) + sum / n;
303  }
304 
305  /* be wary of these interpolated values */
306  for(n = order + 1; n <= cep.length(); n++)
307  {
308  sum = 0.0;
309  for (k = n - (order - 1); k < n; k++)
310  sum += k * cep(k-1) * lpc(n - k);
311  cep[n-1] = sum / n;
312  }
313 
314  /* very occasionally the above can go unstable, fudge if this happens */
315 
316  for (n = 0; n < cep.length(); n++)
317  {
318  // check if NaN -- happens on some frames of silence
319  if (isnanf(cep[n]) ) cep[n] = 0.0;
320 
321  if (cep[n] > MAX_ABS_CEPS){
322  cerr << "WARNING : cepstral coeff " << n << " was " <<
323  cep[n] << endl;
324  cerr << "lpc coeff " << n << " = " << lpc(n + 1) << endl;
325 
326  cep[n] = MAX_ABS_CEPS;
327  }
328  if (cep[n] < -MAX_ABS_CEPS) {
329  cerr << "WARNING : cepstral coeff " << n << " was " <<
330  cep[n] << endl;
331  cep[n] = -MAX_ABS_CEPS;
332  }
333  }
334 }
335 
336 /* Sergio Oller <sergioller@gmail.com>
337  * This function returns the same ref coefficients as given by:
338  * sig2lpc(sig, acf, ref, lpc). (at least on my tests).
339  */
340 void lpc2ref(const EST_FVector &lpc, EST_FVector &ref)
341 {
342  ssize_t order = lpc.length() - 1;
343  ssize_t p,m, i;
344  float f;
345  float *x, *xp;
346  x = new float[order+1];
347  xp = new float[order+1];
348  for (i=0;i<lpc.length();i++)
349  x[i] = lpc(i);
350  for (p=order-1;p>0;p--) {
351  memcpy(xp,x,(order+1)*sizeof(float));
352  ref[p] = xp[p+1];
353  f = 1-ref[p]*ref[p];
354  for (m=0;m<p;m++) {
355  x[m+1] = (xp[m+1]+ref[p]*xp[p-m])/f;
356  }
357  }
358  ref[0] = x[1];
359  delete[] x;
360  delete[] xp;
361  return;
362 }
363 
364 void ref2lpc(const EST_FVector &ref, EST_FVector &lpc)
365 {
366  // Here we use Christopher Longet Higgin's algorithm converted to
367  // an equivalent by awb. It doesn't have the reverse order or
368  // negation requirement.
369  int order = ref.length() - 1;
370  float a, b;
371  int n, k;
372 
373  for (n=0; n < order; n++)
374  {
375  lpc[n] = ref(n);
376  for (k=0; 2 * (k+1) <= n + 1; k++)
377  {
378  a = lpc[k];
379  b = lpc[n-(k + 1)];
380  lpc[k] = a-b * lpc[n];
381  lpc[n-(k+1)] = b-a * lpc[n];
382  }
383  }
384 }
385 
386 
387 /************************************************************
388  ** LPC_TO_LSF -
389  ** pass the LENGTH of the LPC vector - this is the LPC
390  ** order plus 1. Must pre-allocate lsfs to length+1
391  ************************************************************/
392 void lpc2lsf(const EST_FVector &lpc, EST_FVector &lsf)
393 {
394  (void) lpc;
395  (void) lsf;
396  EST_error("LSF Code unfinished\n");
397 }
398 
399 void lsf2lpc(const EST_FVector &lpc, EST_FVector &lsf)
400 {
401  (void) lpc;
402  (void) lsf;
403  EST_error("LSF Code unfinished\n");
404 }
405 
406 void sig2lpc(const EST_FVector &sig, EST_FVector &acf,
407  EST_FVector &ref, EST_FVector &lpc)
408 {
409 
410  int i, j;
411  float e, ci, sum;
412  int order = lpc.length() -1;
413  EST_FVector tmp(order);
414  int stableorder=-1;
415 
416  if ((acf.length() != ref.length()) ||
417  (acf.length() != lpc.length()))
418  EST_error("sig2lpc: acf, ref are not of lpc's order");
419 
420  //cerr << "sig2lpc order " << order << endl;
421 
422 
423  for (i = 0; i <= order; i++)
424  {
425  sum = 0.0;
426  for(j = 0; j < sig.length() - i; j++)
427  sum += sig.a_no_check(j) * sig.a_no_check(j + i);
428  acf.a_no_check(i) = sum;
429  }
430 
431  // find lpc coefficients
432  e = acf.a_no_check(0);
433  lpc.a_no_check(0) = 1.0;
434 
435  for (i = 1; i <= order; i++)
436  {
437  ci = 0.0;
438  for(j = 1; j < i; j++)
439  ci += lpc.a_no_check(j) * acf.a_no_check(i-j);
440  if (e == 0)
441  ref.a_no_check(i) = ci = 0.0;
442  else
443  ref.a_no_check(i) = ci = (acf.a_no_check(i) - ci) / e;
444  //Check stability of the recursion
445  if (absval(ci) < 1.000000)
446  {
447  lpc.a_no_check(i) = ci;
448  for (j = 1; j < i; j++)
449  tmp.a_no_check(j) = lpc.a_no_check(j) -
450  (ci * lpc.a_no_check(i-j));
451  for( j = 1; j < i; j++)
452  lpc.a_no_check(j) = tmp.a_no_check(j);
453 
454  e = (1 - ci * ci) * e;
455  stableorder = i;
456  }
457  else break;
458  }
459  if (stableorder != order)
460  {
461  fprintf(stderr,
462  "warning:levinson instability, order restricted to %d\n",
463  stableorder);
464  for (; i <= order; i++)
465  lpc.a_no_check(i) = 0.0;
466  }
467 
468  // normalisation for frame length
469  lpc.a_no_check(0) = e / sig.length();
470 }
471 
472 void sig2pow(EST_FVector &frame, float &power)
473 {
474  power = 0.0;
475  for (int i = 0; i < frame.length(); i++)
476  power += pow(frame(i), float(2.0));
477 
478  power /= frame.length();
479 }
480 
481 void sig2rms(EST_FVector &frame, float &rms_energy)
482 {
483  sig2pow(frame, rms_energy);
484  rms_energy = sqrt(rms_energy);
485 }
486 
487 
488 float lpredict2(EST_FVector &adc, int wsize,
489  EST_FVector &acf, float *ref, float *lpc,
490  int order)
491 {
492  int i, j;
493  float e, ci, sum;
494  EST_TBuffer<float> tmp(order);
495  int stableorder=-1;
496 
497  EST_FVector vref(order + 1), vlpc(order + 1);
498 
499  for (i = 0; i <= order; i++)
500  {
501  sum = 0.0;
502  for (j = 0; j < wsize - i; j++)
503  sum += adc[j] * adc[j + i];
504  acf[i] = sum;
505  }
506  /* find lpc coefficients */
507  e = acf[0];
508  lpc[0] = 1.0;
509  for(i = 1; i <= order; i++) {
510  ci = 0.0;
511  for(j = 1; j < i; j++)
512  ci += lpc[j] * acf[i-j];
513  ref[i] = ci = (acf[i] - ci) / e;
514  //Check stability of the recursion
515  if (absval(ci) < 1.000000) {
516  lpc[i] = ci;
517  for(j = 1; j < i; j++)
518  tmp[j] = lpc[j] - ci * lpc[i-j];
519  for(j = 1; j < i; j++)
520  lpc[j] = tmp[j];
521  e = (1 - ci * ci) * e;
522  stableorder = i;
523  }
524  else break;
525  }
526  if (stableorder != order) {
527  fprintf(stderr,
528  "warning:levinson instability, order restricted to %d\n",
529  stableorder);
530  for (;i<=order;i++)
531  lpc[i]=0.0;
532  }
533  return(e);
534 }
535 
536 
537 
538 void sig2fbank(const EST_FVector &sig,
539  EST_FVector &fbank_frame,
540  const float sample_rate,
541  const bool use_power_rather_than_energy,
542  const bool take_log)
543 {
544 
545  EST_FVector fft_frame;
546  int i,fbank_order;
547  float Hz_per_fft_coeff;
548 
549  // upper and lower limits of filter bank
550  // where the upper limit depends on the sampling frequency
551  // TO DO : add low/high pass filtering HERE
552  float mel_low=0;
553  float mel_high=Hz2Mel(sample_rate / 2);
554 
555  // FFT this frame. FFT order will be computed by sig2fft
556  // FFT frame returned will be half length of actual FFT performed
557  sig2fft(sig,fft_frame,use_power_rather_than_energy);
558 
559  // this is more easily understood as half the sampling
560  // frequency over half the fft order, but fft_frame_length()
561  // is already halved
562  Hz_per_fft_coeff = 0.5 * sample_rate / fft_frame.length();
563 
564  fbank_order = fbank_frame.length();
565 
566  // store the list of centre frequencies and lower and upper bounds of
567  // the triangular filters
568  EST_FVector mel_fbank_centre_frequencies(fbank_order+2);
569 
570  mel_fbank_centre_frequencies[0]=mel_low;
571 
572  for(i=1;i<=fbank_order;i++)
573  mel_fbank_centre_frequencies[i] = mel_low +
574  (float)(i) * (mel_high - mel_low) / (fbank_order+1);
575 
576  mel_fbank_centre_frequencies[fbank_order+1]=mel_high;
577 
578  // bin FFT in Mel filters
579  fft2fbank(fft_frame,
580  fbank_frame,
581  Hz_per_fft_coeff,
582  mel_fbank_centre_frequencies);
583 
584  if(take_log)
585  for(i=0;i<fbank_frame.length();i++)
586  fbank_frame[i] = safe_log(fbank_frame[i]);
587 
588 }
589 
590 void sig2fft(const EST_FVector &sig,
591  EST_FVector &fft_vec,
592  const bool use_power_rather_than_energy)
593 {
594 
595  int i,half_fft_order;
596  float real,imag;
597  float window_size = sig.length();
598  int fft_order; /* = fft_vec.length();*/
599 
600  // work out FFT order required
601  fft_order = 2;
602  while (window_size > fft_order)
603  fft_order *= 2;
604 
605  fft_vec = sig;
606 
607  // pad with zeros
608  fft_vec.resize(fft_order);
609 
610  // in place FFT
611  (void)fastFFT(fft_vec);
612 
613  // of course, we only need the lower half of the fft
614  half_fft_order = fft_order/2;
615 
616  for(i=0;i<half_fft_order;i++)
617  {
618  real = fft_vec(i*2);
619  imag = fft_vec(i*2 + 1);
620 
621  fft_vec[i] = real * real + imag * imag;
622 
623  if(!use_power_rather_than_energy)
624  fft_vec[i] = sqrt(fft_vec(i));
625 
626  }
627 
628  // discard mirror image, retaining energy/power spectrum
629  fft_vec.resize(half_fft_order);
630 
631 }
632 
633 
634 
635 void fft2fbank(const EST_FVector &fft_frame,
636  EST_FVector &fbank_vec,
637  const float Hz_per_fft_coeff,
638  const EST_FVector &mel_fbank_frequencies)
639 {
640 
641  // expects "half length" FFT - i.e. energy or power spectrum
642  // energy is magnitude; power is squared magnitude
643 
644  // mel_fbank_frequencies is a vector of centre frequencies
645  // BUT : first element is lower bound of first filter
646  // last element is upper bound of final filter
647  // i.e. length = num filters + 2
648 
649  int i,k;
650  float this_mel_centre,this_mel_low,this_mel_high;
651  EST_FVector filter;
652  int fft_index_start;
653 
654  // check that fbank_vec and mel_fbank_frequencies lengths match
655  if(mel_fbank_frequencies.length() != fbank_vec.length() + 2)
656  {
657  EST_error("Filter centre frequencies length (%i) is not equal to fbank order (%i) plus 2\n",mel_fbank_frequencies.length(),
658  fbank_vec.length());
659  return;
660  }
661 
662  // filters are computed on the fly
663  for(i=0;i<fbank_vec.length();i++)
664  {
665 
666  // work out shape of the i'th filter
667  this_mel_low=mel_fbank_frequencies(i);
668  this_mel_centre=mel_fbank_frequencies(i+1);
669  this_mel_high=mel_fbank_frequencies(i+2);
670 
671  make_mel_triangular_filter(this_mel_centre,this_mel_low,this_mel_high,
672  Hz_per_fft_coeff,fft_frame.length(),
673  fft_index_start,filter);
674 
675  // do filtering
676  fbank_vec[i]=0.0;
677  for(k=0;k<filter.length();k++)
678  fbank_vec[i] += fft_frame(fft_index_start + k) * filter(k);
679  }
680 
681 }
682 
683 
684 void fbank2melcep(const EST_FVector &fbank_vec,
685  EST_FVector &mfcc_vec,
686  const float liftering_parameter,
687  const bool include_c0)
688 {
689  // a cosine transform of the fbank output
690  // remember to pass LOG fbank params (energy or power)
691 
692  int i,j,actual_mfcc_index;
693  float pi_i_over_N,const_factor;
694  /*float cos_xform_order;*/
695  float PI_over_liftering_parameter;
696 
697  if(liftering_parameter != 0.0)
698  PI_over_liftering_parameter = PI / liftering_parameter;
699  else
700  PI_over_liftering_parameter = PI; // since sin(n.PI) == 0
701 
702  // if we are not including cepstral coeff 0 (c0) then we need
703  // to do a cosine transform 1 longer than otherwise
704  /*cos_xform_order = include_c0 ? mfcc_vec.length() : mfcc_vec.length() + 1;*/
705 
706  const_factor = sqrt(2 / (float)(fbank_vec.length()));
707 
708  for(i=0;i<mfcc_vec.length();i++)
709  {
710 
711  actual_mfcc_index = include_c0 ? i : i+1;
712 
713  pi_i_over_N =
714  PI * (float)(actual_mfcc_index) / (float)(fbank_vec.length());
715 
716  for(j=0;j<fbank_vec.length();j++)
717  // j + 0.5 is because we want (j+1) - 0.5
718  mfcc_vec[i] += fbank_vec(j) * cos(pi_i_over_N * ((float)j + 0.5));
719 
720  mfcc_vec[i] *= const_factor;
721 
722  // liftering
723  mfcc_vec[i] *= 1 + (0.5 * liftering_parameter
724  * sin(PI_over_liftering_parameter * (float)(actual_mfcc_index)));
725  }
726 
727 }
728 
729 
730 void make_mel_triangular_filter(const float this_mel_centre,
731  const float this_mel_low,
732  const float this_mel_high,
733  const float Hz_per_fft_coeff,
734  const int half_fft_order,
735  int &fft_index_start,
736  EST_FVector &filter)
737 {
738 
739  // makes a triangular (on a Mel scale) filter and creates
740  // a weight vector to apply to FFT coefficients
741 
742  int i,filter_vector_length,fft_index_stop;
743  float rise_slope,fall_slope,this_mel;
744 
745 
746  // slopes are in units per Mel
747  // this is important - slope is linear in MEl domain, not Hz
748  rise_slope = 1/(this_mel_centre - this_mel_low);
749  fall_slope = 1/(this_mel_centre - this_mel_high);
750 
751 
752  // care with rounding - we want FFT indices **guaranteed**
753  // to be within filter so we get no negative filter gains
754  // (irint gives the _nearest_ integer)
755 
756  // round up
757  if(this_mel_low == 0)
758  fft_index_start=0;
759  else
760  fft_index_start = irint(0.5 + (Mel2Hz(this_mel_low) / Hz_per_fft_coeff));
761 
762  // round down
763  fft_index_stop = irint((Mel2Hz(this_mel_high) / Hz_per_fft_coeff) - 0.5);
764 
765  if(fft_index_stop > half_fft_order-1)
766  fft_index_stop = half_fft_order-1;
767 
768 
769  filter_vector_length = fft_index_stop - fft_index_start + 1;
770  filter.resize(filter_vector_length);
771 
772  for(i=0;i<filter_vector_length;i++)
773  {
774  this_mel = Hz2Mel( (i + fft_index_start) * Hz_per_fft_coeff );
775 
776  if(this_mel <= this_mel_centre)
777  {
778  filter[i] = rise_slope * (this_mel - this_mel_low);
779  }
780  else
781  {
782  filter[i] = 1 + fall_slope * (this_mel - this_mel_centre);
783  }
784 
785  }
786 
787 }
788 
789 
790 float Hz2Mel(float frequency_in_Hertz)
791 {
792  return 1127 * log(1 + frequency_in_Hertz/700.0);
793 }
794 
795 float Mel2Hz(float frequency_in_Mel)
796 {
797  return (exp(frequency_in_Mel / 1127) - 1) * 700;
798 }
void make_mel_triangular_filter(const float this_mel_centre, const float this_mel_low, const float this_mel_high, const float Hz_per_fft_coeff, const int half_fft_order, int &fft_index_start, EST_FVector &filter)
Definition: sigpr_frame.cc:730
void fft2fbank(const EST_FVector &fft_frame, EST_FVector &fbank_vec, const float Hz_per_fft_coeff, const EST_FVector &mel_fbank_frequencies)
Definition: sigpr_frame.cc:635
void frame_convert(const EST_FVector &in_frame, const EST_String &in_type, EST_FVector &out_frame, const EST_String &out_type)
Definition: sigpr_frame.cc:206
double safe_log(const double x)
Definition: EST_math.h:158
void ref2area(const EST_FVector &ref, EST_FVector &area)
Definition: sigpr_frame.cc:261
void sig2ref(const EST_FVector &sig, EST_FVector &ref)
Definition: sigpr_frame.cc:253
A vector class for floating point numbers. EST_FVector x should be used instead of float *x wherever ...
Definition: EST_FMatrix.h:119
void convert2cep(const EST_FVector &in_frame, const EST_String &in_type, EST_FVector &out_frame)
Definition: sigpr_frame.cc:131
void convert2lsf(const EST_FVector &in_frame, const EST_String &in_type, EST_FVector &out_frame)
Definition: sigpr_frame.cc:182
INLINE const T & a_no_check(ssize_t n) const
read-only const access operator: without bounds checking
Definition: EST_TVector.h:254
void sig2pow(EST_FVector &frame, float &power)
Definition: sigpr_frame.cc:472
void power(EST_Wave &sig, EST_Track &a, float factor)
Definition: sigpr_utt.cc:422
float lpredict(float *adc, int wsize, float *acf, float *ref, float *lpc, int order)
int ssize_t
int fastFFT(EST_FVector &invec)
Fast FFT An optimised implementation by Tony Robinson to be used in preference to slowFFT...
Definition: fft.cc:256
float lpredict2(EST_FVector &adc, int wsize, EST_FVector &acf, float *ref, float *lpc, int order)
Definition: sigpr_frame.cc:488
void lsf2lpc(const EST_FVector &lpc, EST_FVector &lsf)
Definition: sigpr_frame.cc:399
#define ALMOST1
Definition: sigpr_frame.cc:49
float Hz2Mel(float frequency_in_Hertz)
Definition: sigpr_frame.cc:790
void fbank2melcep(const EST_FVector &fbank_vec, EST_FVector &mfcc_vec, const float liftering_parameter, const bool include_c0)
Definition: sigpr_frame.cc:684
INLINE ssize_t length() const
number of items in vector.
Definition: EST_TVector.h:249
void sig2rms(EST_FVector &frame, float &rms_energy)
Definition: sigpr_frame.cc:481
void sig2fft(const EST_FVector &sig, EST_FVector &fft_vec, const bool use_power_rather_than_energy)
Definition: sigpr_frame.cc:590
void ref2logarea(const EST_FVector &ref, EST_FVector &logarea)
Definition: sigpr_frame.cc:267
void ref2truearea(const EST_FVector &ref, EST_FVector &area)
Definition: sigpr_frame.cc:282
#define EST_error
Definition: EST_error.h:104
f
Definition: EST_item_aux.cc:48
void convert2area(const EST_FVector &in_frame, const EST_String &in_type, EST_FVector &out_frame)
Definition: sigpr_frame.cc:107
float ogi_lpc(float *adc, int wsize, int order, float *acf, float *ref, float *lpc)
void ref2lpc(const EST_FVector &ref, EST_FVector &lpc)
Definition: sigpr_frame.cc:364
void convert2lpc(const EST_FVector &in_frame, const EST_String &in_type, EST_FVector &out_frame)
Definition: sigpr_frame.cc:69
#define PI
Definition: EST_Complex.h:48
void lpc2ref(const EST_FVector &lpc, EST_FVector &ref)
Definition: sigpr_frame.cc:340
void sig2fbank(const EST_FVector &sig, EST_FVector &fbank_frame, const float sample_rate, const bool use_power_rather_than_energy, const bool take_log)
Definition: sigpr_frame.cc:538
#define MAX_ABS_CEPS
Definition: sigpr_frame.cc:50
void convert2ref(const EST_FVector &in_frame, const EST_String &in_type, EST_FVector &out_frame)
Definition: sigpr_frame.cc:83
void lpc2lsf(const EST_FVector &lpc, EST_FVector &lsf)
Definition: sigpr_frame.cc:392
Extending buffer class.
Definition: EST_TBuffer.h:86
#define isnanf(N)
float sum(const EST_FMatrix &a)
sum of elements
Definition: vec_mat_aux.cc:147
void lpc2cep(const EST_FVector &lpc, EST_FVector &cep)
Definition: sigpr_frame.cc:291
float Mel2Hz(float frequency_in_Mel)
Definition: sigpr_frame.cc:795
void resize(int n, int set=1)
resize vector
void sig2lpc(const EST_FVector &sig, EST_FVector &acf, EST_FVector &ref, EST_FVector &xlpc)
Definition: sigpr_frame.cc:406