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_DELETE
2 #define SAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } }
3 #endif
4
5 #ifdef UNICODE
6 typedef WCHAR TCHAR;
7 #else
8 typedef char TCHAR;
9 #endif

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

代码只简单的呈现了WAVE的读出与写入,有不合理或不正确的地方还望大家指正!

原文地址:https://www.cnblogs.com/CPFlying/p/2045510.html