"Fossies" - the Fresh Open Source Software Archive 
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 /* */
34 /* Author : Paul Taylor and Alan W Black */
35 /* Rewritten : Richard Caley */
36 /* ------------------------------------------------------------------- */
37 /* EST_Wave Class header file */
38 /* */
39 /*************************************************************************/
40
41 #ifndef __Wave_H__
42 #define __Wave_H__
43
44 #include <cstdio>
45 #include "EST_Featured.h"
46 #include "EST_rw_status.h"
47 #include "EST_types.h"
48
49 class EST_Track;
50 class EST_String;
51 class EST_TokenStream;
52
53
54 /** A class for storing digital waveforms. The waveform is stored as
55 an array of 16 bit shorts. Multiple channels are supported, but if no
56 channel information is given the 0th channel is accessed.
57 <p>
58
59 The waveforms can be of any sample rate, and can be changed to another
60 sampling rate using the <tt>resample</tt> function.
61
62 */
63
64 class EST_Wave : public EST_Featured
65 {
66 protected:
67 EST_SMatrix p_values;
68
69 int p_sample_rate;
70
71 void default_vals(int n=0, int c=1);
72 void free_wave();
73 void copy_data(const EST_Wave &w);
74 void copy_setup(const EST_Wave &w);
75
76 public:
77
78 static const int default_sample_rate;
79 static const int default_num_channels;
80
81 /// default constructor
82 EST_Wave();
83 /// copy constructor
84 EST_Wave(const EST_Wave &a);
85
86 EST_Wave(int n, int c, int sr);
87
88 /// Construct from memory supplied by caller
89 EST_Wave(int samps, int chans,
90 short *memory, int offset=0, int sample_rate=default_sample_rate,
91 int free_when_destroyed=0);
92
93 ~EST_Wave();
94
95
96 /**@name Access functions for finding amplitudes of samples */
97 //@{
98
99 /** return amplitude of sample <tt>i</tt> from channel <tt>
100 channel</tt>. By default the 0th channel is selected. This
101 function can be used for assignment.
102 */
103 short &a(int i, int channel = 0);
104 short a(int i, int channel = 0) const;
105 INLINE short &a_no_check(int i, int channel = 0)
106 { return p_values.a_no_check(i,channel); }
107 INLINE short a_no_check(int i, int channel = 0) const
108 { return p_values.a_no_check(i,channel); }
109 INLINE short &a_no_check_1(int i, int channel = 0)
110 { return p_values.a_no_check_1(i,channel); }
111 INLINE short a_no_check_1(int i, int channel = 0) const
112 { return p_values.a_no_check_1(i,channel); }
113
114
115 /** explicit set_a, easier to wrap than assignment
116 */
117 INLINE short set_a(int i, int channel = 0, short val = 0)
118 { return a(i,channel) = val; }
119
120 /** return amplitude of sample <tt>i</tt> from channel <tt>
121 channel</tt>. By default the 0th channel is selected.
122 */
123 short operator()(int i, int channel) const
124 { return a(i,channel); }
125
126 /** return amplitude of sample <tt>i</tt> from channel 0.
127 */
128 short operator()(int i) const
129 { return a(i,0); }
130
131 /** Version of a() that returns zero if index is out of array
132 bounds. This is particularly useful in signal processing when
133 you want to have windows going off the end of the waveform. */
134 short &a_safe(int i, int channel = 0);
135
136 /// return the time position in seconds of the ith sample
137 float t(int i) const { return (float)i/(float)p_sample_rate; }
138 //@}
139
140 /**@name Information functions */
141 //@{
142 /// return the number of samples in the waveform
143 int num_samples() const { return p_values.num_rows();}
144 /// return the number of channels in the waveform
145 int num_channels() const { return p_values.num_columns(); }
146 /// return the sampling rate (frequency)
147 int sample_rate() const { return p_sample_rate; }
148 /// Set sampling rate to <tt>n</tt>
149 void set_sample_rate(const int n){p_sample_rate = n;}
150 /// return the size of the waveform, i.e. the number of samples.
151 int length() const { return num_samples();}
152 /// return the time position of the last sample.
153 float end(){ return t(num_samples()-1); }
154
155 /// Can we look N samples to the left?
156 bool have_left_context(unsigned int n) const
157 { return p_values.have_rows_before(n); }
158
159 /** returns the file format of the file from which the waveform
160 was read. If the waveform has not been read from a file, this is set
161 to the default type */
162
163 EST_String sample_type() const { return f_String("sample_type","short"); }
164 void set_sample_type(const EST_String t) { f_set("sample_type", t); }
165
166 EST_String file_type() const { return f_String("file_type","riff"); }
167 void set_file_type(const EST_String t) { f_set("file_type", t); }
168
169 /// A string identifying the waveform, commonly used to store the filename
170 EST_String name() const { return f_String("name"); }
171
172 /// Sets name.
173 void set_name(const EST_String n){ f_set("name", n); }
174
175 //@}
176
177 const EST_SMatrix &values() const { return p_values; }
178 EST_SMatrix &values() { return p_values; }
179
180 /**@name Waveform manipulation functions */
181 //@{
182
183 /// resize the waveform
184 void resize(int num_samples, int num_channels = EST_ALL, int set=1)
185 { p_values.resize(num_samples, num_channels, set); }
186
187 /// Resample waveform to <tt>rate</tt>
188 void resample(int rate);
189
190 /// Dynamic Range Compression - SaiKrishna May 2017
191 void compress(float mu, float limit);
192
193 /** multiply all samples by a factor <tt>gain</tt>. This checks for
194 overflows and puts them to the maximum positive or negative value
195 as appropriate.
196 */
197 void rescale(float gain,int normalize=0);
198
199 // multiply samples by a factor contour. The factor_contour track
200 // should contains factor targets at time points throughout the wave,
201 // between which linear interpolation is used to calculate the factor
202 // for each sample.
203 void rescale( const EST_Track &factor_contour );
204
205 /// clear waveform and set size to 0.
206 void clear() {resize(0,EST_ALL);}
207
208 void copy(const EST_Wave &from);
209
210 void fill(short v=0, int channel=EST_ALL);
211
212 void empty(int channel=EST_ALL) { fill(0,channel); }
213
214 void sample(EST_TVector<short> &sv, int n)
215 { p_values.row(sv, n); }
216 void channel(EST_TVector<short> &cv, int n)
217 { p_values.column(cv, n); }
218
219 void copy_channel(int n, short *buf, int offset=0, int num=EST_ALL) const
220 { p_values.copy_column(n, buf, offset, num); }
221 void copy_sample(int n, short *buf, int offset=0, int num=EST_ALL) const
222 { p_values.copy_row(n, buf, offset, num); }
223
224 void set_channel(int n, const short *buf, int offset=0, int num=EST_ALL)
225 { p_values.set_column(n, buf, offset, num); }
226 void set_sample(int n, const short *buf, int offset=0, int num=EST_ALL)
227 { p_values.set_row(n, buf, offset, num); }
228
229
230 void sub_wave(EST_Wave &sw,
231 int offset=0, int num=EST_ALL,
232 int start_c=0, int nchan=EST_ALL);
233
234 void sub_wave(EST_Wave &sw,
235 int offset=0, int num=EST_ALL,
236 int start_c=0, int nchan=EST_ALL) const
237 { ((EST_Wave *)this)->sub_wave(sw, offset, num, start_c, nchan); }
238
239 //@}
240
241 /**@name File i/o functions */
242 //@{
243
244 /** Load a file into the waveform. The load routine attempts to
245 automatically determine which file type is being loaded. A
246 portion of the waveform can be loaded by setting <tt>
247 offset</tt> to the sample position from the beginning and
248 <length> to the number of required samples after this. */
249
250 EST_read_status load(const EST_String filename,
251 int offset=0,
252 int length = 0,
253 int rate = default_sample_rate);
254
255 EST_read_status load(EST_TokenStream &ts,
256 int offset=0,
257 int length = 0,
258 int rate = default_sample_rate);
259
260 EST_read_status load(const EST_String filename,
261 const EST_String filetype,
262 int offset=0,
263 int length = 0,
264 int rate = default_sample_rate);
265
266 EST_read_status load(EST_TokenStream &ts,
267 const EST_String filetype,
268 int offset=0,
269 int length = 0,
270 int rate = default_sample_rate);
271
272 /** Load a file of type <tt>filetype</tt> into the waveform. This
273 can be used to load unheadered files, in which case the fields
274 <tt>sample_rate, sample_type, bo</tt> and <tt>nc</tt> are used
275 to specify the sample rate, type, byte order and number of
276 channels. A portion of the waveform can be loaded by setting
277 <tt> offset</tt> to the sample position from the beginning and
278 <length> to the number of required samples after this.
279 */
280
281 EST_read_status load_file(const EST_String filename,
282 const EST_String filetype, int sample_rate,
283 const EST_String sample_type, int bo, int nc,
284 int offset = 0, int length = 0);
285 EST_read_status load_file(EST_TokenStream &ts,
286 const EST_String filetype, int sample_rate,
287 const EST_String sample_type, int bo, int nc,
288 int offset = 0, int length = 0);
289
290 /* Save waveform to a file called <tt>filename</tt> of file
291 format <tt>EST_filetype</tt>.
292 */
293 EST_write_status save(const EST_String filename,
294 const EST_String EST_filetype = "");
295
296 EST_write_status save(FILE *fp,
297 const EST_String EST_filetype = "");
298
299 EST_write_status save_file(const EST_String filename,
300 EST_String filetype,
301 EST_String sample_type, int bo);
302
303 EST_write_status save_file(FILE *fp,
304 EST_String filetype,
305 EST_String sample_type, int bo);
306 //@}
307
308 /// Assignment operator
309 EST_Wave& operator = (const EST_Wave& w);
310 /** Add to existing wave in serial. Waveforms must have the same
311 number of channels.
312 */
313 EST_Wave& operator +=(const EST_Wave &a);
314 /** Add wave in parallel, i.e. make wave <tt>a</tt> become new
315 channels in existing waveform.
316 */
317 EST_Wave& operator |=(const EST_Wave &a);
318
319 /// print waveform
320 friend ostream& operator << (ostream& p_values, const EST_Wave &sig);
321
322 // integrity check *** debug
323 void integrity() const { p_values.integrity() ; }
324
325 };
326
327 typedef EST_TList<EST_Wave> EST_WaveList;
328
329 int operator != (EST_Wave a, EST_Wave b);
330 int operator == (EST_Wave a, EST_Wave b);
331
332 #endif /* __Wave_H__ */