C++如何读取wav文件中的PCM数据
发表于:2025-11-14 作者:千家信息网编辑
千家信息网最后更新 2025年11月14日,这篇文章主要介绍C++如何读取wav文件中的PCM数据,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!前言wav文件通常会使用PCM格式数据存储音频,这种格式的数据读取出来直接就
千家信息网最后更新 2025年11月14日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安全错误
数据库的锁怎样保障安全
软件开发如何锁死表头
能否自己做个服务器
设置云服务器的安全性
化工 网络安全 执法 罚单
数据库保存
江西省网络技术市场专项补贴
网络安全班会主题设计
网络安全吉林行
服务器 永夜港
sql网页服务器架设
网络安全知识微信群
租服务器能干嘛
网络安全设计展
虎眼科技软件开发技术
网络安全法以什么为中心
日照平台软件开发
网络安全施工设备表
网络安全切实从制度
疫情后定制服务器发展趋势
软件开发专业简介
dell服务器管理端口
剑侠情缘3点卡服务器
荆门订制软件开发团队
大连软件开发年终奖情况
数据库组件包括什么情况
软件开发专业是学什么软件
编办做好网络安全工作
网络安全事件分为一般
网络安全图标logo
hmi软件开发工程师