Edinburgh Speech Tools 2.4-release
 
Loading...
Searching...
No Matches
EST_Window.cc
1/*************************************************************************/
2/* */
3/* Centre for Speech Technology Research */
4/* University of Edinburgh, UK */
5/* Copyright (c) 1994,1995,1996 */
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 : Simon King (taken from Tony Robinson) */
34/* Date : July 1994 */
35/*-----------------------------------------------------------------------*/
36/* windowing functions */
37/* */
38/*=======================================================================*/
39
40#include <iostream>
41#include <fstream>
42#include "EST_system.h"
43//#include "EST_sigpr.h"
44#include "sigpr/EST_Window.h"
45#include "EST_TNamedEnum.h"
46#include "EST_math.h"
47
48//static inline int irint(float f) { return (int)(f+0.5); }
49//static inline int irint(double f) { return (int)(f+0.5); }
50static inline int min(int a, int b) { return (a<b)?a:b; }
51static inline int max(int a, int b) { return (a>b)?a:b; }
52
53 /*************************************************************************/
54 /* */
55 /* The actual window functions are defined here. */
56 /* */
57 /*************************************************************************/
58
59static void Rectangular(int size, EST_TBuffer<float> &r_window, int window_centre=-1)
60{
61 // this may be a little silly
62 (void) window_centre; // not useful for rectangular window
63 r_window.ensure(size);
64
65 for( int i=0; i<size; i++ )
66 r_window[i] = 1.0;
67}
68
69static void Triangular(int size, EST_TBuffer<float> &r_window, int window_centre=-1)
70{
71 int i, c, end=size-1;
72
73 r_window.ensure(size);
74
75 if( window_centre < 0 ) { // symmetric window (default)
76 c=size/2;
77 const float k = 2.0 / (float)size;
78
79 if( (size & 1) != 0 ) // odd
80 r_window[c]=1.0;
81
82 for( i=0; i<c; i++ ){
83 r_window[i] = i * k;
84 r_window[end-i] = r_window[i];
85 }
86 }
87 else{
88 c = window_centre;
89 const float k_left = 1.0 / (float) (window_centre+1);
90 const float k_right = 1.0 / (float) (size-(window_centre+1));
91
92 r_window[c] = 1.0;
93
94 // left half
95 for( i=0; i<c; ++i )
96 r_window[i] = i * k_left;
97
98 // right half
99 const int righthand_size = size-1-window_centre;
100 for( i=0; i<righthand_size; ++i )
101 r_window[end-i] = i * k_right;
102 }
103}
104
105static void Hanning(int size, EST_TBuffer<float> &r_window, int window_centre=-1)
106{
107 int i,c;
108 float k;
109 r_window.ensure(size);
110 int end = size-1;
111
112 if( window_centre < 0 ){ // symmetric window (default)
113 c = size/2;
114
115 // only need to calculate one half + copy
116 if( (size & 1) != 0) // when odd
117 r_window[c]=1.0;
118
119 k = 2.0 * M_PI / size;
120 for( i=0; i<c; ++i )
121 r_window[end-i] = r_window[i] = 0.5 - 0.5 * cos(k * (i + 0.5));
122 }
123 else{
124 c = window_centre;
125 r_window[c]=1.0; // we assume "centre" is 1.0
126
127 // first half
128 int effective_size = (2*window_centre)+1;
129 k = 2.0 * M_PI / effective_size;
130 for( i=0; i<c; ++i )
131 r_window[i] = 0.5 - 0.5 * cos(k * (i + 0.5));
132
133 // second half
134 const int righthand_size = size-1-window_centre;
136 k = 2.0 * M_PI / effective_size;
137 for( i=0; i<righthand_size; ++i )
138 r_window[end-i] = 0.5 - 0.5 * cos(k * (i + 0.5));
139 }
140}
141
142static void Hamming(int size, EST_TBuffer<float> &r_window, int window_centre=-1)
143{
144 float k;
145 int i, c, end=size-1;
146
147 r_window.ensure(size);
148
149 if( window_centre < 0 ){ // symmetric window (default)
150 c=size/2;
151 k = 2.0 * M_PI / size;
152
153 if( (size & 1) != 0) // odd
154 r_window[c]=1.0;
155
156 for( i=0; i<c; i++ ){
157 r_window[i] = 0.54 - 0.46 * cos(k * (i + 0.5));
158 r_window[end-i] = r_window[i];
159 }
160 }
161 else{
162 c = window_centre;
163 r_window[c] = 1.0;
164
165 //first half
166 int effective_size = (2*window_centre)+1;
167 k = 2.0 * M_PI / effective_size;
168 for( i=0; i<c ; ++i )
169 r_window[i] = 0.54 - 0.46 * cos(k * (i + 0.5));
170
171 //second half
172 const int righthand_size = size-1-window_centre;
174 k = 2.0 * M_PI / effective_size;
175 for( i=0; i<righthand_size; ++i )
176 r_window[end-i] = 0.54 - 0.46 * cos(k * (i + 0.5));
177 }
178}
179
180 /*************************************************************************/
181 /* */
182 /* Here is the interface. */
183 /* */
184 /*************************************************************************/
185
186typedef enum EST_WindowType {
187 wf_none=0,
188 wf_rectangle=1,
189 wf_triangle=2,
190 wf_hanning=3,
191 wf_hamming=4
192} EST_WindowType;
193
194typedef struct Info {
195 EST_Window::Func *func;
196 const char *description;
197 } Info;
198
200{
201 { wf_none, { "none" },
202 {NULL, "unknown window type"}},
203 { wf_rectangle, {"rectangle", "rect", "rectangular"},
204 {Rectangular, "Rectangular window"}},
205 { wf_triangle, {"triangle", "tri", "triangular"},
206 {Triangular, "Triangular window"}},
207 { wf_hanning, {"hanning", "han"},
208 {Hanning, "Hanning window"}},
209 { wf_hamming, {"hamming", "ham"},
210 {Hamming, "Hamming window"}},
211 { wf_none, { NULL }},
212};
213
214static EST_TNamedEnumI<EST_WindowType, Info> map(window_names);
215
217{
218 EST_WindowType key = map.token(name);
219
220 if (key == wf_none)
221 {
222 if (report_error)
223 cerr << "no such window type %s" << name << endl;
224 return NULL;
225 }
226 else
227 return map.info(key).func;
228}
229
231{
232 EST_WindowType key = map.token(name);
233
234 return map.info(key).description;
235}
236
237/** Return the dc offset for a section of speech.
238 * This can safely go off the limits of the waveform.
239 */
240
241static float find_dc(const EST_Wave &sig, int start, int size)
242{
243 int i;
244 double sum = 0;
245
246 start = max(0, start);
247 size = min(size, sig.num_samples()-start);
248
249 for(i=0; i<size; i++)
250 sum += sig.a_no_check(start+i);
251
252 return (sum / (float)size);
253}
254
256 const char *name, int window_centre )
257{
258 EST_WindowFunc *make_window = EST_Window::creator(name);
259 window_vals.ensure(size, (bool)FALSE);
261}
262
264 const char *name, int window_centre )
265{
267 EST_WindowFunc *make_window = EST_Window::creator(name);
268 fwindow.ensure(size, (bool)FALSE);
270 window_vals.resize(size);
271 for (int i = 0; i < size; ++i)
272 window_vals[i] = fwindow[i];
273}
274
276 EST_WindowFunc *make_window,
277 int start, int size,
279{
281 int i;
282 float dc;
283
284 // create the window shape
285 make_window(size, window_vals,-1);
286 window.ensure(size, (bool)FALSE);
287 dc = find_dc(sig, start, size);
288
289 /* There are three separate loops, one each for the beginning and
290 ends, where virtual values off the end of the sig array are
291 requested, and one for the majority of the processing which falls
292 in the middle of the sig array.*/
293
294 for(i=0; i<size && start+i<0; i++)
295 window[i] =0;
296
297 for(; i<size && start+i < sig.num_samples(); i++)
298 window[i] = (window_vals(i) * (sig.a(start + i) - dc) + dc);
299
300 for(; i<size; i++)
301 window[i] = 0;
302
303}
304
306 const EST_String &window_name,
307 int start, int size,
308 EST_FVector &frame, int resize)
309{
310 EST_WindowFunc *wf = creator(window_name, true);
311 window_signal(sig, wf, start, size, frame, resize);
312}
313
315 EST_WindowFunc *make_window,
316 int start, int size,
317 EST_FVector &frame, int resize)
318{
320 // create the window shape
321 make_window(size, window_vals,-1);
322
325 start, size,
326 frame, resize);
327}
328
331 int start, int size,
332 EST_FVector &frame, int resize)
333{
334 int i;
335 float dc;
336
337 if (resize)
338 frame.resize(size);
339 else if (frame.length() < size)
340 {
341 cerr << "Frame is wrong size: expected " << size << " got "
342 << frame.length() << endl;
343 return;
344 }
345
346/* cout << "window vals\n";
347 for (i = 0; i < size; ++i)
348 cout << window_vals[i] << " ";
349
350 cout << endl << endl;
351*/
352
353 dc = find_dc(sig, start, size);
354// cout << "dc is " << dc << endl;
355 /* There are three separate loops, one each for the beginning and
356 ends, where virtual values off the end of the sig array are
357 requested, and one for the majority of the processing which falls
358 in the middle of the sig array.*/
359
360 for(i = 0; i < size && start+i< 0; i++)
361 frame.a_no_check(i) = 0;
362
363 for (; (i < size) && (start + i < sig.num_samples()); i++)
364 frame.a_no_check(i) = (window_vals(i) * (sig.a_no_check(start + i) - dc) + dc);
365
366 for(; i < frame.length(); i++)
367 frame.a_no_check(i) = 0;
368
369/* cout << "sig vals\n";
370 for (i = 0; i < size; ++i)
371 cout << sig.a(i + start) << " ";
372
373 cout << "frame vals\n";
374 for (i = 0; i < size; ++i)
375 cout << frame[i] << " ";
376
377 cout << endl << endl;
378*/
379}
380
382{
383 EST_String s;
384
385 for(int n=0; n< map.n() ; n++)
386 {
387 const char *nm = map.name(map.token(n));
388 const char *d = map.info(map.token(n)).description;
389
390 s += EST_String::cat(" ", nm, EST_String(" ")*(12-strlen(nm)), d, "\n");
391 }
392 return s;
393}
394
396{
397 EST_String s("");
398
399 for(int n=0; n< map.n() ; n++)
400 {
401 const char *nm = map.name(map.token(n));
402
403 if (s != "")
404 s += ", ";
405
406 s += nm;
407
408 }
409 return s;
410}
411
412#if defined(INSTANTIATE_TEMPLATES)
413
414#include "../base_class/EST_TNamedEnum.cc"
415
418
419#endif
static EST_String cat(const EST_String s1, const EST_String s2=Empty, const EST_String s3=Empty, const EST_String s4=Empty, const EST_String s5=Empty, const EST_String s6=Empty, const EST_String s7=Empty, const EST_String s8=Empty, const EST_String s9=Empty)
void resize(int n, int set=1)
resize vector
INLINE int length() const
number of items in vector.
INLINE const T & a_no_check(int n) const
read-only const access operator: without bounds checking
static EST_String options_supported(void)
Return a paragraph describing the available windows.
static EST_String description(const char *name)
Return the description for a given window type.
static void window_signal(const EST_Wave &sig, EST_WindowFunc *make_window, int start, int size, EST_TBuffer< float > &frame)
static void make_window(EST_TBuffer< float > &window_vals, int size, const char *name, int window_centre)
EST_WindowFunc Func
A function which creates a window.
Definition EST_Window.h:120
static EST_String options_short(void)
Return a comma separated list of the available window types.
static Func * creator(const char *name, bool report_error=false)
Return the creation function for the given window type.