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
cepstrum_params(front_channel * channel,front_wave * waveobj,front_freq * freqobj,front_cep * cepobj)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
icostrans(cepdata * cs,cepdata fb[],cepdata cep[],int nf,int nc)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
mel_spectrum_correction(cepdata * fbo,cepdata * ch_gain,int nf)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
mel_loglookup_with_offset(front_cep * cepobj,front_channel * channel)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