Main Page   Namespace List   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   Related Pages  

wav_writer.cpp

00001 //----------------------------------------------------------------------------
00008 //----------------------------------------------------------------------------
00009 #include "WAVWriter.h"
00010 #include "BitResConverter.h"
00011 //----------------------------------------------------------------------------
00013 namespace ac3 {
00014 //----------------------------------------------------------------------------
00015 using namespace std;
00016 //----------------------------------------------------------------------------
00017 // Error messages of CWAVWriterException error numbers
00018 std::string CWAVWriterException::m_sUnknownError = "Unknown error";
00019 std::string CWAVWriterException::m_sError[WAVWRITER_ERROR_NUM] =
00020 {
00021   "No error",
00022   "File could not be created",
00023   "No file was openend",
00024   "Could not write to file",
00025   "Invalid format",
00026   "Format not supported"
00027 };
00028 //----------------------------------------------------------------------------
00029 // WAV-file format tags
00030 #define WAV_FORMAT_PCM 1
00031 //----------------------------------------------------------------------------
00036 std::string CWAVWriterException::GetString() const
00037 {
00038   if ((m_nReason >= 0) &&
00039       (m_nReason < WAVWRITER_ERROR_NUM))
00040   {
00041     string message = m_sError[m_nReason];
00042     if (m_sHint.length() > 0)
00043     {
00044       message += " (";
00045       message += m_sHint;
00046       message += ")";
00047     }
00048     return message;
00049   }
00050   else
00051     return m_sUnknownError;
00052 }
00053 //----------------------------------------------------------------------------
00055 CWAVWriter::CWAVWriter() : m_bFileOpen(false)
00056 {
00057 }
00058 //----------------------------------------------------------------------------
00060 CWAVWriter::CWAVWriter(const char* pszFilename, UINT32 nSampleRate,
00061                        UINT16 nChannelNum, UINT16 nBitResolution)
00062                         : m_bFileOpen(false)
00063 {
00064   OpenFile(pszFilename, nSampleRate, nChannelNum, nBitResolution);
00065 }
00066 //----------------------------------------------------------------------------
00068 CWAVWriter::CWAVWriter(const std::string& sFilename, UINT32 nSampleRate,
00069                        UINT16 nChannelNum, UINT16 nBitResolution)
00070                         : m_bFileOpen(false)
00071 {
00072   OpenFile(sFilename, nSampleRate, nChannelNum, nBitResolution);
00073 }
00074 //----------------------------------------------------------------------------
00076 CWAVWriter::~CWAVWriter()
00077 {
00078   CloseFile();
00079 }
00080 //----------------------------------------------------------------------------
00092 void CWAVWriter::OpenFile(const std::string& sFilename, UINT32 nSampleRate,
00093                           UINT16 nChannelNum, UINT16 nBitResolution)
00094 {
00095   OpenFile(sFilename.c_str(), nSampleRate, nChannelNum, nBitResolution);
00096 }
00097 //----------------------------------------------------------------------------
00109 void CWAVWriter::OpenFile(const char* pszFilename, UINT32 nSampleRate,
00110                           UINT16 nChannelNum, UINT16 nBitResolution)
00111 {
00112   // close file if opened
00113   CloseFile();
00114 
00115   if ((nSampleRate == 0) ||
00116       (nChannelNum == 0) ||
00117       ((nBitResolution !=  8) && (nBitResolution != 16) &&
00118        (nBitResolution != 24) && (nBitResolution != 32)))
00119     throw CWAVWriterException(WAVWRITER_INVALID_FORMAT);
00120 
00121   // create file for writing
00122   m_file.open(pszFilename, ios::out | ios::binary);
00123   if (!m_file.is_open())
00124     throw CWAVWriterException(WAVWRITER_COULD_NOT_CREATE_FILE, pszFilename);
00125 
00126   m_nSampleRate = nSampleRate;
00127   m_nChannels = nChannelNum;
00128   m_nBitsPerSample = nBitResolution;
00129   m_nAllSize = 0;
00130   m_nDataSize = 0;
00131   WriteHeader();  
00132   
00133   m_bFileOpen = true;  
00134 }
00135 //----------------------------------------------------------------------------
00140 void CWAVWriter::CloseFile()
00141 {
00142   if (m_bFileOpen)
00143   {
00144     // finish writing the file by writing the appropriate sizes
00145     // write all size
00146     m_file.seekp(m_allSizePos);
00147     WriteUINT32(m_nAllSize);
00148     // write data size
00149     m_file.seekp(m_dataSizePos);
00150     WriteUINT32(m_nDataSize);
00151     m_file.close();
00152     m_bFileOpen = false;
00153   }
00154   else if (m_file.is_open())
00155   {
00156     // well, something went wrong, but we have to close the file
00157     m_file.close();
00158   }
00159 }
00160 //----------------------------------------------------------------------------
00173 void CWAVWriter::Write8BitSamples(UINT8** ppSource, UINT32 nCount)
00174 {
00175   switch (m_nBitsPerSample)
00176   {
00177     case 8:
00178     {
00179       for (UINT32 nSample = 0; nSample < nCount; ++nSample)
00180         for (UINT16 nChannel = 0; nChannel < m_nChannels; ++nChannel)
00181         {
00182           WriteUINT8(ppSource[nChannel][nSample]);
00183             ++m_nDataSize;
00184             ++m_nAllSize;
00185         }
00186     }
00187     break;
00188     case 16:
00189     {
00190       for (UINT32 nSample = 0; nSample < nCount; ++nSample)
00191         for (UINT16 nChannel = 0; nChannel < m_nChannels; ++nChannel)
00192         {
00193           WriteINT16(CBitResConverter::UINT8ToINT16(
00194                        ppSource[nChannel][nSample]));
00195           m_nDataSize += 2;
00196           m_nAllSize += 2;
00197         }
00198     }
00199     break;
00200     case 24:
00201     {
00202       for (UINT32 nSample = 0; nSample < nCount; ++nSample)
00203         for (UINT16 nChannel = 0; nChannel < m_nChannels; ++nChannel)
00204         {
00205           WriteINT24(CBitResConverter::UINT8ToINT24(
00206                        ppSource[nChannel][nSample]));
00207           m_nDataSize += 3;
00208           m_nAllSize += 3;
00209         }
00210     }
00211     break;
00212     case 32:
00213     {
00214       for (UINT32 nSample = 0; nSample < nCount; ++nSample)
00215         for (UINT16 nChannel = 0; nChannel < m_nChannels; ++nChannel)
00216         {
00217           WriteINT32(CBitResConverter::UINT8ToINT32(
00218                        ppSource[nChannel][nSample]));
00219           m_nDataSize += 4;
00220           m_nAllSize += 4;
00221         }
00222     }
00223     break;
00224   }
00225 }
00226 //----------------------------------------------------------------------------
00239 void CWAVWriter::Write16BitSamples(INT16** ppSource, UINT32 nCount)
00240 {
00241   switch (m_nBitsPerSample)
00242   {
00243     case 8:
00244     {
00245       for (UINT32 nSample = 0; nSample < nCount; ++nSample)
00246         for (UINT16 nChannel = 0; nChannel < m_nChannels; ++nChannel)
00247         {
00248           WriteUINT8(CBitResConverter::INT16ToUINT8(
00249                        ppSource[nChannel][nSample]));
00250             ++m_nDataSize;
00251             ++m_nAllSize;
00252         }
00253     }
00254     break;
00255     case 16:
00256     {
00257       for (UINT32 nSample = 0; nSample < nCount; ++nSample)
00258         for (UINT16 nChannel = 0; nChannel < m_nChannels; ++nChannel)
00259         {
00260           WriteINT16(ppSource[nChannel][nSample]);
00261           m_nDataSize += 2;
00262           m_nAllSize += 2;
00263         }
00264     }
00265     break;
00266     case 24:
00267     {
00268       for (UINT32 nSample = 0; nSample < nCount; ++nSample)
00269         for (UINT16 nChannel = 0; nChannel < m_nChannels; ++nChannel)
00270         {
00271           WriteINT24(CBitResConverter::INT16ToINT24(
00272                        ppSource[nChannel][nSample]));
00273           m_nDataSize += 3;
00274           m_nAllSize += 3;
00275         }
00276     }
00277     break;
00278     case 32:
00279     {
00280       for (UINT32 nSample = 0; nSample < nCount; ++nSample)
00281         for (UINT16 nChannel = 0; nChannel < m_nChannels; ++nChannel)
00282         {
00283           WriteINT32(CBitResConverter::INT16ToINT32(
00284                        ppSource[nChannel][nSample]));
00285           m_nDataSize += 4;
00286           m_nAllSize += 4;
00287         }
00288     }
00289     break;
00290   }
00291 }
00292 //----------------------------------------------------------------------------
00306 void CWAVWriter::Write24BitSamples(INT32** ppSource, UINT32 nCount)
00307 {
00308   switch (m_nBitsPerSample)
00309   {
00310     case 8:
00311     {
00312       for (UINT32 nSample = 0; nSample < nCount; ++nSample)
00313         for (UINT16 nChannel = 0; nChannel < m_nChannels; ++nChannel)
00314         {
00315           WriteUINT8(CBitResConverter::INT24ToUINT8(
00316                        ppSource[nChannel][nSample]));
00317             ++m_nDataSize;
00318             ++m_nAllSize;
00319         }
00320     }
00321     break;
00322     case 16:
00323     {
00324       for (UINT32 nSample = 0; nSample < nCount; ++nSample)
00325         for (UINT16 nChannel = 0; nChannel < m_nChannels; ++nChannel)
00326         {
00327           WriteINT16(CBitResConverter::INT24ToINT16(
00328                        ppSource[nChannel][nSample]));
00329           m_nDataSize += 2;
00330           m_nAllSize += 2;
00331         }
00332     }
00333     break;
00334     case 24:
00335     {
00336       for (UINT32 nSample = 0; nSample < nCount; ++nSample)
00337         for (UINT16 nChannel = 0; nChannel < m_nChannels; ++nChannel)
00338         {
00339           WriteINT24(ppSource[nChannel][nSample]);
00340           m_nDataSize += 3;
00341           m_nAllSize += 3;
00342         }
00343     }
00344     break;
00345     case 32:
00346     {
00347       for (UINT32 nSample = 0; nSample < nCount; ++nSample)
00348         for (UINT16 nChannel = 0; nChannel < m_nChannels; ++nChannel)
00349         {
00350           WriteINT32(CBitResConverter::INT24ToINT32(
00351                        ppSource[nChannel][nSample]));
00352           m_nDataSize += 4;
00353           m_nAllSize += 4;
00354         }
00355     }
00356     break;
00357   }
00358 }
00359 //----------------------------------------------------------------------------
00372 void CWAVWriter::Write32BitSamples(INT32** ppSource, UINT32 nCount)
00373 {
00374   switch (m_nBitsPerSample)
00375   {
00376     case 8:
00377     {
00378       for (UINT32 nSample = 0; nSample < nCount; ++nSample)
00379         for (UINT16 nChannel = 0; nChannel < m_nChannels; ++nChannel)
00380         {
00381           WriteUINT8(CBitResConverter::INT32ToUINT8(
00382                        ppSource[nChannel][nSample]));
00383             ++m_nDataSize;
00384             ++m_nAllSize;
00385         }
00386     }
00387     break;
00388     case 16:
00389     {
00390       for (UINT32 nSample = 0; nSample < nCount; ++nSample)
00391         for (UINT16 nChannel = 0; nChannel < m_nChannels; ++nChannel)
00392         {
00393           WriteINT16(CBitResConverter::INT32ToINT16(
00394                        ppSource[nChannel][nSample]));
00395           m_nDataSize += 2;
00396           m_nAllSize += 2;
00397         }
00398     }
00399     break;
00400     case 24:
00401     {
00402       for (UINT32 nSample = 0; nSample < nCount; ++nSample)
00403         for (UINT16 nChannel = 0; nChannel < m_nChannels; ++nChannel)
00404         {
00405           WriteINT24(CBitResConverter::INT32ToINT24(
00406                        ppSource[nChannel][nSample]));
00407           m_nDataSize += 3;
00408           m_nAllSize += 3;
00409         }
00410     }
00411     break;
00412     case 32:
00413     {
00414       for (UINT32 nSample = 0; nSample < nCount; ++nSample)
00415         for (UINT16 nChannel = 0; nChannel < m_nChannels; ++nChannel)
00416         {
00417           WriteINT32(ppSource[nChannel][nSample]);
00418           m_nDataSize += 4;
00419           m_nAllSize += 4;
00420         }
00421     }
00422     break;
00423   }
00424 }
00425 //----------------------------------------------------------------------------
00426 // Writes the header of a WAV-file.
00427 void CWAVWriter::WriteHeader()
00428 {
00429   // write RIFF chunk Header
00430   WriteFOURCC("RIFF");
00431   // save actual position for writing size of file later.
00432   m_allSizePos = m_file.tellp();
00433   WriteUINT32(0);
00434   WriteFOURCC("WAVE");
00435   m_nAllSize += 4;
00436 
00437   // write "fmt" subschunk
00438   WriteFOURCC("fmt");
00439   // Currently only PCM-WAVE is supported. The chunk length is
00440   // 16 characters.
00441   WriteUINT32(16);
00442   m_nAllSize += 8;
00443   
00444   // Structure of format chunk is:
00445   // UINT16 nFormatTag;
00446   // UINT16 nChannels;
00447   // UINT32 nSampleRate;
00448   // UINT32 nAvgBytesPerSec;
00449   // UINT16 nBlockAlign;
00450   // UINT16 nBitsPerSample;
00451   WriteUINT16(WAV_FORMAT_PCM);
00452   WriteUINT16(m_nChannels);
00453   WriteUINT32(m_nSampleRate);
00454   WriteUINT32(m_nSampleRate * (UINT32)m_nChannels * 
00455               (UINT32)(m_nBitsPerSample/8));
00456   WriteUINT16(m_nChannels * (m_nBitsPerSample/8));
00457   WriteUINT16(m_nBitsPerSample);
00458   m_nAllSize += 16;
00459 
00460   // write start of "data" chunk
00461   WriteFOURCC("data");
00462   // save actual position for writing data size later.
00463   m_dataSizePos = m_file.tellp();
00464   WriteUINT32(0);
00465   m_nAllSize += 8;
00466 }
00467 //----------------------------------------------------------------------------
00468 // Writes a FOURCC code to the current position. That's a 4 character
00469 // string. If length of string is less than 4 space characters are written.
00470 void CWAVWriter::WriteFOURCC(std::string sFOURCC)
00471 {
00472   while (sFOURCC.length() < 4)
00473     sFOURCC += ' ';
00474   if (!m_file.write(sFOURCC.c_str(), 4))
00475     throw CWAVWriterException(WAVWRITER_WRITE_ERROR);
00476 }
00477 //----------------------------------------------------------------------------
00478 // Writes an usigned 8 bit integer to the current file position.
00479 void CWAVWriter::WriteUINT8(UINT8 nValue)
00480 {
00481   if (!m_file.write((char*)&nValue, 1))
00482     throw CWAVWriterException(WAVWRITER_WRITE_ERROR);
00483 }
00484 //----------------------------------------------------------------------------
00485 // Writes a signed 8 bit integer to the current file position.
00486 void CWAVWriter::WriteINT8(INT8 nValue)
00487 {
00488   WriteUINT8((UINT8)nValue);
00489 }
00490 //----------------------------------------------------------------------------
00491 // Writes an usigned 16 bit integer to the current file position.
00492 void CWAVWriter::WriteUINT16(UINT16 nValue)
00493 {
00494   char szBuffer[2];
00495   szBuffer[0] = (char)(nValue & 0xFF);
00496   szBuffer[1] = (char)(nValue >> 8);
00497   if (!m_file.write(szBuffer, 2))
00498     throw CWAVWriterException(WAVWRITER_WRITE_ERROR);
00499 }
00500 //----------------------------------------------------------------------------
00501 // Writes a signed 16 bit integer to the current file position.
00502 void CWAVWriter::WriteINT16(INT16 nValue)
00503 {
00504   WriteUINT16((UINT16)nValue);
00505 }
00506 //----------------------------------------------------------------------------
00507 // Writes an usigned 24 bit integer to the current file position.
00508 void CWAVWriter::WriteUINT24(UINT32 nValue)
00509 {
00510   char szBuffer[3];
00511   szBuffer[0] = (char)(nValue & 0xFF);
00512   nValue >>= 8;
00513   szBuffer[1] = (char)(nValue & 0xFF);
00514   szBuffer[2] = (char)(nValue >> 8);
00515   if (!m_file.write(szBuffer, 3))
00516     throw CWAVWriterException(WAVWRITER_WRITE_ERROR);
00517 }
00518 //----------------------------------------------------------------------------
00519 // Writes a signed 24 bit integer to the current file position.
00520 void CWAVWriter::WriteINT24(INT32 nValue)
00521 {
00522   WriteUINT24((UINT32)nValue);
00523 }
00524 //----------------------------------------------------------------------------
00525 // Writes an usigned 32 bit integer to the current file position.
00526 void CWAVWriter::WriteUINT32(UINT32 nValue)
00527 {
00528   char szBuffer[4];
00529   szBuffer[0] = (char)(nValue & 0xFF);
00530   nValue >>= 8;
00531   szBuffer[1] = (char)(nValue & 0xFF);
00532   nValue >>= 8;
00533   szBuffer[2] = (char)(nValue & 0xFF);
00534   szBuffer[3] = (char)(nValue >> 8);
00535   if (!m_file.write(szBuffer, 4))
00536     throw CWAVWriterException(WAVWRITER_WRITE_ERROR);
00537 }
00538 //----------------------------------------------------------------------------
00539 // Writes a signed 32 bit integer to the current file position.
00540 void CWAVWriter::WriteINT32(INT32 nValue)
00541 {
00542   WriteUINT32((UINT32)nValue);
00543 }
00544 //----------------------------------------------------------------------------
00545 } // namespace ac3
00546 //----------------------------------------------------------------------------

Generated on Sat Sep 25 14:06:43 2004 for ac3 by doxygen1.2.18