PHP 根据wav文件绘制声波图

效果图:

参考:

http://php.net/manual/zh/function.pack.php

https://www.jianshu.com/p/947528f3dff8

http://blog.csdn.net/midfar/article/details/7227758

<?php

function wav_graph($file)
{
	if(!is_file($file)) return false;
	$fp=fopen($file, 'r');
	$size=36;
	$offset=0;
	$raw=fread($fp, $size);
	$header=unpack('A4Riff/VSize/A4Type/A4Head/VHeadSize/vAudioFormat/vNumChannels/VSampleRate/VByteRate/vBlockAlign/vBitsPerSample', $raw);
	$offset+=$size;
	fseek($fp, $offset);
	while(true){
		$size=8;
		$raw=fread($fp, 8);
		$chunk=unpack('A4ID/VSize', $raw);
		if($chunk['ID']==='data') break;
		$offset+=($size+$chunk['Size']);
		fseek($fp, $offset);
	}

	$samples=$chunk['Size']/$header['BlockAlign'];//wave length = samples
	$px_per_second=100;//px
	$second_per_sample=1/$header['SampleRate'];//s
	$time=$samples*$second_per_sample;//time of media
	$width=$px_per_second*$time;
	$samples_per_px=$header['SampleRate']/$px_per_second;//
	$amplitude=pow(2,intval($header['BitsPerSample'])-1);//2^16 max amplitude
	$height=400;//px height of one channel
	$px_per_amp=$height/$amplitude;//px per amplitude
	//var_dump($width);var_dump($height);exit;
	$im=imagecreate($width, $height*$header['NumChannels']);//two channels
	$bg_color=imagecolorallocate($im, 255, 255, 255);
	$line_color=imagecolorallocate($im, 255, 0, 0);

	$offset+=8;
	fseek($fp, $offset);
	$x=0;
	$y1=[];//start y
	$y2=[];//end y
	for($i=0;$i<$header['NumChannels'];$i++){
		$y1[$i]=$height*$i+($height/2);//start height of per channel
	}
	while (true) {
		$raw=fread($fp, $header['BlockAlign']*$samples_per_px);// read n samples in 1 px
		if($raw==false) break;
    	$len=strlen($raw);//bytes
		$sample=unpack('s*', $raw);

		$y_sum=[];
		for($i=0;$i<$header['NumChannels'];$i++){
			$y_sum[$i]=0;
		}
		foreach ($sample as $key=>$value) {
			$channel=($key+1)%intval($header['NumChannels']);//0 or 1
			$y_sum[$channel]+=$value;
		}
		foreach ($y_sum as $channel=>$value) {
			$y_ave=$value/($len/$header['BlockAlign']);//average of y
			$y2[$channel]=$y_ave*$px_per_amp+$height*$channel+($height/2);
			imageline($im,$x,$y1[$channel],$x+1,$y2[$channel],$line_color);
			$y1[$channel]=$y2[$channel];
		}
		$x++;
	}
	fclose($fp);
	
	header("Content-type:image/png");
   	imagepng($im);
   	imagedestroy($im);
}
wav_graph('test.wav');

发表评论

电子邮件地址不会被公开。 必填项已用*标注