mirror of
https://github.com/Yetangitu/ampache
synced 2025-10-06 03:49:56 +02:00
Add Waveform feature and few ShoutBox links
This commit is contained in:
parent
96736475cc
commit
0ec26ed623
16 changed files with 517 additions and 38 deletions
309
lib/class/waveform.class.php
Normal file
309
lib/class/waveform.class.php
Normal file
|
@ -0,0 +1,309 @@
|
|||
<?php
|
||||
/* vim:set softtabstop=4 shiftwidth=4 expandtab: */
|
||||
/**
|
||||
*
|
||||
* LICENSE: GNU General Public License, version 2 (GPLv2)
|
||||
* Copyright 2001 - 2013 Ampache.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License v2
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Waveform code generation license:
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2011, Andrew Freiday
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
|
||||
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* https://github.com/afreiday/php-waveform-png
|
||||
*
|
||||
*/
|
||||
|
||||
class Waveform
|
||||
{
|
||||
public $id;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
private function __construct()
|
||||
{
|
||||
// Static
|
||||
return false;
|
||||
|
||||
} // Constructor
|
||||
|
||||
public static function get($song_id)
|
||||
{
|
||||
$song = new Song($song_id);
|
||||
$waveform = null;
|
||||
|
||||
if ($song->id)
|
||||
{
|
||||
$song->format();
|
||||
$waveform = $song->waveform;
|
||||
if (!$waveform)
|
||||
{
|
||||
$catalog = Catalog::create_from_id($song->catalog);
|
||||
if ($catalog->get_type() == 'local')
|
||||
{
|
||||
$transcode_to = 'wav';
|
||||
$valid_types = $song->get_stream_types();
|
||||
|
||||
if ($song->type != $transcode_to)
|
||||
{
|
||||
$basedir = AmpConfig::get('tmp_dir_path');
|
||||
if ($basedir)
|
||||
{
|
||||
if ($transcode_cfg != 'never' && in_array('transcode', $valid_types))
|
||||
{
|
||||
$tmpfile = tempnam($basedir, $transcode_to);
|
||||
|
||||
$tfp = fopen($tmpfile, 'wb');
|
||||
if (!is_resource($tfp)) {
|
||||
debug_event('waveform', "Failed to open " . $tmpfile, 3);
|
||||
return null;
|
||||
}
|
||||
|
||||
$transcoder = Stream::start_transcode($song, $transcode_to);
|
||||
$fp = $transcoder['handle'];
|
||||
if (!is_resource($fp)) {
|
||||
debug_event('waveform', "Failed to open " . $song->file . " for waveform.", 3);
|
||||
return null;
|
||||
}
|
||||
|
||||
do {
|
||||
$buf = fread($fp, 2048);
|
||||
fwrite($tfp, $buf);
|
||||
} while (!feof($fp));
|
||||
|
||||
fclose($fp);
|
||||
fclose($tfp);
|
||||
|
||||
$waveform = self::create_waveform($tmpfile);
|
||||
//$waveform = self::create_waveform("C:\\tmp\\test.wav");
|
||||
|
||||
@unlink($tmpfile);
|
||||
}
|
||||
else
|
||||
{
|
||||
debug_event('waveform', 'transcode setting to wav required for waveform.', '3');
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
debug_event('waveform', 'tmp_dir_path setting required for waveform.', '3');
|
||||
}
|
||||
}
|
||||
// Already wav file, no transcode required
|
||||
else
|
||||
{
|
||||
$waveform = self::create_waveform($song->file);
|
||||
}
|
||||
}
|
||||
|
||||
if($waveform)
|
||||
{
|
||||
self::save_to_db($song_id, $waveform);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $waveform;
|
||||
}
|
||||
|
||||
protected static function findValues($byte1, $byte2){
|
||||
$byte1 = hexdec(bin2hex($byte1));
|
||||
$byte2 = hexdec(bin2hex($byte2));
|
||||
return ($byte1 + ($byte2*256));
|
||||
}
|
||||
|
||||
/**
|
||||
* Great function slightly modified as posted by Minux at
|
||||
* http://forums.clantemplates.com/showthread.php?t=133805
|
||||
*/
|
||||
protected static function html2rgb($input) {
|
||||
$input=($input[0]=="#")?substr($input, 1,6):substr($input, 0,6);
|
||||
return array(
|
||||
hexdec(substr($input, 0, 2)),
|
||||
hexdec(substr($input, 2, 2)),
|
||||
hexdec(substr($input, 4, 2))
|
||||
);
|
||||
}
|
||||
|
||||
protected static function create_waveform($filename)
|
||||
{
|
||||
$detail = 5;
|
||||
$width = 400;
|
||||
$height = 32;
|
||||
$foreground = '#FF0000';
|
||||
$background = '';
|
||||
$draw_flat = true;
|
||||
|
||||
// generate foreground color
|
||||
list($r, $g, $b) = self::html2rgb($foreground);
|
||||
|
||||
$handle = fopen($filename, "r");
|
||||
// wav file header retrieval
|
||||
$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));
|
||||
|
||||
// wav bitrate
|
||||
$peek = hexdec(substr($heading[10], 0, 2));
|
||||
$byte = $peek / 8;
|
||||
|
||||
// checking whether a mono or stereo wav
|
||||
$channel = hexdec(substr($heading[6], 0, 2));
|
||||
|
||||
$ratio = ($channel == 2 ? 40 : 80);
|
||||
|
||||
// start putting together the initial canvas
|
||||
// $data_size = (size_of_file - header_bytes_read) / skipped_bytes + 1
|
||||
$data_size = floor((filesize($filename) - 44) / ($ratio + $byte) + 1);
|
||||
$data_point = 0;
|
||||
|
||||
// create original image width based on amount of detail
|
||||
// each waveform to be processed with be $height high, but will be condensed
|
||||
// and resized later (if specified)
|
||||
$img = imagecreatetruecolor($data_size / $detail, $height);
|
||||
|
||||
// fill background of image
|
||||
if ($background == "") {
|
||||
// transparent background specified
|
||||
imagesavealpha($img, true);
|
||||
$transparentColor = imagecolorallocatealpha($img, 0, 0, 0, 127);
|
||||
imagefill($img, 0, 0, $transparentColor);
|
||||
} else {
|
||||
list($br, $bg, $bb) = self::html2rgb($background);
|
||||
imagefilledrectangle($img, 0, 0, (int) ($data_size / $detail), $height, imagecolorallocate($img, $br, $bg, $bb));
|
||||
}
|
||||
|
||||
while(!feof($handle) && $data_point < $data_size){
|
||||
if ($data_point++ % $detail == 0) {
|
||||
$bytes = array();
|
||||
|
||||
// get number of bytes depending on bitrate
|
||||
for ($i = 0; $i < $byte; $i++)
|
||||
$bytes[$i] = fgetc($handle);
|
||||
|
||||
switch($byte){
|
||||
// get value for 8-bit wav
|
||||
case 1:
|
||||
$data = self::findValues($bytes[0], $bytes[1]);
|
||||
break;
|
||||
// get value for 16-bit wav
|
||||
case 2:
|
||||
if(ord($bytes[1]) & 128)
|
||||
$temp = 0;
|
||||
else
|
||||
$temp = 128;
|
||||
$temp = chr((ord($bytes[1]) & 127) + $temp);
|
||||
$data = floor(self::findValues($bytes[0], $temp) / 256);
|
||||
break;
|
||||
}
|
||||
|
||||
// skip bytes for memory optimization
|
||||
fseek($handle, $ratio, SEEK_CUR);
|
||||
|
||||
// draw this data point
|
||||
// relative value based on height of image being generated
|
||||
// data values can range between 0 and 255
|
||||
$v = (int) ($data / 255 * $height);
|
||||
|
||||
// don't print flat values on the canvas if not necessary
|
||||
if (!($v / $height == 0.5 && !$draw_flat))
|
||||
// draw the line on the image using the $v value and centering it vertically on the canvas
|
||||
imageline(
|
||||
$img,
|
||||
// x1
|
||||
(int) ($data_point / $detail),
|
||||
// y1: height of the image minus $v as a percentage of the height for the wave amplitude
|
||||
$height - $v,
|
||||
// x2
|
||||
(int) ($data_point / $detail),
|
||||
// y2: same as y1, but from the bottom of the image
|
||||
$height - ($height - $v),
|
||||
imagecolorallocate($img, $r, $g, $b)
|
||||
);
|
||||
|
||||
} else {
|
||||
// skip this one due to lack of detail
|
||||
fseek($handle, $ratio + $byte, SEEK_CUR);
|
||||
}
|
||||
}
|
||||
|
||||
// close and cleanup
|
||||
fclose($handle);
|
||||
|
||||
ob_start();
|
||||
// want it resized?
|
||||
if ($width) {
|
||||
// resample the image to the proportions defined in the form
|
||||
$rimg = imagecreatetruecolor($width, $height);
|
||||
// save alpha from original image
|
||||
imagesavealpha($rimg, true);
|
||||
imagealphablending($rimg, false);
|
||||
// copy to resized
|
||||
imagecopyresampled($rimg, $img, 0, 0, 0, 0, $width, $height, imagesx($img), imagesy($img));
|
||||
imagepng($rimg);
|
||||
imagedestroy($rimg);
|
||||
} else {
|
||||
imagepng($img);
|
||||
}
|
||||
imagedestroy($img);
|
||||
|
||||
$imgdata = ob_get_contents();
|
||||
ob_clean ();
|
||||
return $imgdata;
|
||||
}
|
||||
|
||||
protected static function save_to_db($song_id, $waveform)
|
||||
{
|
||||
$sql = "UPDATE `song_data` SET `waveform` = ? WHERE `song_id` = ?";
|
||||
return Dba::write($sql, array($waveform, $song_id));
|
||||
}
|
||||
|
||||
} // Waveform class
|
Loading…
Add table
Add a link
Reference in a new issue