c++读取wav文件

utils.h 

#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;

void showWavHead(WAVHEADER Header);
#endif  // #ifndef _EXTRACTDATA_H_

utils.cpp

#include <stdio.h>   
#include "utils.h"

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);
}

main.cpp

#include <iostream>
#include <math.h>
#include "main.h"
#include "utils.h"
using namespace std;

#define  W  128             //每次读写文件的数据量  
int     FileSet = 0;                //定义一个整型变量, 用于保存fseek函数的返回值
int     FileEnd = 0;                //整个文件的字节数 
int     FileLength = 0;             //文件的数据长度。(注:每2个字节作为一个数据 )
short   InputData[W];               //文件读写数据缓冲区  
WAVHEADER    FileHeader;            //存文件头的结构体

int main() {
    // 保存raw数据
	FILE *outfile;
	int wave_index = 1;
	char dst_wave_path[256] = { 0 };
	sprintf(dst_wave_path, "test_%d.raw", wave_index);
	if ((outfile = fopen(dst_wave_path, "wb+")) == NULL) {
		return -1;
	}

    // 待解析wav文件和保存为txt文件
    FILE *Ifp, *txt;    //定义文件读写指针
	Ifp = fopen("p1.wav", "rb");    /*以只读方式打开wav文件*/
	txt = fopen("p1.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 = FileHeader.DataChunkSize / 2;
	while (FileLength >= W) {
		fread(InputData, sizeof(short), W, Ifp);
		for (int i = 0; i < W; i++) {
			fprintf(txt, "%d\n", InputData[i]);
		}
        fwrite(&InputData, sizeof(char), W * 2, outfile);
		FileLength -= W;
	}

	fread(InputData, sizeof(short), FileLength, Ifp);
	for (int i = 0; i < FileLength; i++) {
		fprintf(txt, "%d\n", InputData[i]);
	}
    fwrite(&InputData, sizeof(char), FileLength * 2, outfile);

	fclose(outfile);
	return 0;
}

音频文件(.wav)解析读取

利用C语言读取WAV文件

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
好的,以下是一个简单的读取wav文件的C语言程序: ```c #include <stdio.h> #include <stdlib.h> typedef struct { char chunk_id[4]; int chunk_size; char format[4]; } ChunkHeader; typedef struct { char subchunk1_id[4]; int subchunk1_size; short audio_format; short num_channels; int sample_rate; int byte_rate; short block_align; short bits_per_sample; } FormatSubchunk; typedef struct { char subchunk2_id[4]; int subchunk2_size; } DataSubchunk; int main() { FILE *wav_file = fopen("test.wav", "rb"); if (!wav_file) { printf("Failed to open file.\n"); return 1; } ChunkHeader chunk_header; FormatSubchunk format_subchunk; DataSubchunk data_subchunk; fread(&chunk_header, sizeof(ChunkHeader), 1, wav_file); fread(&format_subchunk, sizeof(FormatSubchunk), 1, wav_file); fread(&data_subchunk, sizeof(DataSubchunk), 1, wav_file); printf("File format: %s\n", format_subchunk.audio_format == 1 ? "PCM" : "Unknown"); printf("Channels: %d\n", format_subchunk.num_channels); printf("Sample rate: %d Hz\n", format_subchunk.sample_rate); printf("Bits per sample: %d\n", format_subchunk.bits_per_sample); int num_samples = data_subchunk.subchunk2_size / (format_subchunk.bits_per_sample / 8); short *data = malloc(num_samples * sizeof(short)); fread(data, sizeof(short), num_samples, wav_file); // Do something with the audio data fclose(wav_file); free(data); return 0; } ``` 这个程序使用了三个结构体来解析wav文件的格式信息: - `ChunkHeader`:包含了RIFF块的信息,包括块标识符、块大小以及文件格式。 - `FormatSubchunk`:包含了格式子块的信息,包括子块标识符、子块大小、音频格式、声道数、采样率、字节率、块对齐方式以及每个样本的位数。 - `DataSubchunk`:包含了数据子块的信息,包括子块标识符和子块大小。 程序首先打开了一个wav文件,然后读取了三个结构体,分别对应wav文件的三个块。接着,程序输出了一些文件格式的信息,包括音频格式、声道数、采样率和每个样本的位数。最后,程序读取了音频数据并将其存储在一个short类型的数组中,可以在数组中进行进一步的处理。最后,程序关闭文件并释放分配的内存。 请注意,这只是一个简单的示例程序,实际上,解析wav文件需要更多的处理和错误检查。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

东城青年

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值