"Fossies" - the Fresh Open Source Software Archive 
Member "speech_tools/speech_class/EST_Wave.cc" (24 Oct 2017, 16431 Bytes) of package /linux/misc/speech_tools-2.5.0-release.tar.gz:
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
58 const EST_String DEF_FILE_TYPE = "riff";
59 const EST_String DEF_SAMPLE_TYPE = "short";
60
61 const int EST_Wave::default_sample_rate=16000;
62
63 EST_Wave::EST_Wave()
64 {
65 default_vals();
66 }
67
68 EST_Wave::EST_Wave(const EST_Wave &w)
69 {
70 default_vals();
71 copy(w);
72 }
73
74 EST_Wave::EST_Wave(int n, int c, int sr)
75 {
76 default_vals(n,c);
77 set_sample_rate(sr);
78 }
79
80 EST_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);
86 set_sample_rate(sample_rate);
87 }
88
89 void 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
98 void EST_Wave::free_wave()
99 {
100 if (!p_values.p_sub_matrix)
101 p_values.resize(0,0);
102 clear_features();
103 }
104
105 EST_Wave::~EST_Wave()
106 {
107 free_wave();
108 }
109
110 void EST_Wave::copy_setup(const EST_Wave &w)
111 {
112 p_sample_rate = w.p_sample_rate;
113 copy_features(w);
114 }
115
116 void EST_Wave::copy_data(const EST_Wave &w)
117 {
118 p_values.copy(w.p_values);
119 }
120
121 void EST_Wave::copy(const EST_Wave &w)
122 {
123 copy_setup(w);
124
125 copy_data(w);
126 }
127
128 short &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
147 short EST_Wave::a(int i, int channel) const
148 {
149 return ((EST_Wave *)this)->a(i,channel);
150 }
151
152 short &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
166 void 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
180 EST_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;
185 EST_TokenStream ts;
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
198 EST_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
239 EST_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;
245 EST_TokenStream ts;
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
260 EST_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
288 EST_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;
294 EST_TokenStream ts;
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
309 EST_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
339 void 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);
349 sw.set_sample_rate(sample_rate());
350 }
351
352 EST_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
372 EST_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
395 EST_write_status EST_Wave::save_file(const EST_String filename,
396 EST_String ftype,
397 EST_String stype, int obo)
398 {
399 FILE *fp;
400
401 if (filename == "-")
402 fp = stdout;
403 else if ((fp = fopen(filename,"wb")) == 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
416 EST_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 }
440
441 void EST_Wave::resample(int new_freq)
442 {
443 // Resample wave to new sample rate
444 if (new_freq != p_sample_rate)
445 {
446 if (p_values.rateconv(p_sample_rate, new_freq) != 0)
447 cerr << "rateconv: failed to convert from " << p_sample_rate <<
448 " to " << new_freq << "\n";
449 else
450 set_sample_rate(new_freq);
451 }
452
453 }
454
455 void EST_Wave::compress(float mu, float lim)
456 {
457 int x;
458
459 for (int i = 0; i < num_samples(); ++i)
460 {
461 for (int j = 0; j< num_channels(); ++j)
462 {
463 x = a_no_check(i,j);
464 a_no_check(i,j) = lim * (sgn(x)*(log(1+(mu/lim)*abs(x))/log(1+mu)));
465 }
466 }
467 }
468
469 void EST_Wave::rescale(float gain, int normalize)
470 {
471 int ns;
472 float factor = gain;
473 float nsf;
474
475 if (normalize)
476 {
477 int max = 0;
478 for (int i = 0; i < num_samples(); ++i)
479 for (int j = 0; j < num_channels(); ++j)
480 if (abs(a_no_check(i,j)) > max)
481 max = abs(a_no_check(i,j));
482 if (fabs(max/32766.0-gain) < 0.001)
483 return; /* already normalized */
484 else
485 factor *= 32766.0/(float)max;
486 }
487
488 for (int i = 0; i < num_samples(); ++i)
489 for (int j = 0; j < num_channels(); ++j)
490 {
491 if (factor == 1.0)
492 ns = a_no_check(i,j); // avoid float fluctuations
493 else if (factor == -1.0)
494 ns = -a_no_check(i,j); // avoid float fluctuations
495 else
496 {
497 nsf = (float)a_no_check(i,j) * factor;
498 if (nsf < 0.0)
499 ns = (int)(nsf - 0.5);
500 else
501 ns = (int)(nsf + 0.5);
502 }
503 if (ns < -32766)
504 a_no_check(i,j)= -32766;
505 else if (ns > 32766)
506 a_no_check(i,j)= 32766;
507 else
508 a_no_check(i,j)= ns;
509 }
510 }
511
512 void EST_Wave::rescale( const EST_Track &fc )
513 {
514 int ns, start_sample, end_sample;
515 float target1, target2, increment, factor, nsf;
516
517 int fc_length = fc.length();
518 int _num_channels = num_channels();
519
520 cerr << ((int)(fc.t(fc_length-1) * p_sample_rate)) << endl;
521
522 if( ((int)(fc.t(fc_length-1) * p_sample_rate)) > num_samples() )
523 EST_error( "Factor contour track exceeds waveform length (%d samples)",
524 (fc.t(fc_length-1) * p_sample_rate) - num_samples() );
525
526 start_sample = static_cast<unsigned int>( fc.t( 0 )*p_sample_rate );
527 target1 = fc.a(0,0); // could use separate channels for each waveform channel
528
529 for ( int k = 1; k<fc_length; ++k ){
530 end_sample = static_cast<unsigned int>( fc.t( k )*p_sample_rate );
531 target2 = fc.a(k);
532
533 increment = (target2-target1)/(end_sample-start_sample+1);
534
535 factor = target1;
536 for( int i=start_sample; i<end_sample; ++i, factor+=increment )
537 for( int j=0; j<_num_channels; ++j ){
538 if (factor == 1.0)
539 ns = a_no_check(i,j); // avoid float fluctuations
540 else if (factor == -1.0)
541 ns = -a_no_check(i,j); // avoid float fluctuations
542 else
543 {
544 nsf = (float)a_no_check(i,j) * factor;
545 if (nsf < 0.0)
546 ns = (int)(nsf - 0.5);
547 else
548 ns = (int)(nsf + 0.5);
549 }
550 if (ns < -32766)
551 a_no_check(i,j)= -32766;
552 else if (ns > 32766)
553 a_no_check(i,j)= 32766;
554 else
555 a_no_check(i,j)= ns;
556 }
557 start_sample = end_sample;
558 target1 = target2;
559 }
560 }
561
562
563
564 EST_Wave &EST_Wave::operator =(const EST_Wave &w)
565 {
566 copy(w);
567 return *this;
568 }
569
570 EST_Wave &EST_Wave::operator +=(const EST_Wave &w)
571 {
572 EST_Wave w2;
573 const EST_Wave *toadd = &w;
574
575 if (w.num_channels() != num_channels())
576 {
577 cerr << "Cannot concatenate waveforms with differing numbers of channels\n";
578 return *this;
579 }
580
581 if (p_sample_rate != w.sample_rate())
582 {
583 w2 = w;
584 w2.resample(p_sample_rate);
585 toadd= &w2;
586 }
587
588 p_values.add_rows(toadd->p_values);
589
590 return *this;
591 }
592
593 // add wave p_values to existing wave in parallel to create multi-channel wave.
594 EST_Wave &EST_Wave::operator |=(const EST_Wave &wi)
595 {
596 int i, k;
597 EST_Wave w = wi; // to allow resampling of const
598
599 w.resample(p_sample_rate); // far too difficult otherwise
600
601 int o_channels = num_channels();
602 int r_channels = num_channels()+w.num_channels();
603 int r_samples = Gof(num_samples(), w.num_samples());
604
605 resize(r_samples, r_channels);
606
607 for (k = 0; k < w.num_channels(); ++k)
608 for (i=0; i < w.num_samples(); i++)
609 a(i,k+o_channels) += w.a(i, k);
610
611 return *this;
612 }
613
614 ostream& operator << (ostream& p_values, const EST_Wave &sig)
615 {
616 for (int i = 0; i < sig.num_samples(); ++i)
617 p_values << sig(i) << "\n";
618
619 return p_values;
620 }
621
622 int operator != (EST_Wave a, EST_Wave b)
623 { (void)a; (void)b; return 1; }
624 int operator == (EST_Wave a, EST_Wave b)
625 { (void)a; (void)b; return 0; }