> 文档中心 > VS语音信号处理(1) C语言读取WAV语音文件文件头数据

VS语音信号处理(1) C语言读取WAV语音文件文件头数据

VS语音信号处理(1) C语言读取WAV语音文件文件头数据

  • 前言
  • 一. 工程实现
  • 二. 结果
  • 三. 小结

前言

语音识别相关算法一般在MATLAB上进行仿真验证与实验,在工程上一般还是在VS中进行实现落地,本系列将介绍语音信号处理在C语言中的一系列应用,后期将以此为基础,再落地移植到嵌入式平台。

语音文件的格式多种多样都存在不同的标准,在WAV格式的语音文件中主要包含两个部分:文件头与语音数据,本文将介绍读取WAV语音文件的文件头数据。WAV格式语音文件数据标准如下图所示。
VS语音信号处理(1) C语言读取WAV语音文件文件头数据

即前44位位文件头数据,44位之后为语音数据。

一. 工程实现

// ExtractData.h// 读取wav格式语音文件文件头数据// date:2022-4-27 22:44:36// author : C.S#ifndef _EXTRACTDATA_H_#define _EXTRACTDATA_H_#include typedef struct tagWAVHEADER {uint8_t   ChunkID[4];     // 文档标识。大写字符串"RIFF",标明该文件为有效的 RIFF 格式文档。uint32_t  ChunkSize;      // 文件数据长度。   从下一个字段首地址开始到文件末尾的总字节数。该字段的数值加 8 为当前文件的实际长度。uint8_t   Format[4];      // 文件格式类型。   所有 WAV 格式的文件此处为字符串"WAVE",标明该文件是 WAV 格式文件。uint8_t   FmtChunkID[4];  // 格式块标识。     小写字符串,"fmt "。uint32_t  FmtChunkSize;   // 格式块长度。     其数值不确定,取决于编码格式。可以是 16、 18 、20、40 等。uint16_t  AudioFormat;    // 编码格式代码。   常见的 WAV 文件使用 PCM 脉冲编码调制格式,该数值通常为 1。uint16_t  NumChannels;    // 声道个数。单声道为 1,立体声或双声道为 2。uint32_t  SampleRate;     // 采样频率。每个声道单位时间采样次数。常用的采样频率有 11025, 22050 和 44100 kHz。uint32_t  ByteRate;// 数据传输速率。   该数值为:声道数×采样频率×每样本的数据位数/8。播放软件利用此值可以估计缓冲区的大小。uint16_t  BlockAlign;     // 数据块对齐单位。 采样帧大小。该数值为:声道数×位数/8。播放软件需要一次处理多个该值大小的字节数据,用该数值调整缓冲区。uint16_t  BitsPerSample;  // 采样位数。存储每个采样值所用的二进制数位数。常见的位数有 4、8、12、16、24、32。uint8_t   DataChunkID[4];uint32_t  DataChunkSize;} WAVHEADER;#endif  // #ifndef _EXTRACTDATA_H_
// ExtractData.cpp// 读取wav格式语音文件文件头数据// date:2022-4-27 22:44:36// author : C.S#include  #include#include#include#include "ExtractData.h"#define  W  128      //每次读写文件的数据量  int     FileSet = 0;  //定义一个整型变量, 用于保存fseek函数的返回值int     FileEnd = 0;  //整个文件的字节数 int     FileLength = 0;      //文件的数据长度。(注:每2个字节作为一个数据 )short   InputData[W]; //文件读写数据缓冲区  WAVHEADER    FileHeader;     //存文件头的结构体void showWavHead(WAVHEADER Header) {printf("ChunkID: %c%c%c%c\t", Header.ChunkID[0], Header.ChunkID[1], Header.ChunkID[2], Header.ChunkID[3]);printf("ChunkSize: %u\t", Header.ChunkSize);printf("Format: %c%c%c%c\n", Header.Format[0], Header.Format[1], Header.Format[2], Header.Format[3]);printf("FmtChunkID: %c%c%c%c\t", Header.FmtChunkID[0], Header.FmtChunkID[1], Header.FmtChunkID[2], Header.FmtChunkID[3]);printf("FmtChunkSize: %u\t", Header.FmtChunkSize);printf("AudioFormat: %d\t", Header.AudioFormat);printf("NumChannels: %d\t", Header.NumChannels);printf("SampleRate: %u\t", Header.SampleRate);printf("ByteRate: %u\t", Header.ByteRate);printf("BlockAlign: %d\t", Header.BlockAlign);printf("BitsPerSample: %d\n", Header.BitsPerSample);printf("DataChunkID: %c%c%c%c\t", Header.DataChunkID[0], Header.DataChunkID[1], Header.DataChunkID[2], Header.DataChunkID[3]);printf("DataChunkSize: %u\n", Header.DataChunkSize);}int main() {FILE *Ifp, *txt;    //定义文件读写指针 Ifp = fopen("456.wav", "rb");    /*以只读方式打开wav文件*/txt = fopen("456.txt", "w");/* 获得文件字节数,fseek函数将文件内部指针指向文件末尾,ftell函数获取文件内部指针相对于文件头的偏移量,rewind函数将文件内部指针指向文件头 */fseek(Ifp, 0L, SEEK_END);FileEnd = ftell(Ifp);printf("total file size: %d bytes \n", FileEnd);rewind(Ifp);// 读取文件头,并打印部分信息,wav格式的文件头一般是44个字节,后面是音频数据fread(&FileHeader, 1, sizeof(WAVHEADER), Ifp);showWavHead(FileHeader);// 读取数据。这里的数据大小是2字节,按照实际格式改。while循环每次读写 W 个数据量,for循环写最后剩余的FileLength = FileEnd / 2;while (FileLength >= W) {fread(InputData, sizeof(short), W, Ifp);for (int i = 0; i < W; i++) {fprintf(txt, "%d\n", InputData[i]);}FileLength -= W;}fread(InputData, sizeof(short), FileLength, Ifp);for (int i = 0; i < FileLength; i++) {fprintf(txt, "%d\n", InputData[i]);}char  *buf;long filesize;filesize = ftell(Ifp);//ftell求文件指针相对于0的便宜字节数,就求出了文件字节数buf = (char *)malloc(sizeof(char)*filesize);//开辟空间给缓存数组fread(buf, 1, (filesize - 44), Ifp);//每次读一个字节到buf,同时求读的次数return 0;}

二. 结果

VS语音信号处理(1) C语言读取WAV语音文件文件头数据

三. 小结

WAV格式语音数据文件头数据中包含许多关键的语音文件信息如:

// 文档标识。 大写字符串"RIFF",标明该文件为有效的 RIFF 格式文档。

// 文件数据长度。 从下一个字段首地址开始到文件末尾的总字节数。该字段的数值加 8 为当前文件的实际长度。

// 文件格式类型。 所有 WAV 格式的文件此处为字符串"WAVE",标明该文件是 WAV 格式文件。

// 格式块标识。 小写字符串,"fmt "。

// 格式块长度。 其数值不确定,取决于编码格式。可以是 16、 18 、20、40 等。

// 编码格式代码。 常见的 WAV 文件使用 PCM 脉冲编码调制格式,该数值通常为 1。

// 声道个数。 单声道为 1,立体声或双声道为 2。

// 采样频率。 每个声道单位时间采样次数。常用的采样频率有11025,16000 , 22050 和 44100 Hz。

// 数据传输速率。 该数值为:声道数×采样频率×每样本的数据位数/8。播放软件利用此值可以估计缓冲区的大小。

// 数据块对齐单位。 采样帧大小。该数值为:声道数×位数/8。播放软件需要一次处理多个该值大小的字节数据,用该数值调整缓冲区。

// 采样位数。 存储每个采样值所用的二进制数位数。常见的位数有 4、8、12、16、24、32。

通过读取文件头数据信息,就可以得知语音文件数据的大多数格式信息,下一篇将介绍分段读取WAV语音文件中语音数据部分的实例。