00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
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
00064
00065
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();
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 'R', 'I', 'F', 'F',
00081
00082 byte(fsiz & 0xFF), byte((fsiz >> 8) & 0xFF),
00083 byte((fsiz >> 16) & 0xFF), byte((fsiz >> 24) & 0xFF),
00084
00085 'W', 'A', 'V', 'E', 'f', 'm', 't', ' ', 0x10, 0, 0, 0, 1, 0,
00086 byte(buf[0].nchans()), 0,
00087
00088 byte(freq & 0xFF), byte((freq >> 8) & 0xFF),
00089 byte((freq >> 16) & 0xFF), byte((freq >> 24) & 0xFF),
00090
00091 byte(brate & 0xFF), byte((brate >> 8) & 0xFF),
00092 byte((brate >> 16) & 0xFF), byte((brate >> 24) & 0xFF),
00093
00094 byte(blockalign & 0xFF), byte((blockalign >> 8) & 0xFF),
00095 bps, 0, 'd', 'a', 't', 'a',
00096
00097 byte(bufsiz & 0xFF), byte((bufsiz >> 8) & 0xFF),
00098 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
00121
00122
00123 byte header[44];
00124 if (fread(header, 44, 1, fil) != 1)
00125 PLFATAL("Error reading header from %s", fname.c_str());
00126
00127
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
00146 AudioBuffer<T> b(bufsiz / (nchan * (bps / 8)), nchan, float(freq), NO_INIT);
00147
00148
00149 if (fread(b.getDataPtr(), bufsiz, 1, fil) != 1)
00150 PLFATAL("Error reading data from %s", fname.c_str());
00151
00152
00153 fclose(fil);
00154 buf = b;
00155 }
00156
00157
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
00181
00182
00183
00184
00185
00186 #endif // DEVICES_AUDIOWAVFILE_C_DEFINED