1 /*---------------------------------------------------------------------------*
2 * cheldsp4.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 #include <stdlib.h>
22 #include <limits.h>
23 #ifndef _RTT
24 #include <stdio.h>
25 #endif
26 #include <string.h>
27 #include <math.h>
28 #include <assert.h>
29
30
31 #include "hmm_desc.h"
32 #include "voicing.h"
33 #include "specnorm.h"
34 #include "portable.h"
35 #include "front.h"
36 #include "portable.h"
37
38 #include "sh_down.h"
39 #include "memmove.h"
40
41
42 #define DEBUG 0
43 #define LOG_AS_PRINT 0
44
45
46 #if LOG_AS_PRINT /* BP temp debug mode */
47 #define log_report printf
48 #endif
49
50
51
52 /* Rasta */
53 #define RASTA_SOFT_START 1 /* if this is not 1, rasta initialization is weighted */
54
55 #if RASTA_SOFT_START
56 #define RASTA_CONSTANT 0.92
57 #define RASTA_SOFT_CONST (RASTA_CONSTANT/(1-RASTA_CONSTANT))
58 #else
59 #define RASTA_CONSTANT 0.85
60 #endif
61
62 static void regress(cepdata *rg, const cepdata *cp_buf, unsigned short frmind,
63 int mel_dim);
64 static void dd_regress(cepdata *dd, const cepdata *cp_buf, unsigned short frmind,
65 int mel_dim);
66 static void scale_data(const front_cep *cepobj, const featdata *rpram, featdata *pram1,
67 featdata *pram2, featdata *ddpram, const cepdata *rast,
68 const cepdata *cep, const cepdata *rcep, const cepdata *ddcep);
69 static void pack_frame(const front_cep *cepobj, featdata *dest_frame,
70 const featdata *rasta_data, const featdata *mel_data,
71 const featdata *del_data, const featdata *deldel_data);
72
73
74
regress(cepdata * rg,const cepdata * cp_buf,unsigned short frmind,int mel_dim)75 static void regress(cepdata *rg, const cepdata*cp_buf, unsigned short frmind,
76 int mel_dim)
77 {
78 int i, j, d;
79 cepdata val;
80 const cepdata* cpt;
81 /*
82 static cepdata a = (cepdata) 0.0;
83
84 if (a == (cepdata) 0.0)
85 {
86 for (j = 1; j <= DELTA; j++)
87 a += j * j;
88 a *= (cepdata) 2.0;
89 }
90 */
91 /* replace above code with the following constant */
92 cepdata a = (DELTA * (DELTA + 1) * (2 * DELTA + 1) / 6) * 2;
93 d = DELTA;
94 if (frmind < Q2 - 1)
95 {
96 cpt = cp_buf + (d - 1) * (mel_dim + 1);
97 for (i = 0; i <= mel_dim; i++, cpt++)
98 rg[i] = (cepdata) SHIFT_DOWN((*cpt - *(cpt + mel_dim + 1)), 1 + COSINE_TABLE_SHIFT); /* Shift does rounding. */
99 } /* reversed */
100 else
101 /* regression coefficients */
102 for (i = 0; i <= mel_dim; i++)
103 {
104 cpt = cp_buf + i;
105 val = (cepdata) 0.;
106 for (j = 0; j < Q2; j++, cpt += (mel_dim + 1))
107 val += (d - j) * SHIFT_DOWN(*cpt, 5); /* note d-j from j-d */
108 rg[i] = (cepdata) SHIFT_DOWN((bigdata)(val / a), COSINE_TABLE_SHIFT - 5); /* scale down the deltas here */
109 }
110 return;
111 }
112 static const cepdata deldel[] = {2, 0, -1, -2, -1, 0, 2}; /* delta - delta */
113
dd_regress(cepdata * dd,const cepdata * cp_buf,unsigned short frmind,int mel_dim)114 void dd_regress(cepdata *dd, const cepdata *cp_buf, unsigned short frmind, int mel_dim)
115 /*
116 ** Computes ALL delta delta mel cep pars. BP 8/96 */
117 {
118 int i, j, d;
119 cepdata val;
120 const cepdata *cpt;
121
122 d = DELTA;
123 if (frmind < Q2 - 1)
124 {
125 cpt = cp_buf + (mel_dim + 1);
126 for (i = 0;i <= mel_dim;i++)
127 {
128 dd[i] = (*(cpt + 2 * (mel_dim + 1) + i)
129 + *(cpt + i)
130 - 2 * (*(cpt + (mel_dim + 1) + i)));
131 /* Undo cosine table shifting */
132 dd[i] = (cepdata) SHIFT_DOWN((bigdata)(dd[i]), COSINE_TABLE_SHIFT);
133 }
134 }
135 else
136 {
137 /* DD coefficient*/
138 for (i = 0; i <= mel_dim; i++)
139 {
140 cpt = cp_buf + i;
141 val = (cepdata) 0.;
142 for (j = 0; j < Q2; j++, cpt += (mel_dim + 1))
143 val += deldel[j] * SHIFT_DOWN((*cpt), 4); /* Q2 frames forward, not around...? */
144 /* Watch out for overflows here */
145 dd[i] = (cepdata) SHIFT_DOWN((bigdata)(val), COSINE_TABLE_SHIFT - 4);
146 }
147 }
148 return;
149 }
150
151
scale_data(const front_cep * cepobj,const featdata * rpram,featdata * pram1,featdata * pram2,featdata * ddpram,const cepdata * rast,const cepdata * cep,const cepdata * rcep,const cepdata * ddcep)152 static void scale_data(const front_cep *cepobj, const featdata *rpram, featdata *pram1,
153 featdata *pram2, featdata *ddpram, const cepdata *rast,
154 const cepdata *cep, const cepdata *rcep, const cepdata *ddcep)
155 {
156 size_t i;
157 bigdata a;
158
159 if (pram1)
160 for (i = 0; i <= cepobj->mel_dim; i++)
161 {
162 /* Now take the costable scaling off the ceps. */
163 ASSERT((cepobj->melA_scale[i] *(float)SHIFT_DOWN(cep[i], COSINE_TABLE_SHIFT))
164 < LONG_MAX);
165 ASSERT((cepobj->melA_scale[i] *(float)SHIFT_DOWN(cep[i], COSINE_TABLE_SHIFT))
166 > -LONG_MAX);
167 a = (bigdata)(SHIFT_DOWN((bigdata)cepobj->melA_scale[i]
168 * (bigdata) SHIFT_DOWN(cep[i], COSINE_TABLE_SHIFT)
169 + (bigdata)cepobj->melB_scale[i], BYTERANGE_SHIFT + LOG_SCALE_SHIFT));
170 pram1[i] = (featdata) MAKEBYTE(a);
171 }
172 if (pram2)
173 for (i = 0; i <= cepobj->mel_dim; i++)
174 {
175 ASSERT((cepobj->dmelA_scale[i] *(float)rcep[i]) < LONG_MAX);
176 ASSERT((cepobj->dmelA_scale[i] *(float)rcep[i]) > -LONG_MAX);
177 a = (bigdata) SHIFT_DOWN((bigdata)cepobj->dmelA_scale[i] * (bigdata)rcep[i] +
178 (bigdata)cepobj->dmelB_scale[i], BYTERANGE_SHIFT + LOG_SCALE_SHIFT);
179 pram2[i] = (featdata) MAKEBYTE(a);
180 }
181
182 /* Double-deltas parameter scaling */
183 if (cepobj->do_dd_mel && ddpram)
184 for (i = 0; i <= cepobj->mel_dim; i++)
185 {
186 ASSERT((cepobj->ddmelA_scale[i] *(float)ddcep[i]) < LONG_MAX);
187 ASSERT((cepobj->ddmelA_scale[i] *(float)ddcep[i]) > -LONG_MAX);
188 a = (bigdata) SHIFT_DOWN((bigdata)cepobj->ddmelA_scale[i] * (bigdata)ddcep[i] +
189 (bigdata)cepobj->ddmelB_scale[i], BYTERANGE_SHIFT + LOG_SCALE_SHIFT);
190 ddpram[i] = (featdata) MAKEBYTE(a); /* sort out scaling of deldel? */
191 }
192 return;
193 }
194
pack_frame(const front_cep * cepobj,featdata * dest_frame,const featdata * rasta_data,const featdata * mel_data,const featdata * del_data,const featdata * deldel_data)195 static void pack_frame(const front_cep *cepobj, featdata *dest_frame,
196 const featdata *rasta_data, const featdata *mel_data,
197 const featdata *del_data, const featdata *deldel_data)
198 {
199 size_t ii, cnt;
200
201 cnt = 0;
202 for (ii = 0; ii < cepobj->mel_dim; ii++, cnt++)
203 dest_frame[cnt] = (featdata) mel_data[ii];
204 for (ii = 0; ii < cepobj->mel_dim; ii++, cnt++)
205 dest_frame[cnt] = (featdata) del_data[ii];
206 if (cepobj->do_dd_mel)
207 for (ii = 0; ii < cepobj->mel_dim; ii++, cnt++)
208 dest_frame[cnt] = (featdata) deldel_data[ii];
209
210 #if DEBUG
211 log_report("Frame: ");
212 for (ii = 0; ii < 24; ii++)
213 log_report("%d ", dest_frame[ii]);
214 if (cepobj->do_dd_mel)
215 for (ii = 0; ii < cepobj->mel_dim; ii++)
216 log_report("%d ", dest_frame[2*cepobj->mel_dim+ii]);
217 log_report("\n");
218 #endif
219 return;
220 }
221
make_std_frame(front_channel * channel,front_cep * cepobj,featdata * hFrame)222 int make_std_frame(front_channel *channel, front_cep *cepobj, featdata *hFrame)
223 {
224 featdata rpram[MAX_CEP_DIM+1], spram1[MAX_CEP_DIM+1], spram2[MAX_CEP_DIM+1], ddpram[MAX_CEP_DIM+1];
225 cepdata rgmcep[MAX_CEP_DIM+1]; /*regression MCEP coef. */
226 cepdata ddmcep[MAX_CEP_DIM+1]; /*del-del-MCEP coef. */
227 cepdata rastapar[MAX_CEP_DIM+1]; /*del-del-MCEP coef. */
228
229 channel->frame_valid = False;
230 if (channel->frame_count >= channel->frame_delay)
231 {
232 /* Part III. Delta Cepstrum calculations
233 */
234 regress(rgmcep, channel->cep, (unsigned short) channel->frame_count, channel->mel_dim);
235 if (cepobj->do_dd_mel)
236 dd_regress(ddmcep, channel->cep, (unsigned short) channel->frame_count, channel->mel_dim);
237 #if DEBUG
238 log_report("Cep before scaling: ");
239 write_scaled_frames(channel->mel_dim + 1, 1,
240 channel->cep + (DELTA) *(channel->mel_dim + 1),
241 D_FIXED, (float)1 / (0x01 << (LOG_SCALE_SHIFT + COSINE_TABLE_SHIFT)));
242 log_report("Delta Cep before scaling: ");
243 write_scaled_frames(channel->mel_dim + 1, 1, rgmcep, D_FIXED, (float)1 / (0x01 << LOG_SCALE_SHIFT));
244 log_report("DeltaDelta Cep before scaling: ");
245 write_scaled_frames(channel->mel_dim + 1, 1, ddmcep, D_FIXED, (float)1 / (0x01 << LOG_SCALE_SHIFT));
246 #endif
247 scale_data(cepobj, rpram, spram1, spram2, ddpram, rastapar,
248 channel->cep + (DELTA) *(channel->mel_dim + 1), rgmcep, ddmcep);
249 #if DEBUG
250 log_report("Cep after scaling: ");
251 write_frames(channel->mel_dim + 1, 1, spram1, D_CHAR);
252 log_report("Delta Cep after scaling: ");
253 write_frames(channel->mel_dim + 1, 1, spram2, D_CHAR);
254 log_report("DeltaDelta Cep after scaling: ");
255 write_frames(channel->mel_dim + 1, 1, ddpram, D_CHAR);
256 #endif
257 channel->frame_valid = True; /* True even if do_skip_even_frames, */
258 pack_frame(cepobj, hFrame, rpram, spram1, spram2, ddpram);
259 } /* >=DELTA */
260
261 channel->frame_count++;
262 return (channel->frame_valid);
263 }
264