Edinburgh Speech Tools 2.4-release
 
Loading...
Searching...
No Matches
pcb_smoother.cc
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
50float median (int *counter, float valin, float valbuf[], int lmed, int mmed);
51float hanning (int *counter, float valin, float valhan[], float win_coeff[],
52 struct Ms_Op *ms);
53void mk_window_coeffs (int length, float win_coeff[]);
54
55struct Ms_Op *default_ms_op(struct Ms_Op *ms);
56
57void 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 xdel[2 * MAX_LEN - 2], ydel[2 * MAX_LEN - 2];
66 float medbuf1[MAX_LEN], medbuf2[MAX_LEN];
67 float hanbuf1[MAX_LEN], hanbuf2[MAX_LEN], win_coeffs[MAX_LEN];
69
70 inarray = new float[arraylen];
71 for (i = 0; i < arraylen; ++i)
72 inarray[i] = p_array[i];
73
74 if (ms == NULL)
75 {
76 ms = new Ms_Op;
77 default_ms_op(ms);
78 }
79
80 mk_window_coeffs (ms->window_length, win_coeffs);
81 /* determine the size and delay of each stage concerned */
82 mid1 = ms->first_median / 2;
83 C1 = delay = ms->first_median - 1;
84 if (ms->apply_hanning)
85 {
86 C2 = ms->window_length - 1;
87 delay = ms->first_median + ms->window_length - 2;
88 }
89 if (ms->smooth_double) {
90 mid2 = ms->second_median / 2;
91 C3 = ms->second_median - 1;
92 if (!ms->apply_hanning) {
93 delx = ms->first_median;
94 dely = ms->second_median;
95 }
96 else {
97 C4 = ms->window_length - 1;
98 delx = ms->first_median + ms->window_length - 1;
99 dely = ms->second_median + ms->window_length - 1;
100 }
101 delay = delx + dely - 2;
102 }
103 /* prepare for smoothing */
104 c1 = C1;
105 c2 = C2;
106 c3 = C3;
107 c4 = C4;
108 if (!ms->extrapolate) {
109 /* pad with breakers at the beginning */
110 for (i = 0; i < delay / 2; i++)
111 p_array[out++] = ms->breaker;
112 filler = 0;
114 }
115 else {
116 /* extrapolate by initialising filter with dummy breakers */
117 filler = delay / 2;
119 }
120 /* smooth track element by track element */
121 for (j = 0; j < nloops; j++)
122 {
123 if (j < filler || j >= nloops - filler)
124 input = ms->breaker;
125 else
126 input = inarray[in++];
127
128 /* store input value if double smoothing */
129 if (ms->smooth_double) {
130 for (i = delx - 1; i > 0; i--)
131 xdel[i] = xdel[i - 1];
132 xdel[0] = input;
133 }
134 /* first median smoothing */
135
136 medval1 = median (&c1, input, medbuf1, ms->first_median, mid1);
137
138 if (c1 == -1)
139 {
140 output = medval1;
141 /* first hanning window (optional) */
142 if (ms->apply_hanning)
143 {
144 hanval1 = hanning (&c2, medval1, hanbuf1, win_coeffs, ms);
145 if (c2 == -1)
146 output = hanval1;
147 else
148 continue;
149 }
150 /* procedures for double smoothing (optional) */
151 if (ms->smooth_double)
152 {
153 /* compute rough component z(n) */
154 if (output != ms->breaker && xdel[delx - 1]
155 != ms->breaker)
156 zatn = xdel[delx - 1] - output;
157 else
158 zatn = ms->breaker;
159 /* store results of first smoothing */
160 for (i = dely - 1; i > 0; i--)
161 ydel[i] = ydel[i - 1];
162 ydel[0] = output;
163 /* second median smoothing */
164 medval2 = median (&c3, zatn, medbuf2,
165 ms->second_median, mid2);
166 if (c3 == -1)
167 {
168 output = medval2;
169 /* second hanning smoothing (optional) */
170 if (ms->apply_hanning) {
171 hanval2 = hanning (&c4, medval2, hanbuf2,
172 win_coeffs, ms);
173 if (c4 == -1)
174 output = hanval2;
175 else
176 continue;
177 }
178 if (output != ms->breaker && ydel[dely - 1]
179 != ms->breaker)
180 output += ydel[dely - 1];
181 else
182 output = ms->breaker;
183 }
184 else
185 continue;
186 }
187 /* write filtered result */
188 p_array[out++] = output;
189 }
190 }
191 if (!ms->extrapolate) /* pad with breakers at the end */
192 for (i = 0; i < delay / 2; i++)
193 p_array[out++] = ms->breaker;
194
195 delete inarray;
196}
197
198float median (int *counter, float valin, float valbuf[], int lmed, int mmed)
199{
200 int i, j;
201 float tmp, filmed[MAX_LEN];
202
203 for (i = lmed - 1; i > 0; i--)
204 valbuf[i] = valbuf[i - 1];
205 valbuf[0] = valin;
206
207 if (*counter > 0)
208 {
209 (*counter)--;
210 return (0.0);
211 }
212 else
213 {
214 *counter = -1;
215
216 for (i = 0; i < lmed; i++)
217 filmed[i] = valbuf[i];
218
219 for (j = lmed - 1; j > 0; j--)
220 for (i = 0; i < j; i++)
221 if (filmed[i] > filmed[i + 1])
222 {
223 tmp = filmed[i + 1];
224 filmed[i + 1] = filmed[i];
225 filmed[i] = tmp;
226 }
227 return (filmed[mmed]);
228 }
229
230}
231
232#define TWO_PI 6.28318530717958647698
233
234void mk_window_coeffs (int length, float win_coeff[])
235{
236 int i;
237 double x;
238
239 for (i = 0; i < length; i++) {
240 x = TWO_PI * (i + 1.0) / (length + 1.0);
241 win_coeff[i] = (1.0 - (float) cos (x)) / (length + 1.0);
242 }
243
244}
245
246float hanning (int *counter, float valin, float valhan[], float win_coeff[],
247 struct Ms_Op *par)
248{
249 int i, j, k = 0;
250 float valout = 0.0, weight[MAX_LEN];
251
252 for (i = par->window_length - 1; i > 0; i--)
253 valhan[i] = valhan[i - 1];
254 valhan[0] = valin;
255 if (*counter > 0) {
256 (*counter)--;
257 return (0.0);
258 }
259 else {
260 *counter = -1;
261 for (i = 0; i < par->window_length; i++)
262 if (valhan[i] == par->breaker)
263 k++;
264 if (!k)
265 for (i = 0; i < par->window_length; i++)
266 valout += valhan[i] * win_coeff[i];
267 else if (k <= par->window_length / 2 && par->extrapolate) {
268 mk_window_coeffs (par->window_length - k, weight);
269 for (i = 0, j = 0; i < par->window_length; i++)
270 if (valhan[i] != par->breaker)
271 valout += valhan[i] * weight[j++];
272 }
273 else
274 valout = par->breaker;
275 return (valout);
276 }
277
278}
279
280void initialise_parameters (struct Ms_Op *p_par)
281{
282 p_par->smooth_double = 0;
283 p_par->apply_hanning = 0;
284 p_par->extrapolate = 0;
285 p_par->window_length = DEFAULT_WLEN;
286 p_par->first_median = DEFAULT_MED_1;
287 p_par->second_median = DEFAULT_MED_2;
288 return;
289}
290
291struct Ms_Op *default_ms_op(struct Ms_Op *ms)
292{
293 ms->smooth_double = FALSE;
294 ms->apply_hanning = TRUE;
295 ms->extrapolate = TRUE;
296 ms->first_median = 11;
297 ms->second_median = 1;
298 ms->window_length = 7;
299 ms->breaker = -1.0;
300 return (ms);
301}