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

  • 相关阅读:
    MiniOS系统
    《硅谷传奇》
    《构建之法》1—3章
    学术诚信与职业道德
    Sprint2
    Scrum 项目 7.0 Sprint回顾
    Scrum 项目 6.0 sprint演示
    Scrum 项目 5.0
    Scrum 项目4.0
    操作系统 实验三 进程调度模拟程序
  • 原文地址:https://www.cnblogs.com/CPFlying/p/2045510.html
Copyright © 2020-2023  润新知