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