C++ wave文件的写入与读取

操作Wave文件,先了解Wave文件的组织结构

WAVE文件由"块"组成。块的基本结构如下:

------------------------------

偏移量 名称 字节数 类型

------------------------------

00 块标志 4 字符

04 块长度 4 长整型

08 块内容 数据

--------------------------------

WAVE文件一般有四种块,它们依次是:RIFF块、格式块、附加块(可选),数据块

--------------------------------

名称 字节数 说明

--------------------------------

RIFF块 12 RIFF WAVE Chunk

格式块 24或26 Format Chunk

附加块 12 Fact Chunk

数据块 不定 Data Chunk

--------------------------------

1.RIFF块的数据结构

---------------------------------------------------

偏移量 名称 字节数 数据类型 内容

---------------------------------------------------

00 标志符 4 字符 “RIFF”的Ascii码

04 文件长度 4 长整形 文件的总字节数

08 WAV标志 4 字符 “WAVE”的Ascii码

---------------------------------------------------

2.格式块的数据结构

----------------------------------------------------------------------------

偏移地址 字节数 数据类型 内容

----------------------------------------------------------------------------

0C 4 字符 波形格式标志“fmt ”

10 4 长整型 格式块长度(一般=16,若=18表示最后有2字节附加信息)

14 2 整型 格式类别(值=1表示编码方式为PCMμ律编码)

16 2 整型 声道数(单声道=1,双声音=2)

18 4 长整型 采样频率(每秒样本数,表示每个通道的播放速度)

1C 4 长整型 数据传送速率(每秒字节=采样频率×每个样本字节数)

20 2 整型 每个样本字节数(又称基准块=每个样本位数×声道数÷8)

22 2 整型 每个样本位数(又称量化位数)

24 2 整型 附加信息(可选,通过块长度来判断有无)

----------------------------------------------------------------------------


3.附加块的数据结构

---------------------------------------------------

偏移地址 字节数 数据类型 内容

---------------------------------------------------

24 4 字符 标志符“fact”

28 4 长整形 块长度(=4)

2C 4

---------------------------------------------------


4.数据块的数据结构

----------------------------------------

偏移地址 字节数 类型 内容

----------------------------------------

24 4 字符 数据标志符“data”

28 4 长整型 样本数据长度

2C 不定 样本数据

----------------------------------------

C++代码实现:

1 #include <mmsystem.h> 2  3  class CWaveFile 4 { 5  public: 6     CWaveFile(void); 7     CWaveFile(TCHAR * strFileName); 8     CWaveFile(TCHAR * strFileName, WAVEFORMATEX wfx); 9  public:10     ~CWaveFile(void);11 12  public:13     BOOL WriteDataToFile(LPSTR pData, DWORD dwSize);14     BOOL ReadData(char **pData, DWORD *pdwSize, WAVEFORMATEX *pwfx);15  public:16     LPSTR m_pData;17     DWORD m_dwSize;18     WAVEFORMATEX m_wfx;19  private:20     TCHAR * m_strFileName;21 };
1 #include "StdAfx.h" 2 #include "WaveFile.h" 3  4 CWaveFile::CWaveFile(void) 5 { 6  7 } 8  9 CWaveFile::CWaveFile(TCHAR * strFileName)10 {11     m_strFileName = strFileName;12 }13 14 CWaveFile::CWaveFile(TCHAR * strFileName, WAVEFORMATEX wfx)15 {16     m_strFileName = strFileName;17     m_wfx = wfx;18 }19 20 CWaveFile::~CWaveFile(void)21 {22 23 }24 25 BOOL CWaveFile::WriteDataToFile(LPSTR pData, DWORD dwSize)26 {27     CFile file;28     CFileException fileException;29     file.Open(m_strFileName,CFile::modeCreate|CFile::modeReadWrite, &fileException);30     DWORD WaveHeaderSize = 38; // RIFF 12个字节, 格式块26个字节31      DWORD WaveFormatSize = 18; // 格式块内容长度32     file.SeekToBegin();33     file.Write("RIFF",4);34     // RIFF + 格式块 +数据块长度[8+dwSize]35     long int fileLen=(8 + dwSize + WaveHeaderSize); 36     file.Write(&fileLen,sizeof(fileLen));37 38     file.Write("WAVE",4);39     file.Write("fmt ",4);40     file.Write(&WaveFormatSize,sizeof(WaveFormatSize));41     file.Write(&m_wfx.wFormatTag,sizeof(m_wfx.wFormatTag));42     file.Write(&m_wfx.nChannels,sizeof(m_wfx.nChannels));43     file.Write(&m_wfx.nSamplesPerSec,sizeof(m_wfx.nSamplesPerSec));44     file.Write(&m_wfx.nAvgBytesPerSec,sizeof(m_wfx.nAvgBytesPerSec));45     file.Write(&m_wfx.nBlockAlign,sizeof(m_wfx.nBlockAlign));46     file.Write(&m_wfx.wBitsPerSample,sizeof(m_wfx.wBitsPerSample));47     file.Write(&m_wfx.cbSize,sizeof(m_wfx.cbSize)); // 附加信息,2个字节48     file.Write("data",4);49     file.Write(&dwSize,sizeof(dwSize));50     file.Write(pData,dwSize);51     file.Seek(dwSize,CFile::begin);52     file.Close();53     return TRUE;54 }55 BOOL CWaveFile::ReadData(char **pData, DWORD *pdwSize, WAVEFORMATEX *pwfx)56 {57 58     CFile file(m_strFileName,CFile::modeRead);59     int nSize = file.GetLength();60     char *pBuf = new char [nSize+1];61     nSize = file.Read(pBuf,nSize+1);62 63     //long int nFileLen = 0;64     //memcpy(&nFileLen,pBuf+4,4); // WAVE文件长度65 66     int nFormatLen = 0;67     memcpy(&nFormatLen,pBuf+12+4,4); // 读取wave格式的大小68 69     memcpy(pwfx,pBuf+12+8,nFormatLen); // 读取wave格式70     71     char dataflag[5];72     memcpy(dataflag,pBuf+12+8+nFormatLen,4); // 读取数据标志73     dataflag[4] = '\0';74     int nFactLen = 0;75     if(strcmp(dataflag,"fact") == 0) // 判断是否包含附加块76     {77         nFactLen += 12;78     }79     DWORD nDataLen = 0;80     memcpy(&nDataLen,pBuf+12+8+nFormatLen+nFactLen+4,4); // 读取样本大小81     *pData = new char[nDataLen];82 83     memcpy(*pData,pBuf+12+8+nFormatLen+nFactLen+4+4,nDataLen); // 复制数据84     *pdwSize = nDataLen;85 86     SAFE_DELETE(pBuf);87     file.Close();88     return TRUE;89 }
1 #ifndef SAFE_DELETE2 #define SAFE_DELETE(p)  { if(p) { delete (p);     (p)=NULL; } }3 #endif4 5 #ifdef UNICODE6  typedef WCHAR TCHAR;7 #else8  typedef char TCHAR;9 #endif

WAVE文件结构参考 http://yajun566.blog.163.com/blog/static/396396272011336353799/

代码只简单的呈现了WAVE的读出与写入,有不合理或不正确的地方还望大家指正!
原文链接: https://www.cnblogs.com/CPFlying/archive/2011/05/13/2045510.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/25397

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月8日 上午3:15
下一篇 2023年2月8日 上午3:16

相关推荐