PHP分析.wav文件並繪製png格式的波形圖

參考http://blog.csdn.net/midfar/article/details/7227758php

     http://www.2cto.com/kf/200804/25499.htmlhtml

表1 WAV文件的文件頭編碼

偏移地址spa

字節數.net

類型code

內容htm

00H~03Hblog

4ci

字符資源

資源交換文件標誌(RIFF注意字符大小寫!

04H~07H

4

長整數

從下個地址開始到文件尾的總字節數

08H~0BH

4

字符

WAV文件標誌(WAVE注意字符大小寫!

0CH~0FH

4

字符

波形格式標誌(fmt注意字符大小寫!

10H~13H

4

整數

過濾字節(通常爲00000010H)

14H~15H

2

整數

格式種類(值爲1時,表示數據爲線性PCM編碼)

16H~17H

2

整數

通道數,單聲道爲1,雙聲音爲2

18H~1BH

4

長整數

採樣頻率

1CH~1FH

4

長整數

波形數據傳輸速率(每秒平均字節數)

20H~21H

2

整數

數據的調整數(按字節計算)

22H~23H

2

整數

樣本數據位數

 

表2 WAV聲音文件的數據塊

偏移地址

字節數

類型

內容

24H~27H

4

字符

數據標誌符(data注意字符大小寫!

28H~2BH

4

長整型

採樣數據總數

2CH...

...

...

採樣數據

 

首先須要瞭解wav的這3個重要指標:採樣率、採樣位數、聲道數。下面以16KHz, 16Bit, 單聲道爲例來講明。

採樣率:(也稱爲採樣速度或者採樣頻率)定義了每秒從連續信號中提取並組成離散信號的採樣個數,單位用赫茲(Hz)來表示。採樣頻率的倒數是採樣周 期(也稱爲採樣時間),它表示採樣之間的時間間隔。採樣率爲16KHz,代表每秒鐘採樣有16K次,即0.001秒內採集16個值。

採樣位數:即採樣值或取樣值,用來衡量聲音波動變化的參數,是指聲卡在採集和播放聲音文件時所使用數字聲音信號的二進制位數。聲卡的位客觀地反映了數字聲音信號對輸入聲音信號描述的準確程度。16Bit表示用計算機的16位(即2字節)來標示一個值。

聲道數:是指支持能不一樣發聲的音響的個數。常見的有單聲道和雙聲道。

比特率:每秒傳送的比特(bit)數,等於採樣率*採樣位數,單位爲bps(Bit Per Second)。示例音頻的比特率爲256kbps。

 

 

瞭解了這些東西,咱們就能夠開始寫代碼了:

<?php
   function wav_graph($file,$f=0,$w=0)
   {
      if(!is_file($file))return 0;   
      $fp=fopen($file,r);
      $raw=fread($fp,36);//對應36個字節的文件頭,包含該文件的一些信息
      $str="";
      $header=unpack('A4Riff/VSize/A4Wav/A4Head/VHeadSize/vPCM/vChannels/VSampleRate/VByteRate/vBlockAlign/vSampleBits', $raw);
       //print_r($header);//查看文件頭
      foreach($header as $k=>$v)
      $str.=$k.":".$v." ";
       fseek($fp,36+$header['HeadSize']-16);
       $raw=fread($fp,8);
       $data=unpack('A4Data/VDataSize',$raw);
       
       foreach($data as $k=>$v)
       $str.=$k.":".$v." ";
       $b=$header['SampleBits'];//樣本數據位數
       $c=$header['Channels'];//聲道數
       $l=$b*$c/8;//須要用16比特的緣由就在這裏,16比特表明採集位數是2個字節,除於8
       $s=$data['DataSize']/$l;//文件數據長度/(樣本採集位數*採集頻率)=歌曲時間吧
       $r=$header['SampleRate'];//採集頻率
       if($f) $h=pow(2,$b)/$f;//設定波的高度
       else {$h=200;$f=pow(2,$b-1)/$h;}
       if($w==0)$w=round($r/5);//後面的5是時間,1000表示按秒爲單位
     
       
      header("Content-type:image/png");//查看彈出數據時須要把畫圖的部分隱藏掉哦
        
       $im=@imagecreate($s/$w,$h*$c*2);
      
       $background_color = imagecolorallocate($im, 255, 255, 255);
       $text_color = imagecolorallocate($im, 233, 14, 91);
        $x=0;$y=array();$yn=array();
       for($i=0;$i<$c;$i++)$y[$i]=$h*$i+$h;
       $n=$l*$w;
      
    
       while(1)
   {
           if($s==0) break;
           if($s<$n)$n=$s;
           $samples=fread($fp,5*$n);//後面的5是時間,1000表示按秒爲單位
           
           if($samples==FALSE)break;
           $packed=unpack('s*',$samples);
          
           foreach($packed as $k=>$v)
           {
            $cnt=($k-1)%($w*$l);
            if($cnt>$c-1)continue;
            $yn[$cnt]=$h*$cnt+$h-$v/$f;
            imageline($im,$x,$y[$cnt],$x+1,$yn[$cnt],$text_color);
            $y[$cnt]=$yn[$cnt];
            $x++;
               
           }
           $s-=$n;
       }
      
       
      /**/
       imagepng($im);
       imagedestroy($im);
      
   }
wav_graph('aa.wav');
?>

上傳一張結果圖

相關文章
相關標籤/搜索