查找wav文件头关键struct 位置,当然也可查找avi文件头。用这个方法找到avi文件data位置后,可直接读出文件的每一帧图片。当然avi数据的标志位不是data,可以是00dc等。
WAV音频头文件有三个关键struct:RIFF, fmt,data。
AVI 视频文件头的关键struct:RIFF, LIST, avih,movi,strl,strh,strf.
搞懂了wav 音频格式后,可以把wav加入avi视频中,合成带音乐的avi视频,也可以把麦克风的语音录入合成为avi音视频文件。
1. struct RIFF {
char[4] id; //RIFF
int size;
char[4] type; //WAV
}
RIFF 下面必须有 fmt 和data 两个块
2. fmt:
struct fmt{
char[4] id; //fmt
unsigned int size;
short format_tag
2字节,表示音频数据的格式。如值为1,表示使用PCM格式。
short channels
2字节,声道数。值为1则为单声道,为2则是双声道。
unsigned int samples_per_sec
采样率,主要有22.05KHz,44.1kHz和48KHz。
unsigned int bytes_per sec
音频的码率,每秒播放的字节数。samples_per_sec * channels * bits_per_sample / 8,可以估算出使用缓冲区的大小
short block_align
数据块对齐单位,一次采样的大小,值为声道数 * 量化位数 / 8,在播放时需要一次 处理多个该值大小的字节数据。
short bits_per_sample
音频sample的量化位数,有16位,24位和32位等。
// cbSize
// 扩展区的长度
}
3. data 块
struct data{
char [4] id; //data
unsigned int size;
}
4. data 块的size 字节后面紧跟音频数据。
音频数据按时间先后顺序放入,如采样后数据是8位,刚好一字节,则直接放入,如是16位,则采样数据的低位放在文件的低位,高位放高位。
FILE * 与int 文件描述符之间的互转;
nt fileno(FILE *tream)
FILE *fdopen(int fd, const char *mode) //mode 读写方式
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- #include <malloc.h>
- #include <wait.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <sys/ioctl.h>
- #include <sys/mman.h>
-
- static unsigned int t=0;
- static unsigned int q=0;
-
-
- int main(void){
- struct riff{
- char id[4];
- int size;
- char type[4];
- }ri;
-
- struct fmt{
- char id[4]; //fmt
- unsigned int size;
- unsigned short format_tag; //1
- unsigned short channels; //1
- unsigned int samples_per_sec; //22.05khz,44.1,48
- unsigned int bytes_per_sec; //每秒播发的字节数
- unsigned short block_align; //数据块对齐单位,一次采样的大小,值为声道数 * 量化位数 / 8
- unsigned short bits_per_sample; //16,24,32
-
- }fm;
- struct data{
- char id[4];//data
- unsigned int size;
- }da;
-
-
- FILE *f=fopen("/home/wzpc/1.wav","r+b");
- FILE *file=fopen("/home/wzpc/sample.wav","w+b"); //生成wav文件
-
- fseek(f, 0, SEEK_END);
- int size = ftell(f);
-
- fseek(f, 0, SEEK_SET);
-
-
- int fd=open("/home/wzpc/1.wav",O_RDONLY);
- char *m=mmap(NULL,size,PROT_READ,MAP_SHARED,fd,0);
-
- // unsigned int a=40;
- // unsigned int len=256*256*256*( unsigned char)m[a+3]+256*256*(unsigned char)m[a+2]+256*( unsigned char)m[a+1]+(unsigned char)m[a]; //4字节ascii转int
- // printf("%d\n",len);
-
-
- for(int t=0;t<size;t++){
- if((m[t]=='R')&&(m[t+1]=='I')&&(m[t+2]=='F')&&(m[t+3])=='F'){
-
- memcpy(&ri,&m[t],sizeof(ri));
- printf("%s\n",ri.id);
- printf("%d\n",ri.size);
- printf("%s\n",ri.type);
- printf("--------------------------------------\n");
-
- typedef struct riff RIFF;
- RIFF r={
- {'R','I','F','F'},
- 3382308,
- {'W','A','V','E'}
- };
-
- q=size;
- fseek(file,0,SEEK_SET);
- fwrite(&r,12,1,file);
-
- }
- }
- for(t=0;t<size;t++){
- if((m[t]=='f')&&(m[t+1]=='m')&&(m[t+2]=='t')){
- printf("t:%d\n",t);
-
- memcpy(&fm,&m[t],sizeof(fm));
- printf("%s\n",fm.id);
- printf("%d\n",fm.size);
- printf("%d\n",fm.format_tag);
- printf("%d\n",fm.channels);
- printf("%d\n",fm.samples_per_sec);
- printf("%d\n",fm.bytes_per_sec);
- printf("%d\n",fm.block_align);
- printf("%d\n",fm.bits_per_sample);
- printf("---------------------------------------\n");
-
- typedef struct fmt FMT;
- FMT m1={
- {'f','m','t',' '}, //必须要加' '
- 16,
- 1, //pcm
- 2, //两声道
- 44100, //每秒采样频率
- 176400, //每秒播发的字节数:声道数*采样频率*采样宽度/8=2*44100*16/8=17600
- 4, //声道数*采样宽度/8=2*16/8=4
- 16 // 采样宽度:8,16,24,32
-
- };
-
- fwrite(&m1,24,1,file);
-
- }
- }
-
- for(int t=0;t<size;t++){
- if((m[t]=='d')&&(m[t+1]=='a')&&(m[t+2]=='t')&&(m[t+3])=='a'){
-
-
- printf("t:%d\n",t);
- memcpy(&da,&m[t],sizeof(da));
- printf("%s\n",da.id);
- printf("%d\n",da.size);
- printf("--------------------------------------\n");
-
- typedef struct data DATA;
- DATA d={
- {'d','a','t','a'},
- 3382272
- };
- fwrite(&d,8,1,file);
- fwrite(&m[44],(size-44),1,file); //此内容为纯音频数据,由alsa部分输入
- }
- }
-
- //---------------------------------------------------------------------------------------------------
-
- fclose(file);
- munmap(m,size);
- puts("采集over");
- return 0;
- }