Skip to content

Instantly share code, notes, and snippets.

@jeedee
Created July 22, 2010 19:12
Show Gist options
  • Save jeedee/486434 to your computer and use it in GitHub Desktop.
Save jeedee/486434 to your computer and use it in GitHub Desktop.
<?php
class wave {
var $fp, $filesize;
var $data, $blocktotal, $blockfmt, $blocksize;
function __construct($file) {
if(!$this->fp = @fopen($file, 'rb')) {
return false;
}
$this->filesize = filesize($file);
}
function wavechunk() {
rewind($this->fp);
$riff_fmt = 'a4ID/VSize/a4Type';
$riff_cnk = @unpack($riff_fmt, fread($this->fp, 12));
if($riff_cnk['ID'] != 'RIFF' || $riff_cnk['Type'] != 'WAVE') {
return -1;
}
$format_header_fmt = 'a4ID/VSize';
$format_header_cnk = @unpack($format_header_fmt, fread($this->fp, 8));
if($format_header_cnk['ID'] != 'fmt ' || !in_array($format_header_cnk['Size'], array(16, 18))) {
return -2;
}
$format_fmt = 'vFormatTag/vChannels/VSamplesPerSec/VAvgBytesPerSec/vBlockAlign/vBitsPerSample'.($format_header_cnk['Size'] == 18 ? '/vExtra' : '');
$format_cnk = @unpack($format_fmt, fread($this->fp, $format_header_cnk['Size']));
if($format_cnk['FormatTag'] != 1) {
return -3;
}
if(!in_array($format_cnk['Channels'], array(1, 2))) {
return -4;
}
$fact_fmt = 'a4ID/VSize/Vdata';
$fact_cnk = @unpack($fact_fmt, fread($this->fp, 12));
if($fact_cnk['ID'] != 'fact') {
fseek($this->fp, ftell($this->fp) - 12);
}
$data_fmt = 'a4ID/VSize';
$data_cnk = @unpack($data_fmt, fread($this->fp, 8));
if($data_cnk['ID'] != 'data') {
return -5;
}
if($data_cnk['Size'] % $format_cnk['BlockAlign'] != 0) {
return -6;
}
$this->data = fread($this->fp, $data_cnk['Size']);
$this->blockfmt = $format_cnk['Channels'] == 1 ? 'sLeft' : 'sLeft/sRight';
$this->blocktotal = $data_cnk['Size'] / 4;
$this->blocksize = $format_cnk['BlockAlign'];
$return = array
(
'Channels' => $format_cnk['Channels'],
'SamplesPerSec' => $format_cnk['SamplesPerSec'],
'AvgBytesPerSec' => $format_cnk['AvgBytesPerSec'],
'BlockAlign' => $format_cnk['BlockAlign'],
'BitsPerSample' => $format_cnk['BitsPerSample'],
'Extra' => $format_cnk['Extra'],
'seconds' => ($data_cnk['Size'] / $format_cnk['AvgBytesPerSec'])
);
return $return;
}
function waveimage($channel = 'Left', $width = 1000, $height = 300, $bgcolor = array(255, 255, 255), $cenlinecolor = array(180, 180, 180), $imgcolor = array(0, 0, 0)) {
if(!$this->data) {
if(!is_array($this->wavechunk())) {
return false;
}
}
$width = max(10, $width);
$height = max(10, $height);
$border = 1;
$center = ($height - $border * 2) / 2;
$num_merge = max(1, round($this->blocktotal / $width));
$width = min($width, ceil($this->blocktotal / $num_merge));
$max = $min = 0;
$x = 1;
$pixels = array();
$wavetotal = 0;
for($i = 0; $i < $this->blocktotal; $i++) {
$blocks[] = @unpack($this->blockfmt, substr($this->data, $i * 4, $this->blocksize));
}
if(!isset($blocks[0][$channel])) {
return false;
}
for($i = 0; $i < $this->blocktotal; ) {
for($j = 0; $j < $num_merge; $j++) {
if(isset($blocks[$i + $j])) {
$wavetotal += $blocks[$i + $j][$channel];
}
}
$y = round($wavetotal / ($j + 1));
$pixels[] = array($x, $y);
$max = max($max, $y);
$min = min($min, $y);
$x++;
$i += $num_merge;
$wavetotal = 0;
}
$maxblock = max(abs($max), abs($min));
$zoom = $maxblock / $center;
$im = imagecreate($width, $height);
$background = imagecolorallocate($im, $bgcolor[0], $bgcolor[1], $bgcolor[2]);
if($cenlinecolor) {
$cenline = imagecolorallocate($im, $cenlinecolor[0], $cenlinecolor[1], $cenlinecolor[2]);
imageline($im, 1, $center, $width, $center, $cenline);
}
$color = imagecolorallocate($im, $imgcolor[0], $imgcolor[1], $imgcolor[2]);
$y_old = 0;
foreach($pixels as $pixel) {
$y = $center - round($pixel[1] / $zoom);
imagesetpixel($im, $pixel[0], $y, $color);
if($pixel[0] > 1) {
imageline($im, $pixel[0] - 1, $y_old, $pixel[0], $y, $color);
}
$y_old = $y;
}
return $im;
}
}
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment