我需要构建一个web脚本,将mp3文件转换为json格式的波形数据,Android开发人员可以使用这些数据生成包含此数据的波形图像。
为了在php中生成波形数据,我使用了这个git repo => https://github.com/alexkirs/php-waveform-json和工作正常。
现在问题是从php生成的波形数据不适合android。那么,如何在php中生成可以在android中生成波形的波形数据呢?
详细说明, 我使用一个示例mp3文件在php中生成波形数据作为json并接收输出,如下所示,
{
"left": [0.002, 0.002, 0.002, 0.002, 0.0176, 0.002, 0.0216, 0.002, 0.0255, 0.002, 0.0255, 0.002]
}
这意味着所有正面,它会从android端抛出错误来生成波形。然而,对于相同的samle mp3文件,我从在线工具生成波形并收到如下的数据,这在android上完美地生成。该数据形成第1个零或负数,第二个零和正数等等。 下面的数据通过在线工具生成,适用于Android。
{
"data": [0, 3, 0, 3, -1, 6, -8, 11, -23, 26, -26, 24, -29, 21, -32, 25, -30, 24, -25, 23, -28, 26, -30, 30, -32, 31]
}
有人能告诉我如何在php中生成波形,可以在android上运行吗?或任何替代解决方案?
以下是PHP代码(也可用in this repository on GitHub)。
<?php
error_reporting(0);
ini_set('display_error', false);
ini_set("max_execution_time", "30000");
$file = "test.mp3";
$flat = "on";
// how much detail we want. Larger number means less detail
// (basically, how many bytes/frames to skip processing)
// the lower the number means longer processing time
define("DETAIL", 5);
if (file_exists($file)) {
/**
* PROCESS THE FILE
*/
// temporary file name
$tmpname = tempnam(sys_get_temp_dir(), "wav2json_");
// copy from temp upload directory to current
copy($file, "{$tmpname}_o.mp3");
// support for stereo waveform?
$stereo = false;
// $stereo = true;
// array of wavs that need to be processed
$wavs_to_process = array();
/**
* convert mp3 to wav using lame decoder
* First, resample the original mp3 using as mono (-m m), 16 bit (-b 16), and 8 KHz (--resample 8)
* Secondly, convert that resampled mp3 into a wav
* We don't necessarily need high quality audio to produce a waveform, doing this process reduces the WAV
* to it's simplest form and makes processing significantly faster
*/
if ($stereo) {
// scale right channel down (a scale of 0 does not work)
exec("lame {$tmpname}_o.mp3 --scale-r 0.1 -m m -S -f -b 16 --resample 8 {$tmpname}.mp3 && lame -S --decode {$tmpname}.mp3 {$tmpname}_l.wav");
// same as above, left channel
exec("lame {$tmpname}_o.mp3 --scale-l 0.1 -m m -S -f -b 16 --resample 8 {$tmpname}.mp3 && lame -S --decode {$tmpname}.mp3 {$tmpname}_r.wav");
$wavs_to_process[] = "{$tmpname}_l.wav";
$wavs_to_process[] = "{$tmpname}_r.wav";
} else {
exec("lame {$tmpname}_o.mp3 -m m -S -f -b 16 --resample 8 {$tmpname}.mp3 && lame -S --decode {$tmpname}.mp3 {$tmpname}.wav");
$wavs_to_process[] = "{$tmpname}.wav";
}
// delete temporary files
unlink("{$tmpname}_o.mp3");
unlink("{$tmpname}.mp3");
unlink("{$tmpname}");
// get user vars from form
$draw_flat = (isset($flat) && $flat == "on") ? true : false;
$json = new stdclass;
// process each wav individually
for ($wav = 1; $wav <= sizeof($wavs_to_process); $wav++) {
$filename = $wavs_to_process[$wav - 1];
if ($wav == 1) {
$json->left = array();
$array = & $json->left;
} else {
$json->right = array();
$array = & $json->right;
}
/**
* Below as posted by "zvoneM" on
* http://forums.devshed.com/php-development-5/reading-16-bit-wav-file-318740.html
* as findValues() defined above
* Translated from Croation to English - July 11, 2011
*/
$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;
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 = 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(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 = ($data / 255);
$array[] = (float) number_format(abs(0.5 - $v), 4);
} else {
// skip this one due to lack of detail
fseek($handle, $ratio + $byte, SEEK_CUR);
}
}
// close and cleanup
fclose($handle);
// delete the processed wav file
unlink($filename);
}
header("Content-Type: application/json");
echo json_encode($json);
} else {
"Please select file";
}
/**
* GENERAL FUNCTIONS
*/
function findValues($byte1, $byte2) {
$byte1 = hexdec(bin2hex($byte1));
$byte2 = hexdec(bin2hex($byte2));
return ($byte1 + ($byte2 * 256));
}