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   */
operator()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     */
operator()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
t(int i)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
num_samples()143   int num_samples() const { return p_values.num_rows();}
144   /// return the number of channels in the waveform
num_channels()145   int num_channels() const { return p_values.num_columns(); }
146   /// return the sampling rate (frequency)
sample_rate()147   int sample_rate() const { return p_sample_rate; }
148   /// Set sampling rate to <tt>n</tt>
set_sample_rate(const int n)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.
length()151   int length() const { return num_samples();}
152   /// return the time position of the last sample.
end()153   float end(){ return t(num_samples()-1); }
154 
155   /// Can we look N samples to the left?
have_left_context(unsigned int n)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 
sample_type()163   EST_String sample_type() const { return f_String("sample_type","short"); }
set_sample_type(const EST_String t)164   void set_sample_type(const EST_String t) { f_set("sample_type", t); }
165 
file_type()166   EST_String file_type() const { return f_String("file_type","riff"); }
set_file_type(const EST_String t)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
name()170   EST_String name() const { return f_String("name"); }
171 
172   /// Sets name.
set_name(const EST_String n)173   void set_name(const EST_String n){ f_set("name", n); }
174 
175   //@}
176 
values()177   const EST_SMatrix &values() const { return p_values; }
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   /** multiply all samples by a factor <tt>gain</tt>. This checks for
191       overflows and puts them to the maximum positive or negative value
192       as appropriate.
193   */
194   void rescale(float gain,int normalize=0);
195 
196   // multiply samples by a factor contour.  The factor_contour track
197   // should contains factor targets at time points throughout the wave,
198   // between which linear interpolation is used to calculate the factor
199   // for each sample.
200   void rescale( const EST_Track &factor_contour );
201 
202   /// clear waveform and set size to 0.
clear()203   void clear() {resize(0,EST_ALL);}
204 
205   void copy(const EST_Wave &from);
206 
207   void fill(short v=0, int channel=EST_ALL);
208 
209   void empty(int channel=EST_ALL) { fill(0,channel); }
210 
sample(EST_TVector<short> & sv,int n)211   void sample(EST_TVector<short> &sv, int n)
212     { p_values.row(sv, n); }
channel(EST_TVector<short> & cv,int n)213   void channel(EST_TVector<short> &cv, int n)
214     { p_values.column(cv, n); }
215 
216   void copy_channel(int n, short *buf, int offset=0, int num=EST_ALL) const
217     { p_values.copy_column(n, buf, offset, num); }
218   void copy_sample(int n, short *buf, int offset=0, int num=EST_ALL) const
219     {  p_values.copy_row(n, buf, offset, num); }
220 
221   void set_channel(int n, const short *buf, int offset=0, int num=EST_ALL)
222     { p_values.set_column(n, buf, offset, num); }
223   void set_sample(int n, const short *buf, int offset=0, int num=EST_ALL)
224     { p_values.set_row(n, buf, offset, num); }
225 
226 
227   void sub_wave(EST_Wave &sw,
228 		int offset=0, int num=EST_ALL,
229 		int start_c=0, int nchan=EST_ALL);
230 
231   void sub_wave(EST_Wave &sw,
232 		int offset=0, int num=EST_ALL,
233 		int start_c=0, int nchan=EST_ALL) const
234     { ((EST_Wave *)this)->sub_wave(sw, offset, num, start_c, nchan); }
235 
236   //@}
237 
238   /**@name File i/o functions */
239   //@{
240 
241   /** Load a file into the waveform. The load routine attempts to
242       automatically determine which file type is being loaded.  A
243       portion of the waveform can be loaded by setting <tt>
244       offset</tt> to the sample position from the beginning and
245       <length> to the number of required samples after this.  */
246 
247   EST_read_status load(const EST_String filename,
248 		       int offset=0,
249 		       int length = 0,
250 		       int rate = default_sample_rate);
251 
252   EST_read_status load(EST_TokenStream &ts,
253 		       int offset=0,
254 		       int length = 0,
255 		       int rate = default_sample_rate);
256 
257   EST_read_status load(const EST_String filename,
258 		       const EST_String filetype,
259 		       int offset=0,
260 		       int length = 0,
261 		       int rate = default_sample_rate);
262 
263   EST_read_status load(EST_TokenStream &ts,
264 		       const EST_String filetype,
265 		       int offset=0,
266 		       int length = 0,
267 		       int rate = default_sample_rate);
268 
269   /** Load a file of type <tt>filetype</tt> into the waveform. This
270       can be used to load unheadered files, in which case the fields
271       <tt>sample_rate, sample_type, bo</tt> and <tt>nc</tt> are used
272       to specify the sample rate, type, byte order and number of
273       channels.  A portion of the waveform can be loaded by setting
274       <tt> offset</tt> to the sample position from the beginning and
275       <length> to the number of required samples after this.
276   */
277 
278   EST_read_status load_file(const EST_String filename,
279 			    const EST_String filetype, int sample_rate,
280 			    const EST_String sample_type, int bo, int nc,
281 			    int offset = 0, int length = 0);
282   EST_read_status load_file(EST_TokenStream &ts,
283 			    const EST_String filetype, int sample_rate,
284 			    const EST_String sample_type, int bo, int nc,
285 			    int offset = 0, int length = 0);
286 
287   /* Save waveform to a file called <tt>filename</tt> of file
288      format <tt>EST_filetype</tt>.
289   */
290   EST_write_status save(const  EST_String filename,
291 			const EST_String EST_filetype = "");
292 
293   EST_write_status save(FILE *fp,
294 			const EST_String EST_filetype = "");
295 
296   EST_write_status save_file(const EST_String filename,
297 			     EST_String filetype,
298 			     EST_String sample_type, int bo);
299 
300   EST_write_status save_file(FILE *fp,
301 			     EST_String filetype,
302 			     EST_String sample_type, int bo);
303   //@}
304 
305   /// Assignment operator
306   EST_Wave& operator = (const EST_Wave& w);
307   /** Add to existing wave in serial. Waveforms must have the same
308       number of channels.
309   */
310   EST_Wave& operator +=(const EST_Wave &a);
311   /** Add wave in parallel, i.e. make wave <tt>a</tt> become new
312       channels in existing waveform.
313   */
314   EST_Wave& operator |=(const EST_Wave &a);
315 
316   /// print waveform
317   friend ostream& operator << (ostream& p_values, const EST_Wave &sig);
318 
319   // integrity check *** debug
integrity()320   void integrity() const { p_values.integrity() ; }
321 
322 };
323 
324 typedef EST_TList<EST_Wave> EST_WaveList;
325 
326 int operator != (EST_Wave a, EST_Wave b);
327 int operator == (EST_Wave a, EST_Wave b);
328 
329 #endif /* __Wave_H__ */
330