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