linux下lame&alsa进行音频流操作(五)alsa使用和wav格式分析

1.wave文件的四个部分

1.0 四个部分

RIFF HeaderID = ‘RIFF’RIFF_TYPE=‘WAVE’
Format ChunkID = 'fmt ’
Fact Chunk 可选ID = ‘fact’
Data ChunkID =‘data’

1.1 RIFF_WAVE_Chunk

名称长度内容
ID4 Bytes‘RIFF’
Size4 Bytes整个文件大小-8
Type4 Bytes‘WAVE’

1.2 Format Chunk

名称长度内容
ID4 Bytes'fmt ’
Size4 Bytes整个文件大小-818/16 (有无附加信息)本结构大小(除ID,Size)
FormatTag2 Bytes通常0x0001编码方式
Channels2 Bytes1–单声道;2–双声道立体声声道数目
SamplesPerSec4 Bytes采样频率
AvgBytesPerSec4 Bytes每秒所需字节数
BlockAlign2 Bytes数据块对齐单位
BitsPerSample2 Bytes每个采样需要的位bit数
BlockAlign2 Bytes(可选,通过Size来判断有无)附加信息

1.3 Fact_Chunk

ID4 Bytes‘fact’
Size4 Bytes数值为4
data4 Bytes

1.4 Data_Chunk

ID4 Bytes‘data’
Size4 Bytes数据区大小
data4 Bytes数据区,真正存储数据的地方

二.

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:

在这里插入图片描述

所以要区分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
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值