Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2150482
  • 博文数量: 438
  • 博客积分: 3871
  • 博客等级: 中校
  • 技术积分: 6075
  • 用 户 组: 普通用户
  • 注册时间: 2011-09-10 00:11
个人简介

邮箱: wangcong02345@163.com

文章分类

全部博文(438)

文章存档

2017年(15)

2016年(119)

2015年(91)

2014年(62)

2013年(56)

2012年(79)

2011年(16)

分类: LINUX

2015-09-08 11:47:12

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个字节,并按顺序打印出来。并作分析
  1. cong@msi:/work/ffmpeg/test/alsa/testalsa/1wave$ ls ../../../resource/test.wav -l
  2. -rw-rw-r-- 1 cong cong 39623500 Aug 17 16:35 ../../../resource/test.wav
这个文件的总长度是39623500=0x25C9B4C
  1. RIFF_HEADER:
  2. 0=0x52 1=0x49 2=0x46  3=0x46     --> 'RIFF'
  3. 4=0x44 5=0x9b 6=0x5c  7=0x02     --> size=0x025c9b44=文件的总长度-8(即这个size代表去除RIFF与本身之外的文件长度)
  4. 8=0x57 9=0x41 10=0x56 11=0x45    --> 'WAVE'

  5. Format Chunk:
  6. 12=0x66 13=0x6d 14=0x74 15=0x20   --> 'fmt'
  7. 16=0x10 17=0x00 18=0x00 19=0x00   --> len=16=Format部分的长度是16个byte(不包括自身)
  8. 20=0x01 21=0x00                   --> FormatTag=0x0001(1代表WAV_FMT_PCM)
  9. 22=0x02 23=0x00                   --> channels=0x0002
  10. 24=0x44 25=0xac 26=0x00 27=0x00   --> SamplePerSec=0x0000ac44=44100
  11. 28=0x10 29=0xb1 30=0x02 31=0x00   --> AvgBytePerSec=0x0002b110=176400
  12. 32=0x04 33=0x00                   --> BlockAlign=0x0004=4
  13. 34=0x10 35=0x00                   --> BitsPerSample=0x0010=16

  14. Fact Chunk: none

  15. Data Chunk:
  16. 36=0x64 37=0x61 38=0x74 39=0x61   -->'data'
  17. 40=0x20 41=0x9b 42=0x5c 43=0x02   --> size=0x025c9b20=剩余的数据长度=文件总长度-RIFF-Format-Data
  18. 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个字节
  1. RIFF_Header:
  2. 0=0x52 1=0x49 2=0x46 3=0x46
  3. 4=0x24 5=0xe0 6=0xd5 7=0x02
  4. 8=0x57 9=0x41 10=0x56 11=0x45

  5. Format_Chunk:
  6. 12=0x66 13=0x6d 14=0x74 15=0x20
  7. 16=0x10 17=0x00 18=0x00 19=0x00
  8. 20=0x01 21=0x00
  9. 22=0x02 23=0x00
  10. 24=0x44 25=0xac 26=0x00 27=0x00
  11. 28=0x10 29=0xb1 30=0x02 31=0x00
  12. 32=0x04 33=0x00
  13. 34=0x10 35=0x00

  14. Fact Chunk: none

  15. Data Chunk:
  16. 36=0x64 37=0x61 38=0x74 39=0x61
  17. 40=0x00 41=0xe0 42=0xd5 43=0x02

  18. 44=0xff 45=0x1f 46=0x00 47=0xe8 48=0xf1 49=0x07
  19. 50=0xdf
  20. 51=0xfc
  21. 52=0x98
  22. 53=0xfc
  23. 54=0x01
  24. 55=0xec
  25. 56=0xe9
  26. 57=0xf4
  27. 58=0x09
  28. 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 代码
  1. #include "utils.h"
  2. #include <stdlib.h>
  3. typedef struct {
  4.     u_int magic;        /* 'RIFF' */
  5.     u_int length;        /* filelen */
  6.     u_int type;        /* 'WAVE' */
  7. } WaveHeader;

  8. typedef struct {
  9.     u_short format;        /* see WAV_FMT_* */
  10.     u_short channels;
  11.     u_int sample_fq;    /* frequence of sample */
  12.     u_int byte_p_sec;
  13.     u_short byte_p_spl;    /* samplesize; 1 or 2 bytes */
  14.     u_short bit_p_spl;    /* 8, 12 or 16 bit */
  15. } WaveFmtBody;

  16. typedef struct {
  17.     WaveFmtBody format;
  18.     u_short ext_size;
  19.     u_short bit_p_spl;
  20.     u_int channel_mask;
  21.     u_short guid_format;    /* WAV_FMT_* */
  22.     u_char guid_tag[14];    /* WAV_GUID_TAG */
  23. } WaveFmtExtensibleBody;

  24. typedef struct {
  25.     u_int type;        /* 'data' */
  26.     u_int length;        /* samplecount */
  27. } WaveChunkHeader;


  28. #define COMPOSE_ID(a,b,c,d) ((a) | ((b)<<8) | ((c)<<16) | ((d)<<24))
  29. #define WAV_RIFF COMPOSE_ID('R','I','F','F')
  30. #define WAV_WAVE COMPOSE_ID('W','A','V','E')
  31. #define WAV_FMT COMPOSE_ID('f','m','t',' ')
  32. #define WAV_DATA COMPOSE_ID('d','a','t','a')

  33. int check_wavfile(int fd)
  34. {
  35.     int ret;
  36.     int i, len;
  37.     WaveHeader* header;
  38.     WaveFmtBody* fmt;
  39.     WaveChunkHeader* chunk_header;
  40.     unsigned char* pbuf = (unsigned char*)malloc(128);
  41.     if(NULL == pbuf)
  42.     {
  43.         dbmsg("pbuf malloc error");
  44.         return -1;
  45.     }
  46.     //1. 读取wave的Header部分并解析
  47.     len = sizeof(WaveHeader);
  48.     if( (ret=read(fd, pbuf, len)) != len)
  49.     {
  50.         dbmsg("read error");
  51.         return -1;
  52.     }
  53.     header = (WaveHeader*)pbuf;
  54.     if( (header->magic!=WAV_RIFF) || (header->type!=WAV_WAVE))
  55.     {
  56.         dbmsg("not a wav file");
  57.         return -1;
  58.     }
  59.     //2.读取wave的FormatChunk部分并解析
  60.     //2.FormatChunk又可分为header和body两部分
  61.     len = sizeof(WaveChunkHeader)+sizeof(WaveFmtBody);
  62.     if( (ret=read(fd, pbuf, len)) != len)
  63.     {
  64.         dbmsg("read error");
  65.         return -1;
  66.     }
  67.     chunk_header = (WaveChunkHeader*)pbuf;
  68.     if( chunk_header->type!=WAV_FMT)
  69.     {
  70.         dbmsg("fmt body error");
  71.         return -1;
  72.     }
  73.     fmt = (WaveFmtBody*)(pbuf+sizeof(WaveChunkHeader));
  74.     if(fmt->format != 0x0001) //WAV_FMT_PCM
  75.     {
  76.         dbmsg("format is not pcm");
  77.         return -1;
  78.     }
  79.     dbmsg("format=0x%x, channels=0x%x,sample_fq=%d,byte_p_sec=%d,byte_p_sample=%d,bit_p_sample=%d",
  80.             fmt->format, fmt->channels,fmt->sample_fq, fmt->byte_p_sec,
  81.             fmt->byte_p_spl, fmt->bit_p_spl);
  82.     //3.读取wave的DataChunk部分并解析
  83.     //3.DataChunk只包括header部分
  84.     len = sizeof(WaveChunkHeader);
  85.     if( (ret=read(fd, pbuf, len)) != len)
  86.     {
  87.         dbmsg("read error");
  88.         return -1;
  89.     }
  90.     chunk_header = (WaveChunkHeader*)pbuf;
  91.     if(chunk_header->type != WAV_DATA)
  92.     {
  93.         dbmsg("not data chunk");
  94.         return -1;
  95.     }
  96.     dbmsg("pcm_data_size=0x%x",chunk_header->length)//这个长度就是wav文件中的纯数据的长度.

  97.     free(pbuf);
  98.     pbuf = NULL;
  99.     return -1;
  100. }

  101. int main ( int argc, char *argv[] )
  102. {
  103.     int fd;
  104.     if(argc < 2)
  105.     {
  106.         dbmsg("usage: ./waveinfo ");
  107.         return -1;
  108.     }
  109.     fd = open(argv[1], O_RDWR);
  110.     if(fd<0)
  111.     {
  112.         dbmsg("open error");
  113.         return -1;
  114.     }
  115.     check_wavfile(fd);
  116.     return EXIT_SUCCESS;
  117. }
3.2 运行结果
  1. cong@msi:/work/ffmpeg/test/alsa/testalsa/1wave$ make run
  2. ./wave /work/ffmpeg/test/resource//test.wav
  3. wave.c:check_wavfile[86]: format=0x1, channels=0x2,sample_fq=44100,byte_p_sec=176400,byte_p_sample=4,bit_p_sample=16
  4. wave.c:check_wavfile[100]: pcm_data_size=0x25c9b20
3.2 代码打包
1wave.rar(下载后改名为1wave.tar.gz)



阅读(1966) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~