erbi_lucifer吧 关注:406贴子:3,325
  • 10回复贴,共1

【win32 ASM】File format parsing (part 2)

只看楼主收藏回复




一楼度娘……


1楼2013-04-29 15:31回复

    【文件格式解析(二)】WAV文件格式
    WAV:
    为微软公司(Microsoft)开发的一种声音文件格式,它符合RIFF(Resource Interchange File Format)文件规范,用于保存Windows平台的音频信息资源,被Windows平台及其应用程序所广泛支持,该格式也支持MSADPCM,CCITT A LAW等多种压缩运算法,支持多种音频数字,取样频率和声道,标准格式化的WAV文件和CD格式一样,也是44.1K的取样频率,16位量化数字,因此在声音文件质量和CD相差无几。


    本楼含有高级字体2楼2013-04-29 15:32
    回复
      2025-08-02 07:16:25
      广告
      不感兴趣
      开通SVIP免广告

      (一)文件组成
      WAV文件主要包括以下4大结构快:
      RIFF WAVE Chunk, Format Chunk, Fact Chunk(可选), DataChunk。
      具体见下图:
      ------------------------------------------------
      | RIFF WAVE Chunk |
      | ID = 'RIFF' |
      | RiffType = 'WAVE' |
      ------------------------------------------------
      | Format Chunk |
      | ID = 'fmt ' |
      ------------------------------------------------
      | Fact Chunk(optional) |
      | ID = 'fact' |
      ------------------------------------------------
      | Data Chunk |
      | ID = 'data' |


      本楼含有高级字体3楼2013-04-29 15:33
      回复

        RIFF WAVE Chunk结构
        1. 标志位,内容为RIFF 4字节
        2. 文件大小 4字节
        3. WAVE标志位 4字节
        Format Chunk 结构
        1. FMT标志位 4字节
        2. PCMbit(数值为16或18,18则最后又附加信息) 4字节
        3. 编码方式(为1时表示线性PCM编码,大于1时表示有压缩的编码。)2字节
        4. 通道数(1为单声道,2为双声道) 2字节
        5. 采样频率 4字节
        6. Byte率,Byte率=采样频率*音频通道数*每次采样得到的样本位数/8 4字节
        7. 块对齐=通道数*每次采样得到的样本位数/8 2字节
        8. 一个样本的位数 2字节
        附加信息(可选,通过Size来判断有无) 2字节
        Fact Chunk(optional) 结构
        1. FACT标志 4字节
        2. FACT大小 4字节
        3. FACT数据 4字节
        Data Chunk 结构
        1. data标志 4字节
        2. 音频数据大小 4字节


        4楼2013-04-29 15:33
        回复

          (二)构建结构体
          根据文件结构我们可以构建下面的结构体,然后读取文件即可获取文件的信息。
          ; RIFF WAVE Chunk结构和FormatChunk结构

          WAVHead struct
          flag db 4 dup(?);//RIFF
          file_size DWORD ?; //文件大小
          WAVE_flag db 4 dup(?);
          FMT_flag db4 dup(?);
          PCMbit DWORD ?; //数值为16或18,18则最后又附加信息
          encoding WORD ?;//为1时表示线性PCM编码,大于1时表示有压缩的编码。
          channel WORD ?; //通道数 //1为单声道,2为双声道
          frequency DWORD ?; //采样频率
          Bps DWORD ?; //Byte率,
          chunkset WORD ?;//块对齐=通道数*每次采样得到的样本位数/8
          sample_num_bit WORD ?; //一个样本的位数
          WAVHead ends
          ;//附加信息(可选,通过Size来判断有无)
          WAVEx WORD ?;
          ;//可选块,FactChunk(optional) 结构
          FACT_BLOCK struct
          flag db4 dup(?); // 'f','a','c','t'
          dwFactSize DWORD ?;
          dsData DWORD ?;
          FACT_BLOCK ends
          ; Data Chunk结构
          DataChunk struct
          data_flag db 4 dup(?);
          data_size DWORD ?; //数据大小
          DataChunk ends


          本楼含有高级字体5楼2013-04-29 15:34
          回复

            (三)读取图像信息

            接下来以图标文件“1.wav”(文件见附件)为例子读取它的结构信息。
            (1)图片为“1.wav”的RIFF WAVE Chunk结构(12字节)结构:

            1. 第1-4字节:数值是“52 49 46 46”,即标志“RIFF”
            2. 第5-8字节:数值是“24 40 5E 00”,即文件大小为 :6176804 byte
            3. 第9-12字节:数值是“57 41 56 45”,即wav标志为“WAVE”
            读取:


            本楼含有高级字体6楼2013-04-29 15:35
            回复

              (2)图片为“1.wav”的Format Chunk结构

              1. 第1-4字节:数值为“66 6D 74 20”,故FMT标志为“fmt”。
              2. 第5-8字节:数值为“10 00 00 00”,故量化结果为16,不是18,故结构后面没有附加数据。
              3. 第9-10字节:数值为“01 00”,压缩类型1(线性PCM编码)。
              4. 第11-12字节:数值为“02 00”,通道数为2(双声道)。
              5. 第13-16字节:数值为“44 AC 00 00”,采样频率44100 Hz。
              6. 第17-20字节:数值为“10 B1 02 00”,Byte率:4098555 kbps。
              7. 第21-22字节:数值为“04 00 ”,块对齐:4。
              8. 第23-24字节:数值为“10 00”,样本位数:16。
              读取结果:


              7楼2013-04-29 15:36
              回复

                (3)图片为“1.wav”的Data Chunk结构(8字节)结构:

                1. 第1-4字节:数值为“64 61 74 61”,即标志为“data”
                2. 第5-8字节:数值为“00 40 5E 00”,即音频数据大小:6176768 byte
                读取结果:


                8楼2013-04-29 15:37
                回复
                  2025-08-02 07:10:25
                  广告
                  不感兴趣
                  开通SVIP免广告

                  START:
                  ;获取参数
                  invoke GetCommandLine
                  mov CommandLine,eax
                  ;提取参数
                  invoke PathGetArgs,CommandLine
                  mov LpArg,eax mov esi,eax
                  lodsb ;[esi]-->al
                  cmp al,0
                  je noArgs
                  cmp al,34 ;双引号
                  jne @F
                  invoke PathUnquoteSpaces,LpArg ;去双引号
                  mov LpArg,eax
                  @@:
                  invoke PlaySound,LpArg,NULL,SND_ASYNC or SND_FILENAME or SND_NODEFAULT or SND_LOOP
                  invoke RtlZeroMemory,addr WAV,sizeof WAV
                  invoke
                  CreateFile,LpArg, GENERIC_READ,FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL
                  .if eax!=INVALID_HANDLE_VALUE
                  mov hFile, eax
                  invoke ReadFile,hFile,addr WAV, sizeof WAV, addr dwRead, NULL
                  .if dwRead!= sizeof WAV
                  jmp colseend
                  .else
                  invoke ShowWavFileH,WAV
                  cmp WAV.PCMbit,18
                  jne readnext
                  invoke ReadFile,hFile,addr WAVEx, sizeof WAVEx, addr dwRead, NULL
                  .if dwRead != sizeof WAVEx
                  jmp colseend
                  .else;显示附加数据
                  invoke wsprintf,addr info,CTXT("附加数据 :%d",13,10),WAVEx
                  invoke StdOut,addr info
                  .endif
                  readnext:
                  invoke ReadFile,hFile,addr whatH, sizeof whatH, addr dwRead, NULL
                  .if dwRead != sizeof whatH
                  jmp colseend
                  .else
                  .if whatH[0]!='f' && whatH[1]!='a' && whatH[2]!='c' && whatH[3]!='t'
                  invoke SetFilePointer,hFile, -4, NULL, FILE_CURRENT
                  invoke ReadFile,hFile,addr FACT, sizeof FACT, addr dwRead, NULL
                  invoke ShowFACTInfo,FACT
                  .else
                  invoke SetFilePointer,hFile, -4, NULL, FILE_CURRENT
                  .endif
                  invoke ReadFile,hFile,addr WAVD, sizeof WAVD, addr dwRead, NULL
                  .if dwRead != sizeof WAVD
                  jmp colseend
                  .else
                  invoke ShowDATAChunk,WAVD
                  .endif
                  .endif
                  .endif
                  .else
                  jmp openerror
                  .endif
                  colseend: invoke CloseHandle, hFile
                  jmp endexit
                  noArgs:
                  invoke StdOut,addr lpMsg
                  jmp endexit
                  openerror:
                  invoke StdOut,addr lpMsg_fileerr
                  jmp endexit
                  endexit:
                  invoke wsprintf,addr info,CTXT(13,10,"==================WAV播放中,回车退出===================",13,10)
                  invoke StdOut,addr info
                  ;暂停显示,回车键关闭
                  invoke StdIn,addr buffer,sizeof buffer
                  invoke ExitProcess,0


                  10楼2013-04-29 15:40
                  回复

                    ShowWavFileH proc wavH:WAVHead
                    invoke wsprintf,addr info,CTXT(13,10,"====================RIFF WAVE Chunk====================",13,10)
                    invoke StdOut,addr info
                    invoke wsprintf,addr info,CTXT("文件标志为 :%c%c%c%c"), DWORD ptr WAV.flag[0],DWORD ptr WAV.flag[1], DWORD ptr WAV.flag[2] ,DWORD ptr WAV.flag[3]
                    invoke StdOut,addr info
                    invoke wsprintf,addr info,CTXT(13,10,"文件大小为 :%ld byte",13,10),WAV.file_size
                    invoke StdOut,addr info
                    invoke wsprintf,addr info,CTXT("WAVE标志为 :%c%c%c%c"), DWORD ptr WAV.WAVE_flag[0],DWORD ptr WAV.WAVE_flag[1],DWORD ptr WAV.WAVE_flag[2],DWORD ptr WAV.WAVE_flag[3]
                    invoke StdOut,addr info
                    invoke wsprintf,addr info,CTXT(13,10,"==================== Format Chunk ====================",13,10)
                    invoke StdOut,addr info
                    invoke wsprintf,addr info,CTXT("FMT标志为 :%c%c%c%c"),DWORD ptr WAV.FMT_flag[0], DWORD ptr WAV.FMT_flag[1], DWORD ptr WAV.FMT_flag[2], DWORD ptr WAV.FMT_flag[3]
                    invoke StdOut,addr info
                    invoke wsprintf,addr info,CTXT(13,10,"量化结果 :%d",13,10), DWORD ptr WAV.PCMbit
                    invoke StdOut,addr info
                    invoke wsprintf,addr info,CTXT("压缩类型 :%d",13,10),WAV.encoding
                    invoke StdOut,addr info
                    invoke wsprintf,addr info,CTXT("音频通道数 :%d",13,10),WAV.channel
                    invoke StdOut,addr info
                    invoke wsprintf,addr info,CTXT("采样频率 :%d Hz",13,10),WAV.frequency
                    invoke StdOut,addr info
                    ;WAV.Bps*8/1000
                    mov eax,WAV.Bps
                    mov edx ,8
                    mul edx
                    mov eax,ecx
                    mov edx,0
                    mov ecx,1000
                    div ecx
                    mov WAV.Bps,eax
                    invoke wsprintf,addr info,CTXT("Byte率 :%ld kbps",13,10),WAV.Bps
                    invoke StdOut,addr info
                    invoke wsprintf,addr info,CTXT("块对齐 :%ld",13,10),WAV.chunkset
                    invoke StdOut,addr info
                    invoke wsprintf,addr info,CTXT("样本位数 :%d",13,10),WAV.sample_num_bit
                    invoke StdOut,addr info
                    ret
                    ShowWavFileH endp


                    11楼2013-04-29 15:41
                    回复

                      ShowFACTInfo proc pactH:FACT_BLOCK
                      invoke wsprintf,addr info,CTXT(13,10,"===================Fact Chunk(optional)===================",13,10)
                      invoke StdOut,addr info
                      invoke wsprintf,addr info,CTXT("FACT标志为 :%c%c%c%c",13,10),DWORD ptr pactH.flag[0], DWORD ptr pactH.flag[1], DWORD ptr pactH.flag[2], DWORD ptr pactH.flag[3]
                      invoke StdOut,addr info
                      invoke wsprintf,addr info,CTXT(13,10,"FACT大小为 :%ld byte",13,10),FACT.dwFactSize
                      invoke StdOut,addr info
                      invoke wsprintf,addr info,CTXT("FACT数据为 :%ld",13,10),FACT.dsData
                      invoke StdOut,addr info
                      ret
                      ShowFACTInfo endp
                      ShowDATAChunk proc dataC:DataChunk
                      invoke wsprintf,addr info,CTXT(13,10,"=================== Data Chunk ===================",13,10)
                      invoke StdOut,addr info
                      invoke wsprintf,addr info,CTXT("data标志为 :%c%c%c%c"),DWORD ptr dataC.data_flag[0],DWORD ptr dataC.data_flag [1],DWORD ptr dataC.data_flag[2],DWORD ptr dataC.data_flag[3]
                      invoke StdOut,addr info
                      invoke wsprintf,addr info,CTXT(13,10,"音频数据大小:%ld byte",13,10),dataC.data_size
                      invoke StdOut,addr info
                      ret
                      ShowDATAChunk endp
                      end START


                      12楼2013-04-29 15:41
                      回复