美文网首页
关于Wav格式的介绍

关于Wav格式的介绍

作者: 阑珊处等你 | 来源:发表于2019-08-16 17:39 被阅读0次

    在介绍Wav格式之前先聊聊RIFF。

    1.RIFF是什么?

    RIFF(Resources Interchange File Format)资源互换文件格式。在Windows中有很多多媒体文件都遵循RIFF的文件结构。以RIFF格式存储的数据有:

    Audio/visual interleaved data (.AVI)

    Waveform data (.WAV)

    Bitmapped data (.RDI)

    MIDI information (.RMI)

    Color palette (.PAL)

    Multimedia movie (.RMN)

    Animated cursor (.ANI)

    A bundle of other RIFF files (.BND)

    2. RIFF的结构?

    chunk是RIFF文件的基本单元。通常情况下,一个chunk是指多媒体数据的一个基本逻辑单元,比如视频的一帧数据,音频的一帧数据等。

    chunk的结构是:

    id  4字节,用于标识块中所包含的数据。如:RIFF,LIST,fmt,data,wav,avi等。

    size  块大小,存储在data域中数据长度,不包含id和size的大小。

    data 包含数据,如果数据长度为奇书,则最后添加一个空字节。

    3.chunk嵌套?

    chunk是可以嵌套的,只有块id为RIFFLIST的chunk才能包含其他的chunk。

    每个RIFF文件首先存放的必须是RIFF chunk,并且只能有一个标志为RIFF的chunk。RIFF的数据域的起始位置是一个4字节码(ROURCC),用于标识其数据域的格式,比如 WAV,AVI等 ;接着数据域的内容是包含的subChunk。

    如上图所示,RIFF的数据域的初始位置是 form Type,接着是嵌套了两个chunk,每个chunk都有字节的标识,数据域大小和数据域。

    RIFF chunk的数据域下嵌套了一个 LIST chunk 和一个 chunk。LIST chunk嵌套了两个chunk。

    LIST chunk的数据域的起始位置也有一个四字节码( List Type)用于说明LIST数据域的数据内容。

    4.Wav 是什么?

    Wav是一种音频文件格式,它符合RIFF文件格式。一个Wav文件通常有三个chunk和一个可选的chunk组成。

    在文件中排列循序是:RIFF chunk  ,Format chunk ,Fact chunk(可选),Data chunk。

    在这个Wav文件中,首先是一个RIFF chunk, RIFF chunk的数据域中包含了Format chunk ,Data chunk 和Fact chunk(可选)。

    大致的意思是

     RIFF chunk 的格式是 WAVE,包含了 fmt 和 data 两个subchunk。

    fmt chunk 描述了 data chunk  音频的信息。

    data  chunk 描述 音频的大小,包含音频数据。

    Chunk ID     包含 'R' , 'I' , 'F' , 'F' 字母;

    ChunkSize   36 + SubChunk2Size 或者  4 + (8 + SubChunk1Size) + (8 + SubChunk2Size);

    Format         包含'W' , 'A' , 'V' , 'E';

    Subchunk1ID      包含'f' , 'm' , 't' ;

    Subchunk1Size    Subchunk的数据域大小。如果是PCM的话是16

    AudioFormat        1 PCM格式,  2 音频数据格式

    NumChannels      1为 单声道, 2 为双声道

    SampleRate         采样率

    ByteRate            音频的码率(每秒播放的字节数)  SampleRate * NumChannels * BitsPerSample / 8

    BlockAlign          一次采样的大小  NumChannels * BitsPerSample / 8

    BitsPerSample   位宽 8bit,16bit

    ExtraParamSize   扩展长度

    ExtraParams        扩展内容(22字节)

    Subchunk2ID      包含 'd' , 'a' , 't' , 'a' 字母

    Subchunk2Size   NumSamples* NumChannels * BitsPerSample / 8

    Data                    音频数据

    5. PCM转Wav

    5.1 写Wav头部信息

    private byte[]writeWavHeader(FileOutputStream dataOutputStream, long totalAudioLen, long totalDataLen, long longSampleRate,

                                  int channels, long byteRate)throws IOException {

    byte[] header =new byte[44];

        //RIFF WAVE Chunk

    // RIFF标记占据四个字节

        header[0] ='R';

        header[1] ='I';

        header[2] ='F';

        header[3] ='F';

        //数据大小表示,由于原始数据为long型,通过四次计算得到长度

        header[4] = (byte) (totalDataLen &0xff);

        header[5] = (byte) ((totalDataLen >>8) &0xff);

        header[6] = (byte) ((totalDataLen >>16) &0xff);

        header[7] = (byte) ((totalDataLen >>24) &0xff);

        //WAVE标记占据四个字节

        header[8] ='W';

        header[9] ='A';

        header[10] ='V';

        header[11] ='E';

        //FMT Chunk

        header[12] ='f';

        // 'fmt '标记符占据四个字节

        header[13] ='m';

        header[14] ='t';

        header[15] =' ';//过渡字节

    //数据大小

        header[16] =16; // 4 bytes: size of 'fmt ' chunk

        header[17] =0;

        header[18] =0;

        header[19] =0;

        //编码方式 10H为PCM编码格式

        header[20] =1; // format = 1

        header[21] =0;

        //通道数

        header[22] = (byte) channels;

        header[23] =0;

        //采样率,每个通道的播放速度

        header[24] = (byte) (longSampleRate &0xff);

        header[25] = (byte) ((longSampleRate >>8) &0xff);

        header[26] = (byte) ((longSampleRate >>16) &0xff);

        header[27] = (byte) ((longSampleRate >>24) &0xff);

        //音频数据传送速率,采样率*通道数*采样深度/8

        header[28] = (byte) (byteRate &0xff);

        header[29] = (byte) ((byteRate >>8) &0xff);

        header[30] = (byte) ((byteRate >>16) &0xff);

        header[31] = (byte) ((byteRate >>24) &0xff);

        // 确定系统一次要处理多少个这样字节的数据,确定缓冲区,通道数*采样位数

        header[32] = (byte) (1 *16 /8);

        header[33] =0;

        //每个样本的数据位数

        header[34] =16;

        header[35] =0;

        //Data chunk

        header[36] ='d';//data标记符

        header[37] ='a';

        header[38] ='t';

        header[39] ='a';

        //数据长度

        header[40] = (byte) (totalAudioLen &0xff);

        header[41] = (byte) ((totalAudioLen >>8) &0xff);

        header[42] = (byte) ((totalAudioLen >>16) &0xff);

        header[43] = (byte) ((totalAudioLen >>24) &0xff);

        dataOutputStream.write(header, 0, 44);

        return header;

    }

    5.2 转换

    fileTarget =new File(rootFile, "test.pcm");

    fileWav =new File(rootFile, "test.wav");

    DataInputStream dataInputStream =null;

    DataOutputStream dataOutputStream =null;

    if (!fileWav.exists()) {

    try {

    fileWav.createNewFile();

        }catch (IOException e) {

    e.printStackTrace();

        }

    }

    convertPcmToWav(fileTarget.getPath(),fileWav.getPath(),mSampleRate,1,mAudioFormat);

    public void convertPcmToWav(String inPcmFilePath, String outWavFilePath, int sampleRate,

                                int channels, int bitNum) {

    FileInputStream in =null;

        FileOutputStream out =null;

        byte[] data =new byte[1024];

        try {

    long byteRate = sampleRate * channels * bitNum /8; //码率

            in =new FileInputStream(inPcmFilePath);

            out =new FileOutputStream(outWavFilePath);

            long totalAudioLen = in.getChannel().size(); //PCM文件大小

    //不包括'RIFF'和'WAV',所以是44 - 8 = 36,在加上PCM文件大小

            long totalDataLen = totalAudioLen +36;

            writeWavHeader(out, totalAudioLen, totalDataLen, sampleRate, channels, byteRate);

            int length =0;

            while ((length = in.read(data)) >0) {

    out.write(data, 0, length);

            }

    }catch (Exception e) {

    e.printStackTrace();

        }finally {

    if (in !=null) {

    try {

    in.close();

                }catch (IOException e) {

    e.printStackTrace();

                }

    }

    if (out !=null) {

    try {

    out.close();

                }catch (IOException e) {

    e.printStackTrace();

                }

    }

    }

    }

    参考:感谢!

    Microsoft WAVE soundfile format

    Android音频开发(4):如何存储和解析wav文件-Jhuster的专栏-51CTO博客

    RIFF和WAVE音频文件格式 - Brook_icv - 博客园

    相关文章

      网友评论

          本文标题:关于Wav格式的介绍

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