添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

一、音频格式总览

说到语音技术就不得不说起音频数据,从硬件设备采集语音信号,语音信号的处理,到语音信号A/D转换得到原始数据(raw data),再到对原始数据进行编码得到音频文件,对音频文件解码进行播放。那么为什么会出现如此多的音频格式?使用最多的几种音频格式有MP3、WMA、WAV、AAC、FLAC、APE、WV、ASF、VQF、MID、OGG、M4A、eAAC+。目前只用到了其中三种,故详细分析WAV、MP3、OGG。

二、原始数据(raw data,以PCM编码为例)

模拟音频信号经模数转换(A/D变换)直接形成的二进制序列,该文件没有附加的文件头和文件结束标志。而PCM(Pulse-code Modulation,脉冲编码调制)是一种模拟信号的数字化方法,常被用于数字电信系统中,非常频繁地,PCM编码以一种串行通信的形式,使数字传讯由一点至下一点变得更容易——不论在已给定的系统内,或物理位置。

PCM过程放在ALSA的实践中作为理论部分呈现,这里给出多通道音频数据的比特位特征。

图1 多通道音频数据的比特流格式

如图1所示,单通道音频数据以采样位数(bit)串行记录在比特流中:

1) 8 bit 采样位数: 意味着每个采样值能占据1个字节大小;

+------+------+------+------+------+------+------+------+------+
|  500 |  300 | -100 | -20  | -300 |  900 | -200 |  -50 |  250 |      
+------+------+------+------+------+------+------+------+------+

2)16 bit 采样位数:分为两个字节以小端(little-endian)方式存储在比特流中;

双通道及多通道数据音频数据以采样位数组织如下(n 为采样位数):

 +-- n bit---+---n bit---+-----+---n bit---+---n bit--+------+--n bit---+---n bit---+----------+
 |  channel1 |  channel2 | ... | channel1  | channel2 |  ... | channel1 |  channel2 |  ... |      
 +----------+----------+---------+----------+---------+----------+---------+----------+----------+

PCM的每个样本值包含在一个整数i中,i的长度为容纳指定样本长度所需的最小字节数。首先存储低有效字节,表示样本幅度的位放在i的高有效位上,剩下的位置为0。

计算机读入原始音频数据的方式与打开二进制文件相同。

#include <stdio.h>
#include <stdlib.h>
int main()
    char *fn;
    char *data;
    FILE *fp;
    int len;
    fn = "./test.pcm";
    fp = fopen(fn, "rb");
    if(!fp) {
        printf("file open failed.\n");
        exit(1);
    fseek(fp, 0, SEEK_END);
    len = ftell(fp);
    if(!len) {
        printf("file is null.\n");
        fclose(fp);
        exit(1);
    printf("file len = %d\n",len);
    data = (char *)malloc(len);
    fseek(fp, 0, SEEK_SET);
    fread(data, sizeof(__int16_t), len/sizeof(__int16_t), fp);
    fclose(fp);
    printf("%.*s\n",1,data);
    free(data);
    return 0;

三、wav文件

        wav(Waveform Audio FIle Format),即波形声音文件,由微软公司开发,是最早的数字音频格式,音质与CD相差无几,但缺点是wav文件非常庞大,不利于数据传输。

struct waitor_wav_format
#pragma pack(1)
    char riff_id[4];                     //  "RIFF",big-endian
    __uint32_t file_len;                 //  file length,little-endian
    char wave_id[4];                     //  "WAVE“,big-endian
    char fmt_id[4];                      //  "fmt",big-endian,beginning of fmt chunk
    char transition[4];                  //  size of fmt chunk
    __uint16_t fmt_type;                 //  1-PCM
    __uint16_t channel;                  //  通道数
    __uint16_t sample_rate;              //  采样率
    __uint32_t avg_bytes_per_sec;        //  sample_rate * block_align
    __uint16_t block_align;              //  每次采样大小
    __uint16_t bit_per_second;           //  采样精度
    //__uint16_t cbsize                    //  附加数据大小
    char data_id[4];                     //  "data"
    __uint32_t audio_len;                //  音频数据的长度
#pragma pack()

       wav文件分为3个(或4个)chunk,每个chunk基本格式为 chunk_id + chunk_size + chunk_data。总体结构为 文件头 wav_hdr + 音频数据 PCM格式。在解析wav文件时,可能会由于不同系统不同调制方式方式的不同增加几个额外的字节,这时应在数据结构中加入#pragma pack(1),以设置对齐的方式空出额外长度。

int main()
    waitor_wav_t *w;
    char *fn, *audio;
    // char buffer[4096];
    int ret;
    FILE *fp = fopen("./enc.ogg", "wb");
    fn = "../data/test.wav";
    w = waitor_wav_read(audio, fn);                    // 解析wav文件格式,转为二进制流voice
    if(!w) {
        printf("wavfile read failed.\n");
        fclose(fp);
        free(w);
        exit(1);
    printf(" chunk_id1 : %.*s\n", 4, w->riff_id);
    printf(" file len : %d\n", w->file_len);
    printf(" fomat : %.*s\n", 4, w->wave_id);
    printf(" sub chunk id : %.*s\n", 4, w->fmt_id);
    printf(" fmt type : %d\n", w->fmt_type);
    printf(" channel : %d.\n", w->channel);
    printf(" sample_rate : %d \n", w->sample_rate);
    fclose(fp);
    free(w);
    return 0;

四、MP3文件

        MP3(Moving Picture Experts Group Audio Layer III),是利用同名压缩技术,将音乐以1:10甚至1:12的压缩率压缩成容量较小的文件,并且能够保证损失音质极少,也因此成为网络音乐传输的主要格式。特点:兼具少损音质和小体积的特点,缺点是最高比特率是320K,高频部分一刀切,音质不高。

        MPEG压缩有

        MP3音频压缩包含编码和解码两个部分。编码是将WAV文件中的数据转换成高压缩率的位流形式,解码是接受位流并将其重建到WAV文件中。

        MP3采用了感知音频编码(Perceptual Audio Coding)这一失真算法。人耳感受声音的频率范围是20Hz-220kHz,MP3截掉了大量的冗余信号和无关的信号,编码器通过混合滤波器组将原始声音变换到频率域,利用心理声学模型,估算刚好能被察觉到的噪声水平,再经过量化,转换成Huffman编码,形成MP3位流。解码器要简单得多,它的任务是从编码后的谱线成分中,经过反量化和逆变换,提取出声音信号。

        在压缩音频数据时,先将原始声音数据分成固定的分块,然后作顺向MDCT变换,MDCT本身并不进行数据压缩,只是将一组时域数据转换成频域数据,以得知时域变化情况,顺向MDCT将每块的值转换为512个MDCT系数。量化使数据得到压缩,在对量化后的变换样值进行比特分配时要考虑使整个量化块最小,这就成为有损压缩了。解压时,经反向MDCT将512个系数还原成原始声音数据,前后的原始声音数据是不一致的,因为在压缩过程中,去掉了冗余和不相关数据。

       MP3文件的详细格式参见以下两个博客:

       MP3文件格式全解

       MP3文件结构解析(超详细)

         libmad库常被用来作为mp3解码器,不需要自己造轮子,基于libmad的mp3解码播放器参见:

       基于libmad的解码播放器

 接下来总结MP3文件的格式与libmad解码应用过程。

   1、MPEG压缩格式

        MP3文件格式分为三个部分:

 标签头和标签帧数据结构,每个ID3V2都包含一个标签头和若干标签帧,而标签帧由帧头和至少一个字节的内容组成。

ID3V2有四个版本,但流行的只有ID3V2.3:

/* ID3V2 的标签头结构 */
struct ID3V2Header
#pragma pack(1)
    unsigned char Header[3];   /* 保存的值比如为"ID3"表示是ID3V2 */
    unsigned char Version;     /* 如果是ID3V2.3则保存3,如果是ID3V2.4则保存4 */
    unsigned char Revision;    /* 副版本号 */
    unsigned char Flag;        /* 标志,使用高三位,其它位为0 */
    unsigned char Size[4];     /* 整个标签帧大小,除去本结构体的 10 个字节 */
#pragma pack()
/* 标签帧帧头的结构 */
struct ID3V2Frame
#pragma pack(1)
    unsigned char id[4];       /* 标志帧,说明其内容,例如作者/标题等*/
    char size[4];              /* 标志帧大小 */
    char flags[2];             /* 标志帧,只定义了6位 */
#pragma pack()

ID3V1:

/* ID3V1信息结构 */
struct ID3V1
    char Header[3];   /* 标签头"TAG",标识ID3V1 */
    char Title[30];   /* 歌名 */
    char Artist[30];  /* 作者 */
    char Album[30];   /* 专辑 */
    char Year[4];     /* 年份 */
    char Comment[30]; /* 备注 */
    char Genre;       /* 类型 */

 音频数据帧由帧头和音频数据组成:

struct DataFrameHeader
    unsigned int bzFrameSyncFlag1:8;   /* 全为 1 */
    unsigned int bzProtectBit:1;       /* CRC */
    unsigned int bzVersionInfo:4;      /* 包括 mpeg 版本,layer 版本 */
    unsigned int bzFrameSyncFlag2:3;   /* 全为 1 */
    unsigned int bzPrivateBit:1;       /* 私有 */
    unsigned int bzPaddingBit:1;      /* 是否填充,1 填充,0 不填充
    layer1 是 4 字节,其余的都是 1 字节 */
    unsigned int bzSampleIndex:2;     /* 采样率索引 */
    unsigned int bzBitRateIndex:4;    /* bit 率索引 */
    unsigned int bzExternBits:6;      /* 版权等,不关心 */ 
    unsigned int bzCahnnelMod:2;      /* 通道
    * 00 - Stereo 01 - Joint Stereo
    * 10 - Dual   11 - Single

   2、MPEG解码(以libmad-0.15.1b源代码为例)

       libmad运行demo为minimad.c,从其中的用法可以看出需要用户设置几个回调函数已控制程序运行。分别为input, output,header,filter 和error 。其中input实现mp3文件输入并转换为mad_stream,output实现根据用户需求对数据的再处理。

        使用libmad几个封装好的基本结构如下:

/* 存储未解码的比特流 */
struct mad_stream {
  unsigned char const *buffer;		/* input bitstream buffer */
  unsigned char const *bufend;		/* end of buffer */
  unsigned long skiplen;		/* bytes to skip before next frame */
  int sync;				/* stream sync found */
  unsigned long freerate;		/* free bitrate (fixed) */
  unsigned char const *this_frame;	/* start of current frame */
  unsigned char const *next_frame;	/* start of next frame */
  struct mad_bitptr ptr;		/* current processing bit pointer */
  struct mad_bitptr anc_ptr;		/* ancillary bits pointer */
  unsigned int anc_bitlen;		/* number of ancillary bits */
  unsigned char (*main_data)[MAD_BUFFER_MDLEN];
					/* Layer III main_data() */
  unsigned int md_len;			/* bytes in main_data */
  int options;				/* decoding options (see below) */
  enum mad_error error;			/* error code (see above) */
/* 数据帧帧头  */
struct mad_header {
  enum mad_layer layer;			/* audio layer (1, 2, or 3) */
  enum mad_mode mode;			/* channel mode (see above) */
  int mode_extension;			/* additional mode info */
  enum mad_emphasis emphasis;		/* de-emphasis to use (see above) */
  unsigned long bitrate;		/* stream bitrate (bps) */
  unsigned int samplerate;		/* sampling frequency (Hz) */
  unsigned short crc_check;		/* frame CRC accumulator */
  unsigned short crc_target;		/* final target CRC checksum */
  int flags;				/* flags (see below) */
  int private_bits;			/* private bits (see below) */
  mad_timer_t duration;			/* audio playing time of frame */
/* 有效数据帧 */
struct mad_frame {
  struct mad_header header;		/* MPEG audio header */
  int options;				/* decoding options (from stream) */
  mad_fixed_t sbsample[2][36][32];	/* synthesis subband filter samples */
  mad_fixed_t (*overlap)[2][32][18];	/* Layer III block overlap data */
/* 采样后的PCM音频数据 */
struct mad_pcm {
  unsigned int samplerate;		/* sampling frequency (Hz) */
  unsigned short channels;		/* number of channels */
  unsigned short length;		/* number of samples per channel */
  mad_fixed_t samples[2][1152];		/* PCM output samples [ch][sample] */
/* 解码后的音频数据 */
struct mad_synth {
  mad_fixed_t filter[2][2][2][16][8];	/* polyphase filterbank outputs */
  					/* [ch][eo][peo][s][v] */
  unsigned int phase;			/* current processing phase */
  struct mad_pcm pcm;			/* PCM output */
/* 解码过程控制 */
enum mad_flow {
  MAD_FLOW_CONTINUE = 0x0000,	/* continue normally */
  MAD_FLOW_STOP     = 0x0010,	/* stop decoding normally */
  MAD_FLOW_BREAK    = 0x0011,	/* stop decoding and signal an error */
  MAD_FLOW_IGNORE   = 0x0020	/* ignore the current frame */

  libmad的示例程序流程如下,用户可以直接使用回调机制使用libmad,也可以使用decoder.c的接口按照需求获取中间数据。 

五、OGG 文件 (参考:RFC 3533)

       OGG(OGG Vobis)是一种新的音频压缩格式,类似于MP3等现有的音乐格式。完全免费,没有专利限制。Vorbis 是这种音频压缩机制的名字,OGG是一个计划的名字,该计划意图设计一个完全开放的多媒体系统,OGG Vorbis是该计划的一部分。

       特点:支持多声道;现在创建的OGG文件可以在未来的任何播放器上播放,因此,这种文件格式可以不断地进行大小和音质的改良,而不影响既有的编码器和播放器;目前最好的有损格式之一,最高比特率500K。  

1、相关概念

     stream : 分为逻辑流与物理流,Ogg封装的结果称作物理流,一个物理流包含一个或多个逻辑流,这些逻辑流由ogg编码器创建,每个物理流中的逻辑流以一个特殊的页开始 -- bos,以一个特殊的页结束 -- eos;

physical bitstream with pages of
          different logical bitstreams grouped and chained
      -------------------------------------------------------------
      |*A*|*B*|*C*|A|A|C|B|A|B|#A#|C|...|B|C|#B#|#C#|*D*|D|...|#D#|
      -------------------------------------------------------------
       bos bos bos             eos           eos eos bos       eos                  
bos : beginning of stream; eos : end of stream
图中有两个物理流,第一个时序上有三个逻辑流ABC,分别以bos和eos为头尾;第二个只有一个逻辑流D

   packet : 一个解码单元,或是一帧数据;
   segment : 由 packet 分割而成,一个segment 最多包含255格式bytes,segment没有header ;
   page : 是 ogg 文件格式的基本组成单元,是对 segment 的封装,为几个连续的 segment 添加 header 构成 page;

2、音频格式剖析:

        OGG文件基本构成单位是页(Page),编码过程是由物理流向页转换的过程,OGG编码的主要过程如下:

          逻辑流由若干个packet组成
 -----------------------------------------------------------------
 > |       packet_1             | packet_2         | packet_3 |  <
 -----------------------------------------------------------------
                     |每个packet可以分成若干个segment
      packet_1 (5 segments)          packet_2 (4 segs)    p_3 (2 segs)
     ------------------------------ -------------------- ------------
 ..  |seg_1|seg_2|seg_3|seg_4|s_5 | |seg_1|seg_2|seg_3|| |seg_1|s_2 | ..
     ------------------------------ -------------------- ------------
                     | 给连续的几个segment加上page header就组成了page
 page_1 (packet_1 data)   page_2 (pket_1 data)   page_3 (packet_2 data)
------------------------  ----------------  ------------------------
|H|------------------- |  |H|----------- |  |H|------------------- |
|D||seg_1|seg_2|seg_3| |  |D|seg_4|s_5 | |  |D||seg_1|seg_2|seg_3| | ...
|R|------------------- |  |R|----------- |  |R|------------------- |
------------------------  ----------------  ------------------------
pages of            |
other    --------|  |
logical         -------
bitstreams      | MUX |
                -------
              page_1  page_2          page_3
      ------  ------  -------  -----  -------
 ...  ||   |  ||   |  ||    |  ||  |  ||    |  ...
      ------  ------  -------  -----  -------
              physical Ogg bitstream

   1)从编码器获得逻辑流的各个packet;
   2)将packet分割成Segment,分片;
   3)将Segment 打包成Page,页封装;
   4)将多个已经封装 page 完毕的逻辑流按应用要求的时序关系合成物理流,从而获得 OGG文件,对于只包含一个 stream 的文件,这个过程可以没有; 

3、OGG页结构

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1| Byte
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| capture_pattern: Magic number for page start "OggS"           | 0-3
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| version       | header_type   | granule_position              | 4-7
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                                                               | 8-11
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                               | bitstream_serial_number       | 12-15
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                               | page_sequence_number          | 16-19
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                               | CRC_checksum                  | 20-23
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                               |page_segments  | segment_table | 24-27
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ...                                                           | 28-
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

    1) 0~3字节:magic numbers,标识page开始;

    2) version: 1字节;

    3) page头类型:1字节:

         位 0x01 : 1-该页包含前一页的连续的packet ;0- 该页和前后页无联系;

         位 0x02 :  1- 该页为bos ; 0- 该页不是 bos;

         位 0x04 :  1-该页为eos ; 0- 该页不是 eos ;

    4) 位置信息: 8字节,对于音频

    5) serial number: 4字节,唯一标识stream;

    6) page sequence number: 4 字节,page序列号,为解码器提供页丢失标识,每个逻辑流中递增;

    7) CRC校验和: 4字节;

    8) number_page_segment : 1字节,segment table 中segment的个数;

    9) segment table: 长度为 number_page_segment字节,每个字节对应一个segment的长度。

     总的来说,我了解了三种主流的音频文件格式,在以后的开发中打好了基础,但依然有一些不足,细节上不够深入,后续在接触后更新。libogg编解码ogg文件源码阅读进行中...

1、  维基百科-WAV

2、  音频格式比较

3、   https://blog.csdn.net/ljxt523/article/details/52068241

4、   MP3:https://wenku.baidu.com/view/a071bf4e852458fb770b56a0.html

5、   OGG:https://blog.csdn.net/yu_yuan_1314/article/details/16884313

一、音频格式总览 说到语音技术就不得不说起音频数据,从硬件设备采集语音信号,语音信号的处理,到语音信号A/D转换得到原始数据(raw data),再到对原始数据进行编码得到音频文件,对音频文件解码进行播放。那么为什么会出现如此多的音频格式?使用最多的几种音频格式有MP3、WMA、WAV、AAC、FLAC、APE、WV、ASF、VQF、MID、OGG、M4A、eAAC+。目前只用到... // add in 2016.11 lxh BOOL AudioTagParser:: ParseM4aTag(HANDLE hFile, MP3_INFO *pMp3Info){ unsigned char headsize[4] = {0}; unsigned ...
M4A是一种用于压缩MPEG-4编码文件的扩展名。MPEG-4官方扩展名是MP4格式,它包含了音频文件及视频文件。而MP4文件中标准的音频格式无疑就是M4A了。其实M4A格式以前并不知名,直到2007年苹果公司首次用M4A与AAC、ALAC等作为iTunes及iPod歌曲收录格式,它才逐渐使用广泛起来。M4a不受版权保护。 文件格式:由很多box组成 存储形式:box length(4bit 大端格式) + box type(4 bit) + box content (box lengt...
本转码适用于pcm裸流音频转码(pcm音频较大)mp3ogg较小,ogg可以chorme内核播放,mp3貌似chorme内核不能播放 ogg是完全开源的,mp3有版权,对于chrome开源内核可能需要做内核改动才能播放mp3,如果使用chrome内核播放音频,推荐ogg 使用转码库需要使用自己的编译环境重新编译,库中有相应的vs版本 再把编译好的库加入自己的项目中 lame-3.99.5.tar.gz libogg-1.3.2.tar.gz libvorbis-1.3.5.tar.gz 使用方法见两个文件,使用这两个函数就能实现转码了 pcmmp3.txt pcmogg.txt
m4a 格式文件中的内容是有很多的box 组成的,box 格式如下: box length(4B 大端格式) + box type(4B)+ box content(box length - 8) 例如如下是ftyp这个box 的数据内容,可以看到该box 长度是0x20字节。 在日常生活中,我们会听各种音乐,而这些音乐大多数都是以数码的形式传播的,无论是在电脑上试听或下载还是在MP3或CD机上试听。当然也会经常看到各式各类的诸如MP3、WMV、APE等格式,但你是否明白这些格式的意思呢?下面小编就为你整理了一些这方面的内容,希望能有帮助。 1.1数码音乐简介 数字音源,也就是数字音频格式,最早指的是CD,CD经过压缩之后,又衍生出多种适于在随身听上播放的格式,这些压缩过的格式,我们可以分为两大类:有损压缩的和无损压缩的。这里所说的压缩,是指把PCM编码的或者是WA
音频世界充满了很多选择,这次提到的四种基本格式只是十几种不同音频格式中的几种。最终,无论您使用哪种用例,都将找到一种可以满足您需求的音频格式,包括一些压缩无损文件格式。现在您已经知道如何使用基础知识,我迫不及待想听听您创作的音乐。这里为大家大致介绍这四种格式的区别。 什么是.WAV文件? 文件扩展名: .wav 格式类型:无压缩无损 波形音频文件(也称为WAV文件)是较流行的数字音频格式之一,并且是录音棚录制的黄金标准。WAV是最早的数字音频格式之一,并迅速成为所有平台的主要内容。尽管取得了数十年的
转载自:http://blog.csdn.net/vblittleboy/article/details/6538355 ISO/IEC 14496是MPEG专家组制定的MPEG-4标准于1998年10月公布第1版,1999年1月成为国际标准,1999年12月公布了第2版,2000年初成为国际标准。 全文分为21个部分: (1)ISO/IEC 14496-1系统部分,描述了组成一个场景的音频
您好!对于测试音频文件系统找不到指定的路径的问题,您可以尝试以下几个步骤来排查和解决问题: 1. 确认路径是否正确:确保您提供的路径是准确的,并且文件确实存在于指定的路径中。可以使用文件浏览器或命令行来验证文件是否存在。 2. 检查文件权限:确保您的应用程序有足够的权限来访问指定路径中的文件。如果文件位于受保护的目录中,您可能需要提升应用程序的权限或更改文件的权限。 3. 使用绝对路径:尝试使用绝对路径而不是相对路径来访问文件。相对路径可能会导致找不到文件的问题,因为它们相对于当前工作目录。 4. 考虑文件类型和格式:检查文件类型和格式是否与您的应用程序兼容。某些音频文件可能需要特定的解码器或库才能正确读取。 5. 调试错误信息:如果您收到有关找不到指定路径的错误消息,请尝试捕获和打印更详细的错误信息,以便更好地理解问题所在。可以使用调试工具或日志记录来帮助您分析错误。 希望以上建议能够帮助您解决问题!如果还有其他问题,请随时提问。