Edinburgh Speech Tools  2.4-release
 All Classes Functions Variables Typedefs Enumerations Enumerator Friends Pages
EST_wave_aux.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 : June 1996 */
35 /*-----------------------------------------------------------------------*/
36 /* more EST_Wave class methods */
37 /* */
38 /*=======================================================================*/
39 
40 #include <cstring>
41 #include "EST_unix.h"
42 #include <cstdlib>
43 #include "EST_cutils.h"
44 #include "EST_string_aux.h"
45 #include "EST_Wave.h"
46 #include "EST_wave_utils.h"
47 #include "EST_wave_aux.h"
48 #include "EST_io_aux.h"
49 #include "EST_error.h"
50 
51 void extract(EST_Wave &sig, EST_Option &al);
52 
53 /* Allow EST_Wave to be used in an EST_Val */
54 VAL_REGISTER_CLASS(wave,EST_Wave)
55 
56 static EST_TValuedEnumDefinition<EST_sample_type_t, const char *,NO_INFO> st_names[] = {
57 {st_unknown, {"undef"}},
58 {st_schar, {"schar","byte"}},
59 {st_uchar, {"uchar"}},
60 {st_short, {"short"}},
61 {st_shorten, {"shorten"}},
62 {st_int, {"int"}},
63 {st_float, {"float"}},
64 {st_double, {"double"}},
65 {st_mulaw, {"mulaw"}},
66 {st_adpcm, {"adpcm"}},
67 {st_alaw, {"alaw"}},
68 {st_ascii, {"ascii"}},
69 {st_unknown, {0}}
70 };
71 
72 EST_TNamedEnum<EST_sample_type_t> EST_sample_type_map(st_names);
73 
74 void differentiate(EST_Wave &sig)
75 {
76  for (int i = 0; i < sig.num_samples() -1; ++i)
77  sig.a(i) = sig.a(i + 1) - sig.a(i);
78  sig.resize(sig.num_samples()-1);
79 }
80 
81 
82 void extract_channels(EST_Wave &single, const EST_Wave &multi,
83  EST_IList &ch_list)
84 {
85 
86  if (&single == &multi)
87  {
88  // some nasty person has passed us the same wave for output and input.
89  EST_Wave tmp;
90  extract_channels(tmp, multi, ch_list);
91  single.copy(tmp);
92  return;
93  }
94 
95  int channel, i;
96  int c = multi.num_channels();
97  int num_samples = multi.num_samples();
98 
99  short *buf = new short [num_samples];
100  EST_Litem *p;
101 
102  single.resize(num_samples, ch_list.length());
103  single.set_sample_rate(multi.sample_rate());
104  single.set_file_type(multi.file_type());
105 
106  for (i = 0, p = ch_list.head(); p; p = p->next(), ++i)
107  {
108  channel = ch_list(p);
109 
110  if (channel < 0 || channel >= c)
111  EST_error("Can't extract channel %d from %d channel waveform\n",
112  channel, c);
113 
114  multi.copy_channel(channel, buf);
115  single.set_channel(i, buf);
116  }
117 }
118 
119 int wave_extract_channel(EST_Wave &single, const EST_Wave &multi, int channel)
120 {
121  if (&single == &multi)
122  {
123  // some nasty person has passed us the same wave for output and input.
124  EST_Wave tmp;
125  int v = wave_extract_channel(tmp, multi, channel);
126  if(v==0)
127  single.copy(tmp);
128  return v;
129  }
130 
131  int c = multi.num_channels();
132 
133  if (channel < 0 || channel >= c)
134  {
135  cerr << "Can't extract channel " << channel << " from " <<
136  c << " channel waveform\n";
137  return -1;
138  }
139 
140  EST_Wave subwave;
141 
142  multi.sub_wave(subwave, 0, EST_ALL, channel, 1);
143 
144  single.copy(subwave);
145 
146  return 0;
147 }
148 
149 void extract_channels(EST_Wave &single, const EST_Wave &multi, int channel)
150 {
151  EST_IList a;
152  a.append(channel);
153  extract_channels(single, multi, a);
154 }
155 
156 void wave_combine_channels(EST_Wave &s,const EST_Wave &m)
157 {
158  if (&s == &m)
159  {
160  // some nasty person has passed us the same wave for output and input.
161  EST_Wave tmp;
162  wave_combine_channels(tmp,m);
163  s = tmp;
164  return;
165  }
166  s.resize(m.num_samples(), 1, FALSE);
168 
169  for(int i=0; i<m.num_samples(); i++)
170  {
171  double sum=0.0;
172  for(int j=0; j<m.num_channels(); j++)
173  sum += m.a(i,j);
174  s.a(i,0) = (int)(sum/m.num_channels() + 0.5);
175  }
176 }
177 
178 void add_waves(EST_Wave &s, const EST_Wave &m)
179 {
180  int new_samples = Gof(s.num_samples(), m.num_samples());
181  int new_channels = Gof(s.num_channels(), m.num_channels());
182 
183  s.resize(new_samples, new_channels, 1);
184 
185  for (int i = 0; i < m.num_samples(); i++)
186  for (int j = 0; j < m.num_channels(); j++)
187  s.a(i, j) += m.a(i, j);
188 }
189 
190 void invert(EST_Wave &sig)
191 {
192  sig.rescale(-1.0);
193 }
194 
195 void reverse(EST_Wave &sig)
196 {
197  int i, n;
198  short t;
199  n = (int)floor((float)(sig.num_samples())/2.0);
200 
201  for (i = 0; i < n; ++i)
202  {
203  t = sig.a_no_check(i);
204  sig.a_no_check(i) = sig.a_no_check(sig.num_samples() - 1 -i);
205  sig.a_no_check(sig.num_samples() - 1 -i) = t;
206  }
207 }
208 
209 void extract(EST_Wave &sig, EST_Option &al)
210 {
211  int from, to;
212  EST_Wave sub_wave, w2;
213 
214  if (al.present("-start"))
215  from = (int)(sig.sample_rate() * al.fval("-start"));
216  else if (al.present("-from"))
217  from = al.ival("-from");
218  else
219  from = 0;
220 
221  if (al.present("-end"))
222  to = (int)(sig.sample_rate() * al.fval("-end"));
223  else if (al.present("-to"))
224  to = al.ival("-to");
225  else
226  to = sig.num_samples();
227 
228  sig.sub_wave(sub_wave, from, to - from);
229  w2 = sub_wave;
230  sig = w2;
231 }
232 
233 void wave_info(EST_Wave &w)
234 {
235  EST_String t;
236  cout << "Duration: " <<
237  ftoString((float)w.num_samples()/(float)w.sample_rate(),4,1) << endl;
238 
239  cout << "Sample rate: " << w.sample_rate() << endl;
240  cout << "Number of samples: " << w.num_samples() << endl;
241  cout << "Number of channels: " << w.num_channels() << endl;
242  cout << "Header type: " << w.file_type() << endl;
243  cout << "Data type: " << w.sample_type() << endl;
244 }
245 
246 static EST_String options_wave_filetypes(void)
247 {
248  // Returns list of currently support wave file types
249  // Should be extracted from the list in EST_Wave (but that's
250  // not very clear :-(
251 
252  return "nist, est, esps, snd, riff, aiff, audlab, raw, ascii";
253 }
254 
255 EST_String options_subwave(void)
256 {
257  return
258  EST_String("")+
259  "-start <float> Extract sub-wave starting at this time, specified in \n"
260  " seconds\n\n"
261  "-end <float> Extract sub-wave ending at this time, specified in \n"
262  " seconds\n\n"
263  "-from <int> Extract sub-wave starting at this sample point\n\n"
264  "-to <int> Extract sub-wave ending at this sample point\n\n";
265 }
266 EST_String options_wave_input(void)
267 {
268  // The standard waveform input options
269  return
270  EST_String("")+
271  "-itype <string> Input file type (optional). If set to raw, this \n"
272  " indicates that the input file does not have a header. While \n"
273  " this can be used to specify file types other than raw, this is \n"
274  " rarely used for other purposes\n"
275  " as the file type of all the existing supported \n"
276  " types can be determined automatically from the \n"
277  " file's header. If the input file is unheadered, \n"
278  " files are assumed to be shorts (16bit). \n"
279  " Supported types are \n"
280  " "+options_wave_filetypes()+"\n\n"
281  "-n <int> Number of channels in an unheadered input file \n\n"
282  "-f <int> Sample rate in Hertz for an unheadered input file \n\n"
283  "-ibo <string> Input byte order in an unheadered input file: \n"
284  " possibliities are: MSB , LSB, native or nonnative. \n"
285  " Suns, HP, SGI Mips, M68000 are MSB (big endian) \n"
286  " Intel, Alpha, DEC Mips, Vax are LSB (little \n"
287  " endian)\n\n"
288  "-iswap Swap bytes. (For use on an unheadered input file)\n\n"
289  "-istype <string> Sample type in an unheadered input file:\n"
290  " short, mulaw, byte, ascii\n\n"
291  "-c <string> Select a single channel (starts from 0). \n"
292  " Waveforms can have multiple channels. This option \n"
293  " extracts a single channel for progcessing and \n"
294  " discards the rest. \n\n"+
295  options_subwave();
296 
297 // old option
298 // "-ulaw Assume unheadered input is 8k ulaw\n\n"
299 // this facility moved into na_play
300 // "-r* Select subrange of file. (ESPS compatible)\n\n"
301 
302 }
303 
304 EST_String options_wave_output(void)
305 {
306  return
307  EST_String("")+
308  "-o <ofile> Output filename. If not specified output is\n"
309  " to stdout.\n\n"
310  "-otype <string> Output file type, (optional). If no type is\n"
311  " Specified the type of the input file is assumed.\n"
312  " Supported types are: \n"
313  " "+options_wave_filetypes()+"\n\n"
314  "-F <int> Output sample rate in Hz. If this is different \n"
315  " from the input sample rate, resampling will occur \n\n"
316  "-obo <string> Output byte order: MSB, LSB, native, or nonnative. \n"
317  " Suns, HP, SGI Mips, M68000 are MSB (big endian) \n"
318  " Intel, Alpha, DEC Mips, Vax are LSB \n"
319  " (little endian)\n\n"
320  "-oswap Swap bytes when saving to output\n\n"+
321  "-ostype <string> Output sample type: short, mulaw, byte or ascii\n\n";
322 }
323 
324 Declare_TNamedEnum(EST_sample_type_t)
325 #if defined(INSTANTIATE_TEMPLATES)
326 #include "../base_class/EST_TNamedEnum.cc"
327 Instantiate_TNamedEnum(EST_sample_type_t)
328 #endif
329