一直以来我都是使用python的wave库读写wav文件的
由于项目需要,故而需要一个读取WAV文件的库
WAV文件是由块(Chunk)组成
读取wav文件需要寻找两个块
fmt 块(音频参数)和 data 块(音频数据)
需要的头文件
// Need Head File
#include <stdio.h>
#include <string.h>
块的定义("写"部分还没有实现,因为我有其他实现的方式)
// Chunk
typedef struct _CHUNK_{
// File Offset
unsigned Offset;
// Chunk Size
unsigned Size;
// Chunk ID
char ID[4];
// Data Buffer (For Write)
void* Data;
} CHUNK,*rCHUNK;
"WAV类"
包含上述两个需要的块
// WAV Struct
typedef struct _WAV_{
FILE *fp;
CHUNK subFMT,subDATA;
} WAV,*rWAV;
读取一个块
// Read Chunk
int __ReadChunk(rCHUNK ck,FILE *fp){
int ret = 1;
ck->Offset = ftell(fp);
ret &= fread(ck->ID,4,1,fp);
ret &= fread(&ck->Size,4,1,fp);
return !ret;
}
知道上一个块,去寻找下一个块
这个地方有些难度
// Move To Next Chunk
int __NextChunk(rCHUNK buf,rCHUNK last,FILE *fp){
int ret = 0;
if(last){
// Move to the last chunk
ret |= fseek(fp,last->Offset,SEEK_SET);
// Move to the next chunk
ret |= fseek(fp,last->Size+8,SEEK_CUR);
}
// read chunk
return ret | __ReadChunk(buf,fp);
}
那么可以开始寻找 fmt 和 data 块了
具体步骤
寻找下一个块
如果下一个块的ID是正在寻找的,那么退出循环
否则再下一个块,直到找完为止
int LoadWav(rWAV wav,FILE *fp){
CHUNK tmp;
tmp.Offset = 0;
tmp.Size = 4;
int flag;
wav->fp = fp;
// Find FMT Chunk
flag = 2;
while(!__NextChunk(&tmp,&tmp,fp)){
if(!memcmp(tmp.ID,"fmt ",4)){
flag = 0;
break;
}
}
if(flag) return flag;
wav->subFMT = tmp;
// Find data Chunk
flag = 2;
while(!__NextChunk(&tmp,&tmp,fp)){
if(!memcmp(tmp.ID,"data ",4)){
flag = 0;
break;
}
}
if(flag) return flag;
wav->subDATA = tmp;
return 0;
}
再写个代码测试一下
打印出 fmt 和 data 块的位置和块数据大小
#include "wav.h"
int main(){
WAV wav;
FILE *fp = fopen("3.wav","rb");
int flag = 0;
if(flag = LoadWav(&wav,fp)) printf("Load Fail! return code %d\n",flag);
else{
printf("fmt at %u , Size is %u\n",wav.subFMT.Offset,wav.subFMT.Size);
printf("data at %u , Size is %u\n",wav.subDATA.Offset,wav.subDATA.Size);
}
fclose(fp);
return 0;
}
EOF awa
(花了一个下午想出来的)