1/*---------------------------------------------------------------------------*
2 *  wav_acc.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
22static const char wav_acc_c[] = "$Id: wav_acc.c,v 1.6.6.7 2007/10/15 18:06:24 dahan Exp $";
23
24#ifndef _RTT
25#include "pstdio.h"
26#endif
27#include <stdlib.h>
28#include <limits.h>
29#include <math.h>
30#include <string.h>
31#include "passert.h"
32#include "pendian.h"
33#include "portable.h"
34
35
36#ifndef _RTT
37#include "duk_io.h"
38#endif
39
40#include "sample.h"
41#include "mulaw.h"
42
43#include "portable.h"
44
45
46void create_sample_buffer(wave_info *wave, int frame_size, int window_size)
47{
48  ASSERT(wave);
49  ASSERT(frame_size > 0);
50  ASSERT(window_size >= frame_size);
51  wave->income = (samdata *) CALLOC(window_size, sizeof(samdata), "cfront.wave.income");
52  wave->outgo = (samdata *) CALLOC(window_size, sizeof(samdata), "cfront.wave.outgo");
53  wave->window_size = window_size;
54  wave->frame_size = frame_size;
55#if DEBUG
56  log_report("window %d frame %d\n", window_size, frame_size);
57#endif
58  return;
59}
60
61void free_sample_buffer(wave_info *wave)
62{
63  ASSERT(wave);
64  if (wave->income)
65    FREE((char *)wave->income);
66  if (wave->outgo)
67    FREE((char *)wave->outgo);
68  wave->income = NULL;
69  wave->outgo = NULL;
70  wave->window_size = 0;
71  wave->frame_size = 0;
72  return;
73}
74
75void reset_sig_check(wave_stats *ws)
76/*
77**  Resets the wave statistics
78*/
79{
80  int ii;
81
82  ASSERT(ws);
83
84  ws->sum  = 0;
85  ws->sum2 = 0;
86  ws->sumsqu = 0;
87  ws->sumsqu2 = 0;
88  ws->nsam = 0;
89  ws->highclip = 0;
90  ws->lowclip = 0;
91
92  for (ii = 0; ii < MAXHISTBITS; ii++)
93    ws->bithist[ii] = 0;
94}
95
96#define OVERFLOW_MASK 0x40000000
97
98void get_sig_check(wave_stats *ws, int *nsam, int *pclowclip, int *pchighclip,
99                   int *dc_offset, int *amp, int *pc5, int *pc95,
100                   int *overflow)
101/*
102**  Returns the wave statistics
103*/
104{
105  float mean;
106  int num;
107  int ntot;
108  int npc;
109  int ii;
110  float sqr_devn;
111
112  ASSERT(ws);
113
114  /* *nsam = ws->nsam / 100; */
115  *nsam = ws->nsam;
116
117  *overflow = 0;
118
119  if (ws->nsam == 0)
120  {
121    *pclowclip  = 0;
122    *pchighclip = 0;
123    *dc_offset  = 0;
124    *amp        = 0;
125    *pc5 = 0;
126    *pc95 = 0;
127    return;
128  }
129
130  if (ws->nsam > OVERFLOW_MASK) *overflow = 1;
131
132  *pclowclip  = (int)(((float)ws->lowclip  * 10000.0) / (float)ws->nsam);
133  *pchighclip = (int)(((float)ws->highclip * 10000.0) / (float)ws->nsam);
134
135  mean = ((float)ws->sum + (float)ws->sum2 * OVERFLOW_MASK) / ws->nsam;
136
137  *dc_offset = (int) mean;
138  sqr_devn = (((float)ws->sumsqu + (float)ws->sumsqu2 * OVERFLOW_MASK)
139              / (float)ws->nsam) - (mean * mean);
140  *amp = integer_square_root((int)sqr_devn);
141
142  /* now analyse the histogram */
143
144  num = 0;
145  for (ii = 0; ii < MAXHISTBITS; ii++)
146  {
147    num += ws->bithist[ii];
148  }
149
150  ntot = num;
151  npc = ntot / 20; /* 5% cutoff */
152
153  for (ii = num = 0; (ii < MAXHISTBITS) && (num < npc); ii++)
154  {
155    num += ws->bithist[ii];
156  }
157
158  *pc5 = ii;
159
160  npc = (int)(0.95 * ntot);  /* 95% cutoff */
161
162  for (ii = num = 0; (ii < MAXHISTBITS) && (num < npc); ii++)
163  {
164    num += ws->bithist[ii];
165  }
166
167  *pc95 = ii;
168  return;
169}
170
171void acc_wave_stats(wave_info* wave)
172/*
173**  Updates the wave statistics
174*/
175{
176  int ii;
177  int val;
178  samdata hclip;
179  samdata lclip;
180  wave_stats *ws;
181  int sumabs;
182  int num;
183
184  ASSERT(wave);
185
186  ws = &wave->stats;
187  hclip = ws->highclip_level;
188  lclip = ws->lowclip_level;
189
190  if (ws->nsam > OVERFLOW_MASK) return;
191  /* as soon as we have at least 1073741824 */
192  /* samples, stop accumulating.   */
193
194  sumabs = 0;
195  num = 0;
196
197  for (ii = 0; ii < wave->num_samples; ii++)
198  {
199    val = (int) wave->income[ii];
200    ws->sum += val;
201    ws->sumsqu += val * val;
202    if (ws->sumsqu > OVERFLOW_MASK)
203    {
204      ws->sumsqu -= OVERFLOW_MASK;
205      ws->sumsqu2++;
206    }
207    /* nasty bit here as ANSI C does not do >32bit */
208    /* Assumes that samples are no larger than */
209    /* signed shorts    */
210
211    ws->nsam++;
212
213    if (val >= hclip) ws->highclip++;
214    if (val <= lclip) ws->lowclip++;
215
216    sumabs += abs(val);
217    num++;
218  }
219
220  if (ws->sum >= OVERFLOW_MASK)
221  {
222    ws->sum -= OVERFLOW_MASK;
223    ws->sum2++;
224  }
225  else if (ws->sum < -OVERFLOW_MASK)
226  {
227    ws->sum += OVERFLOW_MASK;
228    ws->sum2--;
229  }
230  /* another >32bit workaround  */
231  /* assumes wave->num_samples < 32878 */
232  /* this is really overkill as we expect */
233  /* the mean to be around zero anyway */
234
235  if (num > 0) sumabs /= num;
236  ii = 0;
237  while (sumabs)
238  {
239    sumabs >>= 1;
240    ii++;
241  }
242
243  ASSERT(ii <= 16); /* unusual case i=16 if all samples -32678 */
244  ws->bithist[ii]++;
245  return;
246}
247