Edinburgh Speech Tools  2.1-release
pcb_smoother.cc
Go to the documentation of this file.
1 /*************************************************************************/
2 /* */
3 /* Centre for Speech Technology Research */
4 /* University of Edinburgh, UK */
5 /* Copyright (c) 1997 */
6 /* All Rights Reserved. */
7 /* */
8 /* Permission is hereby granted, free of charge, to use and distribute */
9 /* this software and its documentation without restriction, including */
10 /* without limitation the rights to use, copy, modify, merge, publish, */
11 /* distribute, sublicense, and/or sell copies of this work, and to */
12 /* permit persons to whom this work is furnished to do so, subject to */
13 /* the following conditions: */
14 /* 1. The code must retain the above copyright notice, this list of */
15 /* conditions and the following disclaimer. */
16 /* 2. Any modifications must be clearly marked as such. */
17 /* 3. Original authors' names are not deleted. */
18 /* 4. The authors' names are not used to endorse or promote products */
19 /* derived from this software without specific prior written */
20 /* permission. */
21 /* */
22 /* THE UNIVERSITY OF EDINBURGH AND THE CONTRIBUTORS TO THIS WORK */
23 /* DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING */
24 /* ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT */
25 /* SHALL THE UNIVERSITY OF EDINBURGH NOR THE CONTRIBUTORS BE LIABLE */
26 /* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES */
27 /* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN */
28 /* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, */
29 /* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF */
30 /* THIS SOFTWARE. */
31 /* */
32 /*************************************************************************/
33 /* Author : Paul Bagshaw */
34 /* Date : 1993 */
35 /*-----------------------------------------------------------------------*/
36 /* */
37 /* The above copyright was given by Paul Bagshaw, he retains */
38 /* his original rights */
39 /* */
40 /*************************************************************************/
41 #include <cmath>
42 #include <cstdio>
43 #include "array_smoother.h"
44 #include "EST_cutils.h"
45 
46 #define MAX_LEN 127
47 
48 #define MODULE "array_smoother"
49 
50 float median (int *counter, float valin, float valbuf[], int lmed, int mmed);
51 float hanning (int *counter, float valin, float valhan[], float win_coeff[],
52  struct Ms_Op *ms);
53 void mk_window_coeffs (int length, float win_coeff[]);
54 
55 struct Ms_Op *default_ms_op(struct Ms_Op *ms);
56 
57 void array_smoother (float *p_array, int arraylen, struct Ms_Op *ms)
58 {
59  int i, j, mid1, mid2 = 0, filler, nloops;
60  int C1, C2 = 0, C3 = 0, C4 = 0, c1, c2, c3, c4;
61  int delay, delx = 0, dely = 0;
62  int in = 0, out = 0;
63  float input, output;
64  float *inarray;
65  float medbuf1[MAX_LEN] = {};
66  float medbuf2[MAX_LEN] = {};
67  float hanbuf1[MAX_LEN] = {};
68  float hanbuf2[MAX_LEN] = {};
69  float win_coeffs[MAX_LEN] = {};
70  float medval1, medval2, hanval1, hanval2, zatn;
71  float *xdel, *ydel;
72  bool newms = false; /* if ms has to be deleted, then true */
73  xdel = new float[2*MAX_LEN-2]();
74  ydel = new float[2*MAX_LEN-2]();
75  inarray = new float[arraylen];
76  for (i = 0; i < arraylen; ++i)
77  inarray[i] = p_array[i];
78 
79  if (ms == NULL)
80  {
81  ms = new Ms_Op;
82  default_ms_op(ms);
83  newms = true;
84  }
85 
86  mk_window_coeffs (ms->window_length, win_coeffs);
87  /* determine the size and delay of each stage concerned */
88  mid1 = ms->first_median / 2;
89  C1 = delay = ms->first_median - 1;
90  if (ms->apply_hanning)
91  {
92  C2 = ms->window_length - 1;
93  delay = ms->first_median + ms->window_length - 2;
94  }
95  if (ms->smooth_double) {
96  mid2 = ms->second_median / 2;
97  C3 = ms->second_median - 1;
98  if (!ms->apply_hanning) {
99  delx = ms->first_median;
100  dely = ms->second_median;
101  }
102  else {
103  C4 = ms->window_length - 1;
104  delx = ms->first_median + ms->window_length - 1;
105  dely = ms->second_median + ms->window_length - 1;
106  }
107  delay = delx + dely - 2;
108  }
109  /* prepare for smoothing */
110  c1 = C1;
111  c2 = C2;
112  c3 = C3;
113  c4 = C4;
114  if (!ms->extrapolate) {
115  /* pad with breakers at the beginning */
116  for (i = 0; i < delay / 2; i++)
117  p_array[out++] = ms->breaker;
118  filler = 0;
119  nloops = arraylen;
120  }
121  else {
122  /* extrapolate by initialising filter with dummy breakers */
123  filler = delay / 2;
124  nloops = arraylen + delay;
125  }
126  /* smooth track element by track element */
127  for (j = 0; j < nloops; j++)
128  {
129  if (j < filler || j >= nloops - filler)
130  input = ms->breaker;
131  else
132  input = inarray[in++];
133 
134  /* store input value if double smoothing */
135  if (ms->smooth_double) {
136  for (i = delx - 1; i > 0; i--)
137  xdel[i] = xdel[i - 1];
138  xdel[0] = input;
139  }
140  /* first median smoothing */
141 
142  medval1 = median (&c1, input, medbuf1, ms->first_median, mid1);
143 
144  if (c1 == -1)
145  {
146  output = medval1;
147  /* first hanning window (optional) */
148  if (ms->apply_hanning)
149  {
150  hanval1 = hanning (&c2, medval1, hanbuf1, win_coeffs, ms);
151  if (c2 == -1)
152  output = hanval1;
153  else
154  continue;
155  }
156  /* procedures for double smoothing (optional) */
157  if (ms->smooth_double)
158  {
159  /* compute rough component z(n) */
160  if (output != ms->breaker && xdel[delx - 1]
161  != ms->breaker)
162  zatn = xdel[delx - 1] - output;
163  else
164  zatn = ms->breaker;
165  /* store results of first smoothing */
166  for (i = dely - 1; i > 0; i--)
167  ydel[i] = ydel[i - 1];
168  ydel[0] = output;
169  /* second median smoothing */
170  medval2 = median (&c3, zatn, medbuf2,
171  ms->second_median, mid2);
172  if (c3 == -1)
173  {
174  output = medval2;
175  /* second hanning smoothing (optional) */
176  if (ms->apply_hanning) {
177  hanval2 = hanning (&c4, medval2, hanbuf2,
178  win_coeffs, ms);
179  if (c4 == -1)
180  output = hanval2;
181  else
182  continue;
183  }
184  if (output != ms->breaker && ydel[dely - 1]
185  != ms->breaker)
186  output += ydel[dely - 1];
187  else
188  output = ms->breaker;
189  }
190  else
191  continue;
192  }
193  /* write filtered result */
194  p_array[out++] = output;
195  }
196  }
197  if (!ms->extrapolate) /* pad with breakers at the end */
198  for (i = 0; i < delay / 2; i++)
199  p_array[out++] = ms->breaker;
200 
201  if (newms) delete ms;
202  delete[] inarray;
203  delete[] xdel;
204  delete[] ydel;
205 }
206 
207 float median (int *counter, float valin, float valbuf[], int lmed, int mmed)
208 {
209  int i, j;
210  float tmp, filmed[MAX_LEN];
211 
212  for (i = lmed - 1; i > 0; i--)
213  valbuf[i] = valbuf[i - 1];
214  valbuf[0] = valin;
215 
216  if (*counter > 0)
217  {
218  (*counter)--;
219  return (0.0);
220  }
221  else
222  {
223  *counter = -1;
224 
225  for (i = 0; i < lmed; i++)
226  filmed[i] = valbuf[i];
227 
228  for (j = lmed - 1; j > 0; j--)
229  for (i = 0; i < j; i++)
230  if (filmed[i] > filmed[i + 1])
231  {
232  tmp = filmed[i + 1];
233  filmed[i + 1] = filmed[i];
234  filmed[i] = tmp;
235  }
236  return (filmed[mmed]);
237  }
238 
239 }
240 
241 #define TWO_PI 6.28318530717958647698
242 
243 void mk_window_coeffs (int length, float win_coeff[])
244 {
245  int i;
246  double x;
247 
248  for (i = 0; i < length; i++) {
249  x = TWO_PI * (i + 1.0) / (length + 1.0);
250  win_coeff[i] = (1.0 - (float) cos (x)) / (length + 1.0);
251  }
252 
253 }
254 
255 float hanning (int *counter, float valin, float valhan[], float win_coeff[],
256  struct Ms_Op *par)
257 {
258  int i, j, k = 0;
259  float valout = 0.0, weight[MAX_LEN];
260 
261  for (i = par->window_length - 1; i > 0; i--)
262  valhan[i] = valhan[i - 1];
263  valhan[0] = valin;
264  if (*counter > 0) {
265  (*counter)--;
266  return (0.0);
267  }
268  else {
269  *counter = -1;
270  for (i = 0; i < par->window_length; i++)
271  if (valhan[i] == par->breaker)
272  k++;
273  if (!k) {
274  for (i = 0; i < par->window_length; i++)
275  valout += valhan[i] * win_coeff[i];
276  }
277  else if (k <= par->window_length / 2 && par->extrapolate) {
278  mk_window_coeffs (par->window_length - k, weight);
279  for (i = 0, j = 0; i < par->window_length; i++)
280  if (valhan[i] != par->breaker)
281  valout += valhan[i] * weight[j++];
282  }
283  else
284  valout = par->breaker;
285  return (valout);
286  }
287 }
288 
289 void initialise_parameters (struct Ms_Op *p_par)
290 {
291  p_par->smooth_double = 0;
292  p_par->apply_hanning = 0;
293  p_par->extrapolate = 0;
294  p_par->window_length = DEFAULT_WLEN;
295  p_par->first_median = DEFAULT_MED_1;
296  p_par->second_median = DEFAULT_MED_2;
297  return;
298 }
299 
300 struct Ms_Op *default_ms_op(struct Ms_Op *ms)
301 {
302  ms->smooth_double = FALSE;
303  ms->apply_hanning = TRUE;
304  ms->extrapolate = TRUE;
305  ms->first_median = 11;
306  ms->second_median = 1;
307  ms->window_length = 7;
308  ms->breaker = -1.0;
309  return (ms);
310 }
float hanning(int *counter, float valin, float valhan[], float win_coeff[], struct Ms_Op *ms)
int first_median
void mk_window_coeffs(int length, float win_coeff[])
float breaker
#define TWO_PI
void initialise_parameters(struct Ms_Op *p_par)
struct Ms_Op * default_ms_op(struct Ms_Op *ms)
#define DEFAULT_WLEN
float median(int *counter, float valin, float valbuf[], int lmed, int mmed)
#define FALSE
Definition: EST_bool.h:119
int apply_hanning
NULL
Definition: EST_WFST.cc:55
int second_median
int smooth_double
#define DEFAULT_MED_2
int window_length
#define DEFAULT_MED_1
#define TRUE
Definition: EST_bool.h:118
int extrapolate
#define MAX_LEN
Definition: pcb_smoother.cc:46
void array_smoother(float *p_array, int arraylen, struct Ms_Op *ms)
Definition: pcb_smoother.cc:57