Edinburgh Speech Tools 2.4-release
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
51void extract(EST_Wave &sig, EST_Option &al);
52
53/* Allow EST_Wave to be used in an EST_Val */
54VAL_REGISTER_CLASS(wave,EST_Wave)
55
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
72EST_TNamedEnum<EST_sample_type_t> EST_sample_type_map(st_names);
73
74void 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
82void 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
119int 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
149void 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
156void 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
178void 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
190void invert(EST_Wave &sig)
191{
192 sig.rescale(-1.0);
193}
194
195void 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
209void 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
233void 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
246static 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
255EST_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}
266EST_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, alaw, 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
304EST_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, alaw, mulaw, byte or ascii\n\n";
322}
323
324Declare_TNamedEnum(EST_sample_type_t)
325#if defined(INSTANTIATE_TEMPLATES)
326#include "../base_class/EST_TNamedEnum.cc"
327Instantiate_TNamedEnum(EST_sample_type_t)
328#endif
329
float fval(const EST_String &rkey, int m=1) const
Definition: EST_Option.cc:98
int ival(const EST_String &rkey, int m=1) const
Definition: EST_Option.cc:76
const int present(const K &rkey) const
Returns true if key is present.
Definition: EST_TKVL.cc:222
void append(const T &item)
add item onto end of list
Definition: EST_TList.h:191
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 sample_rate() const
return the sampling rate (frequency)
Definition: EST_Wave.h:147
void resize(int num_samples, int num_channels=EST_ALL, int set=1)
resize the waveform
Definition: EST_Wave.h:184
void rescale(float gain, int normalize=0)
Definition: EST_Wave.cc:517
EST_String sample_type() const
Definition: EST_Wave.h:163
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