00001
00008
00009 #include "WAVWriter.h"
00010 #include "BitResConverter.h"
00011
00013
00014
00015 using namespace std;
00016
00017
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
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
00056 {
00057 }
00058
00060
00061 UINT16 nChannelNum, UINT16 nBitResolution)
00062 : m_bFileOpen(false)
00063 {
00064 OpenFile(pszFilename, nSampleRate, nChannelNum, nBitResolution);
00065 }
00066
00068
00069 UINT16 nChannelNum, UINT16 nBitResolution)
00070 : m_bFileOpen(false)
00071 {
00072 OpenFile(sFilename, nSampleRate, nChannelNum, nBitResolution);
00073 }
00074
00076
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
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
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
00145
00146 m_file.seekp(m_allSizePos);
00147 WriteUINT32(m_nAllSize);
00148
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
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
00427 void CWAVWriter::WriteHeader()
00428 {
00429
00430 WriteFOURCC("RIFF");
00431
00432 m_allSizePos = m_file.tellp();
00433 WriteUINT32(0);
00434 WriteFOURCC("WAVE");
00435 m_nAllSize += 4;
00436
00437
00438 WriteFOURCC("fmt");
00439
00440
00441 WriteUINT32(16);
00442 m_nAllSize += 8;
00443
00444
00445
00446
00447
00448
00449
00450
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
00461 WriteFOURCC("data");
00462
00463 m_dataSizePos = m_file.tellp();
00464 WriteUINT32(0);
00465 m_nAllSize += 8;
00466 }
00467
00468
00469
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
00479 void CWAVWriter::WriteUINT8(UINT8 nValue)
00480 {
00481 if (!m_file.write((char*)&nValue, 1))
00482 throw CWAVWriterException(WAVWRITER_WRITE_ERROR);
00483 }
00484
00485
00486 void CWAVWriter::WriteINT8(INT8 nValue)
00487 {
00488 WriteUINT8((UINT8)nValue);
00489 }
00490
00491
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
00502 void CWAVWriter::WriteINT16(INT16 nValue)
00503 {
00504 WriteUINT16((UINT16)nValue);
00505 }
00506
00507
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
00520 void CWAVWriter::WriteINT24(INT32 nValue)
00521 {
00522 WriteUINT24((UINT32)nValue);
00523 }
00524
00525
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
00540 void CWAVWriter::WriteINT32(INT32 nValue)
00541 {
00542 WriteUINT32((UINT32)nValue);
00543 }
00544
00545 }
00546