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
62static void regress(cepdata *rg, const cepdata *cp_buf, unsigned short frmind,
63                    int mel_dim);
64static void dd_regress(cepdata *dd, const cepdata *cp_buf, unsigned short frmind,
65                       int mel_dim);
66static 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);
69static 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
75static 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}
112static const cepdata deldel[] = {2, 0, -1, -2, -1, 0, 2};  /* delta - delta */
113
114void 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
152static 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
195static 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
222int 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