1 /*---------------------------------------------------------------------------* 2 * chelmel4.c * 3 * * 4 * Copyright 2007, 2008 Nuance Communciations, Inc. * 5 * * 6 * Licensed under the Apache License, Version 2.0 (the 'License'); * 7 * you may not use this file except in compliance with the License. * 8 * * 9 * You may obtain a copy of the License at * 10 * http://www.apache.org/licenses/LICENSE-2.0 * 11 * * 12 * Unless required by applicable law or agreed to in writing, software * 13 * distributed under the License is distributed on an 'AS IS' BASIS, * 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * 15 * See the License for the specific language governing permissions and * 16 * limitations under the License. * 17 * * 18 *---------------------------------------------------------------------------*/ 19 20 21 22 #include <stdlib.h> 23 #ifndef _RTT 24 #include <stdio.h> 25 #endif 26 #include <string.h> 27 #include <math.h> 28 #include <limits.h> 29 #include <assert.h> 30 31 #include "hmm_desc.h" 32 #include "front.h" 33 #include "portable.h" 34 35 #define DEBUG 0 36 #define LOG_AS_PRINT 0 37 38 #define LPCMAX 100 39 40 41 #if LOG_AS_PRINT /* BP temp hack */ 42 #define log_report printf 43 #endif 44 45 #include "sh_down.h" 46 47 48 /* cepstrum_params has been broken into three functions: 49 filterbank_emulation - does preemp, window, fft and filtbank 50 gain_adjustment - estimates gain 51 cepstrum_params - does gain adj.(if on), spec corr and cos transform 52 This enables us to bypass gain adjustment. 53 */ 54 55 //static void mel_cuberoot_offset(cepdata *fbo, cepdata *ch_off, int nf); 56 #if SPEC_CORRECT 57 static void mel_spectrum_correction(cepdata *fbo, cepdata *ch_gain, int nf); 58 #endif 59 static void mel_loglookup_with_offset(front_cep *cepobj, 60 front_channel *channel); 61 //static void mel_exp(cepdata *fbo, int nf); 62 //static void durbin(cepdata *a, cepdata *r, int n); 63 //static void lpc_to_cepstral_recursion(cepdata *c, cepdata *a, int nc, int n); 64 static void icostrans(cepdata *cs, cepdata fb[], cepdata cep[], int nf, int nc); 65 66 67 void cepstrum_params(front_channel *channel, front_wave *waveobj, 68 front_freq *freqobj, front_cep *cepobj) 69 { 70 #if SPEC_CORRECT 71 /* 2.30 Apply a spectrum correction */ 72 if (cepobj->mel_loop) 73 mel_spectrum_correction(freqobj->filterbank, cepobj->mel_loop, channel->num_freq); 74 #endif 75 /* 2.33 Calculate log dB energy values */ 76 mel_loglookup_with_offset(cepobj, channel); 77 #if DEBUG 78 log_report("Filterbank output: "); 79 write_scaled_frames(freqobj->nf, 1, channel->filterbank, D_FIXED, 1 / (float)LOG_SCALE); 80 #endif 81 82 /* 2.34 Cosine transformation */ 83 icostrans(cepobj->cs, channel->filterbank, channel->cep, 84 channel->num_freq, cepobj->mel_dim); 85 86 #if DEBUG 87 log_report("Cepstrum coefficients: "); 88 write_scaled_frames((cepobj->mel_dim + 1), 1, channel->cep, D_FIXED, (float)1 / (0x01 << (LOG_SCALE_SHIFT + COSINE_TABLE_SHIFT))); 89 #endif 90 return; 91 } 92 93 static void icostrans(cepdata *cs, cepdata fb[], cepdata cep[], int nf, int nc) 94 /* 95 ** inv rotated-cosine transform 96 ** ref Davis and Mermelstein, ASSP 1980 */ 97 { 98 int i, j; 99 cepdata *cp; 100 cepdata temp; 101 102 for (i = 0; i <= nc; i++) 103 { 104 cp = &cs[i*nf]; 105 for (j = 0, temp = 0; j < nf; j++) 106 temp += fb[j] * cp[j]; 107 cep[i] = temp; 108 } 109 return; 110 } 111 112 #if SPEC_CORRECT 113 static void mel_spectrum_correction(cepdata *fbo, cepdata *ch_gain, int nf) 114 /* 115 ** pwr spect -> filter bank output */ 116 { 117 int i; 118 119 for (i = 0;i < nf; i++) 120 fbo[i] = fbo[i] * ch_gain[i]; /* TODO: Fixedpt scale up and down */ 121 return; 122 } 123 #endif 124 125 static void mel_loglookup_with_offset(front_cep *cepobj, 126 front_channel *channel) 127 /* 128 ** pwr spect -> filter bank output */ 129 { 130 int ii; 131 132 if (channel->shift > 0) 133 for (ii = 0; ii < channel->num_freq; ii++) 134 { 135 channel->filterbank[ii] = (cepdata) log_lookup(&cepobj->logtab, 136 (int)(channel->filterbank[ii] + 137 SHIFT_DOWN(cepobj->mel_offset[ii], channel->shift)), 138 channel->shift); 139 } 140 else 141 for (ii = 0; ii < channel->num_freq; ii++) 142 { 143 channel->filterbank[ii] = (cepdata) log_lookup(&cepobj->logtab, 144 (int)(channel->filterbank[ii] + 145 SHIFT_UP(cepobj->mel_offset[ii], -channel->shift)), 146 channel->shift); 147 } 148 149 return; 150 } 151 152 //static void mel_exp(cepdata *fbo, int nf) 153 ///* 154 //** pwr spect -> filter bank output */ 155 //{ 156 // int i; 157 // for (i = 0; i < nf; i++) 158 // { 159 // fbo[i] = (cepdata) exp((double) fbo[i]); 160 // } 161 // return; 162 //} 163 // 164 //static void durbin( 165 // cepdata *a, /* lpc coefficients */ 166 // cepdata *r, /* autocorrelation coefficients */ 167 // int n) /* order of lpc analysis */ 168 //{ 169 // int i, j; 170 // cepdata A[LPCMAX+1][LPCMAX+1], sum; 171 // cepdata k[LPCMAX+1]; 172 // cepdata e[LPCMAX+1]; 173 // 174 // e[0] = r[0]; 175 // for (i = 1; i <= n; i++) 176 // { 177 // sum = 0; 178 // for (j = 1; j <= (i - 1); j++) 179 // { 180 // sum += A[j][i-1] * r[i-j]; 181 // } 182 // k[i] = -(r[i] + sum) / e[i-1]; 183 // A[i][i] = k[i] ; 184 // for (j = 1; j <= (i - 1); j++) 185 // { 186 // A[j][i] = A[j][i-1] + k[i] * A[i-j][i-1]; 187 // } 188 // e[i] = (1 - k[i] * k[i]) * e[i-1]; 189 // } 190 // for (j = 1 ; j <= n; j++) 191 // { 192 // a[j] = A[j][n]; 193 // } 194 // 195 // a[0] = (cepdata) 1.0 ; 196 // return; 197 //} 198 // 199 //static void lpc_to_cepstral_recursion( 200 // cepdata *c, /* cepstral coefficients */ 201 // cepdata *a, /* lpc coeffiecients */ 202 // int nc, /* order of cepstra */ 203 // int n) /* order of lpc */ 204 //{ 205 // int k, i; 206 // cepdata sum; 207 // 208 // ASSERT(nc < LPCMAX); 209 // 210 // for (i = n + 1; i <= nc; i++) 211 // { 212 // a[i] = (cepdata) 0.0; 213 // } 214 // /* if lpc order less */ 215 // /* than cepstral order */ 216 // /* define higher lpccos */ 217 // 218 // for (i = 1; i <= nc; i++) 219 // { 220 // sum = (cepdata) 0.0; 221 // for (k = 1; k <= (i - 1); k++) 222 // { 223 // sum = sum + k * c[k] * a[i-k]; /* TODO: fixedpt range for mult */ 224 // } 225 // c[i] = -a[i] - (sum / i); /* cepstral calculated */ 226 // /* to <=nc in icostrans */ 227 // /* so I shall do the */ /* same here */ 228 // } 229 //} 230 231