00001 #include <string.h>
00002 #include "WaveFile.h"
00003
00004 TWaveFile::TWaveFile()
00005 {
00006 wave = NULL;
00007 userData = NULL;
00008 Clear();
00009 sampleRate = 11025;
00010 bitRate = 8;
00011 bytesPerSample = bitRate / 8;
00012 }
00013
00014 TWaveFile::~TWaveFile()
00015 {
00016 Clear();
00017 }
00018
00019 void TWaveFile::Skip(FILE *fin, int size)
00020 {
00021 char skip[256];
00022
00023 while (size >= 256)
00024 {
00025 fread(skip, 1, 256, fin);
00026 size -= 256;
00027 }
00028 fread(skip, 1, size, fin);
00029 }
00030
00031 int TWaveFile::FindChunk(FILE *fin, char *name)
00032 {
00033 char chunk[5];
00034 int size;
00035
00036 while (true)
00037 {
00038 chunk[4] = '\0';
00039 fread(chunk, 1, 4, fin);
00040 fread(&size, 4, 1, fin);
00041 if (strcmp(chunk, name) == 0)
00042 return size;
00043 Skip(fin, size);
00044 if (feof(fin))
00045 return 0;
00046 }
00047 }
00048
00049 bool TWaveFile::ReadChunk(FILE *fin, void *data, int size, int &restSize)
00050 {
00051 int s;
00052
00053 s = fread(data, 1, size, fin);
00054 restSize -= s;
00055 return s == size && restSize >= 0;
00056 }
00057
00058 bool TWaveFile::Load(char *name)
00059 {
00060 FILE *fin;
00061 char data[5], *cwave;
00062 int totalSize, chunkSize, format, channel;
00063
00064 Clear();
00065
00066 fin = fopen(name, "rb");
00067 if (fin == NULL)
00068 return false;
00069
00070 data[4] = '\0';
00071 fread(data, 1, 4, fin);
00072 if (strcmp(data, "RIFF"))
00073 goto ERROR;
00074 if (fread(&totalSize, 4, 1, fin) < 1)
00075 goto ERROR;
00076 if (!ReadChunk(fin, data, 4, totalSize))
00077 goto ERROR;
00078 if (strcmp(data, "WAVE"))
00079 goto ERROR;
00080
00081 chunkSize = FindChunk(fin, "fmt ");
00082 if (!ReadChunk(fin, data, 4, chunkSize))
00083 goto ERROR;
00084 format = data[0];
00085 if (format != 1 && format != 7)
00086 goto ERROR;
00087 channel = data[2];
00088 if (channel != 1)
00089 goto ERROR;
00090 if (!ReadChunk(fin, &sampleRate, 4, chunkSize))
00091 goto ERROR;
00092 if (!ReadChunk(fin, data, 4, chunkSize))
00093 goto ERROR;
00094 if (!ReadChunk(fin, data, 4, chunkSize))
00095 goto ERROR;
00096 bitRate = (data[0] / channel) * 8;
00097 bytesPerSample = bitRate / 8;
00098 Skip(fin, chunkSize);
00099
00100 chunkSize = FindChunk(fin, "data");
00101 cwave = new char[waveSize = chunkSize];
00102 if (!ReadChunk(fin, cwave, waveSize, chunkSize))
00103 {
00104 delete[] cwave;
00105 waveSize = 0;
00106 goto ERROR;
00107 }
00108
00109 wave = new int[waveSize /= bytesPerSample];
00110 WaveCopy(wave, cwave, waveSize);
00111 delete[] cwave;
00112
00113 chunkSize = FindChunk(fin, "user");
00114 if (chunkSize > 0)
00115 {
00116 userData = new char[chunkSize + 1];
00117 userData[chunkSize] = 0;
00118 ReadChunk(fin, userData, chunkSize, chunkSize);
00119 }
00120
00121 fclose(fin);
00122
00123 if (format == 7)
00124 MuLawToPcm();
00125
00126 return true;
00127
00128 ERROR:
00129 fclose(fin);
00130 return false;
00131 }
00132
00133 bool TWaveFile::Save(char *name)
00134 {
00135 FILE *fout;
00136 int i, userChunkSize;
00137 char *cwave;
00138
00139 fout = fopen(name, "wb");
00140 if (fout == NULL)
00141 return false;
00142
00143 userChunkSize = userData? strlen(userData) + 8 : 0;
00144
00145 fprintf(fout, "RIFF");
00146 i = 38 + userChunkSize + waveSize * bytesPerSample;
00147 fwrite(&i, 4, 1, fout);
00148 fprintf(fout, "WAVEfmt ");
00149 i = 0x12;
00150 fwrite(&i, 4, 1, fout);
00151 i = 0x10001;
00152 fwrite(&i, 4, 1, fout);
00153 fwrite(&sampleRate, 4, 1, fout);
00154 i = sampleRate * bytesPerSample;
00155 fwrite(&i, 4, 1, fout);
00156 i = bytesPerSample | (bitRate << 16);
00157 fwrite(&i, 4, 1, fout);
00158 i = 0;
00159 fwrite(&i, 2, 1, fout);
00160 fprintf(fout, "data");
00161 i = waveSize * bytesPerSample;
00162 fwrite(&i, 4, 1, fout);
00163
00164 cwave = new char[i];
00165 WaveCopy(cwave, wave, waveSize);
00166 fwrite(cwave, 1, i, fout);
00167 delete[] cwave;
00168
00169 if (userData)
00170 {
00171 userChunkSize -= 8;
00172 fprintf(fout, "user");
00173 fwrite(&userChunkSize, 4, 1, fout);
00174 fwrite(userData, 1, userChunkSize, fout);
00175 }
00176
00177 fclose(fout);
00178
00179 return true;
00180 }
00181
00182 int TWaveFile::GetSampleRate(void)
00183 {
00184 return sampleRate;
00185 }
00186
00187 int TWaveFile::GetBitRate(void)
00188 {
00189 return bitRate;
00190 }
00191
00192 void TWaveFile::SetFormat(int newSampleRate, int newBitRate)
00193 {
00194 int i;
00195
00196 if (newBitRate != bitRate)
00197 {
00198 if (newBitRate == 8)
00199 for (i = 0; i < waveSize; i++)
00200 wave[i] = wave[i] >> 8;
00201 else
00202 for (i = 0; i < waveSize; i++)
00203 wave[i] = wave[i] << 8;
00204 }
00205 Resample(newSampleRate);
00206
00207 sampleRate = newSampleRate;
00208 bitRate = newBitRate;
00209 bytesPerSample = bitRate / 8;
00210 }
00211
00212 int TWaveFile::GetDuration(void)
00213 {
00214
00215 return waveSize / sampleRate;
00216 }
00217
00218 void TWaveFile::SetWave(int *w, int size)
00219 {
00220 Clear();
00221 wave = new int[waveSize = size];
00222 memcpy(wave, w, waveSize * sizeof(int));
00223 }
00224
00225 void TWaveFile::Clear(void)
00226 {
00227 delete[] wave;
00228 wave = NULL;
00229 waveSize = 0;
00230 delete[] userData;
00231 userData = NULL;
00232 }
00233
00234 void TWaveFile::Resample(int newSampleRate)
00235 {
00236 int i, j, r, n;
00237 int *newWave;
00238
00239 if (newSampleRate == sampleRate || waveSize == 0)
00240 return;
00241
00242
00243
00244 r = (waveSize - 1) % sampleRate;
00245 waveSize = (waveSize - 1 - r) / sampleRate * newSampleRate + r * newSampleRate / sampleRate;
00246 newWave = new int[waveSize];
00247 for (i = 0; i < waveSize; i++)
00248 {
00249
00250 r = i % newSampleRate;
00251 j = (i - r) / newSampleRate * sampleRate + r * sampleRate / newSampleRate;
00252 n = (10.0f * i * sampleRate) / newSampleRate - 10 * j;
00253 newWave[i] = (wave[j] * (10 - n) + wave[j + 1] * n) / 10;
00254 }
00255 delete[] wave;
00256 wave = newWave;
00257 }
00258
00259 void TWaveFile::MuLawToPcm(void)
00260 {
00261 int i;
00262 static int exp_lut[8] = {0, 132, 396, 924, 1980, 4092, 8316, 16764};
00263 unsigned char mulaw;
00264 int sign, exponent;
00265
00266 for (i = 0; i < waveSize; i++)
00267 {
00268 mulaw = wave[i] + 128;
00269 mulaw = ~mulaw;
00270 sign = mulaw & 0x80;
00271 exponent = (mulaw >> 4) & 0x07;
00272 wave[i] = ((exp_lut[exponent]) + ((mulaw & 0x0F) << (exponent + 3))) >> 8;
00273 if (sign != 0)
00274 wave[i] = -wave[i];
00275 }
00276 }
00277
00278 void TWaveFile::WaveCopy(char *dst, int *src, int size)
00279 {
00280 int i;
00281 unsigned char *ucp;
00282 short *sp;
00283
00284 if (bytesPerSample == 1)
00285 {
00286 ucp = (unsigned char *)dst;
00287 for (i = size - 1; i >= 0; i--)
00288 ucp[i] = src[i] + 128;
00289 }
00290 else
00291 {
00292 sp = (short *)dst;
00293 for (i = size - 1; i >= 0; i--)
00294 sp[i] = src[i];
00295 }
00296 }
00297
00298 void TWaveFile::WaveCopy(int *dst, char *src, int size)
00299 {
00300 int i;
00301 unsigned char *ucp;
00302 short *sp;
00303
00304 if (bytesPerSample == 1)
00305 {
00306 ucp = (unsigned char *)src;
00307 for (i = size - 1; i >= 0; i--)
00308 dst[i] = ucp[i] - 128;
00309 }
00310 else
00311 {
00312 sp = (short *)src;
00313 for (i = size - 1; i >= 0; i--)
00314 dst[i] = sp[i];
00315 }
00316 }
00317
00318
00319 void TWaveFile::WaveCopy(int *dst, char *src, int size, int offset)
00320 {
00321 int i;
00322 unsigned char *ucp;
00323 short *sp;
00324
00325 if (bytesPerSample == 1)
00326 {
00327 ucp = (unsigned char *)src;
00328 for (i = size - 1; i >= 0; i--)
00329 dst[i+offset] = ucp[i] - 128;
00330 }
00331 else
00332 {
00333 sp = (short *)src;
00334 for (i = size - 1; i >= 0; i--)
00335 dst[i+offset] = sp[i];
00336 }
00337 }
00338
00339 int TWaveFile::WaveCopy(char *dst, int off, int len)
00340 {
00341 int i;
00342
00343 if (wave == NULL)
00344 return 0;
00345
00346 if (off+len > waveSize)
00347 len = waveSize - off;
00348
00349 if (bytesPerSample == 1)
00350 for (i = 0; i < len; i++)
00351 dst[i] = wave[i+off] + 128;
00352 else
00353 for (i = 0; i < len; i++)
00354 {
00355 dst[i*2] = wave[i+off] & 0xFF;
00356 dst[i*2 + 1] = (wave[i+off] >> 8) & 0xFF;
00357 }
00358
00359 return len;
00360 }
00361
00362 void TWaveFile::Trim(int from, int to)
00363 {
00364 int *newwave;
00365
00366 if (from < 0)
00367 from = 0;
00368 if (to >= waveSize)
00369 to = waveSize - 1;
00370 newwave = new int[waveSize = to - from + 1];
00371 memcpy(newwave, wave + from, waveSize * sizeof(int));
00372 delete[] wave;
00373 wave = newwave;
00374 }
00375