00001 /*!@file Audio/AudioWavFile.C File I/O on audio .wav files */ 00002 00003 // //////////////////////////////////////////////////////////////////// // 00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005 // 00005 // by the University of Southern California (USC) and the iLab at USC. // 00006 // See http://iLab.usc.edu for information about this project. // 00007 // //////////////////////////////////////////////////////////////////// // 00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00010 // in Visual Environments, and Applications'' by Christof Koch and // 00011 // Laurent Itti, California Institute of Technology, 2001 (patent // 00012 // pending; application number 09/912,225 filed July 23, 2001; see // 00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00014 // //////////////////////////////////////////////////////////////////// // 00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00016 // // 00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00018 // redistribute it and/or modify it under the terms of the GNU General // 00019 // Public License as published by the Free Software Foundation; either // 00020 // version 2 of the License, or (at your option) any later version. // 00021 // // 00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00025 // PURPOSE. See the GNU General Public License for more details. // 00026 // // 00027 // You should have received a copy of the GNU General Public License // 00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00030 // Boston, MA 02111-1307 USA. // 00031 // //////////////////////////////////////////////////////////////////// // 00032 // 00033 // Primary maintainer for this file: 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Audio/AudioWavFile.C $ 00035 // $Id: AudioWavFile.C 8648 2007-07-30 19:41:42Z abondada $ 00036 // 00037 00038 #ifndef AUDIO_AUDIOWAVFILE_C_DEFINED 00039 #define AUDIO_AUDIOWAVFILE_C_DEFINED 00040 00041 #include "Audio/AudioWavFile.H" 00042 #include "Util/log.H" 00043 #include <cstdio> 00044 00045 // ###################################################################### 00046 template <class T> 00047 void writeAudioWavFile(const std::string& fname, 00048 const AudioBuffer<T>& buf) 00049 { 00050 std::vector<AudioBuffer<T> > vbuf; 00051 vbuf.push_back(buf); 00052 writeAudioWavFile(fname, vbuf); 00053 } 00054 00055 // ###################################################################### 00056 template <class T> 00057 void writeAudioWavFile(const std::string& fname, 00058 const std::vector<AudioBuffer<T> >& buf) 00059 { 00060 FILE *fil = fopen(fname.c_str(), "wb"); 00061 if (fil == NULL) PLFATAL("Cannot write %s", fname.c_str()); 00062 00063 // Write a .wav file. Format was gleaned from 00064 // http://www.borg.com/~jglatt/tech/wave.htm and from 00065 // http://ccrma.stanford.edu/courses/422/projects/WaveFormat/ 00066 uint bufsiz = 0; 00067 for (uint i = 0; i < buf.size(); ++ i) bufsiz += buf[i].sizeBytes(); 00068 00069 const uint fsiz = bufsiz + 36; 00070 const uint freq = uint(buf[0].freq()); 00071 const uint brate = freq * sizeof(T) * buf[0].nchans(); // byte rate 00072 const byte bps = byte(sizeof(T) * 8); 00073 const uint blockalign = buf[0].nchans() * sizeof(T); 00074 00075 LDEBUG("buffer: freq=%u, brate=%u, bps=%d", 00076 freq, brate, int(bps)); 00077 00078 const byte header[44] = 00079 { 00080 /* 0-3 */ 'R', 'I', 'F', 'F', 00081 00082 /* 4-5 */ byte(fsiz & 0xFF), byte((fsiz >> 8) & 0xFF), 00083 /* 6-7 */ byte((fsiz >> 16) & 0xFF), byte((fsiz >> 24) & 0xFF), 00084 00085 /* 8-21 */ 'W', 'A', 'V', 'E', 'f', 'm', 't', ' ', 0x10, 0, 0, 0, 1, 0, 00086 /* 22-23 */ byte(buf[0].nchans()), 0, 00087 00088 /* 24-25 */ byte(freq & 0xFF), byte((freq >> 8) & 0xFF), 00089 /* 26-27 */ byte((freq >> 16) & 0xFF), byte((freq >> 24) & 0xFF), 00090 00091 /* 28-29 */ byte(brate & 0xFF), byte((brate >> 8) & 0xFF), 00092 /* 30-31 */ byte((brate >> 16) & 0xFF), byte((brate >> 24) & 0xFF), 00093 00094 /* 32-39 */ byte(blockalign & 0xFF), byte((blockalign >> 8) & 0xFF), 00095 /* 34-39 */ bps, 0, 'd', 'a', 't', 'a', 00096 00097 /* 40-41 */ byte(bufsiz & 0xFF), byte((bufsiz >> 8) & 0xFF), 00098 /* 42-43 */ byte((bufsiz >> 16) & 0xFF), byte((bufsiz >> 24) & 0xFF) 00099 }; 00100 00101 if (fwrite(header, 44, 1, fil) != 1) 00102 PLFATAL("Error writing header to %s", fname.c_str()); 00103 00104 for (uint i = 0; i < buf.size(); ++ i) 00105 if (fwrite(buf[i].getDataPtr(), buf[i].sizeBytes(), 1, fil) != 1) 00106 PLFATAL("Error writing data chunk %u to %s", i, fname.c_str()); 00107 00108 fclose(fil); 00109 00110 LINFO("%d bytes written to %s", bufsiz, fname.c_str()); 00111 } 00112 00113 // ###################################################################### 00114 template <class T> 00115 void readAudioWavFile(const std::string& fname, AudioBuffer<T>& buf) 00116 { 00117 FILE *fil = fopen(fname.c_str(), "rb"); 00118 if (fil == NULL) PLFATAL("Cannot read %s", fname.c_str()); 00119 00120 // Read a .wav file. Format was gleaned from 00121 // http://www.borg.com/~jglatt/tech/wave.htm and from 00122 // http://ccrma.stanford.edu/courses/422/projects/WaveFormat/ 00123 byte header[44]; 00124 if (fread(header, 44, 1, fil) != 1) 00125 PLFATAL("Error reading header from %s", fname.c_str()); 00126 00127 // decode header: 00128 if (header[0]!='R' || header[1]!='I' || header[2]!='F' || header[3]!='F') 00129 LFATAL("Wrong magic - %s is not a .wav file", fname.c_str()); 00130 00131 const uint nchan = header[22]; 00132 const uint freq = header[24] | (header[25]<<8) | 00133 (header[26]<<16) | (header[27]<<24); 00134 const uint blockalign = header[32] + (header[33]<<8); 00135 const uint bps = header[34]; 00136 const uint bufsiz = 00137 header[40] | (header[41]<<8) | (header[42]<<16) | (header[43]<<24); 00138 00139 LDEBUG("%s: nchan=%u, freq=%u, blockalign=%u, bps=%u, bufsiz=%u", 00140 fname.c_str(), nchan, freq, blockalign, bps, bufsiz); 00141 00142 if (bps != sizeof(T) * 8) 00143 LFATAL("Wrong bps: file=%u, buffer=%u", bps, uint(sizeof(T))); 00144 00145 // initialize the AudioBuffer: 00146 AudioBuffer<T> b(bufsiz / (nchan * (bps / 8)), nchan, float(freq), NO_INIT); 00147 00148 // read the audio data: 00149 if (fread(b.getDataPtr(), bufsiz, 1, fil) != 1) 00150 PLFATAL("Error reading data from %s", fname.c_str()); 00151 00152 // return buffer: 00153 fclose(fil); 00154 buf = b; 00155 } 00156 00157 // template instantiations: 00158 template void writeAudioWavFile(const std::string& fname, 00159 const std::vector<AudioBuffer<byte> >& buf); 00160 template void writeAudioWavFile(const std::string& fname, 00161 const std::vector<AudioBuffer<uint16> >& buf); 00162 template void writeAudioWavFile(const std::string& fname, 00163 const std::vector<AudioBuffer<int16> >& buf); 00164 00165 template void writeAudioWavFile(const std::string& fname, 00166 const AudioBuffer<byte>& buf); 00167 template void writeAudioWavFile(const std::string& fname, 00168 const AudioBuffer<uint16>& buf); 00169 template void writeAudioWavFile(const std::string& fname, 00170 const AudioBuffer<int16>& buf); 00171 00172 template void readAudioWavFile(const std::string& fname, 00173 AudioBuffer<byte>& buf); 00174 template void readAudioWavFile(const std::string& fname, 00175 AudioBuffer<uint16>& buf); 00176 template void readAudioWavFile(const std::string& fname, 00177 AudioBuffer<int16>& buf); 00178 00179 // ###################################################################### 00180 /* So things look consistent in everyone's emacs... */ 00181 /* Local Variables: */ 00182 /* mode: c++ */ 00183 /* indent-tabs-mode: nil */ 00184 /* End: */ 00185 00186 #endif // DEVICES_AUDIOWAVFILE_C_DEFINED