参考代码: 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文件相关推荐

  1. c语言读文件编译,C语言读取wav文件的问题,请大侠,编译问题。

    已结贴√ 问题点数:20 回复次数:5 C语言读取wav文件的问题,请大侠,编译问题. 代码如下:#include #include LRESULT CALLBACK WndProc (HWND, U ...

  2. C语言实现wav文件的读写

    C语言实现wav文件的读写 wav文件格式 //wav.h typedef unsigned char uint8_t; typedef signed char int8_t; typedef uns ...

  3. R语言读取excel文件实战(read.xlsx函数、read_excel函数、read.xlsx函数、Write函数)

    R语言读取excel文件实战(read.xlsx函数.read_excel函数.read.xlsx函数.Write函数) 目录 R语言读取excel文件实战(read.xlsx函数.read_exce ...

  4. matlab 读取WAV文件

    最近工作需要,要对wav文件中存储的声音信息进行分析处理.所以花了些时间收集了各种数学软件中处理wav 文件的方法. Matlab Matlab 是最方便的.甚至于不用写任何代码就能读取 wav 文件 ...

  5. java wav 波形_java读取wav文件(波形文件)并绘制波形图的方法

    本文实例讲述了java读取wav文件(波形文件)并绘制波形图的方法.分享给大家供大家参考.具体如下: 因为最近有不少网友询问我波形文件读写方面的问题,出于让大家更方便以及让代码能够得到更好的改进,我将 ...

  6. matlab读取wav文件

    matlab读取wav文件 wavread audioread [y,Fs,bits]=wavread('1.wav'); [y,Fs]=audioread('1.wav'); wavread mat ...

  7. c语言 读取TXT 去空格,C语言读取TXT文件,忽略文件空格,把内容写入数组中应该如何实现...

    C语言读取TXT文件,忽略文件空格,把内容写入数组中应该怎么实现? #include #include #define SIZE_view 50 struct view_info { int id; ...

  8. linux下c语言读取csv文件,C语言读取csv文件

    C语言读取csv文件 逗号分隔值(Comma-Separated Values,CSV,有时也称为字符分隔值,因为分隔字符也可以不是逗号),其文件以纯文本形式存储表格数据(数字和文本).纯文本意味着该 ...

  9. python读取wav文件并进行FFT变换

    一.wav格式文件 WAV为微软公司(Microsoft)开发的一种声音文件格式,它符合RIFF(Resource Interchange File Format)文件规范,用于保存Windows平台 ...

最新文章

  1. latex参考文献Bib Tex的使用
  2. python代码阅读技巧_30个Python程序员需要知道的编程技巧,可以让你的工作事半功倍!...
  3. 阿里云上创建个人网站
  4. 读jQuery源码释疑笔记
  5. 匈牙利算法-指派问题、二分图问题等
  6. AcWing(状态机模型) 1049. 大盗阿福
  7. 最近在做支付宝支付,在本地测试一切正常,上传到服务器就遇到报错:
  8. 实用typescript_从今天开始,拿起 TypeScript 做一个轮子的制造者
  9. ubuntu mysql 编译_Ubuntu下mysql编译安装
  10. 体检结果(2018年10月,胃肠镜)
  11. Confluence 6 重构索引缓慢
  12. effective Java chapter 2创建和销毁对象
  13. Mac彻底卸载搜狗输入法,看这一篇就够了
  14. DICOM worklist入门一
  15. 运筹学笔记 整数规划
  16. 抖音在线无水印解析PHP源码
  17. RESTful 架构介绍
  18. 情商和逆商比智商更重要
  19. 2021华数杯数学建模选题建议
  20. 使用AFN上传图片 下载图片

热门文章

  1. web项目no such method exception
  2. 软件工程--构建之法--功能测试 设计10个或者更多的测试案例完成对钉书钉的功能测试...
  3. 系统日报-20220421(Databricks 缘何成功?)
  4. 粒子群优化能做相机标定吗
  5. 分析iphone11销售数据
  6. 机器学习多步时间序列预测解决方案
  7. Excel2013打印时怎么固定表头及表尾让打印后的每页都可以看得到
  8. ESP-01S烧录MQTT固件连接阿里云
  9. 新特性解读 | MySQL 8.0 对 limit 的优化
  10. POSCMS 支付设置