美文网首页
基础篇_7.音频编码WAV

基础篇_7.音频编码WAV

作者: Allan_Wang | 来源:发表于2018-11-30 16:12 被阅读0次

学习整理的相关章节链接:
基础篇_1.音视频学习框架
基础篇_2. 颜色空间模型 RBG、YUV、HSV
基础篇_3.图像编码之Bmp
基础篇_4.音频基础概念
基础篇_5.音频数据采集
基础篇_6.音频编码PCM
基础篇_7.音频编码WAV
基础篇_8.音频编码MP3\AAC

1.WAV编码

编码包括了两方面内容,一是按一定格式存储数据,二是采用一定的算法压缩数据。
WAV格式对音频流的编码没有硬性规定,支持非压缩的PCM(Puls Code Modulation)脉冲编码调制格式,还支持压缩型的微软自适应分脉冲编码调制Microsoft ADPCM(Adaptive Differential Puls Code Modulation)、国际电报联盟(International Telegraph Union)制定的语音压缩标准ITUG.711 a-law、ITU G.711-law、IMA ADPCM、ITU G.723 ADPCM (Yamaha)、GSM 6.10、ITU G.721 ADPCM编码和其它压缩算法。MP3编码同样也可以运用在WAV中,只要安装相应的Decode,就可以播放WAV中的MP3音乐

特点:音质非常好(因为通常用的编码都是非压缩的PCM),大量软件都支持
适用场景:多媒体开发的中间文件、保存音乐和音效素材

2.将PCM音频数据转换成WAV格式

WAV为微软公司(Microsoft)开发的一种声音文件格式,它符合RIFF(Resource Interchange File Format)文件规范,用于保存Windows平台的音频信息资源,被Windows平台及其应用程序所广泛支持。WAVE文件通常只是一个具有单个“WAVE”块的RIFF文件,该块由两个子块(”fmt”子数据块和”data”子数据块),它的格式如下图所示

WAV_file_format.png WAV中的常见编码格式.png

该格式的实质就是在PCM文件的前面加了一个文件头,每个字段的的含义为

typedef struct{
    char          ChunkID[4];//内容为"RIFF"
    unsigned long ChunkSize;//存储文件的字节数(不包含ChunkID和ChunkSize这8个字节)
    char          Format[4];//内容为"WAVE"
}WAVE_HEADER;

typedef struct{
    char          Subchunk1ID[4];//内容为"fmt"
    unsigned long  Subchunk1Size;//存储该子块的字节数(不含前面的Subchunk1ID和Subchunk1Size这8个字节)
    unsigned short AudioFormat;//存储音频文件的编码格式,例如若为PCM则其存储值为1,若为其他非PCM格式的则有一定的压缩。
    unsigned short NumChannels;//通道数,单通道(Mono)值为1,双通道(Stereo)值为2,等等
    unsigned long  SampleRate;//采样率,如8k,44.1k等
    unsigned long  ByteRate;//每秒存储的bit数,其值=SampleRate * NumChannels * BitsPerSample/8
    unsigned short BlockAlign;//块对齐大小,其值=NumChannels * BitsPerSample/8
    unsigned short BitsPerSample;//每个采样点的bit数,一般为8,16,32等。
   }WAVE_FMT;

typedef struct{
    char          Subchunk2ID[4];//内容为“data”
    unsigned long Subchunk2Size;//内容为接下来的正式的数据部分的字节数,其值=NumSamples * NumChannels * BitsPerSample/8
}WAVE_DATA;

比如下面的例子

这里是一个WAVE文件的开头72字节,字节显示为十六进制数字:

52 49 46 46 24 08 00 00 57 41 56 45 66 6d 74 20 10 00 00 00 01 00 02 00 
22 56 00 00 88 58 01 00 04 00 10 00 64 61 74 61 00 08 00 00 00 00 00 00 
24 17 1e f3 3c 13 3c 14 16 f9 18 f9 34 e7 23 a6 3c f2 24 f2 11 ce 1a 0d 

字段解析:

image

代码实现为

int simplest_pcm16le_to_wave(const char *pcmpath,int channels,int sample_rate,const char *wavepath)
{
    typedef struct WAVE_HEADER{  
        char         fccID[4];        
        unsigned   long    dwSize;            
        char         fccType[4];    
    }WAVE_HEADER;  
    typedef struct WAVE_FMT{  
        char         fccID[4];        
        unsigned   long       dwSize;            
        unsigned   short     wFormatTag;    
        unsigned   short     wChannels;  
        unsigned   long       dwSamplesPerSec;  
        unsigned   long       dwAvgBytesPerSec;  
        unsigned   short     wBlockAlign;  
        unsigned   short     uiBitsPerSample;  
    }WAVE_FMT;  
    typedef struct WAVE_DATA{  
        char       fccID[4];          
        unsigned long dwSize;              
    }WAVE_DATA;  
    if(channels==0||sample_rate==0){
    channels = 2;
    sample_rate = 44100;
    }
    int bits = 16;
    WAVE_HEADER   pcmHEADER;  
    WAVE_FMT   pcmFMT;  
    WAVE_DATA   pcmDATA;  
 
    unsigned   short   m_pcmData;
    FILE   *fp,*fpout;  
    fp=fopen(pcmpath, "rb");
    if(fp == NULL) {  
        printf("open pcm file error\n");
        return -1;  
    }
    fpout=fopen(wavepath,   "wb+");
    if(fpout == NULL) {    
        printf("create wav file error\n");  
        return -1; 
    }        
    //WAVE_HEADER
    memcpy(pcmHEADER.fccID,"RIFF",strlen("RIFF"));                    
    memcpy(pcmHEADER.fccType,"WAVE",strlen("WAVE"));  
    fseek(fpout,sizeof(WAVE_HEADER),1); 
    //WAVE_FMT
    pcmFMT.dwSamplesPerSec=sample_rate;  
    pcmFMT.dwAvgBytesPerSec=pcmFMT.dwSamplesPerSec*sizeof(m_pcmData);  
    pcmFMT.uiBitsPerSample=bits;
    memcpy(pcmFMT.fccID,"fmt ",strlen("fmt "));  
    pcmFMT.dwSize=16;  
    pcmFMT.wBlockAlign=2;  
    pcmFMT.wChannels=channels;  
    pcmFMT.wFormatTag=1;  //1就是pcm
 
    fwrite(&pcmFMT,sizeof(WAVE_FMT),1,fpout); 
    //WAVE_DATA;
    memcpy(pcmDATA.fccID,"data",strlen("data"));  
    pcmDATA.dwSize=0;
    fseek(fpout,sizeof(WAVE_DATA),SEEK_CUR);
    fread(&m_pcmData,sizeof(unsigned short),1,fp);
    while(!feof(fp)){  
        pcmDATA.dwSize+=2;
        fwrite(&m_pcmData,sizeof(unsigned short),1,fpout);
        fread(&m_pcmData,sizeof(unsigned short),1,fp);
    }  
    pcmHEADER.dwSize=44+pcmDATA.dwSize;
    rewind(fpout);
    fwrite(&pcmHEADER,sizeof(WAVE_HEADER),1,fpout);
    fseek(fpout,sizeof(WAVE_FMT),SEEK_CUR);
    fwrite(&pcmDATA,sizeof(WAVE_DATA),1,fpout);
    
    fclose(fp);
    fclose(fpout);
    return 0;
}

相关文章

  • 基础篇_7.音频编码WAV

    学习整理的相关章节链接:基础篇_1.音视频学习框架基础篇_2. 颜色空间模型 RBG、YUV、HSV基础篇_3.图...

  • 音频转码

    音频这块涉及面广,细节也挺多,以下为针对音频转码部分 一、介绍几种压缩编码格式 01、WAV编码 WAV编码的一种...

  • 音频格式

    lpcm是音频的编码格式 可以把他包装成其他的格式 wav

  • flac文件如何快速转换为wav格式

    flac和mp3很相似,都是音频编码的一种音频压缩编码。在将fac转换wav,我们就可以根据flac的特性很容易将...

  • PCM WAV

    pcm(不压缩),也称为raw格式。音频输入最原始的格式,不用再解码。 wav(不压缩,pcm编码):在pcm文件...

  • 通过lame 进行音频格式转化

    背景 因为上一篇音频合成中遇到了一个问题,合成工具不支持wav音频格式转化,而且录音所得的wav格式 是无损的格...

  • 音视频学习(五)

    音频编码 WAV编码是在PCM数据格式的前面加44个字节,分别用来存储PCM的采样率、声道数、数据格式等信息特点:...

  • WAV和PCM的关系和区别

    什么是WAV和PCM? WAV:wav是一种无损的音频文件格式,WAV符合 PIFF(Resource Inter...

  • WAV,PCM学习笔记

    什么是WAV和PCM? WAV:wav是一种无损的音频文件格式,WAV符合 PIFF(Resource Inter...

  • 音乐播放学习

    一、常见音频格式 WAV文件,WAV文件格式是一种由微软和IBM联合开发的用于音频 数字存储的标准,WAV文件...

网友评论

      本文标题:基础篇_7.音频编码WAV

      本文链接:https://www.haomeiwen.com/subject/yeehcqtx.html