1/*---------------------------------------------------------------------------*
2 *  ca_wave.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 * CA_Wave Methods
22 ************************************************************************/
23
24#ifndef _RTT
25#include <stdio.h>
26#endif
27#include <stdlib.h>
28#include <string.h>
29#include <limits.h>
30
31#ifdef unix
32#include <unistd.h>
33#endif
34#include <assert.h>
35
36
37#include "frontapi.h"
38#include "portable.h"
39
40/* CA_Wave functions. See simpars.c for frontend params */
41
42CA_Wave *CA_AllocateWave(char type)
43{
44  CA_Wave *hWave = NULL;
45  TRY_CA_EXCEPT
46  hWave = (CA_Wave *) CALLOC_CLR(1, sizeof(CA_Wave), "cfront.hWave");
47#ifndef _RTT
48  hWave->data.device.file.typ = type;
49#endif
50  hWave->data.channel = create_channel_object();
51  hWave->is_configured = False;
52  hWave->is_configuredForVoicing = False;
53  hWave->ca_rtti = CA_WAVE_SIGNATURE;
54  return (hWave);
55
56  BEG_CATCH_CA_EXCEPT;
57  END_CATCH_CA_EXCEPT(hWave);
58}
59
60void CA_ConfigureWave(CA_Wave *hWave, CA_Frontend *hFrontend)
61{
62  TRY_CA_EXCEPT
63  ASSERT(hWave);
64  ASSERT(hFrontend);
65  ASSERT(FRAMERATE > 0);
66
67  if (hFrontend->is_configured == False)
68    SERVICE_ERROR(UNCONFIGURED_FRONTEND);
69  if (hWave->is_configured == True)
70    SERVICE_ERROR(CONFIGURED_WAVE);
71
72  ASSERT(hFrontend->config->waveobj->samplerate);
73
74  hWave->data.scale  = hFrontend->src_scale;
75  hWave->data.offset = hFrontend->offset;
76  setup_channel_object(hWave->data.channel, hFrontend->config->waveobj,
77                       hFrontend->config->freqobj,
78                       hFrontend->config->cepobj);
79
80  hWave->data.samplerate = hFrontend->config->waveobj->samplerate;
81
82  /* Buffer size is set to one frame's worth of data */
83  create_sample_buffer(&hWave->data,
84                       hFrontend->config->waveobj->samplerate / FRAMERATE,
85                       hFrontend->config->freqobj->window_length);
86
87  hWave->data.stats.highclip_level = hFrontend->config->waveobj->high_clip;
88  hWave->data.stats.lowclip_level  = hFrontend->config->waveobj->low_clip;
89  hWave->data.stats.max_per10000_clip =
90    hFrontend->config->waveobj->max_per10000_clip;
91  hWave->data.stats.max_dc_offset =
92    hFrontend->config->waveobj->max_dc_offset;
93  hWave->data.stats.high_noise_level_bit =
94    hFrontend->config->waveobj->high_noise_level_bit;
95  hWave->data.stats.low_speech_level_bit =
96    hFrontend->config->waveobj->low_speech_level_bit;
97  hWave->data.stats.min_samples =
98    hFrontend->config->waveobj->min_samples;
99
100  hWave->is_configured = True;
101  return;
102
103  BEG_CATCH_CA_EXCEPT;
104  END_CATCH_CA_EXCEPT(hWave);
105}
106
107void CA_ConfigureVoicingAnalysis(CA_Wave *hWave, CA_FrontendInputParams *hFrontPar)
108{
109  TRY_CA_EXCEPT
110
111  hWave->voice.margin = hFrontPar->voice_margin;
112  hWave->voice.fast_margin = hFrontPar->fast_voice_margin;
113  hWave->voice.quiet_margin = hFrontPar->tracker_margin;
114  hWave->voice.voice_duration = hFrontPar->voice_duration;
115  hWave->voice.quiet_duration = hFrontPar->quiet_duration;
116  hWave->is_configuredForVoicing = True;
117  return;
118
119  BEG_CATCH_CA_EXCEPT
120  END_CATCH_CA_EXCEPT(hWave)
121}
122
123void CA_UnconfigureWave(CA_Wave *hWave)
124{
125  TRY_CA_EXCEPT
126  ASSERT(hWave);
127  if (hWave->is_configured == False)
128    SERVICE_ERROR(UNCONFIGURED_WAVE);
129
130  clear_channel_object(hWave->data.channel);
131  free_sample_buffer(&hWave->data);
132  hWave->data.samplerate = 0;
133
134  hWave->is_configured = False;
135
136/* The following is not correct in this place as it does not match where it is set to TRUE.
137 * This is needed for the sample rate change function.
138 * hWave->is_configuredForVoicing = False;
139 */
140  BEG_CATCH_CA_EXCEPT;
141  END_CATCH_CA_EXCEPT(hWave);
142}
143
144void CA_FreeWave(CA_Wave *hWave)
145{
146  TRY_CA_EXCEPT
147  ASSERT(hWave);
148
149  if (hWave->is_configured == True)
150    SERVICE_ERROR(CONFIGURED_WAVE);
151
152  delete_channel_object(hWave->data.channel);
153  FREE((char *) hWave);
154  return;
155  BEG_CATCH_CA_EXCEPT;
156  END_CATCH_CA_EXCEPT(hWave);
157}
158
159int CA_OpenWaveFromDevice(CA_Wave *hWave,
160                          int wave_type,
161                          int samplerate,
162                          int device_id,
163                          int device_type)
164{
165  TRY_CA_EXCEPT
166  ASSERT(hWave);
167  ASSERT(device_id >= 0);
168  ASSERT(device_type == WAVE_DEVICE_RAW);
169
170  if (hWave->is_configured == False)
171    SERVICE_ERROR(UNCONFIGURED_WAVE);
172  if (hWave->is_configuredForVoicing == False)
173    SERVICE_ERROR(UNCONFIGURED_WAVE);
174
175  reset_channel_object(hWave->data.channel);
176  hWave->data.wave_type = wave_type;
177  hWave->data.device_type = device_type;
178  hWave->data.device.ext.op = WAVE_DEVICE_INPUT;
179  hWave->data.samplerate = samplerate;
180  init_voicing_analysis(&hWave->voice);
181
182  reset_sig_check(&hWave->data.stats);
183  hWave->data.do_stats = ESR_TRUE;
184
185  return (True);
186  BEG_CATCH_CA_EXCEPT;
187  END_CATCH_CA_EXCEPT(hWave);
188}
189
190
191ESR_BOOL CA_DoSignalCheck(CA_Wave *hWave,
192                     ESR_BOOL *clipping,
193                     ESR_BOOL *dcoffset,
194                     ESR_BOOL *highnoise,
195                     ESR_BOOL *quietspeech,
196                     ESR_BOOL *too_few_samples,
197                     ESR_BOOL *too_many_samples)
198{
199  TRY_CA_EXCEPT
200
201  int nsam;
202  int pclowclip;
203  int pchighclip;
204  int dc_offset;
205  int amp;
206  int pc5;
207  int pc95;
208  int overflow;
209  ESR_BOOL error;
210  wave_stats *ws;
211
212  ASSERT(hWave);
213
214  ws = &hWave->data.stats;
215  get_sig_check(ws, &nsam, &pclowclip, &pchighclip, &dc_offset, &amp,
216                &pc5, &pc95, &overflow);
217
218  if ((pclowclip + pchighclip) > ws->max_per10000_clip)
219    *clipping = ESR_TRUE;
220  else     *clipping = ESR_FALSE;
221  if (abs(dc_offset) > ws->max_dc_offset) *dcoffset = ESR_TRUE;
222  else     *dcoffset = ESR_FALSE;
223  if (pc5 >= ws->high_noise_level_bit) *highnoise = ESR_TRUE;
224  else     *highnoise = ESR_FALSE;
225  if (pc95 < ws->low_speech_level_bit) *quietspeech = ESR_TRUE;
226  else     *quietspeech = ESR_FALSE;
227  if (nsam < ws->min_samples)  *too_few_samples = ESR_TRUE;
228  else     *too_few_samples = ESR_FALSE;
229  if (overflow)    *too_many_samples = ESR_TRUE;
230  else     *too_many_samples = ESR_FALSE;
231
232  /* This is better than casting the logical expression to ESR_BOOL */
233  if (*clipping || *dcoffset || *highnoise || *quietspeech || *too_few_samples || *too_many_samples)
234  	error = ESR_TRUE;
235  else
236  	error = ESR_FALSE;
237
238  return(error);
239
240  BEG_CATCH_CA_EXCEPT
241  END_CATCH_CA_EXCEPT(hWave)
242}
243
244void CA_CloseDevice(CA_Wave *hWave)
245{
246  TRY_CA_EXCEPT
247  if (hWave->is_configured == False)
248    SERVICE_ERROR(UNCONFIGURED_WAVE);
249
250  ASSERT(hWave->data.device.ext.op == WAVE_DEVICE_INPUT);  /* because I don't have output yet! */
251
252  return;
253  BEG_CATCH_CA_EXCEPT;
254  END_CATCH_CA_EXCEPT(hWave);
255}
256
257
258int CA_LoadSamples(CA_Wave *hWave,
259                   samdata *pPCMData,
260                   int sampleCount)
261{
262  ASSERT(hWave);
263  ASSERT(pPCMData);
264
265  TRY_CA_EXCEPT
266  if (hWave->is_configured == False)
267    SERVICE_ERROR(UNCONFIGURED_WAVE);
268  if (hWave->data.device_type != WAVE_DEVICE_RAW)
269    SERVICE_ERROR(BAD_WAV_DEVICE);
270  if (hWave->data.window_size < sampleCount)
271    SERVICE_ERROR(INCORRECT_SAMPLERATE);
272
273  memcpy(hWave->data.income,
274         pPCMData,
275         sampleCount * sizeof(samdata));
276
277  hWave->data.num_samples = sampleCount;
278
279  if (hWave->data.do_stats)
280    acc_wave_stats(&hWave->data);
281
282  return (True);
283  BEG_CATCH_CA_EXCEPT;
284  END_CATCH_CA_EXCEPT(hWave);
285}
286
287void CA_ConditionSamples(CA_Wave *hWave)
288{
289  TRY_CA_EXCEPT
290  int ii;
291
292  if (hWave->is_configured == False)
293    SERVICE_ERROR(UNCONFIGURED_WAVE);
294
295  if (hWave->data.offset != 0)
296    for (ii = 0; ii < hWave->data.num_samples; ii++)
297      hWave->data.income[ii] = RANGE(hWave->data.income[ii] +
298                                     hWave->data.offset, SHRT_MIN, SHRT_MAX);
299  if (hWave->data.scale != 1.0)
300    for (ii = 0; ii < hWave->data.num_samples; ii++)
301      hWave->data.income[ii] = (short) RANGE(hWave->data.income[ii] *
302                                             hWave->data.scale, SHRT_MIN, SHRT_MAX);
303  return;
304  BEG_CATCH_CA_EXCEPT;
305  END_CATCH_CA_EXCEPT(hWave);
306}
307