D:/work/code_by/Wave/WaveFile.cpp

查看本檔案說明文件.
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   //return (float)waveSize / sampleRate;
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   //本來是 waveSize = (waveSize - 1) * newSampleRate / sampleRate,
00243   //但是 (waveSize - 1) * newSampleRate 可能會overflow,所以寫成這樣
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     //本來是 j = i * sampleRate / newSampleRate
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 /* added by angie */
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)  //dst以byte為單位;off、len以sample為單位
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 

產生日期:Tue Jul 11 11:52:19 2006, 專案:cbmr, 產生器:  doxygen 1.4.7