Advertisement
Guest User

Untitled

a guest
Feb 16th, 2013
575
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 7.02 KB | None | 0 0
  1. <?php defined('SYSPATH') OR die('No direct access allowed.');
  2.  
  3. class Wave_Core {
  4.  
  5.     public $width = 1906;
  6.     public $height = 100;
  7.     public $foreground = "#cccccc";
  8.     public $background = "";
  9.     public $draw_flat = false;
  10.     public $stereo = true;
  11.     public $path = null;
  12.  
  13.     public $img = false;
  14.  
  15.     public $converted_wav = null;
  16.  
  17.     // how much detail we want. Larger number means less detail
  18.     // (basically, how many bytes/frames to skip processing)
  19.     // the lower the number means longer processing time
  20.     public $detail = 5;
  21.  
  22.     public static function instance(){
  23.        
  24.         return new self;
  25.     }
  26.  
  27.     /**
  28.     * Input song data
  29.     *
  30.     * @path string image path
  31.     * @stereo_support bool
  32.     *
  33.     * @return instance
  34.     */
  35.     public function input_file($path, $stereo_support){
  36.  
  37.         $this->path = $path;
  38.  
  39.         $this->stereo = $stereo_support;
  40.  
  41.         return $this;
  42.     }
  43.  
  44.     /**
  45.     * Convert MP3 file to Wav
  46.     *
  47.     * @return void
  48.     */
  49.     public function convert(){
  50.         $tmpname = "temp/".Helper::uuid1();
  51.  
  52.         //make file copy
  53.         copy($this->path, $tmpname."_o.mp3");
  54.  
  55.         // convert mp3 to wav using lame decoder
  56.         // First, resample the original mp3 using as mono (-m m), 16 bit (-b 16), and 8 KHz (--resample 8)
  57.         // Secondly, convert that resampled mp3 into a wav
  58.         // We don't necessarily need high quality audio to produce a waveform, doing this process reduces the WAV
  59.         // to it's simplest form and makes processing significantly faster
  60.  
  61.         exec("lame {$tmpname}_o.mp3 -m m -S -f -b 16 --resample 8 {$tmpname}.mp3 && lame -S --decode {$tmpname}.mp3 {$tmpname}.wav");
  62.         $this->converted_wav = "{$tmpname}.wav";
  63.  
  64.         // delete temporary files
  65.         unlink("{$tmpname}_o.mp3");
  66.         unlink("{$tmpname}.mp3");
  67.     }
  68.  
  69.     /**
  70.     * Convert file
  71.     *
  72.     * @return instance
  73.     */
  74.     public function generate_wave(){
  75.         //convert to wav
  76.         $this->convert();
  77.  
  78.         // generate foreground color
  79.         list($r, $g, $b) = $this->html2rgb($this->foreground);
  80.  
  81.         /**
  82.         * Below as posted by "zvoneM" on
  83.         * http://forums.devshed.com/php-development-5/reading-16-bit-wav-file-318740.html
  84.         * as findValues() defined above
  85.         * Translated from Croation to English - July 11, 2011
  86.         */
  87.         $handle = fopen($this->converted_wav, "r");
  88.         // wav file header retrieval
  89.         $heading[] = fread($handle, 4);
  90.         $heading[] = bin2hex(fread($handle, 4));
  91.         $heading[] = fread($handle, 4);
  92.         $heading[] = fread($handle, 4);
  93.         $heading[] = bin2hex(fread($handle, 4));
  94.         $heading[] = bin2hex(fread($handle, 2));
  95.         $heading[] = bin2hex(fread($handle, 2));
  96.         $heading[] = bin2hex(fread($handle, 4));
  97.         $heading[] = bin2hex(fread($handle, 4));
  98.         $heading[] = bin2hex(fread($handle, 2));
  99.         $heading[] = bin2hex(fread($handle, 2));
  100.         $heading[] = fread($handle, 4);
  101.         $heading[] = bin2hex(fread($handle, 4));
  102.      
  103.         // wav bitrate
  104.         $peek = hexdec(substr($heading[10], 0, 2));
  105.         $byte = $peek / 8;
  106.  
  107.         // checking whether a mono or stereo wav
  108.         $channel = hexdec(substr($heading[6], 0, 2));
  109.  
  110.         $ratio = ($channel == 2 ? 40 : 80);
  111.  
  112.         // start putting together the initial canvas
  113.         // $data_size = (size_of_file - header_bytes_read) / skipped_bytes + 1
  114.         $data_size = floor((filesize($this->converted_wav) - 44) / ($ratio + $byte) + 1);
  115.         $data_point = 0;
  116.      
  117.         // now that we have the data_size for a single channel (they both will be the same)
  118.         // we can initialize our image canvas
  119.         if (!$this->img) {
  120.             // create original image width based on amount of detail
  121.             // each waveform to be processed with be $height high, but will be condensed
  122.             // and resized later (if specified)
  123.             $this->img = imagecreatetruecolor($data_size / $this->detail, $this->height * sizeof($this->converted_wav));
  124.  
  125.             // fill background of image
  126.             if ($this->background == "") {
  127.                 // transparent background specified
  128.                 imagesavealpha($this->img, true);
  129.                 $transparentColor = imagecolorallocatealpha($this->img, 0, 0, 0, 127);
  130.                 imagefill($this->img, 0, 0, $transparentColor);
  131.             } else {
  132.                 list($br, $bg, $bb) = $this->html2rgb($this->background);
  133.                 imagefilledrectangle($this->img, 0, 0, (int) ($data_size / $this->detail), $this->height * sizeof($this->converted_wav), imagecolorallocate($this->img, $br, $bg, $bb));
  134.             }
  135.         }
  136.  
  137.         imagesetthickness($this->img, 3);
  138.  
  139.         while(!feof($handle) && $data_point < $data_size){
  140.             if ($data_point++ % $this->detail == 0) {
  141.                 $bytes = array();
  142.  
  143.                 // get number of bytes depending on bitrate
  144.                 for ($i = 0; $i < $byte; $i++)
  145.                     $bytes[$i] = fgetc($handle);
  146.  
  147.                 switch($byte){
  148.                    
  149.                     // get value for 8-bit wav
  150.                     case 1:
  151.                         $data = $this->findValues($bytes[0], $bytes[1]);
  152.                     break;
  153.  
  154.                     // get value for 16-bit wav
  155.                     case 2:
  156.                         if(ord($bytes[1]) & 128)
  157.                             $temp = 0;
  158.                         else
  159.                             $temp = 128;
  160.  
  161.                         $temp = chr((ord($bytes[1]) & 127) + $temp);
  162.                         $data = floor($this->findValues($bytes[0], $temp) / 256);
  163.                     break;
  164.                 }
  165.  
  166.                 // skip bytes for memory optimization
  167.                 fseek($handle, $ratio, SEEK_CUR);
  168.  
  169.                 // draw this data point
  170.                 // relative value based on height of image being generated
  171.                 // data values can range between 0 and 255
  172.                 $v = (int) ($data / 255 * $this->height);
  173.  
  174.                 if($v < 20)
  175.                     $v = 20;
  176.  
  177.                 // don't print flat values on the canvas if not necessary
  178.                 if (!($v / $this->height == 0.5 && !$this->draw_flat))
  179.                     // draw the line on the image using the $v value and centering it vertically on the canvas
  180.                     imageline(
  181.                         $this->img,
  182.                         // x1
  183.                         (int) ($data_point / $this->detail),
  184.                         // y1: height of the image minus $v as a percentage of the height for the wave amplitude
  185.                         $this->height - $v,
  186.                         // x2
  187.                         (int) ($data_point / $this->detail),
  188.                         // y2: same as y1, but from the bottom of the image
  189.                         $this->height,
  190.                         imagecolorallocate($this->img, 56, 56, 56)
  191.                     );        
  192.  
  193.             } else {
  194.                 // skip this one due to lack of detail
  195.                 fseek($handle, $ratio + $byte, SEEK_CUR);
  196.             }
  197.         }
  198.      
  199.         // close and cleanup
  200.         fclose($handle);
  201.  
  202.         // delete the processed wav file
  203.         unlink($this->converted_wav);
  204.  
  205.         return $this;
  206.     }
  207.  
  208.     /**
  209.     * Save wave file
  210.     *
  211.     * @return void
  212.     */
  213.     public function save($path){
  214.         // resample the image to the proportions defined in the form
  215.         $rimg = imagecreatetruecolor($this->width, $this->height);
  216.  
  217.         // save alpha from original image
  218.         imagesavealpha($rimg, true);
  219.         imagealphablending($rimg, false);
  220.  
  221.         // copy to resized
  222.         imagecopyresampled($rimg, $this->img, 0, 0, 0, 0, $this->width, $this->height, imagesx($this->img), imagesy($this->img));
  223.        
  224.         //save
  225.         imagepng($rimg, $path);
  226.  
  227.         imagedestroy($rimg);
  228.  
  229.         imagedestroy($this->img);
  230.     }
  231.  
  232.     /**
  233.     *
  234.     */
  235.     private function findValues($byte1, $byte2){
  236.  
  237.         $byte1 = hexdec(bin2hex($byte1));
  238.         $byte2 = hexdec(bin2hex($byte2));
  239.  
  240.         return ($byte1 + ($byte2*256));
  241.     }
  242.  
  243.     /**
  244.     * Convert HEX to RGB
  245.     *
  246.     * @return array
  247.     */
  248.     private function html2rgb($input) {
  249.         $input=($input[0]=="#")?substr($input, 1,6):substr($input, 0,6);
  250.  
  251.         return array(
  252.             hexdec(substr($input, 0, 2)),
  253.             hexdec(substr($input, 2, 2)),
  254.             hexdec(substr($input, 4, 2))
  255.         );
  256.     }
  257. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement