用于Android的PHP MP3 JSON波形数据生成波形图像

时间:2017-05-09 11:02:57

标签: php android json git waveform

我需要构建一个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));
}

0 个答案:

没有答案