打印

[原创] Ogg音頻的提取與格式分析

Ogg音頻的提取與格式分析

本文由本人原創,如果對您有幫助,請留下您寶貴的意見.

在網上翻了大半天,一直都米找到比較容易理解的Ogg格式資料.
不得已,只好用破英語直接看英文文檔,對著16進制編輯器看了n個小時,只看出一頭霧水.

幸好現在已經解出來了,反正現在網上貌似還米什麼比較容易理解的資料,就自已寫一份資料好了.有錯誤歡迎指出.

偶只對提取有興趣,至於怎樣還原音頻等等,偶也米心情去研究.





1.Capture pattern:也就是"OggS",文件標識,誰都知道的事情.
2.Version:表示当前Ogg文件格式的版本,目前为0
3.Header type:头部类型标识,1个字节。标识当前页具体类型。其设置分三种情况:
        bit 0x01若已设置,页包含的媒体编码数据于前一页同属于一个逻辑流的同一packet。若未设置,本页是一个新的packet。
        bit 0x02设置,表示逻辑流的第一个页bos。未设,不是第一个页。
        bit 0x04设置,表示逻辑流的最后一页eos。未设,不是最后一页。
4.Granule position:包含了媒体编码相关参数信息.
5.Bitstream serial number:流序列号.
6.Page sequence number:表明了本页在逻辑流中的序列号.
7.Checksum:循环冗余校验码校验和.
8.Page segments:给定了在本页的segment_tabale域中所出现的segement个数
9.Segment table:逻辑流中的每个packet每个segment长度的取值(lacingvalues,除了每个packet的最后一个segment小于 255外,其它segment都为255),这些值以segment出现的先后顺序依次排列。此域的字节数为number_page_segments域所表示的数字(即在0-255之间)。


其實偶主要是被困在Page segments和Segment table這2個結構裡.
看圖就可以清楚這2個結構是怎麼一回事:
Page segments指出了Segment table的前面部分有多少個段;
而Segment table前面部分的數據,就是數據段的大小.

順便附上Ogg的簡易提取程式:
复制内容到剪贴板
代码:
<?php
  ini_set('memory_limit', '1024M');
  set_time_limit(0);
  $filename = 'C:\Music.xp3';
  $outputdir= 'C:\output';
  $data = file_get_contents($filename);
  $filesize = strlen($data);

  $pos = 0;
  for($i = 0;;$i++){
    $pos = strpos($data,'OggS'.chr(0),$pos);
    if($pos !== false){
      
      if(ord($data[$pos + 5]) & 0x02){
        $ogg[$i]['start'] = $pos;
        do{
          $pos++;
          $pos = strpos($data,'OggS'.chr(0),$pos);
          if(ord($data[$pos + 5]) & 0x04){
            break;
          }
        }while($pos !== false);
        
        if($pos){
          $len = ord($data[$pos + 26]);
          $sum = 0;
          for($j = 0;$j < $len; $j++){
            $sum += ord($data[$pos + 27 + $j]);
          }
          $ogg[$i]['size'] = $pos + 26 + $len + $sum + 1 - $ogg[$i]['start'];
          $pos++;
        }else{
          echo 'Error!';
          exit;
        }
      }
    }else{
      break;
    }
  }
  $input  = fopen($filename,'rb');
  for($i = 0;$i < count($ogg);$i++){
      fseek($input,$ogg[$i]['start'],SEEK_SET);
      $data = fread($input,$ogg[$i]['size']);
      file_put_contents(sprintf("$outputdir\\%03d.ogg",$i + 1),$data);
  }
  fclose($input);
?>
首發於 Yukict
超級無敵美工渣.
好东西现Ogg音頻是游戏主流
查看积分策略说明

快速回复主题

选项

[完成后可按 Ctrl+Enter 发布]  预览帖子  恢复数据  清空内容

当前时区 GMT+8, 现在时间是 2024-11-21 22:28

Processed in 0.029918 second(s), 7 queries.