C语言实现wav文件的读写
- wav文件格式
//wav.h
typedef unsigned char uint8_t;
typedef signed char int8_t;
typedef unsigned short int uint16_t;
typedef signed short int int16_t;
typedef unsigned int uint32_t;
typedef signed int int32_t;
typedef struct wave_header
{
uint8_t riff[4]; // 'R I F F'
uint32_t size;
uint8_t waveFlag[4];//' W A V E'
uint8_t fmt[4];//'F M T'
uint32_t fmtLen; /* 16 for PCM */
uint16_t tag;/* PCM = 1*/
uint16_t channels;
uint32_t sampFreq;
uint32_t byteRate;
uint16_t blockAlign;/* = NumChannels * BitsPerSample/8 */
uint16_t bitSamp;
uint8_t dataFlag[4];//'D A T A'
uint32_t length;/* data size */
} wave_header_t;
typedef struct wave_file
{
wave_header_t header;
uint32_t *data;
}wave_file_t;
- 文件操作
function | usage |
---|---|
fread | fread(buffer,size,count,fp); |
fwrite | fwrite(buffer,size,count,fp); |
fopen | FILE * fopen(const char * path,const char * mode); |
fclose | fclose(fp); |
//fread(fa,4,5,fp); 从fp所指的文件中,每次读4个字节(一个实数)送入实数组fa中,连续读5次,即读5个实数到fa中。
3. C语言实现
//wav.c
#include <stdio.h>
#include "wav.h"
#define WAVE_FILE_HEADER_SIZE sizeof(wave_header_t)
static char wav_header[WAVE_FILE_HEADER_SIZE];
uint32_t get_wav_data(wave_file_t *waveFile)
{
uint8_t *dataTemp = (uint8_t *)waveFile->data;
// check for RIFF
memcpy(waveFile->header.riff, dataTemp, 4);
dataTemp += 4;
if( memcmp( (uint8_t*)waveFile->header.riff, "RIFF", 4) )
{
return 0;
}
// Get size
memcpy(&waveFile->header.size, dataTemp, 4);
dataTemp += 4;
printf( "WAV header size [%d]\n", waveFile->header.size);
// .wav file flag
memcpy(waveFile->header.waveFlag, dataTemp, 4);
dataTemp += 4;
if( memcmp( (uint8_t*)waveFile->header.waveFlag, "WAVE", 4) )
{
return 0;
}
// fmt
memcpy(waveFile->header.fmt, dataTemp, 4);
dataTemp += 4;
if( memcmp( (uint8_t*)waveFile->header.fmt, "fmt ", 4) )
{
return 0;
}
// fmt length
memcpy(&waveFile->header.fmtLen, dataTemp, 4);
dataTemp += 4;
// Tag: PCM or not
memcpy(&waveFile->header.tag, dataTemp, 4);
dataTemp += 2;
// Channels
memcpy(&waveFile->header.channels, dataTemp, 4);
dataTemp += 2;
printf( "WAV channels [%d]\n", waveFile->header.channels);
// Sample Rate in Hz
memcpy(&waveFile->header.sampFreq, dataTemp, 4);
dataTemp += 4;
memcpy(&waveFile->header.byteRate, dataTemp, 4);
dataTemp += 4;
printf( "WAV sample_rate [%d]\n", waveFile->header.sampFreq);
printf( "WAV byteRate [%d]\n", waveFile->header.byteRate);
// quantize bytes for per samp point
memcpy(&waveFile->header.blockAlign, dataTemp, 4);
dataTemp += 2;
memcpy(&waveFile->header.bitSamp, dataTemp, 4);
dataTemp += 2;
printf( "WAV bitSamp [%d]\n", waveFile->header.bitSamp);
// Data
memcpy(waveFile->header.dataFlag, dataTemp, 4);
dataTemp += 4;
if( memcmp( (uint8_t*)waveFile->header.dataFlag, "data ", 4) )
{
return 0;
}
memcpy(&waveFile->header.length, dataTemp, 4);
dataTemp += 4;
return 0;
}
wave_file_t wave_file_info;
uint8_t *buf;
uint32_t play_wav_file(char *file_path,char *pcm)
{
uint32_t bytesToRead=0;
FILE *fp=NULL;
FILE *fptr=NULL;
fp=fopen(file_path,"rb");
if (!fp) {
printf("%s can't open audio file\n",file_path);
exit(1);
}
fptr=fopen(pcm,"wb");
if (!fptr) {
printf(" can't 2 open audio file\n");
exit(1);
}
fread(&wav_header, WAVE_FILE_HEADER_SIZE, 1, fp);
wave_file_t *newWav=&wave_file_info;
memset(&wave_file_info, 0, sizeof(wave_file_info));
newWav->data = (uint32_t *)&wav_header;
get_wav_data(newWav);
//add wav header
fwrite(&wav_header, WAVE_FILE_HEADER_SIZE, 1, fptr);
bytesToRead = (newWav->header.length - WAVE_FILE_HEADER_SIZE);
for (; bytesToRead > 0; bytesToRead--)
{
fread(&buf, 1, 1, fp);
fwrite(&buf,1, 1, fptr);//写成pcm检查 正确读取 char
}
//fread(buf, 1, 1en, fp); 可以按需要的长度与类型读取wav
/*static unsigned int curr_play_index = 0;
for(int i=0;i<bytesToRead/len;i++)
{
if(curr_play_index<bytesToRead)
{
fread(buf, 1, 1en, fp);
}
curr_play_index+=len;
}*/
fclose(fp);
fclose(fptr);
return bytesToRead;//when play done it's 0
}
int main(void)
{
char wave[] = "D://1.wav";
char pcm[] = "D://1_out.wav";
uint32_t wav_len =play_wav_file(wave,pcm);
printf("%d\n",wav_len);
return 0;
}