1 ////////////////////////////////////////////////////////////////////////////////
2 ///
3 /// Classes for easy reading & writing of WAV sound files.
4 ///
5 /// For big-endian CPU, define BIG_ENDIAN during compile-time to correctly
6 /// parse the WAV files with such processors.
7 ///
8 /// Admittingly, more complete WAV reader routines may exist in public domain, but
9 /// the reason for 'yet another' one is that those generic WAV reader libraries are
10 /// exhaustingly large and cumbersome! Wanted to have something simpler here, i.e.
11 /// something that's not already larger than rest of the SoundTouch/SoundStretch program...
12 ///
13 /// Author        : Copyright (c) Olli Parviainen
14 /// Author e-mail : oparviai 'at' iki.fi
15 /// SoundTouch WWW: http://www.surina.net/soundtouch
16 ///
17 ////////////////////////////////////////////////////////////////////////////////
18 //
19 // License :
20 //
21 //  SoundTouch audio processing library
22 //  Copyright (c) Olli Parviainen
23 //
24 //  This library is free software; you can redistribute it and/or
25 //  modify it under the terms of the GNU Lesser General Public
26 //  License as published by the Free Software Foundation; either
27 //  version 2.1 of the License, or (at your option) any later version.
28 //
29 //  This library is distributed in the hope that it will be useful,
30 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
31 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
32 //  Lesser General Public License for more details.
33 //
34 //  You should have received a copy of the GNU Lesser General Public
35 //  License along with this library; if not, write to the Free Software
36 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
37 //
38 ////////////////////////////////////////////////////////////////////////////////
39 
40 #ifndef WAVFILE_H
41 #define WAVFILE_H
42 
43 #include <stdio.h>
44 
45 #ifndef uint
46 typedef unsigned int uint;
47 #endif
48 
49 
50 /// WAV audio file 'riff' section header
51 typedef struct
52 {
53     char riff_char[4];
54     uint package_len;
55     char wave[4];
56 } WavRiff;
57 
58 /// WAV audio file 'format' section header
59 typedef struct
60 {
61     char  fmt[4];
62     unsigned int   format_len;
63     unsigned short fixed;
64     unsigned short channel_number;
65     unsigned int   sample_rate;
66     unsigned int   byte_rate;
67     unsigned short byte_per_sample;
68     unsigned short bits_per_sample;
69 } WavFormat;
70 
71 /// WAV audio file 'fact' section header
72 typedef struct
73 {
74     char fact_field[4];
75     uint fact_len;
76     uint fact_sample_len;
77 } WavFact;
78 
79 /// WAV audio file 'data' section header
80 typedef struct
81 {
82     char  data_field[4];
83     uint  data_len;
84 } WavData;
85 
86 
87 /// WAV audio file header
88 typedef struct
89 {
90     WavRiff   riff;
91     WavFormat format;
92     WavFact   fact;
93     WavData   data;
94 } WavHeader;
95 
96 
97 /// Base class for processing WAV audio files.
98 class WavFileBase
99 {
100 private:
101     /// Conversion working buffer;
102     char *convBuff;
103     int convBuffSize;
104 
105 protected:
106     WavFileBase();
107     virtual ~WavFileBase();
108 
109     /// Get pointer to conversion buffer of at min. given size
110     void *getConvBuffer(int sizeByte);
111 };
112 
113 
114 /// Class for reading WAV audio files.
115 class WavInFile : protected WavFileBase
116 {
117 private:
118     /// File pointer.
119     FILE *fptr;
120 
121     /// Position within the audio stream
122     long position;
123 
124     /// Counter of how many bytes of sample data have been read from the file.
125     long dataRead;
126 
127     /// WAV header information
128     WavHeader header;
129 
130     /// Init the WAV file stream
131     void init();
132 
133     /// Read WAV file headers.
134     /// \return zero if all ok, nonzero if file format is invalid.
135     int readWavHeaders();
136 
137     /// Checks WAV file header tags.
138     /// \return zero if all ok, nonzero if file format is invalid.
139     int checkCharTags() const;
140 
141     /// Reads a single WAV file header block.
142     /// \return zero if all ok, nonzero if file format is invalid.
143     int readHeaderBlock();
144 
145     /// Reads WAV file 'riff' block
146     int readRIFFBlock();
147 
148 public:
149     /// Constructor: Opens the given WAV file. If the file can't be opened,
150     /// throws 'runtime_error' exception.
151     WavInFile(const char *filename);
152 
153     WavInFile(FILE *file);
154 
155     /// Destructor: Closes the file.
156     ~WavInFile();
157 
158     /// Rewind to beginning of the file
159     void rewind();
160 
161     /// Get sample rate.
162     uint getSampleRate() const;
163 
164     /// Get number of bits per sample, i.e. 8 or 16.
165     uint getNumBits() const;
166 
167     /// Get sample data size in bytes. Ahem, this should return same information as
168     /// 'getBytesPerSample'...
169     uint getDataSizeInBytes() const;
170 
171     /// Get total number of samples in file.
172     uint getNumSamples() const;
173 
174     /// Get number of bytes per audio sample (e.g. 16bit stereo = 4 bytes/sample)
175     uint getBytesPerSample() const;
176 
177     /// Get number of audio channels in the file (1=mono, 2=stereo)
178     uint getNumChannels() const;
179 
180     /// Get the audio file length in milliseconds
181     uint getLengthMS() const;
182 
183     /// Returns how many milliseconds of audio have so far been read from the file
184     ///
185     /// \return elapsed duration in milliseconds
186     uint getElapsedMS() const;
187 
188     /// Reads audio samples from the WAV file. This routine works only for 8 bit samples.
189     /// Reads given number of elements from the file or if end-of-file reached, as many
190     /// elements as are left in the file.
191     ///
192     /// \return Number of 8-bit integers read from the file.
193     int read(unsigned char *buffer, int maxElems);
194 
195     /// Reads audio samples from the WAV file to 16 bit integer format. Reads given number
196     /// of elements from the file or if end-of-file reached, as many elements as are
197     /// left in the file.
198     ///
199     /// \return Number of 16-bit integers read from the file.
200     int read(short *buffer,     ///< Pointer to buffer where to read data.
201              int maxElems       ///< Size of 'buffer' array (number of array elements).
202              );
203 
204     /// Reads audio samples from the WAV file to floating point format, converting
205     /// sample values to range [-1,1[. Reads given number of elements from the file
206     /// or if end-of-file reached, as many elements as are left in the file.
207     /// Notice that reading in float format supports 8/16/24/32bit sample formats.
208     ///
209     /// \return Number of elements read from the file.
210     int read(float *buffer,     ///< Pointer to buffer where to read data.
211              int maxElems       ///< Size of 'buffer' array (number of array elements).
212              );
213 
214     /// Check end-of-file.
215     ///
216     /// \return Nonzero if end-of-file reached.
217     int eof() const;
218 };
219 
220 
221 /// Class for writing WAV audio files.
222 class WavOutFile : protected WavFileBase
223 {
224 private:
225     /// Pointer to the WAV file
226     FILE *fptr;
227 
228     /// WAV file header data.
229     WavHeader header;
230 
231     /// Counter of how many bytes have been written to the file so far.
232     int bytesWritten;
233 
234     /// Fills in WAV file header information.
235     void fillInHeader(const uint sampleRate, const uint bits, const uint channels);
236 
237     /// Finishes the WAV file header by supplementing information of amount of
238     /// data written to file etc
239     void finishHeader();
240 
241     /// Writes the WAV file header.
242     void writeHeader();
243 
244 public:
245     /// Constructor: Creates a new WAV file. Throws a 'runtime_error' exception
246     /// if file creation fails.
247     WavOutFile(const char *fileName,    ///< Filename
248                int sampleRate,          ///< Sample rate (e.g. 44100 etc)
249                int bits,                ///< Bits per sample (8 or 16 bits)
250                int channels             ///< Number of channels (1=mono, 2=stereo)
251                );
252 
253     WavOutFile(FILE *file, int sampleRate, int bits, int channels);
254 
255     /// Destructor: Finalizes & closes the WAV file.
256     ~WavOutFile();
257 
258     /// Write data to WAV file. This function works only with 8bit samples.
259     /// Throws a 'runtime_error' exception if writing to file fails.
260     void write(const unsigned char *buffer, ///< Pointer to sample data buffer.
261                int numElems                 ///< How many array items are to be written to file.
262                );
263 
264     /// Write data to WAV file. Throws a 'runtime_error' exception if writing to
265     /// file fails.
266     void write(const short *buffer,     ///< Pointer to sample data buffer.
267                int numElems             ///< How many array items are to be written to file.
268                );
269 
270     /// Write data to WAV file in floating point format, saturating sample values to range
271     /// [-1..+1[. Throws a 'runtime_error' exception if writing to file fails.
272     void write(const float *buffer,     ///< Pointer to sample data buffer.
273                int numElems             ///< How many array items are to be written to file.
274                );
275 };
276 
277 #endif
278