Edinburgh Speech Tools  2.4-release
 All Classes Functions Variables Typedefs Enumerations Enumerator Friends Pages
EST_Wave.cc
1 /*************************************************************************/
2 /* */
3 /* Centre for Speech Technology Research */
4 /* University of Edinburgh, UK */
5 /* Copyright (c) 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 : Paul Taylor and Alan Black */
34 /* Date : May 1996 */
35 /*-----------------------------------------------------------------------*/
36 /* EST_Wave Class source file */
37 /* */
38 /*=======================================================================*/
39 
40 #include <iostream>
41 #include <cstdlib>
42 #include <cstdio>
43 #include <cmath>
44 #include <cstring>
45 #include "EST_cutils.h"
46 #include "EST_Wave.h"
47 #include "EST_wave_utils.h"
48 #include "EST_wave_aux.h"
49 #include "EST_TNamedEnum.h"
50 #include "EST_WaveFile.h"
51 
52 #include "EST_Track.h"
53 
54 #include "waveP.h"
55 
56 const EST_String DEF_FILE_TYPE = "riff";
57 const EST_String DEF_SAMPLE_TYPE = "short";
58 
59 const int EST_Wave::default_sample_rate=16000;
60 
62 {
63  default_vals();
64 }
65 
67 {
68  default_vals();
69  copy(w);
70 }
71 
72 EST_Wave::EST_Wave(int n, int c, int sr)
73 {
74  default_vals(n,c);
75  set_sample_rate(sr);
76 }
77 
78 EST_Wave::EST_Wave(int samps, int chans,
79  short *memory, int offset, int sample_rate,
80  int free_when_destroyed)
81 {
82  default_vals();
83  p_values.set_memory(memory, offset, samps, chans, free_when_destroyed);
84  set_sample_rate(sample_rate);
85 }
86 
87 void EST_Wave::default_vals(int n, int c)
88 {
89  // real defaults
90  p_values.resize(n,c);
91  p_sample_rate = default_sample_rate;
92 
93  init_features();
94 }
95 
96 void EST_Wave::free_wave()
97 {
98  if (!p_values.p_sub_matrix)
99  p_values.resize(0,0);
100  clear_features();
101 }
102 
103 EST_Wave::~EST_Wave()
104 {
105  free_wave();
106 }
107 
108 void EST_Wave::copy_setup(const EST_Wave &w)
109 {
110  p_sample_rate = w.p_sample_rate;
111  copy_features(w);
112 }
113 
114 void EST_Wave::copy_data(const EST_Wave &w)
115 {
116  p_values.copy(w.p_values);
117 }
118 
119 void EST_Wave::copy(const EST_Wave &w)
120 {
121  copy_setup(w);
122 
123  copy_data(w);
124 }
125 
126 short &EST_Wave::a(int i, int channel)
127 {
128  if (i<0 || i>= num_samples())
129  {
130  cerr << "Attempt to access sample " << i << " of a " << num_samples() << " sample wave.\n";
131  if (num_samples()>0)
132  return *(p_values.error_return);
133  }
134 
135  if (channel<0 || channel>= num_channels())
136  {
137  cerr << "Attempt to access channel " << channel << " of a " << num_channels() << " channel wave.\n";
138  if (num_samples()>0)
139  return *(p_values.error_return);
140  }
141 
142  return p_values.a_no_check(i,channel);
143 }
144 
145 short EST_Wave::a(int i, int channel) const
146 {
147  return ((EST_Wave *)this)->a(i,channel);
148 }
149 
150 short &EST_Wave::a_safe(int i, int channel)
151 {
152  static short out_of_bound_value = 0;
153 
154  if ((i < 0) || (i >= num_samples()))
155  { // need to give them something but they might have changed it
156  // so reinitialise it to 0 first
157  out_of_bound_value = 0;
158  return out_of_bound_value;
159  }
160  else
161  return a_no_check(i,channel);
162 }
163 
164 void EST_Wave::fill(short v, int channel)
165 {
166  if (channel == EST_ALL)
167  {
168  if (v == 0) // this is *much* more efficient and common
169  memset(values().memory(),0,num_samples()*num_channels()*2);
170  else
171  p_values.fill(v);
172  }
173  else
174  for (int i = 0; i < num_samples(); ++i)
175  p_values.a_no_check(i,channel) = v;
176 }
177 
178 EST_read_status EST_Wave::load(const EST_String filename,
179  int offset, int length,
180  int rate)
181 {
182  EST_read_status stat = read_error;
183  EST_TokenStream ts;
184 
185  if ((ts.open(filename)) == -1)
186  {
187  cerr << "Wave load: can't open file \"" << filename << "\"" << endl;
188  return stat;
189  }
190 
191  stat = load(ts,offset,length,rate);
192  ts.close();
193  return stat;
194 }
195 
196 EST_read_status EST_Wave::load(EST_TokenStream &ts,
197  int offset, int length,
198  int rate)
199 {
200  EST_read_status stat = read_error;
201  int pos = ts.tell();
202 
203  for(int n=0; n< EST_WaveFile::map.n() ; n++)
204  {
205  EST_WaveFileType t = EST_WaveFile::map.token(n);
206 
207  if (t == wff_none)
208  continue;
209 
210  EST_WaveFile::Info *info = &(EST_WaveFile::map.info(t));
211 
212  if (! info->recognise)
213  continue;
214 
215  EST_WaveFile::Load_TokenStream * l_fun =info->load;
216 
217  if (l_fun == NULL)
218  continue;
219 
220  ts.seek(pos);
221  stat = (*l_fun)(ts, *this,
222  rate, st_short, EST_NATIVE_BO, 1,
223  offset, length);
224 
225  if (stat == read_ok)
226  {
227  set_file_type(EST_WaveFile::map.value(t));
228  break;
229  }
230  else if (stat == read_error)
231  break;
232  }
233 
234  return stat;
235 }
236 
237 EST_read_status EST_Wave::load(const EST_String filename,
238  const EST_String type,
239  int offset, int length,
240  int rate)
241 {
242  EST_read_status stat = read_error;
243  EST_TokenStream ts;
244 
245  if (filename == "-")
246  ts.open(stdin,FALSE);
247  else if ((ts.open(filename)) == -1)
248  {
249  cerr << "Wave load: can't open file \"" << filename << "\"" << endl;
250  return stat;
251  }
252 
253  stat = load(ts,type,offset,length,rate);
254  ts.close();
255  return stat;
256 }
257 
258 EST_read_status EST_Wave::load(EST_TokenStream &ts,
259  const EST_String type,
260  int offset, int length,
261  int rate)
262 {
263  EST_WaveFileType t = EST_WaveFile::map.token(type);
264 
265  if (t == wff_none)
266  {
267  cerr << "Unknown Wave file type " << type << endl;
268  return read_error;
269  }
270 
271  EST_WaveFile::Load_TokenStream * l_fun = EST_WaveFile::map.info(t).load;
272 
273  if (l_fun == NULL)
274  {
275  cerr << "Can't load waves to files type " << type << endl;
276  return read_error;
277  }
278 
279  set_file_type(EST_WaveFile::map.value(t));
280  return (*l_fun)(ts, *this,
281  rate, st_short, EST_NATIVE_BO, 1,
282  offset, length);
283 
284 }
285 
286 EST_read_status EST_Wave::load_file(const EST_String filename,
287  const EST_String type, int sample_rate,
288  const EST_String stype, int bov, int nc, int offset,
289  int length)
290 {
291  EST_read_status stat = read_error;
292  EST_TokenStream ts;
293 
294  if (filename == "-")
295  ts.open(stdin,FALSE);
296  else if ((ts.open(filename)) == -1)
297  {
298  cerr << "Wave load: can't open file \"" << filename << "\"" << endl;
299  return stat;
300  }
301 
302  stat = load_file(ts,type,sample_rate,stype,bov,nc,offset,length);
303  ts.close();
304  return stat;
305 }
306 
307 EST_read_status EST_Wave::load_file(EST_TokenStream &ts,
308  const EST_String type, int sample_rate,
309  const EST_String stype, int bov, int nc, int offset,
310  int length)
311 
312 {
313  EST_WaveFileType t = EST_WaveFile::map.token(type);
314 
315  EST_sample_type_t values_type = EST_sample_type_map.token(stype);
316 
317  if (t == wff_none)
318  {
319  cerr << "Unknown Wave file type " << type << endl;
320  return read_error;
321  }
322 
323  EST_WaveFile::Load_TokenStream * l_fun = EST_WaveFile::map.info(t).load;
324 
325  if (l_fun == NULL)
326  {
327  cerr << "Can't load waves to files type " << type << endl;
328  return read_error;
329  }
330 
331  return (*l_fun)(ts, *this,
332  sample_rate, values_type, bov, nc,
333  offset, length);
334 
335 }
336 
337 void EST_Wave::sub_wave(EST_Wave &sw,
338  int offset, int num,
339  int start_c, int nchan)
340 {
341  if (num == EST_ALL)
342  num = num_samples()-offset;
343  if (nchan == EST_ALL)
344  nchan = num_channels()-start_c;
345 
346  p_values.sub_matrix(sw.p_values, offset, num, start_c, nchan);
348 }
349 
350 EST_write_status EST_Wave::save(const EST_String filename,
351  const EST_String type)
352 {
353  FILE *fp;
354 
355  if (filename == "-")
356  fp = stdout;
357  else if ((fp = fopen(filename,"wb")) == NULL)
358  {
359  cerr << "Wave save: can't open output file \"" <<
360  filename << "\"" << endl;
361  return write_fail;
362  }
363 
364  EST_write_status r = save(fp,type);
365  if (fp != stdout)
366  fclose(fp);
367  return r;
368 }
369 
370 EST_write_status EST_Wave::save(FILE *fp, const EST_String type)
371 {
372  EST_String save_type = (type == "") ? DEF_FILE_TYPE : type;
373 
374  EST_WaveFileType t = EST_WaveFile::map.token(save_type);
375 
376  if (t == wff_none)
377  {
378  cerr << "Wave: unknown filetype in saving " << save_type << endl;
379  return write_fail;
380  }
381 
382  EST_WaveFile::Save_TokenStream * s_fun = EST_WaveFile::map.info(t).save;
383 
384  if (s_fun == NULL)
385  {
386  cerr << "Can't save waves to files type " << save_type << endl;
387  return write_fail;
388  }
389 
390  return (*s_fun)(fp, *this, st_short, EST_NATIVE_BO);
391 }
392 
393 EST_write_status EST_Wave::save_file(const EST_String filename,
394  EST_String ftype,
395  EST_String stype, int obo)
396 {
397  FILE *fp;
398 
399  if (filename == "-")
400  fp = stdout;
401  else if ((fp = fopen(filename,"wb")) == NULL)
402  {
403  cerr << "Wave save: can't open output file \"" <<
404  filename << "\"" << endl;
405  return write_fail;
406  }
407 
408  EST_write_status r = save_file(fp,ftype,stype,obo);
409  if (fp != stdout)
410  fclose(fp);
411  return r;
412 }
413 
414 EST_write_status EST_Wave::save_file(FILE *fp,
415  EST_String ftype,
416  EST_String stype, int obo)
417 {
418  EST_WaveFileType t = EST_WaveFile::map.token(ftype);
419  EST_sample_type_t sample_type = EST_sample_type_map.token(stype);
420 
421  if (t == wff_none)
422  {
423  cerr << "Unknown Wave file type " << ftype << endl;
424  return write_fail;
425  }
426 
427  EST_WaveFile::Save_TokenStream * s_fun = EST_WaveFile::map.info(t).save;
428 
429  if (s_fun == NULL)
430  {
431  cerr << "Can't save waves to files type " << ftype << endl;
432  return write_fail;
433  }
434 
435  return (*s_fun)(fp, *this, sample_type, obo);
436 
437 }
438 
439 void EST_Wave::resample(int new_freq)
440 {
441  // Resample wave to new sample rate
442  if (new_freq != p_sample_rate)
443  {
444  if (p_values.rateconv(p_sample_rate, new_freq) != 0)
445  cerr << "rateconv: failed to convert from " << p_sample_rate <<
446  " to " << new_freq << "\n";
447  else
448  set_sample_rate(new_freq);
449  }
450 
451 }
452 
453 void EST_Wave::rescale(float gain, int normalize)
454 {
455  int ns;
456  float factor = gain;
457  float nsf;
458 
459  if (normalize)
460  {
461  int max = 0;
462  for (int i = 0; i < num_samples(); ++i)
463  for (int j = 0; j < num_channels(); ++j)
464  if (abs(a_no_check(i,j)) > max)
465  max = abs(a_no_check(i,j));
466  if (fabs(max/32766.0-gain) < 0.001)
467  return; /* already normalized */
468  else
469  factor *= 32766.0/(float)max;
470  }
471 
472  for (int i = 0; i < num_samples(); ++i)
473  for (int j = 0; j < num_channels(); ++j)
474  {
475  if (factor == 1.0)
476  ns = a_no_check(i,j); // avoid float fluctuations
477  else if (factor == -1.0)
478  ns = -a_no_check(i,j); // avoid float fluctuations
479  else
480  {
481  nsf = (float)a_no_check(i,j) * factor;
482  if (nsf < 0.0)
483  ns = (int)(nsf - 0.5);
484  else
485  ns = (int)(nsf + 0.5);
486  }
487  if (ns < -32766)
488  a_no_check(i,j)= -32766;
489  else if (ns > 32766)
490  a_no_check(i,j)= 32766;
491  else
492  a_no_check(i,j)= ns;
493  }
494 }
495 
496 void EST_Wave::rescale( const EST_Track &fc )
497 {
498  int ns, start_sample, end_sample;
499  float target1, target2, increment, factor, nsf;
500 
501  int fc_length = fc.length();
502  int _num_channels = num_channels();
503 
504  cerr << ((int)(fc.t(fc_length-1) * p_sample_rate)) << endl;
505 
506  if( ((int)(fc.t(fc_length-1) * p_sample_rate)) > num_samples() )
507  EST_error( "Factor contour track exceeds waveform length (%d samples)",
508  (fc.t(fc_length-1) * p_sample_rate) - num_samples() );
509 
510  start_sample = static_cast<unsigned int>( fc.t( 0 )*p_sample_rate );
511  target1 = fc.a(0,0); // could use separate channels for each waveform channel
512 
513  for ( int k = 1; k<fc_length; ++k ){
514  end_sample = static_cast<unsigned int>( fc.t( k )*p_sample_rate );
515  target2 = fc.a(k);
516 
517  increment = (target2-target1)/(end_sample-start_sample+1);
518 
519  factor = target1;
520  for( int i=start_sample; i<end_sample; ++i, factor+=increment )
521  for( int j=0; j<_num_channels; ++j ){
522  if (factor == 1.0)
523  ns = a_no_check(i,j); // avoid float fluctuations
524  else if (factor == -1.0)
525  ns = -a_no_check(i,j); // avoid float fluctuations
526  else
527  {
528  nsf = (float)a_no_check(i,j) * factor;
529  if (nsf < 0.0)
530  ns = (int)(nsf - 0.5);
531  else
532  ns = (int)(nsf + 0.5);
533  }
534  if (ns < -32766)
535  a_no_check(i,j)= -32766;
536  else if (ns > 32766)
537  a_no_check(i,j)= 32766;
538  else
539  a_no_check(i,j)= ns;
540  }
541  start_sample = end_sample;
542  target1 = target2;
543  }
544 }
545 
546 
547 
549 {
550  copy(w);
551  return *this;
552 }
553 
555 {
556  EST_Wave w2;
557  const EST_Wave *toadd = &w;
558 
559  if (w.num_channels() != num_channels())
560  {
561  cerr << "Cannot concatenate waveforms with differing numbers of channels\n";
562  return *this;
563  }
564 
565  if (p_sample_rate != w.sample_rate())
566  {
567  w2 = w;
568  w2.resample(p_sample_rate);
569  toadd= &w2;
570  }
571 
572  p_values.add_rows(toadd->p_values);
573 
574  return *this;
575 }
576 
577 // add wave p_values to existing wave in parallel to create multi-channel wave.
579 {
580  int i, k;
581  EST_Wave w = wi; // to allow resampling of const
582 
583  w.resample(p_sample_rate); // far too difficult otherwise
584 
585  int o_channels = num_channels();
586  int r_channels = num_channels()+w.num_channels();
587  int r_samples = Gof(num_samples(), w.num_samples());
588 
589  resize(r_samples, r_channels);
590 
591  for (k = 0; k < w.num_channels(); ++k)
592  for (i=0; i < w.num_samples(); i++)
593  a(i,k+o_channels) += w.a(i, k);
594 
595  return *this;
596 }
597 
598 ostream& operator << (ostream& p_values, const EST_Wave &sig)
599 {
600  for (int i = 0; i < sig.num_samples(); ++i)
601  p_values << sig(i) << "\n";
602 
603  return p_values;
604 }
605 
606 int operator != (EST_Wave a, EST_Wave b)
607  { (void)a; (void)b; return 1; }
608 int operator == (EST_Wave a, EST_Wave b)
609  { (void)a; (void)b; return 0; }