1.wave文件的四个部分
1.0 四个部分
RIFF Header
|
ID = 'RIFF'
|
RIFF_TYPE='WAVE'
|
Format Chunk
|
ID = 'fmt '
|
|
Fact Chunk 可选
|
ID = 'fact'
|
|
Data Chunk
|
ID ='data'
|
|
1.1 RIFF_WAVE_Chunk
名称
|
长度
|
内容
|
ID
|
4 Bytes
|
'RIFF'
|
Size
|
4 Bytes
|
整个文件大小-8
|
Type
|
4 Bytes
|
'WAVE'
|
1.2 Format Chunk
名称
|
长度
|
内容
|
|
ID
|
4 Bytes
|
'fmt '
|
|
Size
|
4 Bytes
|
18/16 (有无附加信息)
|
本结构大小(除ID,Size)
|
FormatTag
|
2 Bytes
|
通常0x0001
|
编码方式
|
Channels
|
2 Bytes
|
1--单声道;2--双声道立体声
|
声道数目
|
SamplesPerSec
|
4 Bytes
|
|
采样频率
|
AvgBytesPerSec
|
4 Bytes
|
|
每秒所需字节数
|
BlockAlign
|
2 Bytes
|
数据块对齐单位
|
|
BitsPerSample
|
2 Bytes
|
|
每个采样需要的位bit数
|
附加信息
|
2 Bytes
|
(可选,通过Size来判断有无)
|
附加信息
|
1.3 Fact_Chunk
ID
|
4 Bytes
|
'fact'
|
Size
|
4 Bytes
|
数值为4
|
data
|
4 Bytes
|
|
1.4 Data_Chunk
ID
|
4 Bytes
|
'data'
|
Size
|
4 Bytes
|
数据区大小
|
data
|
4 Bytes
|
数据区,真正存储数据的地方
|
参考文章:
WAV文件结构
二.
2.1 读取wave文件的前45个字节,并按顺序打印出来。并作分析
-
cong@msi:/work/ffmpeg/test/alsa/testalsa/1wave$ ls ../../../resource/test.wav -l
-
-rw-rw-r-- 1 cong cong 39623500 Aug 17 16:35 ../../../resource/test.wav
这个文件的总长度是39623500=0x25C9B4C
-
RIFF_HEADER:
-
0=0x52 1=0x49 2=0x46 3=0x46 --> 'RIFF'
-
4=0x44 5=0x9b 6=0x5c 7=0x02 --> size=0x025c9b44=文件的总长度-8(即这个size代表去除RIFF与本身之外的文件长度)
-
8=0x57 9=0x41 10=0x56 11=0x45 --> 'WAVE'
-
-
Format Chunk:
-
12=0x66 13=0x6d 14=0x74 15=0x20 --> 'fmt'
-
16=0x10 17=0x00 18=0x00 19=0x00 --> len=16=Format部分的长度是16个byte(不包括自身)
-
20=0x01 21=0x00 --> FormatTag=0x0001(1代表WAV_FMT_PCM)
-
22=0x02 23=0x00 --> channels=0x0002
-
24=0x44 25=0xac 26=0x00 27=0x00 --> SamplePerSec=0x0000ac44=44100
-
28=0x10 29=0xb1 30=0x02 31=0x00 --> AvgBytePerSec=0x0002b110=176400
-
32=0x04 33=0x00 --> BlockAlign=0x0004=4
-
34=0x10 35=0x00 --> BitsPerSample=0x0010=16
-
-
Fact Chunk: none
-
-
Data Chunk:
-
36=0x64 37=0x61 38=0x74 39=0x61 -->'data'
-
40=0x20 41=0x9b 42=0x5c 43=0x02 --> size=0x025c9b20=剩余的数据长度=文件总长度-RIFF-Format-Data
-
44=0x00
45=0x00
46=0x00
47=0x00
48=0x00
49=0x00
50=0x00
51=0x00
52=0x00
53=0x00
54=0x00
55=0x00
56=0x00
57=0x00
58=0x00
59=0x00
2.2 关于wav与 DTS-in-WAV
下面是打印的一个DTS-in-WAV的前60个字节
-
RIFF_Header:
-
0=0x52 1=0x49 2=0x46 3=0x46
-
4=0x24 5=0xe0 6=0xd5 7=0x02
-
8=0x57 9=0x41 10=0x56 11=0x45
-
-
Format_Chunk:
-
12=0x66 13=0x6d 14=0x74 15=0x20
-
16=0x10 17=0x00 18=0x00 19=0x00
-
20=0x01 21=0x00
-
22=0x02 23=0x00
-
24=0x44 25=0xac 26=0x00 27=0x00
-
28=0x10 29=0xb1 30=0x02 31=0x00
-
32=0x04 33=0x00
-
34=0x10 35=0x00
-
-
Fact Chunk: none
-
-
Data Chunk:
-
36=0x64 37=0x61 38=0x74 39=0x61
-
40=0x00 41=0xe0 42=0xd5 43=0x02
-
-
44=0xff 45=0x1f 46=0x00 47=0xe8 48=0xf1 49=0x07
-
50=0xdf
-
51=0xfc
-
52=0x98
-
53=0xfc
-
54=0x01
-
55=0xec
-
56=0xe9
-
57=0xf4
-
58=0x09
-
59=0x00
DTS-coding有两种格式: raw bitsteam coding 与14bit words,而这两种格式进行coding时既可用big-endian也可用little-endian
所以为了区分就在每帧开头加上如下标志:
Every frame in DTS starts with 32-bit syncword which can be used to distinguish current bitstream encoding:
Sequence
|
Bitstream type
|
7F FE 80 01
|
raw big-endian
|
FE 7F 01 80
|
raw little-endian
|
1F FF E8 00 07 Fx
|
14-bit big-endian
|
FF 1F 00 E8 Fx 07
|
14-bit little-endian
|
所以要区分wav与DTS-in-WAV,文件头(前44个字节)是一样的没法区分,只能判断数据部分是否是以上面的4组开始。
参考:
三.
3.1 代码
-
#include "utils.h"
-
#include <stdlib.h>
-
typedef struct {
-
u_int magic; /* 'RIFF' */
-
u_int length; /* filelen */
-
u_int type; /* 'WAVE' */
-
} WaveHeader;
-
-
typedef struct {
-
u_short format; /* see WAV_FMT_* */
-
u_short channels;
-
u_int sample_fq; /* frequence of sample */
-
u_int byte_p_sec;
-
u_short byte_p_spl; /* samplesize; 1 or 2 bytes */
-
u_short bit_p_spl; /* 8, 12 or 16 bit */
-
} WaveFmtBody;
-
-
typedef struct {
-
WaveFmtBody format;
-
u_short ext_size;
-
u_short bit_p_spl;
-
u_int channel_mask;
-
u_short guid_format; /* WAV_FMT_* */
-
u_char guid_tag[14]; /* WAV_GUID_TAG */
-
} WaveFmtExtensibleBody;
-
-
typedef struct {
-
u_int type; /* 'data' */
-
u_int length; /* samplecount */
-
} WaveChunkHeader;
-
-
-
#define COMPOSE_ID(a,b,c,d) ((a) | ((b)<<8) | ((c)<<16) | ((d)<<24))
-
#define WAV_RIFF COMPOSE_ID('R','I','F','F')
-
#define WAV_WAVE COMPOSE_ID('W','A','V','E')
-
#define WAV_FMT COMPOSE_ID('f','m','t',' ')
-
#define WAV_DATA COMPOSE_ID('d','a','t','a')
-
-
int check_wavfile(int fd)
-
{
-
int ret;
-
int i, len;
-
WaveHeader* header;
-
WaveFmtBody* fmt;
-
WaveChunkHeader* chunk_header;
-
unsigned char* pbuf = (unsigned char*)malloc(128);
-
if(NULL == pbuf)
-
{
-
dbmsg("pbuf malloc error");
-
return -1;
-
}
-
//1. 读取wave的Header部分并解析
-
len = sizeof(WaveHeader);
-
if( (ret=read(fd, pbuf, len)) != len)
-
{
-
dbmsg("read error");
-
return -1;
-
}
-
header = (WaveHeader*)pbuf;
-
if( (header->magic!=WAV_RIFF) || (header->type!=WAV_WAVE))
-
{
-
dbmsg("not a wav file");
-
return -1;
-
}
-
//2.读取wave的FormatChunk部分并解析
-
//2.FormatChunk又可分为header和body两部分
-
len = sizeof(WaveChunkHeader)+sizeof(WaveFmtBody);
-
if( (ret=read(fd, pbuf, len)) != len)
-
{
-
dbmsg("read error");
-
return -1;
-
}
-
chunk_header = (WaveChunkHeader*)pbuf;
-
if( chunk_header->type!=WAV_FMT)
-
{
-
dbmsg("fmt body error");
-
return -1;
-
}
-
fmt = (WaveFmtBody*)(pbuf+sizeof(WaveChunkHeader));
-
if(fmt->format != 0x0001) //WAV_FMT_PCM
-
{
-
dbmsg("format is not pcm");
-
return -1;
-
}
-
dbmsg("format=0x%x, channels=0x%x,sample_fq=%d,byte_p_sec=%d,byte_p_sample=%d,bit_p_sample=%d",
-
fmt->format, fmt->channels,fmt->sample_fq, fmt->byte_p_sec,
-
fmt->byte_p_spl, fmt->bit_p_spl);
-
//3.读取wave的DataChunk部分并解析
-
//3.DataChunk只包括header部分
-
len = sizeof(WaveChunkHeader);
-
if( (ret=read(fd, pbuf, len)) != len)
-
{
-
dbmsg("read error");
-
return -1;
-
}
-
chunk_header = (WaveChunkHeader*)pbuf;
-
if(chunk_header->type != WAV_DATA)
-
{
-
dbmsg("not data chunk");
-
return -1;
-
}
-
dbmsg("pcm_data_size=0x%x",chunk_header->length); //这个长度就是wav文件中的纯数据的长度.
-
-
free(pbuf);
-
pbuf = NULL;
-
return -1;
-
}
-
-
int main ( int argc, char *argv[] )
-
{
-
int fd;
-
if(argc < 2)
-
{
-
dbmsg("usage: ./waveinfo ");
-
return -1;
-
}
-
fd = open(argv[1], O_RDWR);
-
if(fd<0)
-
{
-
dbmsg("open error");
-
return -1;
-
}
-
check_wavfile(fd);
-
return EXIT_SUCCESS;
-
}
3.2 运行结果
-
cong@msi:/work/ffmpeg/test/alsa/testalsa/1wave$ make run
-
./wave /work/ffmpeg/test/resource//test.wav
-
wave.c:check_wavfile[86]: format=0x1, channels=0x2,sample_fq=44100,byte_p_sec=176400,byte_p_sample=4,bit_p_sample=16
-
wave.c:check_wavfile[100]: pcm_data_size=0x25c9b20
3.2 代码打包
1wave.rar(下载后改名为1wave.tar.gz)
阅读(1966) | 评论(0) | 转发(0) |