C语言读取wav文件
参考代码: wav音频文件格式解析
代码的思路是编写wave.h,根据wav文件结构定义struct。大佬的执行结果为
然而我在运行代码的时候遇到的问题:
可以看到fmt长度为18,然而还是按照16来处理,导致读取data的时候只读取到后两位。
- 第一次尝试:
首先分析文件:
WAVE PCM soundfile format中可以看到,在fmt的末尾可能出现ExtraParamSize 和 ExtraParams。在此文件中ExtraParamSize = 0,因此没有ExtraParams。
第三行中,02 00 为BlockAlign,10 00 为BitsPerSample,00 00 为ExtraParamsSize。之后就是data。
据此,我往wave.h的struct WAV_FMT的末尾添加了一行:
uint16_t ExtraParamSize;
运行结果:
发现data又往后多移动了两位,奇怪!为什么会这样?
- 第二次尝试:
我灵光一现,将上面那行ExtraParamSize添加到了struct WAV_data的开头。
运行结果:
结果看似正常!然而我的wav文件时长应该是53秒!而且为什么本属于fmt的内容要添加到data的开头呢?还是有问题!
- 第三次尝试
跟大佬聊了一下,认为可能与C语言字节对齐有关。我找到了这个链接,里面提到struct的每个数据类型都会对齐,并且默认按4字节对齐,这导致长度为18的fmt内容被对齐到了16或20,因此data只能显示两个字节。
据此,我在wave.h的开头加入
#pragma pack (2) /*指定按2字节对齐*/
结尾加入
#pragma pack () /*取消指定对齐,恢复缺省对齐*/
运行结果:
一切正常。
- 总结
一开始只是想省事,用struct自动填充文件头信息。后来发现wav文件头长度还不同。fmt的值可能为16,18,20,40等;有些文件头中还有12字节的fact chunk;WAV文件格式解析及处理中还提到一种由Adobe Premiere Pro CC 创建的WAV,包含LIST chunk。因此更好的做法其实是一个字节一个字节读,手动解析,而不是一股脑填进struct。
代码:
wave.h
#ifndef RESOLVE_WAV_WAVE_H
#define RESOLVE_WAV_WAVE_H#include <stdint.h>
#pragma pack (2) /*指定按2字节对齐*/
// using namespace std;typedef struct WAV_RIFF {/* chunk "riff" */char ChunkID[4]; /* "RIFF" *//* sub-chunk-size */uint32_t ChunkSize; /* 36 + Subchunk2Size *//* sub-chunk-data */char Format[4]; /* "WAVE" */
} RIFF_t;typedef struct WAV_FMT {/* sub-chunk "fmt" */char Subchunk1ID[4]; /* "fmt " *//* sub-chunk-size */uint32_t Subchunk1Size; /* 16 for PCM *//* sub-chunk-data */uint16_t AudioFormat; /* PCM = 1*/uint16_t NumChannels; /* Mono = 1, Stereo = 2, etc. */uint32_t SampleRate; /* 8000, 44100, etc. */uint32_t ByteRate; /* = SampleRate * NumChannels * BitsPerSample/8 */uint16_t BlockAlign; /* = NumChannels * BitsPerSample/8 */uint16_t BitsPerSample; /* 8bits, 16bits, etc. */uint16_t ExtraParamSize;
} FMT_t;typedef struct WAV_data {/* sub-chunk "data" */char Subchunk2ID[4]; /* "data" *//* sub-chunk-size */uint32_t Subchunk2Size; /* data size *//* sub-chunk-data */
// Data_block_t block;
} Data_t;//typedef struct WAV_data_block {
//} Data_block_t;typedef struct WAV_fotmat {RIFF_t riff;FMT_t fmt;Data_t data;
} Wav;#pragma pack () /*取消指定对齐,恢复缺省对齐*/
#endif //RESOLVE_WAV_WAVE_H
wav_open.c
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include "wave.h"int main()
{FILE *fp;Wav wav;RIFF_t riff;FMT_t fmt;Data_t data; errno_t err;err = fopen_s(&fp, "test.wav", "rb");if (err) {printf("The file was not opened\n");}else {fread(&wav, 1, sizeof(wav), fp);fclose(fp);riff = wav.riff;fmt = wav.fmt;data = wav.data;printf("ChunkID \t%c%c%c%c\n", riff.ChunkID[0], riff.ChunkID[1], riff.ChunkID[2], riff.ChunkID[3]);printf("ChunkSize \t%d\n", riff.ChunkSize);printf("Format \t\t%c%c%c%c\n", riff.Format[0], riff.Format[1], riff.Format[2], riff.Format[3]);printf("\n");printf("Subchunk1ID \t%c%c%c%c\n", fmt.Subchunk1ID[0], fmt.Subchunk1ID[1], fmt.Subchunk1ID[2], fmt.Subchunk1ID[3]);printf("Subchunk1Size \t%d\n", fmt.Subchunk1Size);printf("AudioFormat \t%d\n", fmt.AudioFormat);printf("NumChannels \t%d\n", fmt.NumChannels);printf("SampleRate \t%d\n", fmt.SampleRate);printf("ByteRate \t%d\n", fmt.ByteRate);printf("BlockAlign \t%d\n", fmt.BlockAlign);printf("BitsPerSample \t%d\n", fmt.BitsPerSample);// printf("ExtraParamSize \t%d\n", fmt.ExtraParamSize);printf("\n");printf("blockID \t%c%c%c%c\n", data.Subchunk2ID[0], data.Subchunk2ID[1], data.Subchunk2ID[2], data.Subchunk2ID[3]);printf("blockSize \t%d\n", data.Subchunk2Size);printf("\n");if (fmt.ByteRate) {printf("duration \t%d\n", data.Subchunk2Size / fmt.ByteRate);}}
}
运行结果:
C语言读取wav文件相关推荐
- c语言读文件编译,C语言读取wav文件的问题,请大侠,编译问题。
已结贴√ 问题点数:20 回复次数:5 C语言读取wav文件的问题,请大侠,编译问题. 代码如下:#include #include LRESULT CALLBACK WndProc (HWND, U ...
- C语言实现wav文件的读写
C语言实现wav文件的读写 wav文件格式 //wav.h typedef unsigned char uint8_t; typedef signed char int8_t; typedef uns ...
- R语言读取excel文件实战(read.xlsx函数、read_excel函数、read.xlsx函数、Write函数)
R语言读取excel文件实战(read.xlsx函数.read_excel函数.read.xlsx函数.Write函数) 目录 R语言读取excel文件实战(read.xlsx函数.read_exce ...
- matlab 读取WAV文件
最近工作需要,要对wav文件中存储的声音信息进行分析处理.所以花了些时间收集了各种数学软件中处理wav 文件的方法. Matlab Matlab 是最方便的.甚至于不用写任何代码就能读取 wav 文件 ...
- java wav 波形_java读取wav文件(波形文件)并绘制波形图的方法
本文实例讲述了java读取wav文件(波形文件)并绘制波形图的方法.分享给大家供大家参考.具体如下: 因为最近有不少网友询问我波形文件读写方面的问题,出于让大家更方便以及让代码能够得到更好的改进,我将 ...
- matlab读取wav文件
matlab读取wav文件 wavread audioread [y,Fs,bits]=wavread('1.wav'); [y,Fs]=audioread('1.wav'); wavread mat ...
- c语言 读取TXT 去空格,C语言读取TXT文件,忽略文件空格,把内容写入数组中应该如何实现...
C语言读取TXT文件,忽略文件空格,把内容写入数组中应该怎么实现? #include #include #define SIZE_view 50 struct view_info { int id; ...
- linux下c语言读取csv文件,C语言读取csv文件
C语言读取csv文件 逗号分隔值(Comma-Separated Values,CSV,有时也称为字符分隔值,因为分隔字符也可以不是逗号),其文件以纯文本形式存储表格数据(数字和文本).纯文本意味着该 ...
- python读取wav文件并进行FFT变换
一.wav格式文件 WAV为微软公司(Microsoft)开发的一种声音文件格式,它符合RIFF(Resource Interchange File Format)文件规范,用于保存Windows平台 ...
最新文章
- latex参考文献Bib Tex的使用
- python代码阅读技巧_30个Python程序员需要知道的编程技巧,可以让你的工作事半功倍!...
- 阿里云上创建个人网站
- 读jQuery源码释疑笔记
- 匈牙利算法-指派问题、二分图问题等
- AcWing(状态机模型) 1049. 大盗阿福
- 最近在做支付宝支付,在本地测试一切正常,上传到服务器就遇到报错:
- 实用typescript_从今天开始,拿起 TypeScript 做一个轮子的制造者
- ubuntu mysql 编译_Ubuntu下mysql编译安装
- 体检结果(2018年10月,胃肠镜)
- Confluence 6 重构索引缓慢
- effective Java chapter 2创建和销毁对象
- Mac彻底卸载搜狗输入法,看这一篇就够了
- DICOM worklist入门一
- 运筹学笔记 整数规划
- 抖音在线无水印解析PHP源码
- RESTful 架构介绍
- 情商和逆商比智商更重要
- 2021华数杯数学建模选题建议
- 使用AFN上传图片 下载图片