3 class sml_data_waveforms extends mw_data{
7 function init_waveform_dirs(){
9 $dir = $env->path("content")."tmp";
10 if(!is_dir($dir)) @mkdir($dir);
11 if(!is_dir($dir)) return false;
12 $dir = $env->path("content")."waveforms";
13 if(!is_dir($dir)) @mkdir($dir);
14 if(!is_dir($dir)) return false;
18 function audio_to_png($params = array()){
20 $audio_file = $params["audio_file"];
21 if(!$audio_file) return false;
22 if(!file_exists($audio_file)) return false;
24 $png_file = $params["png_file"];
25 if(!$png_file) return false;
27 $width = isset($params["width"]) ? $params["width"] : "650";
28 $height = isset($params["height"]) ? $params["height"] : "100";
29 $background = isset($params["background"]) ? $params["background"] : "";
30 $foreground = isset($params["foreground"]) ? $params["foreground"] : "#000000";
31 $draw_flat = isset($params["draw_flat"]) ? $params["draw_flat"] : true;
32 $DETAIL = isset($params["DETAIL"]) ? $params["DETAIL"] : 5;
34 if(!is_dir($env->path("content")."waveforms")){
35 @mkdir($env->path("content")."waveforms");
37 if(!is_dir($env->path("content")."waveforms")) return false;
38 if(!is_dir($env->path("content")."tmp")){
39 @mkdir($env->path("content")."tmp");
41 if(!is_dir($env->path("content")."tmp")) return false;
46 $wav_file = $env->path("content")."tmp/".substr(md5(time()), 0, 10).".wav"
53 $img = $this->wav_to_img(
58 "background" => $background,
59 "foreground" => $foreground,
60 "draw_flat" => $draw_flat,
69 if(!$OK) return false;
73 // resample the image to the proportions defined in the form
74 $rimg = imagecreatetruecolor($width, $height);
75 // save alpha from original image
76 imagesavealpha($rimg, true);
77 imagealphablending($rimg, false);
79 imagecopyresampled($rimg, $img, 0, 0, 0, 0, $width, $height, imagesx($img), imagesy($img));
80 $OK = @imagepng($rimg, $png_file);
83 $OK = @imagepng($img, $png_file);
86 if(!$OK) return false;
90 // ----------------------------------------------------------------------------
94 function sox_command($audio_file, $wav_file){
95 return "sox -V \"".$audio_file."\" -r 8000 -c 1 \"".$wav_file."\"";
98 function sox_exists(){
99 if(isset($this->SOX_EXISTS)){
100 return $this->SOX_EXISTS;
103 $whereIsCommand = (PHP_OS == 'WINNT') ? 'where' : 'which';
106 $process = proc_open(
107 "$whereIsCommand $command",
109 0 => array("pipe", "r"), //STDIN
110 1 => array("pipe", "w"), //STDOUT
111 2 => array("pipe", "w"), //STDERR
117 $this->SOX_EXISTS = false;
120 $stdout = stream_get_contents($pipes[1]);
121 $stderr = stream_get_contents($pipes[2]);
124 proc_close($process);
125 $this->SOX_EXISTS = $stdout != '';
127 return $this->SOX_EXISTS;
130 function audio_to_wav($audio_file, $wav_file){
131 if(!$this->sox_exists()){
134 system($this->sox_command($audio_file, $wav_file));
135 return file_exists($wav_file);
138 function wav_to_img($wav_file, $params = array()){
140 $width = isset($params["width"]) ? $params["width"] : "650";
141 $height = isset($params["height"]) ? $params["height"] : "100";
142 $background = isset($params["background"]) ? $params["background"] : "";
143 $foreground = isset($params["foreground"]) ? $params["foreground"] : "#000000";
144 $draw_flat = isset($params["draw_flat"]) ? $params["draw_flat"] : true;
146 // $DETAIL : how much detail we want. Larger number means less detail
147 // (basically, how many bytes/frames to skip processing)
148 // the lower the number means longer processing time
149 $DETAIL = isset($params["DETAIL"]) ? $params["DETAIL"] : 5;
151 list($r, $g, $b) = $this->html2rgb($foreground);
153 if(!($handle = fopen($wav_file, "r"))) return false;
155 // wav file header retrieval
156 $heading[] = fread($handle, 4);
157 $heading[] = bin2hex(fread($handle, 4));
158 $heading[] = fread($handle, 4);
159 $heading[] = fread($handle, 4);
160 $heading[] = bin2hex(fread($handle, 4));
161 $heading[] = bin2hex(fread($handle, 2));
162 $heading[] = bin2hex(fread($handle, 2));
163 $heading[] = bin2hex(fread($handle, 4));
164 $heading[] = bin2hex(fread($handle, 4));
165 $heading[] = bin2hex(fread($handle, 2));
166 $heading[] = bin2hex(fread($handle, 2));
167 $heading[] = fread($handle, 4);
168 $heading[] = bin2hex(fread($handle, 4));
171 $peek = hexdec(substr($heading[10], 0, 2));
174 // checking whether a mono or stereo wav
175 $channel = hexdec(substr($heading[6], 0, 2));
177 $ratio = ($channel == 2 ? 40 : 80);
179 // start putting together the initial canvas
180 // $data_size = (size_of_file - header_bytes_read) / skipped_bytes + 1
181 $data_size = floor((filesize($wav_file) - 44) / ($ratio + $byte) + 1);
184 if($img = imagecreatetruecolor($data_size / $DETAIL, $height)){
185 if($background == ""){
186 imagesavealpha($img, true);
187 $transparentColor = imagecolorallocatealpha($img, 0, 0, 0, 127);
188 imagefill($img, 0, 0, $transparentColor);
191 list($br, $bg, $bb) = $this->html2rgb($background);
192 imagefilledrectangle($img, 0, 0, (int) ($data_size / $DETAIL), $height, imagecolorallocate($img, $br, $bg, $bb));
196 if($img) while(!feof($handle) && $data_point < $data_size){
197 if ($data_point++ % $DETAIL == 0){
199 for ($i = 0; $i < $byte; $i++) $bytes[$i] = fgetc($handle);
201 // get value for 8-bit wav
203 $data = $this->findValues($bytes[0], $bytes[1]);
205 // get value for 16-bit wav
207 if(ord($bytes[1]) & 128)
211 $temp = chr((ord($bytes[1]) & 127) + $temp);
212 $data = floor($this->findValues($bytes[0], $temp) / 256);
216 // skip bytes for memory optimization
217 fseek($handle, $ratio, SEEK_CUR);
218 // draw this data point
219 // relative value based on height of image being generated
220 // data values can range between 0 and 255
221 $v = (int) ($data / 255 * $height);
222 // don't print flat values on the canvas if not necessary
223 if (!($v / $height == 0.5 && !$draw_flat))
224 // draw the line on the image using the $v value and centering it vertically on the canvas
228 (int) ($data_point / $DETAIL),
229 // y1: height of the image minus $v as a percentage of the height for the wave amplitude
232 (int) ($data_point / $DETAIL),
233 // y2: same as y1, but from the bottom of the image
234 $height - ($height - $v),
235 imagecolorallocate($img, $r, $g, $b)
239 // skip this one due to lack of detail
240 fseek($handle, $ratio + $byte, SEEK_CUR);
247 function findValues($byte1, $byte2){
248 return hexdec(bin2hex($byte1)) + (hexdec(bin2hex($byte2)) * 256);
251 function html2rgb($input){
252 $input = $input[0] == "#" ? substr($input, 1, 6) : substr($input, 0, 6);
254 hexdec(substr($input, 0, 2)),
255 hexdec(substr($input, 2, 2)),
256 hexdec(substr($input, 4, 2))