WaveFile.cpp
上传用户:goak128
上传日期:2013-07-17
资源大小:155k
文件大小:7k
- //////////////////////////////////////////////////////////////////////////
- // class CWaveFile
- //
- // 功能: 实现wav文件的操作
- // 创建人: 陈文凯 (chwkai@gmail.com)
- // 创建日期:2005年5月19日
- // 修改人:
- // 修改日期:
- // 版本
- #include "StdAfx.h"
- #include ".wavefile.h"
- //////////////////////////////////////////////////////////////////////////
- // 默认构造函数
- CWaveFile::CWaveFile()
- {
- this->Close();
- }
- //////////////////////////////////////////////////////////////////////////
- // 构造函数
- CWaveFile::CWaveFile(LPCTSTR lpszFileName, UINT nOpenFlags)
- {
- this->Open(lpszFileName, nOpenFlags);
- }
- //////////////////////////////////////////////////////////////////////////
- // 系构函数
- CWaveFile::~CWaveFile(void)
- {
- this->Close();
- }
- //////////////////////////////////////////////////////////////////////////
- // 打开wav文件,并读入header信息
- BOOL CWaveFile::Open(LPCTSTR lpszFileName, UINT nOpenFlags)
- {
- // 若文件已经打开则先关闭
- this->Close();
- // 打开文件
- BOOL bRet = this->m_wavFile.Open(lpszFileName, nOpenFlags);
- // 判断文件是否打开
- if (this->m_wavFile.m_hFile != CFile::hFileNull)
- {
- // 读取文件头信息
- this->ReadHeader();
- }
- return bRet;
- }
- //////////////////////////////////////////////////////////////////////////
- // 关闭wave文件,且将数据置0
- void CWaveFile::Close()
- {
- if (this->m_wavFile.m_hFile != CFile::hFileNull)
- {
- this->m_wavFile.Close();
- }
- this->m_nDataStartFrom = 0;
- this->m_dwDataChunkSize = 0;
- this->m_nBytesWritten = 0;
- }
- //////////////////////////////////////////////////////////////////////////
- // wave文件指针返回到数据部分起始位置
- void CWaveFile::Reset()
- {
- if (this->m_wavFile.m_hFile != CFile::hFileNull)
- {
- this->m_wavFile.Seek(this->m_nDataStartFrom, CFile::begin);
- }
- }
- //////////////////////////////////////////////////////////////////////////
- // 返回wave文件的format chunk信息
- WAVEFORMATEX CWaveFile::GetWaveFormat() const
- {
- WAVEFORMATEX fmt;
- fmt.nAvgBytesPerSec = this->m_format.dwAvgBytesPerSec;
- fmt.nBlockAlign = this->m_format.wBlockAlign;
- fmt.nChannels = this->m_format.wChannels;
- fmt.nSamplesPerSec = this->m_format.dwSamplesPerSec;
- fmt.wBitsPerSample = this->m_format.wBitsPerSample;
- fmt.wFormatTag = this->m_format.wFormatTag;
- fmt.cbSize = this->m_format.wReserved;
- return fmt;
- }
- //////////////////////////////////////////////////////////////////////////
- // 用于wave读取,读取wave的Format信息,并记录data开始位置
- void CWaveFile::ReadHeader()
- {
- INT nOffSet= 0;
- UINT nRead = 0;
- FormatChunk fmt;
- DataChunkHeader dataHeader;
- char chunkId[5];
- DWORD chunkSize;
- // 文件是否打开
- if (this->m_wavFile.m_hFile != CFile::hFileNull)
- {
- // 计算Riff header的长度, 文件指针移到riff header之后
- nOffSet = sizeof(RiffHeader);
- this->m_wavFile.Seek(nOffSet, CFile::begin);
- // 读取format chunk
- nRead = this->m_wavFile.Read(&fmt, sizeof(fmt));
- // 读取Data Chunk header信息
-
- // 计算fmt chunk的长度,移动到下一个chunk的起始处
- nOffSet = fmt.chunkSize + sizeof(fmt.chunkId) + sizeof(fmt.chunkSize) - nRead;
- this->m_wavFile.Seek(nOffSet, CFile::current);
- // 实现strcmp判断
- chunkId[4] = ' ';
- // 忽略其他的chunk
- while (nRead > 0)
- {
- nRead = this->m_wavFile.Read(chunkId, sizeof(chunkId) - sizeof(char));
- // 查找data chunk
- if (strcmp(chunkId, DEFAULT_DATA_ID) == 0)
- {
- // 返回data chunk起始位置
- nOffSet = sizeof(char) - sizeof(chunkId);
- this->m_wavFile.Seek(nOffSet, CFile::current);
- this->m_wavFile.Read(&dataHeader, sizeof(dataHeader));
- break;
- }
- else
- {
- // 忽略其他chunk
- nRead = this->m_wavFile.Read(&chunkSize, sizeof(chunkSize));
- this->m_wavFile.Seek(chunkSize, CFile::current);
- }
- }
- // 保存裸音频数据起始位置
- this->m_nDataStartFrom = this->m_wavFile.GetPosition();
- // 保存format信息
- this->m_format = fmt;
- // 保存裸音频数据总长度
- this->m_dwDataChunkSize = dataHeader.chunkSize;
- }
- }
- //////////////////////////////////////////////////////////////////////////
- // 用于wave读取,桉字节数读取裸数据
- UINT CWaveFile::ReadBytes(void* pData, UINT nCount)
- {
- UINT nRead = 0;
- // 文件是否打开
- if (this->m_wavFile.m_hFile != CFile::hFileNull)
- {
- nRead = this->m_wavFile.Read(pData, nCount);
- }
- return nRead;
- }
- //////////////////////////////////////////////////////////////////////////
- // 按bytes写入数据
- void CWaveFile::WriteBytes(void* pData, UINT nCount)
- {
- // 文件是否打开
- if (this->m_wavFile.m_hFile != CFile::hFileNull)
- {
- this->m_wavFile.Write(pData, nCount);
- //记录所写入的总字节数
- this->m_nBytesWritten += nCount;
- }
- }
- //////////////////////////////////////////////////////////////////////////
- // 用于wave写入,写入wave文件的Format和Riff信息
- void CWaveFile::WriteHeader()
- {
- RiffHeader riff;
- DataChunkHeader dataHeader;
- // 文件是否打开
- if (this->m_wavFile.m_hFile != CFile::hFileNull)
- {
- // 准备data header
- dataHeader.chunkId[0] = 'd';
- dataHeader.chunkId[1] = 'a';
- dataHeader.chunkId[2] = 't';
- dataHeader.chunkId[3] = 'a';
- dataHeader.chunkSize = this->m_nBytesWritten;
- // 准备Riff header
- riff.groupId[0] = 'R';
- riff.groupId[1] = 'I';
- riff.groupId[2] = 'F';
- riff.groupId[3] = 'F';
- riff.riffTypeId[0] = 'W';
- riff.riffTypeId[1] = 'A';
- riff.riffTypeId[2] = 'V';
- riff.riffTypeId[3] = 'E';
- // 计算并写入riff chunksize
- riff.chunkSize = sizeof(riff.riffTypeId) + sizeof(FormatChunk) +
- sizeof(DataChunkHeader) + this->m_nBytesWritten;
- // 经头部信息写入文件
- this->m_wavFile.Seek(0, CFile::begin);
- this->m_wavFile.Write(&riff, sizeof(RiffHeader));
- this->m_wavFile.Write(&this->m_format, sizeof(FormatChunk));
- this->m_wavFile.Write(&dataHeader, sizeof(DataChunkHeader));
- }
- }
- //////////////////////////////////////////////////////////////////////////
- // 用于wave写入,在wave文件首部预留写入riff header + format chunk + data chunk header的空间,
- // 并设定wave的format chunk
- void CWaveFile::PrepareWriteHeader(WAVEFORMATEX& fmt)
- {
- UINT nOffSet = 0;
- // 文件是否打开
- if (this->m_wavFile.m_hFile != CFile::hFileNull)
- {
- // 设定format信息
- this->m_format.dwSamplesPerSec = fmt.nSamplesPerSec;
- this->m_format.wBitsPerSample = fmt.wBitsPerSample;
- this->m_format.wChannels = fmt.nChannels;
- this->m_format.wBlockAlign =
- this->m_format.wChannels * (this->m_format.wBitsPerSample % 8);
- this->m_format.dwAvgBytesPerSec =
- this->m_format.wBlockAlign * this->m_format.dwSamplesPerSec;
- this->m_format.wFormatTag = WAVE_FORMAT_PCM;
- this->m_format.chunkSize =
- sizeof(FormatChunk) - sizeof(this->m_format.chunkId) - sizeof(this->m_format.chunkSize);
- // 设定format chunk id
- this->m_format.chunkId[0] = 'f';
- this->m_format.chunkId[1] = 'm';
- this->m_format.chunkId[2] = 't';
- //wave文件头部预留空间写入riff header + format chunk + data chunk header
- nOffSet = sizeof(RiffHeader) + sizeof(FormatChunk) + sizeof(DataChunkHeader);
- this->m_wavFile.Seek(nOffSet, CFile::begin);
- }
- }