利用C语言读取WAV文件

简介

改了一下网上的代码,文件头不再写入txt。使用时,代码中填入wav文件和txt文件路径。wav文件的文件头信息会打印出来,音频数据则写入txt文件。

打印文件头信息

终端中会打印出文件头的一些信息,包括NumChannels(声道数),SampleRate(采样频率),BitsPerSample(每个样本多少位)等。通过更改showWavHead()函数来打印你需要的信息。

调整代码

你需要根据文件头中各种信息来调整代码。

文件头中各项信息的含义见:http://soundfile.sapp.org/doc/WaveFormat/

比如说,我的wav文件BitsPerSample是16,一个声道的一个样本占2字节。如果你的BitsPerSample不是16,你的FileLength(txt文件数据长度,或者叫数据个数)就不是由FileEnd(wav文件字节数)除以2(改成对应的字节数)来得到。

ExtractData.c

#include <stdio.h>   
#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(".wav","rb");    /*以只读方式打开wav文件*/
    txt = fopen(".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]);
    }

    return 0;
}

ExtractData.h

wav文件的文件头一般是44字节(除非fmt块后面有ExtraParamSize 和ExtraParams 项)。Header详细信息见上文链接。

  • uint8_t: unsigned char
  • uint16_t: unsigned short
  • uint32_t: unsigned int
#ifndef _EXTRACTDATA_H_
#define _EXTRACTDATA_H_

#include <stdint.h>

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_
  • 5
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值