00001
00008
00009 #include <vector>
00010 #include <cmath>
00011 #include "WAVReader.h"
00012 #include "BitResConverter.h"
00013
00015
00016
00017 using namespace std;
00018
00019
00020 std::string CWAVReaderException::m_sUnknownError = "Unknown error";
00021 std::string CWAVReaderException::m_sError[WAVREADER_ERROR_NUM] =
00022 {
00023 "No error",
00024 "File could not be opened",
00025 "No file is opened",
00026 "Read error (file corrupt?)",
00027 "Invalid format (file corrupt?)",
00028 "Format not supported",
00029 "Chunk not found",
00030 "Sample does not exist",
00031 "Channel does not exist"
00032 };
00033
00034
00035 #define WAV_FORMAT_PCM 1
00036
00041 std::string CWAVReaderException::GetString() const
00042 {
00043 if ((m_nReason >= 0) &&
00044 (m_nReason < WAVREADER_ERROR_NUM))
00045 {
00046 string message = m_sError[m_nReason];
00047 if (m_sHint.length() > 0)
00048 {
00049 message += " (";
00050 message += m_sHint;
00051 message += ")";
00052 }
00053 return message;
00054 }
00055 else
00056 return m_sUnknownError;
00057 }
00058
00060
00061 {
00062 }
00063
00065
00066 {
00067 OpenFile(pszFilename);
00068 }
00069
00071
00072 {
00073 OpenFile(sFilename);
00074 }
00075
00077
00078 {
00079 CloseFile();
00080 }
00081
00083
00084 {
00085 if (m_bFileOpen)
00086 {
00087 m_file.close();
00088 m_bFileOpen = false;
00089 }
00090 }
00091
00098 void CWAVReader::OpenFile(const std::string& sFilename)
00099 {
00100 OpenFile(sFilename.c_str());
00101 }
00102
00109 void CWAVReader::OpenFile(const char* pszFilename)
00110 {
00111
00112 CloseFile();
00113 m_file.open(pszFilename, ios::in | ios::binary);
00114 if (!m_file.is_open())
00115 throw CWAVReaderException(WAVREADER_FILE_OPEN_ERROR, pszFilename);
00116
00117
00118 ParseHeader();
00119
00120 m_bFileOpen = true;
00121 }
00122
00145 void CWAVReader::GetSamplesAs8Bit(UINT32 nCount, UINT16 nChannel,
00146 UINT8* pnBuffer, UINT32 nStart)
00147 {
00148
00149
00150 switch (m_nBitsPerSample)
00151 {
00152 case 8:
00153 {
00154 vector<UINT8> data(nCount);
00155 Read8BitSamples(nStart, nCount, nChannel, &data[0]);
00156 CBitResConverter::ConvertBitResolution(nCount, &data[0], 8,
00157 pnBuffer, 8);
00158 }
00159 break;
00160 case 16:
00161 {
00162 vector<INT16> data(nCount);
00163 Read16BitSamples(nStart, nCount, nChannel, &data[0]);
00164 CBitResConverter::ConvertBitResolution(nCount, &data[0], 16,
00165 pnBuffer, 8);
00166 }
00167 break;
00168 case 24:
00169 {
00170 vector<INT32> data(nCount);
00171 Read24BitSamples(nStart, nCount, nChannel, &data[0]);
00172 CBitResConverter::ConvertBitResolution(nCount, &data[0], 24,
00173 pnBuffer, 8);
00174 }
00175 break;
00176 case 32:
00177 {
00178 vector<INT32> data(nCount);
00179 Read32BitSamples(nStart, nCount, nChannel, &data[0]);
00180 CBitResConverter::ConvertBitResolution(nCount, &data[0], 32,
00181 pnBuffer, 8);
00182 }
00183 break;
00184 }
00185 }
00186
00208 void CWAVReader::GetSamplesAs16Bit(UINT32 nCount, UINT16 nChannel,
00209 INT16* pnBuffer, UINT32 nStart)
00210 {
00211
00212
00213 switch (m_nBitsPerSample)
00214 {
00215 case 8:
00216 {
00217 vector<UINT8> data(nCount);
00218 Read8BitSamples(nStart, nCount, nChannel, &data[0]);
00219 CBitResConverter::ConvertBitResolution(nCount, &data[0], 8,
00220 pnBuffer, 16);
00221 }
00222 break;
00223 case 16:
00224 {
00225 vector<INT16> data(nCount);
00226 Read16BitSamples(nStart, nCount, nChannel, &data[0]);
00227 CBitResConverter::ConvertBitResolution(nCount, &data[0], 16,
00228 pnBuffer, 16);
00229 }
00230 break;
00231 case 24:
00232 {
00233 vector<INT32> data(nCount);
00234 Read24BitSamples(nStart, nCount, nChannel, &data[0]);
00235 CBitResConverter::ConvertBitResolution(nCount, &data[0], 24,
00236 pnBuffer, 16);
00237 }
00238 break;
00239 case 32:
00240 {
00241 vector<INT32> data(nCount);
00242 Read32BitSamples(nStart, nCount, nChannel, &data[0]);
00243 CBitResConverter::ConvertBitResolution(nCount, &data[0], 32,
00244 pnBuffer, 16);
00245 }
00246 break;
00247 }
00248 }
00249
00273 void CWAVReader::GetSamplesAs24Bit(UINT32 nCount, UINT16 nChannel,
00274 INT32* pnBuffer, UINT32 nStart)
00275 {
00276
00277
00278 switch (m_nBitsPerSample)
00279 {
00280 case 8:
00281 {
00282 vector<UINT8> data(nCount);
00283 Read8BitSamples(nStart, nCount, nChannel, &data[0]);
00284 CBitResConverter::ConvertBitResolution(nCount, &data[0], 8,
00285 pnBuffer, 24);
00286 }
00287 break;
00288 case 16:
00289 {
00290 vector<INT16> data(nCount);
00291 Read16BitSamples(nStart, nCount, nChannel, &data[0]);
00292 CBitResConverter::ConvertBitResolution(nCount, &data[0], 16,
00293 pnBuffer, 24);
00294 }
00295 break;
00296 case 24:
00297 {
00298 vector<INT32> data(nCount);
00299 Read24BitSamples(nStart, nCount, nChannel, &data[0]);
00300 CBitResConverter::ConvertBitResolution(nCount, &data[0], 24,
00301 pnBuffer, 24);
00302 }
00303 break;
00304 case 32:
00305 {
00306 vector<INT32> data(nCount);
00307 Read32BitSamples(nStart, nCount, nChannel, &data[0]);
00308 CBitResConverter::ConvertBitResolution(nCount, &data[0], 32,
00309 pnBuffer, 24);
00310 }
00311 break;
00312 }
00313 }
00314
00336 void CWAVReader::GetSamplesAs32Bit(UINT32 nCount, UINT16 nChannel,
00337 INT32* pnBuffer, UINT32 nStart)
00338 {
00339
00340
00341 switch (m_nBitsPerSample)
00342 {
00343 case 8:
00344 {
00345 vector<UINT8> data(nCount);
00346 Read8BitSamples(nStart, nCount, nChannel, &data[0]);
00347 CBitResConverter::ConvertBitResolution(nCount, &data[0], 8,
00348 pnBuffer, 32);
00349 }
00350 break;
00351 case 16:
00352 {
00353 vector<INT16> data(nCount);
00354 Read16BitSamples(nStart, nCount, nChannel, &data[0]);
00355 CBitResConverter::ConvertBitResolution(nCount, &data[0], 16,
00356 pnBuffer, 32);
00357 }
00358 break;
00359 case 24:
00360 {
00361 vector<INT32> data(nCount);
00362 Read24BitSamples(nStart, nCount, nChannel, &data[0]);
00363 CBitResConverter::ConvertBitResolution(nCount, &data[0], 24,
00364 pnBuffer, 32);
00365 }
00366 break;
00367 case 32:
00368 {
00369 vector<INT32> data(nCount);
00370 Read32BitSamples(nStart, nCount, nChannel, &data[0]);
00371 CBitResConverter::ConvertBitResolution(nCount, &data[0], 32,
00372 pnBuffer, 32);
00373 }
00374 break;
00375 }
00376 }
00377
00385 void CWAVReader::SetChannelPos(UINT16 nChannel, UINT32 nNewPos)
00386 {
00387
00388 if (nChannel >= m_nChannels)
00389 throw CWAVReaderException(WAVREADER_CHANNEL_DOES_NOT_EXIST);
00390
00391
00392 if (!SampleExists(nNewPos))
00393 throw CWAVReaderException(WAVREADER_SAMPLE_DOES_NOT_EXIST);
00394
00395 m_channelPos[nChannel] = nNewPos;
00396 }
00397
00402 UINT32 CWAVReader::GetChannelPos(UINT16 nChannel)
00403 {
00404
00405 if (nChannel >= m_nChannels)
00406 throw CWAVReaderException(WAVREADER_CHANNEL_DOES_NOT_EXIST);
00407
00408 return m_channelPos[nChannel];
00409 }
00410
00414 UINT32 CWAVReader::GetSampleRate() const
00415 {
00416 if (!m_bFileOpen)
00417 throw CWAVReaderException(WAVREADER_FILE_NOT_OPEN);
00418 return m_nSampleRate;
00419 }
00420
00424 UINT16 CWAVReader::GetChannelCount() const
00425 {
00426 if (!m_bFileOpen)
00427 throw CWAVReaderException(WAVREADER_FILE_NOT_OPEN);
00428 return m_nChannels;
00429 }
00430
00434 UINT16 CWAVReader::GetBitsPerSample() const
00435 {
00436 if (!m_bFileOpen)
00437 throw CWAVReaderException(WAVREADER_FILE_NOT_OPEN);
00438 return m_nBitsPerSample;
00439 }
00440
00445 UINT32 CWAVReader::GetSampleCount() const
00446 {
00447 if (!m_bFileOpen)
00448 throw CWAVReaderException(WAVREADER_FILE_NOT_OPEN);
00449 return (m_nDataSize / (m_nChannels * (m_nBitsPerSample / 8)));
00450 }
00451
00460 UINT32 CWAVReader::TimeToSample(double dSec) const
00461 {
00462 if (!m_bFileOpen)
00463 throw CWAVReaderException(WAVREADER_FILE_NOT_OPEN);
00464 return (UINT32)floor((double)m_nSampleRate * dSec);
00465 }
00466
00471 double CWAVReader::SampleToTime(UINT32 nSample) const
00472 {
00473 if (!m_bFileOpen)
00474 throw CWAVReaderException(WAVREADER_FILE_NOT_OPEN);
00475 return (double)nSample / (double)m_nSampleRate;
00476 }
00477
00478
00479
00480 void CWAVReader::ParseHeader()
00481 {
00482
00483 string sFOURCC = ReadFOURCC();
00484 if (sFOURCC != "RIFF")
00485 throw CWAVReaderException(WAVREADER_INVALID_FORMAT);
00486 m_nRiffChunkDataSize = ReadUINT32();
00487 sFOURCC = ReadFOURCC();
00488 if (sFOURCC != "WAVE")
00489 throw CWAVReaderException(WAVREADER_INVALID_FORMAT);
00490
00491
00492 UINT32 nFormatLength = SeekToSubchunk("fmt");
00493
00494
00495 if (nFormatLength < 16)
00496 throw CWAVReaderException(WAVREADER_INVALID_FORMAT);
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507 UINT16 nFormatTag = ReadUINT16();
00508 if (nFormatTag != WAV_FORMAT_PCM)
00509 throw CWAVReaderException(WAVREADER_UNSUPPORTED_FORMAT);
00510 m_nChannels = ReadUINT16();
00511 m_nSampleRate = ReadUINT32();
00512 ReadUINT32();
00513 ReadUINT16();
00514
00515 m_nBitsPerSample = ReadUINT16();
00516 if ((m_nBitsPerSample != 8) &&
00517 (m_nBitsPerSample != 16) &&
00518 (m_nBitsPerSample != 24) &&
00519 (m_nBitsPerSample != 32))
00520 throw CWAVReaderException(WAVREADER_UNSUPPORTED_FORMAT);
00521
00522
00523 m_nDataSize = SeekToSubchunk("data");
00524 m_dataPos = m_file.tellg();
00525
00526
00527 m_channelPos.resize(m_nChannels);
00528 fill(m_channelPos.begin(), m_channelPos.end(), 0);
00529 }
00530
00531
00532
00533 UINT32 CWAVReader::SeekToSubchunk(const std::string& sSubchunk)
00534 {
00535
00536 m_file.seekg(12, ios::beg);
00537 UINT32 nBytesLeft = m_nRiffChunkDataSize - 4;
00538
00539 while (nBytesLeft >= 8)
00540 {
00541 string sFOURCC = ReadFOURCC();
00542 UINT32 nSubchunkSize = ReadUINT32();
00543 if (sFOURCC == sSubchunk)
00544 return nSubchunkSize;
00545 nBytesLeft -= nSubchunkSize;
00546 if (nBytesLeft >= 8)
00547 m_file.seekg(nSubchunkSize, ios::cur);
00548 }
00549 throw CWAVReaderException(WAVREADER_CHUNK_NOT_FOUND, sSubchunk);
00550 }
00551
00552 void CWAVReader::SeekToSample(UINT32 nSample)
00553 {
00554 m_file.seekg(m_dataPos);
00555 UINT32 nOffset = nSample * m_nChannels * (m_nBitsPerSample / 8);
00556 m_file.seekg(nOffset, ios::cur);
00557 }
00558
00559 bool CWAVReader::SampleExists(UINT32 nSample) const
00560 {
00561 UINT32 nBytesPerSample = m_nChannels * (m_nBitsPerSample / 8);
00562 if (nSample*nBytesPerSample < m_nDataSize)
00563 return true;
00564 return false;
00565 }
00566
00567 void CWAVReader::Read8BitSamples(UINT32 nStart, UINT32 nCount,
00568 UINT16 nChannel, UINT8* pnBuffer)
00569 {
00570 if (!m_bFileOpen)
00571 throw CWAVReaderException(WAVREADER_FILE_NOT_OPEN);
00572
00573
00574 if (nStart == (UINT32)-1)
00575 nStart = m_channelPos[nChannel];
00576 else
00577 m_channelPos[nChannel] = nStart;
00578
00579 if (!SampleExists(nStart) ||
00580 !SampleExists(nStart + nCount - 1))
00581 throw CWAVReaderException(WAVREADER_SAMPLE_DOES_NOT_EXIST);
00582
00583
00584 if (nChannel >= m_nChannels)
00585 throw CWAVReaderException(WAVREADER_CHANNEL_DOES_NOT_EXIST);
00586
00587 SeekToSample(nStart);
00588 for (UINT32 i = 0; i < nCount; ++i, ++pnBuffer)
00589 {
00590 int nActChannel = 0;
00591 while (nActChannel != nChannel)
00592 {
00593 ReadUINT8();
00594 ++nActChannel;
00595 }
00596 *pnBuffer = ReadUINT8();
00597 ++m_channelPos[nChannel];
00598 ++nActChannel;
00599 while (nActChannel < m_nChannels)
00600 {
00601 ReadUINT8();
00602 ++nActChannel;
00603 }
00604 }
00605 }
00606
00607 void CWAVReader::Read16BitSamples(UINT32 nStart, UINT32 nCount,
00608 UINT16 nChannel, INT16* pnBuffer)
00609 {
00610 if (!m_bFileOpen)
00611 throw CWAVReaderException(WAVREADER_FILE_NOT_OPEN);
00612
00613
00614 if (nStart == (UINT32)-1)
00615 nStart = m_channelPos[nChannel];
00616 else
00617 m_channelPos[nChannel] = nStart;
00618
00619 if (!SampleExists(nStart) ||
00620 !SampleExists(nStart + nCount - 1))
00621 throw CWAVReaderException(WAVREADER_SAMPLE_DOES_NOT_EXIST);
00622
00623
00624 if (nChannel >= m_nChannels)
00625 throw CWAVReaderException(WAVREADER_CHANNEL_DOES_NOT_EXIST);
00626
00627 SeekToSample(nStart);
00628 for (UINT32 i = 0; i < nCount; ++i, ++pnBuffer)
00629 {
00630 int nActChannel = 0;
00631 while (nActChannel != nChannel)
00632 {
00633 ReadINT16();
00634 ++nActChannel;
00635 }
00636 *pnBuffer = ReadINT16();
00637 ++m_channelPos[nChannel];
00638 ++nActChannel;
00639 while (nActChannel < m_nChannels)
00640 {
00641 ReadINT16();
00642 ++nActChannel;
00643 }
00644 }
00645 }
00646
00647 void CWAVReader::Read24BitSamples(UINT32 nStart, UINT32 nCount,
00648 UINT16 nChannel, INT32* pnBuffer)
00649 {
00650 if (!m_bFileOpen)
00651 throw CWAVReaderException(WAVREADER_FILE_NOT_OPEN);
00652
00653
00654 if (nStart == (UINT32)-1)
00655 nStart = m_channelPos[nChannel];
00656 else
00657 m_channelPos[nChannel] = nStart;
00658
00659 if (!SampleExists(nStart) ||
00660 !SampleExists(nStart + nCount - 1))
00661 throw CWAVReaderException(WAVREADER_SAMPLE_DOES_NOT_EXIST);
00662
00663
00664 if (nChannel >= m_nChannels)
00665 throw CWAVReaderException(WAVREADER_CHANNEL_DOES_NOT_EXIST);
00666
00667 SeekToSample(nStart);
00668 for (UINT32 i = 0; i < nCount; ++i, ++pnBuffer)
00669 {
00670 int nActChannel = 0;
00671 while (nActChannel != nChannel)
00672 {
00673 ReadINT24();
00674 ++nActChannel;
00675 }
00676 *pnBuffer = ReadINT24();
00677 ++m_channelPos[nChannel];
00678 ++nActChannel;
00679 while (nActChannel < m_nChannels)
00680 {
00681 ReadINT24();
00682 ++nActChannel;
00683 }
00684 }
00685 }
00686
00687 void CWAVReader::Read32BitSamples(UINT32 nStart, UINT32 nCount,
00688 UINT16 nChannel, INT32* pnBuffer)
00689 {
00690 if (!m_bFileOpen)
00691 throw CWAVReaderException(WAVREADER_FILE_NOT_OPEN);
00692
00693
00694 if (nStart == (UINT32)-1)
00695 nStart = m_channelPos[nChannel];
00696 else
00697 m_channelPos[nChannel] = nStart;
00698
00699 if (!SampleExists(nStart) ||
00700 !SampleExists(nStart + nCount - 1))
00701 throw CWAVReaderException(WAVREADER_SAMPLE_DOES_NOT_EXIST);
00702
00703
00704 if (nChannel >= m_nChannels)
00705 throw CWAVReaderException(WAVREADER_CHANNEL_DOES_NOT_EXIST);
00706
00707 SeekToSample(nStart);
00708 for (UINT32 i = 0; i < nCount; ++i, ++pnBuffer)
00709 {
00710 int nActChannel = 0;
00711 while (nActChannel != nChannel)
00712 {
00713 ReadINT32();
00714 ++nActChannel;
00715 }
00716 *pnBuffer = ReadINT32();
00717 ++m_channelPos[nChannel];
00718 ++nActChannel;
00719 while (nActChannel < m_nChannels)
00720 {
00721 ReadINT32();
00722 ++nActChannel;
00723 }
00724 }
00725 }
00726
00727
00728
00729 std::string CWAVReader::ReadFOURCC()
00730 {
00731
00732 char szFOURCC[5] = {'\0','\0','\0','\0','\0'};
00733 if (!m_file.read(szFOURCC, 4))
00734 throw CWAVReaderException(WAVREADER_READ_ERROR);
00735
00736
00737 int nPos = 3;
00738 while ((nPos >= 0) && (szFOURCC[nPos] == ' '))
00739 {
00740 szFOURCC[nPos] = '\0';
00741 nPos--;
00742 }
00743 return string(szFOURCC);
00744 }
00745
00746
00747 INT8 CWAVReader::ReadINT8()
00748 {
00749 return (INT8)ReadUINT8();
00750 }
00751
00752
00753 UINT8 CWAVReader::ReadUINT8()
00754 {
00755 char cBuffer;
00756 if (!m_file.read(&cBuffer, 1))
00757 throw CWAVReaderException(WAVREADER_READ_ERROR);
00758 return (UINT8)cBuffer;
00759 }
00760
00761
00762
00763
00764
00765
00766 INT16 CWAVReader::ReadINT16()
00767 {
00768 return (INT16)ReadUINT16();
00769 }
00770
00771
00772
00773
00774
00775
00776 UINT16 CWAVReader::ReadUINT16()
00777 {
00778 unsigned char szBuffer[2];
00779 if (!m_file.read((char*)szBuffer, 2))
00780 throw CWAVReaderException(WAVREADER_READ_ERROR);
00781 return ((UINT16)szBuffer[0] ) |
00782 ((UINT16)szBuffer[1] << 8);
00783 }
00784
00785
00786
00787
00788
00789
00790 INT32 CWAVReader::ReadINT24()
00791 {
00792 return (INT32)ReadUINT24();
00793 }
00794
00795
00796
00797
00798
00799
00800 UINT32 CWAVReader::ReadUINT24()
00801 {
00802 unsigned char szBuffer[3];
00803 if (!m_file.read((char*)szBuffer, 3))
00804 throw CWAVReaderException(WAVREADER_READ_ERROR);
00805 return ((UINT32)szBuffer[0] ) |
00806 ((UINT32)szBuffer[1] << 8) |
00807 ((UINT32)szBuffer[2] << 16);
00808 }
00809
00810
00811
00812
00813
00814
00815 INT32 CWAVReader::ReadINT32()
00816 {
00817 return (INT32)ReadUINT32();
00818 }
00819
00820
00821
00822
00823
00824
00825 UINT32 CWAVReader::ReadUINT32()
00826 {
00827 unsigned char szBuffer[4];
00828 if (!m_file.read((char*)szBuffer, 4))
00829 throw CWAVReaderException(WAVREADER_READ_ERROR);
00830 return ((UINT32)szBuffer[0] ) |
00831 ((UINT32)szBuffer[1] << 8) |
00832 ((UINT32)szBuffer[2] << 16) |
00833 ((UINT32)szBuffer[3] << 24);
00834 }
00835
00836 }
00837