千家信息网

C++如何读取wav文件中的PCM数据

发表于:2026-11-02 作者:千家信息网编辑
千家信息网最后更新 2026年11月02日,这篇文章主要介绍C++如何读取wav文件中的PCM数据,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!前言wav文件通常会使用PCM格式数据存储音频,这种格式的数据读取出来直接就
千家信息网最后更新 2026年11月02日C++如何读取wav文件中的PCM数据

这篇文章主要介绍C++如何读取wav文件中的PCM数据,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!

前言

wav文件通常会使用PCM格式数据存储音频,这种格式的数据读取出来直接就可以播放,要在wav文件中读取数据,我们首先要获取头部信息,wav的文件结构里面分为多个chunk,我们要做的就是识别这些chunk的信息,获取音频的格式以及数据。

一、如何实现?

首先需要构造wav头部,wav文件音频信息全部保存在头部,我们要做的就是读取wav头部信息,并且记录PCM的相关参数。

1.定义头结构

只定义PCM格式的wav文件头,对于PCM格式的数据只需要下面3个结构体即可。

struct WaveRIFF;struct WaveFormat;struct WaveData;

2.读取头部信息

打开文件后需要读取头部信息,需要获取声音的格式以及数据长度。

WaveRIFF riff;WaveFormat format;WaveData data;int userDataSize;f= fopen(fileName.c_str(), "rb+");//读取头部信息fread(&riff, 1, sizeof(riff), f);fread(&format, 1, sizeof(format),f);//判读头部信息是否正确//略//查找data chunk//略//记录数据起始位置

3.读取数据

获取头部信息后,就知道数据在位置及长度了,只需要直接读文件即可。

//跳到数据起始位置seek(f, _dataOffset, SEEK_SET);
//读取数据fread(buf, 1, bufLength, f);

二、完整代码

完整代码总用有3部分,头结构、WavFileReader.h、WavFileReader.cpp。

1.头结构

#pragma pack(push,1)    struct WaveRIFF {        const    char id[4] = { 'R','I', 'F', 'F' };        uint32_t fileLength;        const    char waveFlag[4] = { 'W','A', 'V', 'E' };    };    struct WaveFormat    {        const    char id[4] = { 'f','m', 't', ' ' };        uint32_t blockSize = 16;        uint16_t formatTag;        uint16_t channels;        uint32_t samplesPerSec;        uint32_t avgBytesPerSec;        uint16_t blockAlign;        uint16_t  bitsPerSample;    };    struct  WaveData    {        const    char id[4] = { 'd','a', 't', 'a' };        uint32_t dataLength;    };#pragma pack(pop)

2.WavFileReader.h

#pragma once#include/************************************************************************* @Project:      AC.WavFileWriter* @Decription:  wav文件读取工具* 本版本只支持pcm读取,且未处理字节顺序。    riff文件是小端,通常在intel的设备上是没问题的,在java虚拟机上则需要处理。* @Verision:      v1.0.0.0* @Author:      Xin Nie* @Create:      2019/4/10 11:10:17* @LastUpdate:  2019/4/16 10:45:00************************************************************************* Copyright @ 2019. All rights reserved.************************************************************************/namespace AC {    ///     /// wav文件读取对象    ///     class WavFileReader {    public:        ///         /// 构造方法        ///         WavFileReader();        ///         /// 析构方法        ///         ~WavFileReader();        ///         /// 打开wav文件        ///         /// 文件名        /// 是否打开成功        bool OpenWavFile(const std::string& fileName);        ///         /// 关闭文件        ///         void CloseFlie();        ///         /// 读取音频数据        ///         /// 外部缓存        /// 缓存长度        /// 读取长度        int ReadData(unsigned char* buf, int bufLength);        ///         /// 设置读取位置        ///         ///  读取位置        void SetPosition(int position);        ///         /// 获取读取位置        ///         /// 读取位置        int GetPosition();        ///         /// 获取文件长度        ///         /// 文件长度        int GetFileLength();        ///         /// 获取音频数据长度        ///         /// 音频数据长度        int GetDataLength();        ///         /// 获取声道数        ///         /// 声道数        int GetChannels();        ///         /// 获取采样率        ///         /// 采样率,单位:hz        int GetSampleRate();        ///         /// 获取位深        ///         /// 位深,单位:bits        int GetBitsPerSample();    private:        void* _file = nullptr;        uint32_t _fileLength = 0;        uint32_t _dataLength = 0;        int _channels = 0;        int  _sampleRate = 0;        int  _bitsPerSample = 0;        int _dataOffset = 0;    };}

3.WavFileReader.cpp

#include"WavFileReader.h"namespace AC {    WavFileReader::WavFileReader()    {    }    WavFileReader::~WavFileReader()    {        CloseFlie();    }    bool WavFileReader::OpenWavFile(const std::string& fileName)    {        if (_file)        {            printf("已经打开了文件!\n");            return false;        }        WaveRIFF riff;        WaveFormat format;        WaveData data;        int userDataSize;        _file = fopen(fileName.c_str(), "rb+");        if (!_file)        {            printf("打开文件失败!\n");            return false;        }        //读取头部信息        if (fread(&riff, 1, sizeof(riff), static_cast(_file)) != sizeof(riff))        {            printf("文件读取错误,读取riff失败!\n");            goto error;        }        if (std::string(riff.id, 4) != "RIFF" || std::string(riff.waveFlag, 4) != "WAVE")        {            printf("头部信息不正确,不是wav文件!\n");            goto error;        }        if (fread(&format, 1, sizeof(format), static_cast(_file)) != sizeof(format))        {            printf("文件读取错误,读取format失败!\n");            goto error;        }        if (std::string(format.id, 4) != "fmt ")        {            printf("头部信息不正确,缺少fmt!\n");            goto error;        }        if (format.formatTag != 1)        {            printf("程序不支持,数据格式非pcm,只支持pcm格式的数据!\n");            goto error;        }        userDataSize = format.blockSize - sizeof(format) + 8;        if (userDataSize < 0)        {            printf("头部信息不正确,blockSize大小异常!\n");            goto error;        }        else if (userDataSize > 0)        {            if (fseek(static_cast(_file), userDataSize, SEEK_CUR) != 0)            {                printf("文件读取错误!\n");                goto error;            }        }        while (1)        {            if (fread(&data, 1, sizeof(data), static_cast(_file)) != sizeof(data))            {                printf("文件读取错误!\n");                goto error;            };            if (std::string(data.id, 4) != "data")            {                if (fseek(static_cast(_file), data.dataLength, SEEK_CUR) != 0)                {                    printf("文件读取错误!\n");                    goto error;                }                continue;            }            break;        }        _dataOffset = ftell(static_cast(_file));        _fileLength = riff.fileLength+8;        _dataLength = data.dataLength;        _channels = format.channels;        _sampleRate = format.samplesPerSec;        _bitsPerSample = format.bitsPerSample;        return true;    error:        if (fclose(static_cast(_file)) == EOF)        {            printf("文件关闭失败!\n");        }        _file = nullptr;        return false;    }    void WavFileReader::CloseFlie()    {        if (_file)        {            if (fclose(static_cast(_file)) == EOF)            {                printf("文件关闭失败!\n");            }            _file = nullptr;        }    }    int WavFileReader::ReadData(unsigned char* buf, int bufLength)    {        if (ftell(static_cast(_file)) >= _dataOffset + _dataLength)            return 0;        return fread(buf, 1, bufLength, static_cast(_file));    }    void WavFileReader::SetPosition(int postion)    {        if (fseek(static_cast(_file), _dataOffset + postion, SEEK_SET) != 0)        {            printf("定位失败!\n");        }    }    int WavFileReader::GetPosition()    {        return ftell(static_cast(_file)) - _dataOffset;    }    int WavFileReader::GetFileLength()    {        return _fileLength;    }    int WavFileReader::GetDataLength()    {        return _dataLength;    }    int WavFileReader::GetChannels()    {        return _channels;    }    int WavFileReader::GetSampleRate()    {        return _sampleRate;    }    int WavFileReader::GetBitsPerSample()    {        return _bitsPerSample;    }}

三、使用示例

1、播放

#include "WavFileReader.h"int main(int argc, char** argv) {    AC::WavFileReader read;    unsigned char buf[1024];    if (read.OpenWavFile("test_music.wav"))    {        int channels, sampleRate, bitsPerSample;        //获取声音格式        channels = read.GetChannels();        sampleRate = read.GetSampleRate();        bitsPerSample = read.GetBitsPerSample();        //打开声音设备(channels,sampleRate,bitsPerSample)        int size;        do         {            //读取音频数据            size = read.ReadData(buf,1024);            if (size > 0)            {                //播放(buf,1024)            }                    } while (size);        read.CloseFlie();    }    return 0;}

2、循环播放

#include "WavFileReader.h"int main(int argc, char** argv) {    AC::WavFileReader read;    unsigned char buf[1024];    bool exitFlag = false;    if (read.OpenWavFile("test_music.wav"))    {        int channels, sampleRate, bitsPerSample;        //获取声音格式        channels = read.GetChannels();        sampleRate = read.GetSampleRate();        bitsPerSample = read.GetBitsPerSample();        //打开声音设备(channels,sampleRate,bitsPerSample)        int size;        while (!exitFlag)        {            //读取音频数据            size = read.ReadData(buf, 1024);            if (size > 0)            {                //播放(buf,1024)            }            else            {                   //回到数据起始位置                read.SetPosition(0);                    }        }         read.CloseFlie();    }    return 0;}

以上是"C++如何读取wav文件中的PCM数据"这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注行业资讯频道!

文件 数据 信息 头部 格式 位置 长度 音频 声音 结构 错误 设备 支持 起始 C++ 代码 内容 单位 声道 就是 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 互联网核心科技是什么 互联网科技的发展 高科技与互联网 互联网 视角下的科技创新 江苏南京365互联网科技 移动互联网科技公司 哈尔滨屹滨互联网科技有限公司 消费医药和互联网科技 允成互联网科技有限公司融资 互联网科技创新的路径 朱啸虎曾投资哪些互联网科技企业 科技赋能视角下互联网保险发展 雨阳互联网卡科技有限公司 广州百诚互联网科技有限公司官网 四川互联网展示科技馆设计 风投北京互联网科技 陕西云淼互联网科技公司 上海乐五互联网科技有限公司 平安好医生打造互联网科技医疗 六子台科技互联网展会 互联网科技公司发展 嘟嘟瓜互联网科技 齐家互联网科技 长亮科技互联网金融 互联网科技产品 互联网科技教育视频 语蝶互联网科技有限公司 中国科技创新与世界互联网大会 众安科技工业互联网合作 西安有哪些互联网高科技企业
0