zoukankan      html  css  js  c++  java
  • 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的读出与写入,有不合理或不正确的地方还望大家指正!

  • 相关阅读:
    bzoj2733 永无乡 平衡树按秩合并
    bzoj2752 高速公路 线段树
    bzoj1052 覆盖问题 二分答案 dfs
    bzoj1584 打扫卫生 dp
    bzoj1854 游戏 二分图
    bzoj3316 JC loves Mkk 二分答案 单调队列
    bzoj3643 Phi的反函数 数学 搜索
    有一种恐怖,叫大爆搜
    BZOJ3566 概率充电器 概率dp
    一些奇奇怪怪的过题思路
  • 原文地址:https://www.cnblogs.com/CPFlying/p/2045510.html
Copyright © 2011-2022 走看看