wav文件解析

参考资料:
https://www.cnblogs.com/guojun-junguo/p/10129548.html
http://www.topherlee.com/software/pcm-tut-wavformat.html
http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/Samples.html
https://datatracker.ietf.org/doc/html/draft-ema-vpim-wav-00.txt
https://blog.ibaoger.com/2016/09/21/waveform-audio-file-format/

Wave文件包括Header和Data,其中Header结构如下:

The header of a WAV (RIFF) file is 44 bytes long and has the following format:

PositionsSample ValueDescription
1 - 4“RIFF”Marks the file as a riff file. Characters are each 1 byte long.
5 - 8File size (integer)Size of the overall file - 8 bytes, in bytes (32-bit integer). Typically, you’d fill this in after creation.
9 -12“WAVE”File Type Header. For our purposes, it always equals “WAVE”.
13-16"fmt "Format chunk marker. Includes trailing null
17-2016Length of format data as listed above
21-221Type of format (1 is PCM) - 2 byte integer
23-242Number of Channels - 2 byte integer
25-2844100Sample Rate - 32 byte integer. Common values are 44100 (CD), 48000 (DAT). Sample Rate = Number of Samples per second, or Hertz.
29-32176400(Sample Rate * BitsPerSample * Channels) / 8.
33-344(BitsPerSample * Channels) / 8.1 - 8 bit mono2 - 8 bit stereo/16 bit mono4 - 16 bit stereo
35-3616Bits per sample
37-40“data”“data” chunk header. Marks the beginning of the data section.
41-44File size (data)Size of the data section.

Sample values are given above for a 16-bit stereo source.

具体结构体定义如下:

 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. */
} 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_fotmat {
   RIFF_t riff;
   FMT_t fmt;
   Data_t data;
} Wav;

一个标准的wave文件header示例:

const Wav wav = {
		{
				"RIFF",	//RIFF marker
				9356,	//file-size (equals file-size - 8)
				"WAVE",	//Mark it as type "WAVE"
		},
		{
				"fmt",	//Mark the format section.
				16,		//Length of format data.  Always 16
				1,		//Wave type PCM
				1,		//1 channel(or 2 channels)
				44100,	//44.1 kHz Sample Rate (CD-Quality)
				88200,	//(Sample Rate * Bit Size * Channels) / 8
				2,		//(Bit Size * Channels) / 8
				16,		//Bits per sample (=Bit Size * Samples)
		},
		{
				"data",	//"data" marker
				9320,	//data-size (equals file-size - 44).
		}
};

将wave文件数据保存在头文件中:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdint.h>
#include <unistd.h>
#include <string.h>
#include <stdbool.h>
#include <gulliver.h>
#include <sys/stat.h>
 
#define u8 unsigned char
#define u16 unsigned short
#define u32 unsigned long
 
 
#define FILE_SCALE	8 	//音频文件质量 8或16	 
 
//44字节 
typedef struct {
	u8 riff_mark[4];		//
	u32 file_size;
	u8	wave_str[4];
	u8	fmt_str[4];
	u32 pcm_bit_num;
	u16 pcm_encode;
	u16 sound_channel;
	u32 pcm_sample_freq;
	u32 byte_freq;
	u16 block_alin;
	u16 sample_bits;
	u8	data_str[4]; 
	u32 sound_size;
} WAV_Typedef;
 
WAV_Typedef WAVFile_Array;
 
u16 *Sound_Data; 
 
u8 *Read_Sound_Data;

 
 /* wave head */
 struct RIFF_CHUNK
{
    char riffid[4];
    int32_t dwSize;
    char riffType[4];
};
typedef struct RIFF_CHUNK WAVE_HEADER;

struct FORMAT_CHUNK
{
    char fccid[4];
    int32_t dwSize;
    short wFormatTag;
    short wChannels;
    int32_t dwSamplesPerSec;
    int32_t dwAvgBytePerSec;
    short wBlockAlign;
    short uiBitsPerSample;
};
typedef struct FORMAT_CHUNK WAVE_FORMAT;

struct DATA_CHUNK
{
    char fccid[4];
    int32_t dwSize;
};
typedef struct DATA_CHUNK WAVE_DATA;

char *mWaveDataBuffer;
 
 
 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. */
} 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;
 
 
int main()
{
	FILE *fp,*fw;
	int ret;
	int i;
	int numOfword;
	
	WAVE_HEADER WaveHeader;
    WAVE_FORMAT WaveFormat;
    WAVE_DATA WaveData;
	
	Wav wav;
    RIFF_t riff;
    FMT_t fmt;
    Data_t data;
	
	if((fp=fopen("/fs/mmc2/touch1.wav","rb"))==NULL)	//打开操作不成功
		return 1;
	if((fw=fopen("/fs/mmc2/wav_out.h","w"))==NULL)	//打开操作不成功
		return 1;			
	
	/*
	fread(&wav, 1, sizeof(wav), 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("\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");
    
     printf("duration \t%d\n", data.Subchunk2Size / fmt.ByteRate);
	
	*/
	
	
	
	printf("sizeof(WaveHeader)=%d\n",sizeof(WaveHeader));
	printf("sizeof(WaveFormat)=%d\n",sizeof(WaveFormat));
	printf("sizeof(WaveData)=%d\n",sizeof(WaveData));
	
	if(fread(&WaveHeader,sizeof(WaveHeader),1,fp)==1)
		printf("WaveHeader read ok!\n");
	
	if(fread(&WaveFormat,sizeof(WaveFormat),1,fp)==1)
		printf("WaveFormat read ok!\n");
	
	if(fread(&WaveData,sizeof(WaveData),1,fp)==1)
		printf("WaveData read ok!\n");
	
	
	printf("资源交换文件标志: %.4s\n",WaveHeader.riffid);
	printf("文件大小: %d\n",WaveHeader.dwSize);
	printf("文件格式: %.4s\n",WaveHeader.riffType);
	
	printf("波形格式: %.4s\n",WaveFormat.fccid);
	printf("PCM: %dbits\n",WaveFormat.dwSize);
	printf("声道: %s\n",WaveFormat.wChannels==1?"单声道":"双声道");
	printf("采样速率: %d\n",WaveFormat.dwSamplesPerSec);
	printf("码率: %d Bps\n",WaveFormat.dwAvgBytePerSec);
	printf("块对齐: %d\n",WaveFormat.wBlockAlign);
	printf("采样位宽: %d\n",WaveFormat.uiBitsPerSample);	
	
	printf("Data标志: %.4s\n",WaveData.fccid);	
	printf("声音数据大小: %d\n",WaveData.dwSize);
	

	mWaveDataBuffer = malloc(WaveData.dwSize);
	numOfword = fread(mWaveDataBuffer,sizeof(char),WaveData.dwSize/sizeof(char),fp);

	printf("WaveData.dwSize/sizeof(short): %d\n",WaveData.dwSize/sizeof(char));
	printf("numOfword: %d\n",numOfword);
	
	//fwrite(&WaveHeader,sizeof(WAVE_HEADER),1,fw);
    //fwrite(&WaveFormat,sizeof(WAVE_FORMAT),1,fw);
    //fwrite(&WaveData,sizeof(WAVE_DATA),1,fw);
	//fwrite(mWaveDataBuffer,sizeof(short),numOfword,fw);

	
	{
		int idx=0;
		int line_count=0;
		
		fprintf(fw,"#ifndef __SOUND_DATA_H__\n");
		fprintf(fw,"#define __SOUND_DATA_H__\n\n");
		
		
		fprintf(fw,"#define SOUND_LENGTH\t%d\n\n",WaveData.dwSize);
		fprintf(fw,"const unsigned char WAVE_DATA[SOUND_LENGTH] = {\n\t");
		
		for(i = 0;i < WaveData.dwSize/sizeof(char); i++)
		{

			fprintf(fw,"%02x, ",(mWaveDataBuffer[idx] & 0xff));
			idx++;
			line_count++;
			if(line_count>8-1)
			{
				line_count=0;
				fprintf(fw,"\n\t");
			}
		}
		
		fprintf(fw,"\n};\n#endif\n");
		
		
		printf("\n ***** 已转换成头文件 wav_out.h *****\n"); 
	}


	if(mWaveDataBuffer){
		free(mWaveDataBuffer);
		mWaveDataBuffer = NULL;
	}
	
	
	if(fp!=NULL)
		fclose(fp);	
	if(fw!=NULL)
		fclose(fw);	
	
	
	return 0;	
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

sunxiaolin2016

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

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

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

打赏作者

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

抵扣说明:

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

余额充值