Edinburgh Speech Tools 2.4-release
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#define sgn(x) (x>0?1:x?-1:0)
57
58const EST_String DEF_FILE_TYPE = "riff";
59const EST_String DEF_SAMPLE_TYPE = "short";
60
61const int EST_Wave::default_sample_rate=16000;
62
64{
65 default_vals();
66}
67
69{
70 default_vals();
71 copy(w);
72}
73
74EST_Wave::EST_Wave(int n, int c, int sr)
75{
76 default_vals(n,c);
78}
79
80EST_Wave::EST_Wave(int samps, int chans,
81 short *memory, int offset, int sample_rate,
82 int free_when_destroyed)
83{
84 default_vals();
85 p_values.set_memory(memory, offset, samps, chans, free_when_destroyed);
87}
88
89void EST_Wave::default_vals(int n, int c)
90{
91 // real defaults
92 p_values.resize(n,c);
93 p_sample_rate = default_sample_rate;
94
95 init_features();
96}
97
98void EST_Wave::free_wave()
99{
100 if (!p_values.p_sub_matrix)
101 p_values.resize(0,0);
102 clear_features();
103}
104
105EST_Wave::~EST_Wave()
106{
107 free_wave();
108}
109
110void EST_Wave::copy_setup(const EST_Wave &w)
111{
112 p_sample_rate = w.p_sample_rate;
113 copy_features(w);
114}
115
116void EST_Wave::copy_data(const EST_Wave &w)
117{
118 p_values.copy(w.p_values);
119}
120
121void EST_Wave::copy(const EST_Wave &w)
122{
123 copy_setup(w);
124
125 copy_data(w);
126}
127
128short &EST_Wave::a(int i, int channel)
129{
130 if (i<0 || i>= num_samples())
131 {
132 cerr << "Attempt to access sample " << i << " of a " << num_samples() << " sample wave.\n";
133 if (num_samples()>0)
134 return *(p_values.error_return);
135 }
136
137 if (channel<0 || channel>= num_channels())
138 {
139 cerr << "Attempt to access channel " << channel << " of a " << num_channels() << " channel wave.\n";
140 if (num_samples()>0)
141 return *(p_values.error_return);
142 }
143
144 return p_values.a_no_check(i,channel);
145}
146
147short EST_Wave::a(int i, int channel) const
148{
149 return ((EST_Wave *)this)->a(i,channel);
150}
151
152short &EST_Wave::a_safe(int i, int channel)
153{
154 static short out_of_bound_value = 0;
155
156 if ((i < 0) || (i >= num_samples()))
157 { // need to give them something but they might have changed it
158 // so reinitialise it to 0 first
159 out_of_bound_value = 0;
160 return out_of_bound_value;
161 }
162 else
163 return a_no_check(i,channel);
164}
165
166void EST_Wave::fill(short v, int channel)
167{
168 if (channel == EST_ALL)
169 {
170 if (v == 0) // this is *much* more efficient and common
171 memset(values().memory(),0,num_samples()*num_channels()*2);
172 else
173 p_values.fill(v);
174 }
175 else
176 for (int i = 0; i < num_samples(); ++i)
177 p_values.a_no_check(i,channel) = v;
178}
179
180EST_read_status EST_Wave::load(const EST_String filename,
181 int offset, int length,
182 int rate)
183{
184 EST_read_status stat = read_error;
186
187 if ((ts.open(filename)) == -1)
188 {
189 cerr << "Wave load: can't open file \"" << filename << "\"" << endl;
190 return stat;
191 }
192
193 stat = load(ts,offset,length,rate);
194 ts.close();
195 return stat;
196}
197
198EST_read_status EST_Wave::load(EST_TokenStream &ts,
199 int offset, int length,
200 int rate)
201{
202 EST_read_status stat = read_error;
203 int pos = ts.tell();
204
205 for(int n=0; n< EST_WaveFile::map.n() ; n++)
206 {
207 EST_WaveFileType t = EST_WaveFile::map.token(n);
208
209 if (t == wff_none)
210 continue;
211
212 EST_WaveFile::Info *info = &(EST_WaveFile::map.info(t));
213
214 if (! info->recognise)
215 continue;
216
217 EST_WaveFile::Load_TokenStream * l_fun =info->load;
218
219 if (l_fun == NULL)
220 continue;
221
222 ts.seek(pos);
223 stat = (*l_fun)(ts, *this,
224 rate, st_short, EST_NATIVE_BO, 1,
225 offset, length);
226
227 if (stat == read_ok)
228 {
229 set_file_type(EST_WaveFile::map.value(t));
230 break;
231 }
232 else if (stat == read_error)
233 break;
234 }
235
236 return stat;
237}
238
239EST_read_status EST_Wave::load(const EST_String filename,
240 const EST_String type,
241 int offset, int length,
242 int rate)
243{
244 EST_read_status stat = read_error;
246
247 if (filename == "-")
248 ts.open(stdin,FALSE);
249 else if ((ts.open(filename)) == -1)
250 {
251 cerr << "Wave load: can't open file \"" << filename << "\"" << endl;
252 return stat;
253 }
254
255 stat = load(ts,type,offset,length,rate);
256 ts.close();
257 return stat;
258}
259
260EST_read_status EST_Wave::load(EST_TokenStream &ts,
261 const EST_String type,
262 int offset, int length,
263 int rate)
264{
265 EST_WaveFileType t = EST_WaveFile::map.token(type);
266
267 if (t == wff_none)
268 {
269 cerr << "Unknown Wave file type " << type << endl;
270 return read_error;
271 }
272
273 EST_WaveFile::Load_TokenStream * l_fun = EST_WaveFile::map.info(t).load;
274
275 if (l_fun == NULL)
276 {
277 cerr << "Can't load waves to files type " << type << endl;
278 return read_error;
279 }
280
281 set_file_type(EST_WaveFile::map.value(t));
282 return (*l_fun)(ts, *this,
283 rate, st_short, EST_NATIVE_BO, 1,
284 offset, length);
285
286}
287
288EST_read_status EST_Wave::load_file(const EST_String filename,
289 const EST_String type, int sample_rate,
290 const EST_String stype, int bov, int nc, int offset,
291 int length)
292{
293 EST_read_status stat = read_error;
295
296 if (filename == "-")
297 ts.open(stdin,FALSE);
298 else if ((ts.open(filename)) == -1)
299 {
300 cerr << "Wave load: can't open file \"" << filename << "\"" << endl;
301 return stat;
302 }
303
304 stat = load_file(ts,type,sample_rate,stype,bov,nc,offset,length);
305 ts.close();
306 return stat;
307}
308
309EST_read_status EST_Wave::load_file(EST_TokenStream &ts,
310 const EST_String type, int sample_rate,
311 const EST_String stype, int bov, int nc, int offset,
312 int length)
313
314{
315 EST_WaveFileType t = EST_WaveFile::map.token(type);
316
317 EST_sample_type_t values_type = EST_sample_type_map.token(stype);
318
319 if (t == wff_none)
320 {
321 cerr << "Unknown Wave file type " << type << endl;
322 return read_error;
323 }
324
325 EST_WaveFile::Load_TokenStream * l_fun = EST_WaveFile::map.info(t).load;
326
327 if (l_fun == NULL)
328 {
329 cerr << "Can't load waves to files type " << type << endl;
330 return read_error;
331 }
332
333 return (*l_fun)(ts, *this,
334 sample_rate, values_type, bov, nc,
335 offset, length);
336
337}
338
339void EST_Wave::sub_wave(EST_Wave &sw,
340 int offset, int num,
341 int start_c, int nchan)
342{
343 if (num == EST_ALL)
344 num = num_samples()-offset;
345 if (nchan == EST_ALL)
346 nchan = num_channels()-start_c;
347
348 p_values.sub_matrix(sw.p_values, offset, num, start_c, nchan);
350}
351
352EST_write_status EST_Wave::save(const EST_String filename,
353 const EST_String type)
354{
355 FILE *fp;
356
357 if (filename == "-")
358 fp = stdout;
359 else if ((fp = fopen(filename,"wb")) == NULL)
360 {
361 cerr << "Wave save: can't open output file \"" <<
362 filename << "\"" << endl;
363 return write_fail;
364 }
365
366 EST_write_status r = save(fp,type);
367 if (fp != stdout)
368 fclose(fp);
369 return r;
370}
371
372EST_write_status EST_Wave::save(FILE *fp, const EST_String type)
373{
374 EST_String save_type = (type == "") ? DEF_FILE_TYPE : type;
375
376 EST_WaveFileType t = EST_WaveFile::map.token(save_type);
377
378 if (t == wff_none)
379 {
380 cerr << "Wave: unknown filetype in saving " << save_type << endl;
381 return write_fail;
382 }
383
384 EST_WaveFile::Save_TokenStream * s_fun = EST_WaveFile::map.info(t).save;
385
386 if (s_fun == NULL)
387 {
388 cerr << "Can't save waves to files type " << save_type << endl;
389 return write_fail;
390 }
391
392 return (*s_fun)(fp, *this, st_short, EST_NATIVE_BO);
393}
394
395EST_write_status EST_Wave::save_file(const EST_String filename,
396 EST_String ftype,
397 EST_String stype, int obo, const char *mode)
398{
399 FILE *fp;
400
401 if (filename == "-")
402 fp = stdout;
403 else if ((fp = fopen(filename, mode)) == NULL)
404 {
405 cerr << "Wave save: can't open output file \"" <<
406 filename << "\"" << endl;
407 return write_fail;
408 }
409
410 EST_write_status r = save_file(fp,ftype,stype,obo);
411 if (fp != stdout)
412 fclose(fp);
413 return r;
414}
415
416EST_write_status EST_Wave::save_file(FILE *fp,
417 EST_String ftype,
418 EST_String stype, int obo)
419{
420 EST_WaveFileType t = EST_WaveFile::map.token(ftype);
421 EST_sample_type_t sample_type = EST_sample_type_map.token(stype);
422
423 if (t == wff_none)
424 {
425 cerr << "Unknown Wave file type " << ftype << endl;
426 return write_fail;
427 }
428
429 EST_WaveFile::Save_TokenStream * s_fun = EST_WaveFile::map.info(t).save;
430
431 if (s_fun == NULL)
432 {
433 cerr << "Can't save waves to files type " << ftype << endl;
434 return write_fail;
435 }
436
437 return (*s_fun)(fp, *this, sample_type, obo);
438}
439
440EST_write_status EST_Wave::save_file_data(FILE *fp,
441 EST_String ftype,
442 EST_String stype, int obo)
443{
444 EST_WaveFileType t = EST_WaveFile::map.token(ftype);
445 EST_sample_type_t sample_type = EST_sample_type_map.token(stype);
446
447 if (t == wff_none)
448 {
449 cerr << "Unknown Wave file type " << ftype << endl;
450 return write_fail;
451 }
452
453 EST_WaveFile::Save_TokenStream * s_fun = EST_WaveFile::map.info(t).save_data;
454
455 if (s_fun == NULL)
456 {
457 cerr << "Can't save wave data to files type " << ftype << endl;
458 return write_fail;
459 }
460
461 return (*s_fun)(fp, *this, sample_type, obo);
462}
463
464
465EST_write_status EST_Wave::save_file_header(FILE *fp,
466 EST_String ftype,
467 EST_String stype, int obo)
468{
469 EST_WaveFileType t = EST_WaveFile::map.token(ftype);
470 EST_sample_type_t sample_type = EST_sample_type_map.token(stype);
471
472 if (t == wff_none)
473 {
474 cerr << "Unknown Wave file type " << ftype << endl;
475 return write_fail;
476 }
477
478 EST_WaveFile::Save_TokenStream * s_fun = EST_WaveFile::map.info(t).save_header;
479
480 if (s_fun == NULL)
481 {
482 cerr << "Can't save wave header to files type " << ftype << endl;
483 return write_fail;
484 }
485
486 return (*s_fun)(fp, *this, sample_type, obo);
487}
488
489void EST_Wave::resample(int new_freq)
490{
491 // Resample wave to new sample rate
492 if (new_freq != p_sample_rate)
493 {
494 if (p_values.rateconv(p_sample_rate, new_freq) != 0)
495 cerr << "rateconv: failed to convert from " << p_sample_rate <<
496 " to " << new_freq << "\n";
497 else
498 set_sample_rate(new_freq);
499 }
500
501}
502
503void EST_Wave::compress(float mu, float lim)
504{
505 int x;
506
507 for (int i = 0; i < num_samples(); ++i)
508 {
509 for (int j = 0; j< num_channels(); ++j)
510 {
511 x = a_no_check(i,j);
512 a_no_check(i,j) = lim * (sgn(x)*(log(1+(mu/lim)*abs(x))/log(1+mu)));
513 }
514 }
515}
516
517void EST_Wave::rescale(float gain, int normalize)
518{
519 int ns;
520 float factor = gain;
521 float nsf;
522
523 if (normalize)
524 {
525 int max = 0;
526 for (int i = 0; i < num_samples(); ++i)
527 for (int j = 0; j < num_channels(); ++j)
528 if (abs(a_no_check(i,j)) > max)
529 max = abs(a_no_check(i,j));
530 if (fabs(max/32766.0-gain) < 0.001)
531 return; /* already normalized */
532 else
533 factor *= 32766.0/(float)max;
534 }
535
536 for (int i = 0; i < num_samples(); ++i)
537 for (int j = 0; j < num_channels(); ++j)
538 {
539 if (factor == 1.0)
540 ns = a_no_check(i,j); // avoid float fluctuations
541 else if (factor == -1.0)
542 ns = -a_no_check(i,j); // avoid float fluctuations
543 else
544 {
545 nsf = (float)a_no_check(i,j) * factor;
546 if (nsf < 0.0)
547 ns = (int)(nsf - 0.5);
548 else
549 ns = (int)(nsf + 0.5);
550 }
551 if (ns < -32766)
552 a_no_check(i,j)= -32766;
553 else if (ns > 32766)
554 a_no_check(i,j)= 32766;
555 else
556 a_no_check(i,j)= ns;
557 }
558}
559
560void EST_Wave::rescale( const EST_Track &fc )
561{
562 int ns, start_sample, end_sample;
563 float target1, target2, increment, factor, nsf;
564
565 int fc_length = fc.length();
566 int _num_channels = num_channels();
567
568 cerr << ((int)(fc.t(fc_length-1) * p_sample_rate)) << endl;
569
570 if( ((int)(fc.t(fc_length-1) * p_sample_rate)) > num_samples() )
571 EST_error( "Factor contour track exceeds waveform length (%d samples)",
572 (fc.t(fc_length-1) * p_sample_rate) - num_samples() );
573
574 start_sample = static_cast<unsigned int>( fc.t( 0 )*p_sample_rate );
575 target1 = fc.a(0,0); // could use separate channels for each waveform channel
576
577 for ( int k = 1; k<fc_length; ++k ){
578 end_sample = static_cast<unsigned int>( fc.t( k )*p_sample_rate );
579 target2 = fc.a(k);
580
581 increment = (target2-target1)/(end_sample-start_sample+1);
582
583 factor = target1;
584 for( int i=start_sample; i<end_sample; ++i, factor+=increment )
585 for( int j=0; j<_num_channels; ++j ){
586 if (factor == 1.0)
587 ns = a_no_check(i,j); // avoid float fluctuations
588 else if (factor == -1.0)
589 ns = -a_no_check(i,j); // avoid float fluctuations
590 else
591 {
592 nsf = (float)a_no_check(i,j) * factor;
593 if (nsf < 0.0)
594 ns = (int)(nsf - 0.5);
595 else
596 ns = (int)(nsf + 0.5);
597 }
598 if (ns < -32766)
599 a_no_check(i,j)= -32766;
600 else if (ns > 32766)
601 a_no_check(i,j)= 32766;
602 else
603 a_no_check(i,j)= ns;
604 }
605 start_sample = end_sample;
606 target1 = target2;
607 }
608}
609
610
611
613{
614 copy(w);
615 return *this;
616}
617
619{
620 EST_Wave w2;
621 const EST_Wave *toadd = &w;
622
623 if (w.num_channels() != num_channels())
624 {
625 cerr << "Cannot concatenate waveforms with differing numbers of channels\n";
626 return *this;
627 }
628
629 if (p_sample_rate != w.sample_rate())
630 {
631 w2 = w;
632 w2.resample(p_sample_rate);
633 toadd= &w2;
634 }
635
636 p_values.add_rows(toadd->p_values);
637
638 return *this;
639}
640
641// add wave p_values to existing wave in parallel to create multi-channel wave.
643{
644 int i, k;
645 EST_Wave w = wi; // to allow resampling of const
646
647 w.resample(p_sample_rate); // far too difficult otherwise
648
649 int o_channels = num_channels();
650 int r_channels = num_channels()+w.num_channels();
651 int r_samples = Gof(num_samples(), w.num_samples());
652
653 resize(r_samples, r_channels);
654
655 for (k = 0; k < w.num_channels(); ++k)
656 for (i=0; i < w.num_samples(); i++)
657 a(i,k+o_channels) += w.a(i, k);
658
659 return *this;
660}
661
662ostream& operator << (ostream& p_values, const EST_Wave &sig)
663{
664 for (int i = 0; i < sig.num_samples(); ++i)
665 p_values << sig(i) << "\n";
666
667 return p_values;
668}
669
670int operator != (EST_Wave a, EST_Wave b)
671 { (void)a; (void)b; return 1; }
672int operator == (EST_Wave a, EST_Wave b)
673 { (void)a; (void)b; return 0; }
void fill(const T &v)
fill matrix with value v
Definition: EST_TMatrix.cc:314
INLINE const T & a_no_check(int row, int col) const
const access with no bounds check, care recommend
Definition: EST_TMatrix.h:184
void sub_matrix(EST_TMatrix< T > &sm, int r=0, int numr=EST_ALL, int c=0, int numc=EST_ALL)
Make the matrix {\tt sm} a window into this matrix.
Definition: EST_TMatrix.cc:578
void set_memory(T *buffer, int offset, int rows, int columns, int free_when_destroyed=0)
Definition: EST_TMatrix.cc:371
EST_TMatrix & add_rows(const EST_TMatrix &s)
The two versions of what might have been operator +=.
Definition: EST_TMatrix.cc:167
void resize(int rows, int cols, int set=1)
resize matrix
void copy(const EST_TSimpleMatrix< T > &a)
copy one matrix into another
static T * error_return
Definition: EST_TVector.h:230
void close(void)
Close stream.
Definition: EST_Token.cc:406
int tell(void) const
tell, synonym for filepos
Definition: EST_Token.h:363
int open(const EST_String &filename)
open a \Ref{EST_TokenStream} for a file.
Definition: EST_Token.cc:200
int seek(int position)
seek, reposition file pointer
Definition: EST_Token.cc:305
float & t(int i=0)
return time position of frame i
Definition: EST_Track.h:477
float & a(int i, int c=0)
Definition: EST_Track.cc:1022
int length() const
return number of frames in track
Definition: EST_Track.h:653
EST_read_status load_file(const EST_String filename, const EST_String filetype, int sample_rate, const EST_String sample_type, int bo, int nc, int offset=0, int length=0)
Definition: EST_Wave.cc:288
short & a(int i, int channel=0)
Definition: EST_Wave.cc:128
int num_channels() const
return the number of channels in the waveform
Definition: EST_Wave.h:145
int length() const
return the size of the waveform, i.e. the number of samples.
Definition: EST_Wave.h:151
short & a_safe(int i, int channel=0)
Definition: EST_Wave.cc:152
EST_Wave & operator=(const EST_Wave &w)
Assignment operator.
Definition: EST_Wave.cc:612
void compress(float mu, float limit)
Dynamic Range Compression - SaiKrishna May 2017.
Definition: EST_Wave.cc:503
int sample_rate() const
return the sampling rate (frequency)
Definition: EST_Wave.h:147
EST_read_status load(const EST_String filename, int offset=0, int length=0, int rate=default_sample_rate)
Definition: EST_Wave.cc:180
void resample(int rate)
Resample waveform to rate
Definition: EST_Wave.cc:489
void resize(int num_samples, int num_channels=EST_ALL, int set=1)
resize the waveform
Definition: EST_Wave.h:184
EST_Wave & operator|=(const EST_Wave &a)
Definition: EST_Wave.cc:642
float t(int i) const
return the time position in seconds of the ith sample
Definition: EST_Wave.h:137
void rescale(float gain, int normalize=0)
Definition: EST_Wave.cc:517
EST_Wave()
default constructor
Definition: EST_Wave.cc:63
EST_String sample_type() const
Definition: EST_Wave.h:163
EST_Wave & operator+=(const EST_Wave &a)
Definition: EST_Wave.cc:618
int num_samples() const
return the number of samples in the waveform
Definition: EST_Wave.h:143
void set_sample_rate(const int n)
Set sampling rate to n
Definition: EST_Wave.h:149