/** * Create waves in GD images format from WAV (PCM) file * Wave file reading based on a post by "zvoneM" on * http://forums.devshed.com/php-development-5/reading-16-bit-wav-file-318740.html * Completely rewritten the file read loop, kept the header reading intact. * * Waveform drawing from https://github.com/afreiday/php-waveform-png * * Reads width * ACCURACY data points from the file and takes the peak value of accuracy values. * The peak is the highest value if mean is > 127 and the lowest value otherwise. * Data point is the average of ACCURACY points in the data block. */ private function createWaves($wavfilename) { define('ACCURACY', 100); // default optimal accuracy // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Create palette based image // if background == '' we convert it to true color image later then // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - $this->waveImg = imagecreate($this->width, $this->height); // fill background of image if ($this->backgroundColor == '') { // try to choose color that does not match // waveColor or progressColor // three colors should be sufficient $colors = array('#FFFFFF', '#000000', '#FF0000'); foreach ($colors as $col) { $tempBackground = $col; if ($tempBackground != strtoupper($this->waveColor) && $tempBackground != strtoupper($this->progressColor)) { break; } } } else { $tempBackground = $this->backgroundColor; } list($r, $g, $b) = JustWave::html2rgb($tempBackground); $transparentColor = imagecolorallocate($this->waveImg, $r, $g, $b); imagefilledrectangle($this->waveImg, 0, 0, $this->width, $this->height, $transparentColor); // generate foreground color list($r, $g, $b) = JustWave::html2rgb($this->waveColor); $waveColor = imagecolorallocate($this->waveImg, $r, $g, $b); // $subColor = imagecolorallocate($this->waveImg, (int)$r * 0.5 , (int)$g * 0.5, (int) $b * 0.5); // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Read wave header // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - $handle = fopen($wavfilename, 'rb'); $heading[] = fread($handle, 4); $heading[] = bin2hex(fread($handle, 4)); $heading[] = fread($handle, 4); $heading[] = fread($handle, 4); $heading[] = bin2hex(fread($handle, 4)); $heading[] = bin2hex(fread($handle, 2)); $heading[] = bin2hex(fread($handle, 2)); $heading[] = bin2hex(fread($handle, 4)); $heading[] = bin2hex(fread($handle, 4)); $heading[] = bin2hex(fread($handle, 2)); $heading[] = bin2hex(fread($handle, 2)); $heading[] = fread($handle, 4); $heading[] = bin2hex(fread($handle, 4)); if ($heading[5] != '0100') { $this->raiseError('Wave file should be a PCM file'); return false; } $peek = hexdec(substr($heading[10], 0, 2)); $byte = $peek / 8; $channel = hexdec(substr($heading[6], 0, 2)); // point = one data point (pixel), width total // block = one block, there are $accuracy blocks per point // chunk = one data point 8 or 16 bit, mono or stereo $filesize = filesize($wavfilename); $chunksize = $byte * $channel; $file_chunks = ($filesize - 44) / $chunksize; if ($file_chunks < $this->width) { $this->raiseError("Wave file has {$file_chunks} chunks, " . $this->width . ' required'); return false; } if ($file_chunks < $this->width * ACCURACY) { $accuracy = 1; } else { $accuracy = ACCURACY; } $point_chunks = $file_chunks / $this->width; $block_chunks = $file_chunks / ($this->width * $accuracy); $blocks = array(); $points = 0; $current_file_position = 44.0; // float, because chunks/point and clunks/block are floats too. fseek($handle, 44); // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Read the data points and draw the image // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - while (!feof($handle)) { // The next file position is the float value rounded to the closest chunk // Read the next block, take the first value (of the first channel) $real_pos_diff = ($current_file_position - 44) % $chunksize; if ($real_pos_diff > $chunksize / 2) { $real_pos_diff -= $chunksize; } fseek($handle, $current_file_position - $real_pos_diff); $chunk = fread($handle, $chunksize); if (feof($handle) && !strlen($chunk)) { break; } $current_file_position += $block_chunks * $chunksize; if ($byte == 1) { $blocks[] = ord($chunk[0]); } else { $blocks[] = ord($chunk[1]) ^ 128; } // 16 bit // Do we have enough blocks for the current point? if (count($blocks) >= $accuracy) { // Calculate the mean and add the peak value to the array of blocks sort($blocks); $mean = count($blocks) % 2 ? $blocks[(count($blocks) - 1) / 2] : ($blocks[count($blocks) / 2] + $blocks[count($blocks) / 2 - 1]) / 2; if ($mean > 127) { $point = array_pop($blocks); } else { $point = array_shift($blocks); } // Draw $lineheight = round($point / 255 * $this->height); imageline($this->waveImg, $points, 0 + ($this->height - $lineheight), $points, $this->height - ($this->height - $lineheight), $waveColor); // update vars $points++; $blocks = array(); } } // close wave file fclose($handle); // final line imageline($this->waveImg, 0, round($this->height / 2), $this->width, round($this->height / 2), $waveColor); if ($this->waveColor != $this->progressColor) { $this->progressImg = imagecreate($this->width, $this->height); imagecopy($this->progressImg, $this->waveImg, 0, 0, 0, 0, $this->width, $this->height); // change waveColor to progressColor $index = imagecolorclosest($this->waveImg, $r, $g, $b); list($r, $g, $b) = JustWave::html2rgb($this->progressColor); imagecolorset($this->progressImg, $index, $r, $g, $b); } // try to save transparency if ($this->backgroundColor == '') { imagealphablending($this->waveImg, false); imagesavealpha($this->waveImg, true); imagealphablending($this->waveImg, true); imagecolortransparent($this->waveImg, $transparentColor); if ($this->waveColor != $this->progressColor) { imagealphablending($this->progressImg, false); imagesavealpha($this->progressImg, true); imagealphablending($this->progressImg, true); imagecolortransparent($this->progressImg, $transparentColor); } } return true; }
$mask = array_shift($argv); // default prog_color must be the same as wave_color // in order to generate one image instead of two $argv[] = 'prog_color=#909296'; // we need set prog_color to wave_color // in order to get one wave image instead of two foreach ($argv as $val) { if (preg_match('/^wave_color=(.*)$/', $val, $m)) { $argv[] = 'prog_color=' . $m[1]; } } // always use file mode $argv[] = 'mode=file'; require_once 'JustWave.class.php'; // make class instance with ARGV parameters $justwave = new JustWave('ARGV', $argv); $numOfTotalFiles = $numOfSuccessFiles = 0; foreach (glob($mask) as $fileName) { // create waves' images printf('Creating wave for %s', $fileName); $justwave->create($fileName); // rename image wave from key name to audio name if ($justwave->status == 'ok') { $name = pathinfo($justwave->audio, PATHINFO_FILENAME); $newName = str_replace($justwave->key, $name, $justwave->dataUrlWave); if ($newName) { rename($justwave->dataUrlWave, $newName); $justwave->dataUrlWave = $newName; } $numOfSuccessFiles++; } else {
<?php if (!isset($_GET['mode'])) { header('Location: script.php?mode=file&wave_color=F00&prog_color=F00&back_color=00AC00'); die; } require_once 'JustWave.class.php'; // we accept parameters as GET data // e.g.: script.php?mode=file&wave_color=F00&prog_color=F00&back_color=00AC00 $justwave = new JustWave('GET'); // create waveform image(s) $justwave->create('media/We Wish You.mp3'); if ($justwave->status == 'ok') { echo 'Duration of We Wish You.mp3 = ' . $justwave->duration . '<br>'; echo 'See waveform image under the link: <a href="' . $justwave->dataUrlWave . '">waveform</a>'; } else { echo 'Failed! Message = ' . $justwave->message; }
<?php /* ***************************** */ /* JustWave project */ /* (c) beotiger 2014-2015 AD */ /* http://justwave.beotiger.com */ /* https://github.com/beotiger */ /* email: beotiger@gmail.com */ /* ***************************** */ require_once 'JustWave.class.php'; if (isset($_POST['audio'])) { // make class instance with default to POST parameters $justwave = new JustWave(); // create waveform image(s) $justwave->create($_POST['audio']); // return as JSON data die($justwave->json()); } die(json_encode(array('status' => 'err', 'message' => 'No source audio parameter')));