Link to home
Start Free TrialLog in
Avatar of Ken Meyering
Ken MeyeringFlag for United States of America

asked on

How do I read audio samples in PHP from a 16-bit Mono Signed Big Endian .RAW Audio File produced by sox or ffmpeg for an Automatic 4K Radial Kaleidoscope Video generator originally created in Flash?

User generated image

It cost me $239.88 to join the Experts Exchange to ask this single SIMPLE BASIC QUESTION of the online Experts here.

Here's the user interface to the VideoKaleidoscope3840x2160.air Adobe Air application. I'm in the process of getting a 10-year code-signing certificate to share the Air Application. The timestamping in Flash and Air doesn't work any more now that they are past end-of-life. I figured I give my users 10 years of operation with a real certificate.

https://s3.amazonaws.com/media.mp3cruncher.org/DROID-Kens-Adobe-Air-Video-Kaleidsocope-User-Interface.png

https://www.youtube.com/watch?v=iE84b2IVRqM 

Exhibit 1: Animated Rotating Radial Kaleidoscope Music VIDEO made from an XML list of beautiful STILL images and a URL to an online MP3 audio file. It makes a beat-synchronized 4K Kaleidoscope music VIDEO out of a list of beautiful high resolution STILL images (can you say Creative Commons?).

The website is here: http://mp3cruncher.org . It's just an index.php that performs a simple single function for non-real time video animators. It accepts a URL to an MP3 sound file and a video frameRate and outputs an XML list of AverageVolume and PeakVolume by video frame with timecode information.

The full source is here (as you can see, this is a really short script if you ignore the HTML, CSS, graphics and YouTube video):

http://mp3cruncher.org/mp3cruncher-Source-Code.txt

My name is Ken Meyering. In my writings, I call myself DROID Ken. I am a severely mentally ill educator. I'm a really cool crazy pothead who seems to be a MISTAKE-MAKING MACHINE. I just try to make all of my mistakes EDUCATIONAL for others by being TOTALLY OPEN and TRANSPARENT about my own UNIQUE PERSONAL SITUATION.

So, this may NOT seem like a typical appropriate Experts Exchange question. I am NOT a programmer looking for a job. I live on Social Security Disability. I am totally free to speak my mind. I over-share compulsively so that EVERYTHING I say is INAPPROPRIATE and POLITICALLY INCORRECT. I provide WAY TOO MUCH INFORMATION about myself for EDUCATIONAL PURPOSES. These are ALL symptoms of my VERY REAL severe mental illness. I am requesting that you to please assist me IN SPITE of my mental illness and oversharing. Please don't write me off.

My $1850/month public income is secure. I try to give back. I pretend that I am a one-man scientific think tank consulting for the taxpayers by designing the high-level conceptual outline for an all-new, totally private, completely nonprofit, all-virtual, free and real time futuristic utopian global monetary system. (Getting rid of paper money, doing a worldwide banking jubilee and starting over with an all-virtual economy.)  I am a one-trick pony. A worldwide banking quantum leap is my one trick, which everything else supports.

It's almost like my whole life story is nothing but FODDER for educational scientific critical discussion. I'm like a human CARTOON CHARACTER. Please consider this question and my website to be high-visibility public educational examples for a mass market worldwide audience.

Please bear with me for what on the surface may appear to be stupidity and intellectual laziness. I have a severe mental illness that affects my ability to program. I can pretend to be a programmer, but I'm fooling nobody. I'm a man in need of expert help.

I am an online science fiction writer who has completed several community college introductory programming classes. I know how to use MySQL. I took several Unix System Administration courses that gave me the skills to configure a really basic Ubuntu VPS. I can hack my way to getting simple programs working based on OTHER people's OPEN SOURCE examples and functions, but I feel the need to share this disclaimer as I publicly reach out for help. Just pretend you are talking to a smart student with an invisible mental disability.

I have a form of schizophrenia that affects my MATH and LOGIC abilities and my individual initiative and it severely LIMITS my technical RETENTION and the complexity of what I am capable of doing with computers on my own without the help of more intelligent and experienced others. I have very little technical retention and rely on written notes and code to get things working.

I'm a smart guy but I wasn't able to successfully complete a community college ELEMENTARY SYMBOLIC LOGIC class and I couldn't make it past the UNIT CIRCLE in precalculus. I had to withdraw from both of those classes. Basic logic confuses me. My brain just cannot do the operations and translations. The neural connections just aren't there. I hit an INVISIBLE mental wall. I can forget about taking STATISTICS. That is beyond my ken. So much for neural networks, pattern recognition and quantum physics.

Things that are super easy and intuitive to normal people are hard for me. I lack COMMON SENSE but not for lack of trying. That's why I like writing fiction where anything goes and it's all imaginary fantasy. For a person who suffers from delusions due to no fault of his own, fantasy writing beats programming as an intrinsically rewarding activity. Sorry, Dad, I'm NOT a computer genius. This is the best that I can do with computers.

It is imperative that the solution here be as SIMPLE as possible even if it's NOT the fastest way to produce the MP3 audio analysis. This is a super simple PHP application doing a super simple function, but because of my illness, I am flabbergasted, easily frustrated and confused and need assistance please. I feel really embarrassed that I am so stumped by such a simple thing. I am totally serious and truly need help.

I have a small server set up as a web service for a FREE OPEN SOURCE Adobe Air application that slowly generates 4K video kaleidoscopes as a series of BMP images. I have limited programming experience and am getting confused by the values that are being returned by my 16-bit raw audio analysis. I originally wrote this script in 2012 when I was a Flash student. I just returned to it and tried to make it 16-bit. It worked great almost exactly as it is in 8-bit.

The sole purpose of this script (the whole purpose of the educational nonprofit VPS) is to provide FREE frame-level metadata on MP3 files for entry-level music video animators who are interested in finding the beat for video production (AverageVolume, PeakVolume and video timecode information).

Here is an example of my very first test with frame-level audio synchronization. You can really see the acoustical percussion patterns as visual patterns in the spherical refraction index of the kaleidoscope. All I'm doing is directly plugging amplitude into image refraction after applying a variable scaling factor input by the user with a little bit of application-level look ahead and averaging between frames to smooth the visual decay of the beats.

Basically, it's a computerized visualizer of MP3 music amplitude patterns by applying a 3D spherical displacement map to a 2D radial kaleidoscope made from rotating hi-res still images INPUT by an XML file.

It's a totally AUTOMATIC music video MACHINE. A URL to an mp3 audio file and a LIST of STILL images IN and a 4K Blu-ray, YouTube, Hulu, Amazon Prime and Netflix-ready Kaleidoscope Music Video OUT for FREE if you have a LOT of PATIENCE, a fast computer with a good graphics card and a VERY large hard drive. It's a totally FREE money-making machine for entry-level people who have PATIENCE.

You can do this in Adobe Flash 7 (or scripted with Adobe Photoshop CS5) with these PixelBender filters. Here are the PixelBender filters that will do this functionality in a single step. I'd like the Open Source software community to convert these filters into free plug-ins for the modern Adobe Photoshop and Adobe Premiere applications and also command line versions that will run on Ubuntu.

https://s3.amazonaws.com/media.mp3cruncher.org/RadialKaleidoscope.pbk

https://s3.amazonaws.com/media.mp3cruncher.org/RadialKaleidoscope.pbj

https://s3.amazonaws.com/media.mp3cruncher.org/spherize.pbk

https://s3.amazonaws.com/media.mp3cruncher.org/spherize.pbj

Here is my Adobe Flash and Air Source Code for this Kaleidoscope Video project.

https://s3.amazonaws.com/media.mp3cruncher.org/4K-Flower-Kaleidoscope-Example-Student-Adobe-Flash-and-Air-Project.zip

Pretend I am my 97-year-old grandmother, who doesn't know how to use Google even though my mother bought her a computer and she pays for her monthly internet access. We Skype. She refuses to learn. She has no initiative. She just doesn't have the motivation to learn NEW THINGS. She BELIEVES she doesn't know how to use the computer and NOTHING will shake that BELIEF. She's had breast cancer for 4 years but refuses to get it cut out because she's afraid she will die under general anesthesia.

She has a MENTAL BLOCK. It's not LOGICAL or RATIONAL. I still love her dearly. She's a wonderful loving human being, like me. That's grandma. I have her DNA, for better or worse. I'm not LOGICAL. I know sharing TOO MUCH INFORMATION offends people and drives them way. But I still do it COMPULSIVELY in spite of that knowledge. I'm ALWAYS in BRAIN DUMP MODE. I share my thoughts and feelings without filters with reckless abandon. I am a human CARTOON of exaggerated OPENNESS and TRANSPARENCY.

Assume that I do NOT know how to look up the command line parameters to ffmpeg. I want this little Experts Exchange conversation to embed all of that information into the conversation with the voluntary assistance and participation of members of this online community.

The development environment is PHP 8 and Apache2 on Ubuntu (with sox and ffmpeg installed). It's a super simple basic vanilla server configuration. I've included URLs to sample data files (copyrighted music but used here on a nonprofit website for educational scientific critical discussion purposes). Keeping absolute simplicity in mind, I'd like to try to get this working with the minimum amount of redesign. This is super basic stuff. It's supposed to be SUPER SIMPLE so that anybody can replicate it and scale it.

Here is the meat of the code. This is the PHP sample-reading logic in the source slightly modified to work standalone with the included data files.

http://mp3cruncher.org/examples/standalone_test_01.txt

http://mp3cruncher.org/examples/standalone_test_01.php

Here is the FIRST code snippet for the standalone test. (Below in the SECOND code snippet I provide a standalone example that will accept any mp3 via a GET parameter or command line argument.)

<?php
//Experts Exchange 16-bit Audio Analysis Basic Question Standalone Sample Script Example 1

ini_set('display_errors',1);
$song="http://mp3cruncher.org/examples/David-Essex_Rock-On.mp3";//Original Song for testing
$mp3TEMP="http://mp3cruncher.org/examples/3572ef3c9121e9faa59fdb33b2d7aa84.mp3";//Rock On by David Essex
$rawTEMP="http://mp3cruncher.org/examples/3572ef3c9121e9faa59fdb33b2d7aa84.raw";//16-bit Mono 22KHz Signed Big Endian RAW Audio
$audio=file_get_contents($rawTEMP);

header("content-type:text/xml");
echo "<?xml version='1.0' encoding='UTF-8'?>\r\n";

$sampleRate=22050;
$frameRate=30;
$samplesPerFrame=$sampleRate/$frameRate;
$totalSamples=strlen($audio)/2;
$totalFrames=ceil($totalSamples/$samplesPerFrame);
$mp3LengthSeconds=number_format($totalFrames/$frameRate,3);
$mp3LengthSMPTE=getTimeCode($totalFrames/$frameRate,$frameRate);

echo "\t<frames mp3File='$song' frameRate='$frameRate' mp3Length='$mp3LengthSeconds' mp3LengthSMPTE='$mp3LengthSMPTE' totalFrames='$totalFrames'>\r\n";

for($frame=0;$frame<$totalFrames;$frame++)
{
    $time=$frame/$frameRate;
    $realFrame=substr("000000".($frame+1),-6);
    $timeCode=getTimeCode($time,$frameRate,0);
    $timeCodeSMPTE=getTimeCode($time,$frameRate,1);
    $secondsRnd=substr("00000".floor($time),-5);
    $secondsMilli=substr("000".round(1000*($time-$secondsRnd)),-3);;
    $seconds="$secondsRnd.$secondsMilli";
    $peakVolume=0;
    $totalAmplitude=0;
    
    for($sample=0;$sample<$samplesPerFrame;$sample++)
    {
        $absoluteSample=$frame*$samplesPerFrame+$sample;
        $high_byte=ord(substr($audio,$absoluteSample*2,1));
        $low_byte=ord(substr($audio,$absoluteSample*2+1,1));
        if($high_byte>127) $high_byte=$high_byte-128; //remove the sign
        $amplitude=1-(($high_byte*255+$low_byte)/32768); //normalize with silence 0 and full loud 1
        if($amplitude>$peakVolume) $peakVolume=$amplitude;
        $totalAmplitude+=$amplitude;
    }
    $averageVolume=$totalAmplitude/$samplesPerFrame;
    $peakVolume=number_format($peakVolume,7);
    $averageVolume=number_format($averageVolume,7);
   
    echo "\t\t<peakVolume frame='$realFrame' seconds='$seconds' timeCodeSMPTE='$timeCodeSMPTE' averageVolume='$averageVolume'>$peakVolume</peakVolume>\r\n";
    flush();
}

echo "\t</frames>";
function getTimeCode($time, $inputFrameRate, $smpte=1) 
{
    $thisFrameNumber=floor($time*$inputFrameRate);
    $min = floor($time / 60);
    $hour = floor($min / 60);
    if ($min > 60) $min = $min - ($hour * 60);
    $sec = floor($time % 60);
    $milli = $time - floor($time);
    $frame = round($milli*$inputFrameRate);

    $shour = $hour;
    $smin = $min; 
    $ssec = $sec;

    $sframe = $frame;

    if (strlen($shour) < 2)
    $shour = "0" . $shour;

    if (strlen($smin) < 2)
    $smin = "0" . $smin;

    if (strlen($ssec) < 2)
    $ssec = "0" . $ssec;

    if (strlen($sframe) < 2)
    $sframe = "0" . $sframe;

    $tcSMPTE = $shour . ":" . $smin . ":" . $ssec . ":" . $sframe;
    $tc = $shour . ":" . $smin . ":" . $ssec . number_format($milli,3);

    if($smpte)
        return $tcSMPTE;
    else
        return $tc;
}
?>

Open in new window

For some reason, I'm NOT getting the correct values out of this. It all worked great when the RAW file was signed 8-bit (technically 7 bits because I throw away the sign). I wanted to improve the fidelity of my kaleidoscope scaling to be 16-bit (technically 15-bit because I throw away the sign). I figured that will make for better scaling in-betweens.

Something is wrong right here:
$peakVolume=0;
$totalAmplitude=0;
for($sample=0;$sample<$samplesPerFrame;$sample++)
{
   $absoluteSample=$frame*$samplesPerFrame+$sample;
   $high_byte=ord(substr($audio,$absoluteSample*2,1));
   $low_byte=ord(substr($audio,$absoluteSample*2+1,1));
   if($high_byte>127) $high_byte=$high_byte-128; //remove the sign
   $amplitude=1-(($high_byte*255+$low_byte)/32768); //normalize with silence 0 and full loud 1

    if($amplitude>$peakVolume) $peakVolume=$amplitude;
    $totalAmplitude+=$amplitude;
}
$averageVolume=$totalAmplitude/$samplesPerFrame;
$peakVolume=number_format($peakVolume,7);
$averageVolume=number_format($averageVolume,7);

Open in new window

I understand binary. I'm used to visualizing wave forms in audio editors as having LOUD be big spikes up and down across the zero axis. So, I think of loud as being +32768 and -32768 with 0 being silence. It's the absolute value. But that's not how it's represented. Here is the LOGIC that is IMPOSSIBLE for my BRAIN and I'm sure MANY OTHER BRAINS:

According to the sox documentation, a value of 0 is supposed to indicate full loudness. I'm trying to get the correct value then to normalize and return a floating point value between 0 and 1 with 0 being silence and 1 being full loudness. That doesn't make sense to me. How do you put a sign on a zero if that's supposed to be full volume? That's what's confusing me. For me, it doesn't make sense. It's NOT intuitive.

Here is an example of an MP3 that I'd like to analyze for testing purposes. The MP3 starts with silence with a really low level of background noise, so the first frames should have very low values indicating near silence, until the bass starts doing the hook. Instead the values are high for the whole song and are nearly uniform. So something in my logic is wrong.

Here's the code analyzing this song as a 16-bit signed-integer big endian RAW file. Processing the local MP3 file takes about 2 seconds but it takes about 5 seconds for the browser to render all the XML with thousands of frames, so please be patient.

http://mp3cruncher.org/?mp3File=http://mp3cruncher.org/examples/David-Essex_Rock-On.mp3

Here are copies of the intermediate temp files that are deleted right away during the process.

http://mp3cruncher.org/examples/3572ef3c9121e9faa59fdb33b2d7aa84.mp3

http://mp3cruncher.org/examples/3572ef3c9121e9faa59fdb33b2d7aa84.raw

I loaded the RAW file into an audio editor with the following settings and it sounded fine.

22050 Hz 16-bit Mono Big Endian Signed

It looks like sox is doing it's job exactly as the parameters say. It sounds fine. Below, David suggested that I rewrite this in perl or use ffmpeg instead for reliability and flexibility. In this case with this example, rather than rewrite everything (I have to find the ffmpeg parameters), I'd like just to get my logic working here in this example without a rewrite starting with the RAW file. I'm just interested in grabbing the samples from memory with the correct values.

Perhaps the experts would use more efficient and technically complex means to produce 4K Video Kaleidoscopes and to analyze raw audio from MP3s. In any case, I have the raw audio in memory from the raw file. That's the majority of the work right there. Fixing about 4 lines of sample-reading code should get this working correctly, if NOT optimized for performance. Everything worked as designed when I was analyzing 8-bit RAW audio, but the switch to 16-bit has left me confused.

As you can see, all the TIMING and LENGTH values are CORRECT but all the VOLUME values are wrong as of when I submitted this question.

I realize that this is a super simple application but for the life of me I seem to have no luck finding my own solution.

Thank you.
Avatar of David Favor
David Favor
Flag of United States of America image

Very difficult to tell exactly what's going on in your script.

If I were going to do this, I'd write a standalone PHP or PERL script, which could run without any type of Web interface.

This will allow you to debug problems far easier.

Regards what you're seeing, unsure exactly what column you're equating to loudness.

Maybe averageVolume is what you're looking considering as loudness.

No easy way to run your code because it's plumbed into a complex PHP Webpage.

If it were a standalone script, be easy to run.

As it is, I can't get your sox arguments to produce a similar graph running my version of sox.
Seems like an interesting project.

Keep at it till you get it working.

Random Aside: Another trick I'd likely use for a project like this is to use ffmpeg, rather than sox, so any video or audio format uploaded would work the same.

Also with ffmpeg, you can easily disable video processing (as you're only interested in audio), channel selection will work better (sox has trouble converting stereo/dolby to mono), then you can send the audio output to a file which will speed up each run + require no disk space for an output file.
Avatar of Ken Meyering

ASKER

Thank you, David.

I've updated the code to be standalone so you all can test it. I eliminated the sox shell call and just started with the RAW file for you to test (TEST_01 uses a ready-to-use RAW file) . In the future I can use ffmpeg since it's apparently more flexible and robust, but for testing and problem-solving purposes, let's just begin with the RAW audio and forget about the MP3-to-RAW conversion until I learn the correct syntax and parameters to shell out to ffmpeg (by the end of this conversation we will probably be using ffmpeg to convert any input audio file to 22Khz 16-bit Mono Signed Big Endian). This will be a quick fix once I get the ffmpeg parameters for the conversion. I hear you. I will do that per your expert advice.

My goal is to make this as easy-to-understand for LAYPEOPLE and BEGINNERS as possible. So I am not necessarily looking for the most efficient and highest performing solution. I want it to be SUPER SIMPLE for EDUCATIONAL PURPOSES so entry-level musicians can learn how to access raw audio for beat analysis. This is an educational project as part of a simple tutorial for people just getting started with animation and creating music videos that are automatically synchronized with beat dynamics.

This simple stereo MP3 to RAW functionality currently works with the latest version of sox. So it successfully converts the stereo MP3 of any sample rate to a 16-bit 22 Khz signed big endian Mono file. I have attempted reading the RAW file produced by sox with an audio editor specifying these exact parameters and the audio plays back beautifully. So lets forget about all the audio conversion and my choice to do this as simply as possible in PHP with the fewest lines of code. Please just assume I have the uncompressed audio successfully loaded into a string variable $audio. I just want to get at the samples.

The .mp3 and .raw temporary files are immedately deleted as soon as the RAW audio gets loaded into the string variabe. The VPS is on an SSD so disk access is fast. So let's just focus on the individual sample reading logic here if we can. Thanks.
    
   for($sample=0;$sample<$samplesPerFrame;$sample++)
   {
        $absoluteSample=$frame*$samplesPerFrame+$sample;
        $high_byte=ord(substr($audio,$absoluteSample*2,1));
        $low_byte=ord(substr($audio,$absoluteSample*2+1,1));
        if($high_byte>127) $high_byte=$high_byte-128; //remove the sign
        $amplitude=1-(($high_byte*255+$low_byte)/32768); //normalize with silence 0 and full loud 1
        if($amplitude>$peakVolume) $peakVolume=$amplitude;
        $totalAmplitude+=$amplitude;
    }
    $averageVolume=$totalAmplitude/$samplesPerFrame;

Open in new window



Aside: By "standalone", this means an entire script which can be handed a .mp3 file, do all computations to produce output of "frame level".

Above is a simply a loop, which requires a good bit of code to get working.

You said, "Please bear with me, I require a bit of patience."

No worries!

All questions are good questions!
Thanks again, David. The little loop is my absolute sample reader where I think I'm making my sample reading logical error. Somehow my math is screwed up. This is probably a blatantly obvious logical error to you and any real programmer. I started this project in 2012 but never finished it. I have forgotten most of what I learned in school for lack of use. I just returned to it now in 2021.

Here's a SECOND standalone script that will accept a URL to any MP3 in a string variable (or as the first command line parameter) for testing purposes.

<?php
//Experts Exchange 16-bit Audio Analysis Basic Question Standalone Sample Script Example 2

ini_set('display_errors',1);
header("Content-type:text/plain");

$songURL="";
$applicationPath=getcwd();

if(isset($argv[1])) //Command-line mode
    $songURL=$argv[1];

if(isset($_GET['mp3File'])) //Website mode
    $songURL=$_GET['mp3File'];
    
// Example song
// $songURL="http://mp3cruncher.org/examples/David-Essex_Rock-On.mp3"; //Original song for testing

if(!strlen($songURL)) 
{
    echo "\r\n\r\nNo MP3 URL specified. (?mp3File={full URL to file})\r\n\r\n";
    exit();
}
    
$sampleRate=22050;

$mp3content=file_get_contents($songURL);

if(!strlen($mp3content))
{
    echo "\r\n\r\nNo mp3 content found at that URL.\r\n\r\n";
    exit();
}
$md5=md5($songURL);
$mp3TEMP="$applicationPath/$md5.mp3";
$rawTEMP="$applicationPath/$md5.raw";
$fh=fopen($mp3TEMP,'w');
fwrite($fh,$mp3content);
fclose($fh);

$cmd="sox $mp3TEMP -c 1 -b 16 -r{$sampleRate} -e signed -B $rawTEMP -V"; // mono 16-bit signed big endian raw file
exec($cmd);

if(file_exists($mp3TEMP)) unlink ($mp3TEMP);
if(file_exists($rawTEMP)) 
{
    $audio=file_get_contents($rawTEMP);
    unlink($rawTEMP);
}
else
{
    echo "\r\n\r\nUnable to find RAW temp file.\r\n\r\n";
    exit();
}
echo "<?xml version='1.0' encoding='UTF-8'?>\r\n";

$frameRate=30;
$samplesPerFrame=$sampleRate/$frameRate;
$totalSamples=strlen($audio)/2;
$totalFrames=ceil($totalSamples/$samplesPerFrame);
$mp3LengthSeconds=number_format($totalFrames/$frameRate,3);
$mp3LengthSMPTE=getTimeCode($totalFrames/$frameRate,$frameRate);

echo "\t<frames mp3File='$songURL' frameRate='$frameRate' mp3Length='$mp3LengthSeconds' mp3LengthSMPTE='$mp3LengthSMPTE' totalFrames='$totalFrames'>\r\n";

for($frame=0;$frame<$totalFrames;$frame++)
{
    $time=$frame/$frameRate;
    $realFrame=substr("000000".($frame+1),-6);
    $timeCode=getTimeCode($time,$frameRate,0);
    $timeCodeSMPTE=getTimeCode($time,$frameRate,1);
    $secondsRnd=substr("00000".floor($time),-5);
    $secondsMilli=substr("000".round(1000*($time-$secondsRnd)),-3);;
    $seconds="$secondsRnd.$secondsMilli";
    $peakVolume=0;
    $totalAmplitude=0;
    
    for($sample=0;$sample<$samplesPerFrame;$sample++)
    {
        $absoluteSample=$frame*$samplesPerFrame+$sample;
        $high_byte=ord(substr($audio,$absoluteSample*2,1));
        $low_byte=ord(substr($audio,$absoluteSample*2+1,1));
        if($high_byte>127) $high_byte=$high_byte-128; //remove the sign
        $amplitude=1-(($high_byte*255+$low_byte)/32768); //normalize with silence 0 and full loud 1
        if($amplitude>$peakVolume) $peakVolume=$amplitude;
        $totalAmplitude+=$amplitude;
    }
    $averageVolume=$totalAmplitude/$samplesPerFrame;
    $peakVolume=number_format($peakVolume,7);
    $averageVolume=number_format($averageVolume,7);
   
    echo "\t\t<peakVolume frame='$realFrame' seconds='$seconds' timeCodeSMPTE='$timeCodeSMPTE' averageVolume='$averageVolume'>$peakVolume</peakVolume>\r\n";
    flush();
}

echo "\t</frames>";
function getTimeCode($time, $inputFrameRate, $smpte=1) 
{
    $thisFrameNumber=floor($time*$inputFrameRate);
    $min = floor($time / 60);
    $hour = floor($min / 60);
    if ($min > 60) $min = $min - ($hour * 60);
    $sec = floor($time % 60);
    $milli = $time - floor($time);
    $frame = round($milli*$inputFrameRate);

    $shour = $hour;
    $smin = $min; 
    $ssec = $sec;

    $sframe = $frame;

    if (strlen($shour) < 2)
    $shour = "0" . $shour;

    if (strlen($smin) < 2)
    $smin = "0" . $smin;

    if (strlen($ssec) < 2)
    $ssec = "0" . $ssec;

    if (strlen($sframe) < 2)
    $sframe = "0" . $sframe;

    $tcSMPTE = $shour . ":" . $smin . ":" . $ssec . ":" . $sframe;
    $tc = $shour . ":" . $smin . ":" . $ssec . number_format($milli,3);

    if($smpte)
        return $tcSMPTE;
    else
        return $tc;
}
?>

Open in new window

Maybe this will be easier to debug.

Here are the files:

http://mp3cruncher.org/examples/standalone_test_02.txt

http://mp3cruncher.org/examples/standalone_test_02.php

For anyone else to debug this will require running a scrip... something like this...

create_frame_data foo.mp3

Open in new window


This script should produce only simple data (no HTML)... just a spew of well formed data records, likely something like "frame volume" or any other per frame data you require.

Be sure to include the full code logic, including the sox command.
OK. I updated the standalone script #2 to run on a command line with the song URL as the first argument.

Here is an example running on the command line with a sample URL:

php standalone_test_02.php http://mp3cruncher.org/examples/Goldfrapp_Crystalline-Green.mp3

Open in new window

In a web browser it would be like this:

http://mp3cruncher.org/examples/standalone_test_02.php?mp3File=http://mp3cruncher.org/examples/Goldfrapp_Crystalline-Green.mp3






Perfect!

Now attach your script to this question, for testing.
David, I'm confused. In SAMPLE SCRIPT #2 above I've got the whole script attached as a code example, and as a plain TXT file with PHP source (same source as in the code window). So, you have whole script that will run on the command line with ANY MP3 file.  That's what you asked me for, that's what I'm giving you. It outputs well-formatted XML (except for the sox status message that shows up on the command line version above the XML). But everything is minimal and structured for testing.

Here are the files. This is what you are asking for.

http://mp3cruncher.org/examples/standalone_test_02.txt

http://mp3cruncher.org/examples/standalone_test_02.php 

This is the code. This runs on the command line just like you asked for. It also accepts a URL via a GET string ?mp3File=(URL).  This is your example. What else do you need besides this for testing purposes? I'm trying to be helpful here. I'm trying to do this right. Maybe I should just offer $100 to some Indian web developer to fix my screwed-up 4 lines of code that reads the sample to get this over with. That's where the error is. If I was rich I'd have a team of programmers developing super cool applications at all times, especially with GPUs and gaming cards. So I'd be the idea man, and the programmers would handle the implementation at the code level. I cannot do it all by myself. I'd like to generate a distributed parallel application that allows the visualization of fractal flame images while modifying the parameters under computer-control in real time.

This worked exactly as it is 9 years ago when I wrote it with an 8-bit signed audio file. I don't program every day. I write online delusional fantasy fiction in HTML. My web pages take 5 minutes to load. I have no traffic. I'm a writer who designs Utopias. I think about solving all the worlds problems with an all-new all-virtual FREE WORLD BANK, not reading signed 16-bit big endian Mono RAW files. That's NOT where my head is at at 54-years-old on Social Security Disability living with my 77-year-old mother. I hand feed wild raccoons and squirrels in my back yard. That is the sum total of my social life. I relate to animals.
The only thing that changed is I'm reading 2-bytes instead of one, but I don't intuitively understand how a value of 0 is full loudness. Can't full loudness be both positive and negative, like a big giant spike in waveform that crosses the zero axis. So that is loud. The absolute value of the height of the waveform.

I think I found the syntax for ffmpeg, but I'm not sure if this is all there is to it.

$cmd="ffmpeg -i $mp3TEMP -f -ar 22050 -c:a pcm_s16be $rawTEMP"; 

Open in new window

An easier to debug approach is to build into your script the step which produces the $rawTEMP file... so as mentioned above.

Your script will be...

test $arg

Open in new window


Where $arg can be a local audio file or audio file URL.

The ffmpeg command above only converts your .mp3 file to a .wav file, so no data is emitted like what you're doing with sox.
TOP LEVEL MANAGEMENT in a TOTALLY HORIZONTAL ORGANIZATION. I am a VERY LOW STATUS person. I'm really fucked-up ON PURPOSE for the BENEFIT of OTHERS.

We are publicly TROUBLESHOOTING LIVE CODE here. The OPEN SOURCE CODE is given. We're ALL on the SAME PAGE here. We ALL have the SAME FACTS. THIS CODE is the REALITY that we are TROUBLESHOOTING. This is what we're all working with, in the real world, LIVE, online, for REAL. This is your CODE EXAMPLE.

Thank you for the ffmpeg comment. I didn't realize those parameters were making a WAV file.

http://mp3cruncher.org/examples/standalone_test_02.txt 

This is your easier-to-debug approach already given, David, multiple times, above, already. Please TAKE THE TIME to save this file as a PHP on your computer and run it and look at the simple well-formatted output. It runs. It's done. This should be super easy for you. You are going around in circles with me making me jump through confusing, unneccessary and redundant hoops. You are NOT reading what I'm writing. This is your "test $arg" working already multiple exchanges ago. You are NOT acknowledging what I am giving you already. Stop asking me to give you something DIFFERENT. This is the REALITY that we are working with. This is what we're starting with. This is the real thing. This is the SAME CODE that we are discussing for the fourth time. It runs from the command line and accepts a URL to an MP3 as the first argument. Done. Here it is, right here. Let's go. Game on.

This is as easy as it gets for you. I'm NOT going to be making it ANY EASIER for you to debug than THIS. This is super simple shit AS IS. I am at my wits' end. THIS is it. THIS is what we're working with. Let's get started already on THIS if you don't mind, can we, please? My sample reading is fucked-up. That's about 4-lines of CODE. I think you can handle it without wasting time asking me to rewrite it. It's as SIMPLE as I CAN MAKE it. These are the fundamentals. It CAN'T get any EASIER for you than this if you have the WILL to help me and OTHERS who can benefit from this.

I will be very grateful if you can help me solve this problem AS IS so I can start giving my OPEN SOURCE software away for FREE. I realize that you don't work for me, and that I could probably leave the almost FREE Experts-Exchange and pay somebody smarter than me $100 to fix this, PRIVATELY, in 5 seconds. Case closed. Problem solved. We are done. Life goes on. Then it would ALL be working correctly again just like it was 9 years ago when I made it. Then I could move on with the business of saving the world and giving it all away for FREE.

Let's try to get it fixed here, out in the open, publicly for all to see, for FREE.

I'm a GOVERNMENT-designed HARD CORE LEFT WING RADICAL NUTCASE REVOLUTIONARY genius LONER who fits the profile of TERRORIST. I work for the scientific community. We're taking out the whole international banking system and we're eliminating ALL the WEALTH. We are taking everybody's MONEY away. We're taking back ALL the commercial real estate. This is big. I have Uncle Sam's FULL ATTENTION here. I'm ON the United Nations' radar. They let me do this. We are ALL WATCHING THIS TOGETHER.

I'm TOP-LEVEL MANAGEMENT with severe ADD, severe PTSD, schizoaffective disorder and some technical vocabulary based on entry-level programming classes that Uncle Sam generously paid for, most of which I have FORGOTTEN due LACK of USE due to LACK of personal MOTIVATION and INITIATIVE. I cannot EXERT the EFFORT to take of myself. Just pretend that I am a BAD ROBOT who has been FRONTALLY LOBOTOMIZED by the U.S. Navy with advanced nanotechnology for the GREATER GOOD. Now I have to GET WELL by SHARING my TRUE STORY for others to learn from.

I'm a LEADER. I'm a VISIONARY. I SET the DIRECTION of the enterprise with VALUES, MORALS, ETHICS, FIRST PRINCIPLES and HIGH-LEVEL GOALS. I let other people handle the implementation. I am a DESIGNER, NOT a builder. I delegate the manifestation into REALITY. I work with BIG IDEAS in THEORY before they become REALITY. It's all THEORETICAL to me. It's all HYPOTHETICAL. They are OPTIMISTIC DELUSIONS that SUSTAIN me and GIVE me HOPE. I like the act of FANTASIZING as an INTRINSICALLY REWARDING activity. I enjoy DREAMING BIG. I suffer from grandiosity and pathological optimism. I'm a dreamer. I think BIG. I think from the TOP-DOWN. I write fiction about technological utopia. I design new global constitutions. I write the The Law of The Land for Heaven on Earth from a totally imaginary totally theoretical perspective.

I FANTASIZE ALL DAY LONG about ways to make EVERYBODY HAPPY everywhere on planet Earth. Like the Benevolent King of Earth who gets to daydream about saving the whole world, saving the whole ecosystem and solving all the world's problems, including the religion problem and the climate change problem, with a money-no-object all-virtual global banking system that fully funds everything GREEN so that it is TOTALLY FREE everywhere on Earth. No more poverty. No more war. Much less pollution. A very futuristic, totally automated, all-electric world in Afghanistan, Iraq, Iran, Saudi Arabia, Russia, China, North Korea, South Korea and everywhere else on planet Earth. I am talking about changing the whole system everywhere. I'm talking about GETTING RID of all the nation states. No more national sovereignty over natural resources. All those authorities are NULL and VOID. We fired all those corrupt bastards. The politicians and political systems were ruining this planet. We took way their power. We took over. We are all going GREEN in a BIG WAY. Case closed. Game over. We are done with it.

David, if you are supposed to be an award-winning distinguished expert, why don't you use what I've given you already? You are a smart guy. You can figure it out. It runs from the command-line. Are you even reading the code I'm giving you EVERY TIME I respond you your feedback? Every comment you've made is asking me for the same thing that I'm already giving you. It runs from the command line. It converts any MP3. Please save the TXT example file as a PHP file, read the code, run it, analyze it, and try to see what I'm doing wrong where I'm reading the 16-bit signed big-endian sample from memory.

Show your stuff, David. Please don't ask me to rewrite this again. This is EDUCATIONAL FODDER for ENTRY-LEVEL BEGINNERS. I don't know how to do this. Please try to be more HELPFUL and more INFORMATIVE than you have been so far. I appreciate your helpful comments about ffmpeg but you have NOT downloaded, executed and commented upon the working code example yet, so you're NOT giving much EXPERT bang for buck here, so far. Nobody else has responded at all.

Take some time to think about what I've already given you. Don't blow it off and send me another curt note asking for something different. To me, due to no fault of your own, that feels like an intellectual cat-and-mouse head game. Like you are toying with me for your own entertainment to impress your Expert friends in this community. I know you have good intentions and that all those feelings are symptoms of my mental illness.

I don't blame you for that but that is how it feels, subjectively, to me, inside my damaged brain. Like you are INTENTIONALLY playing dumb with me and giving me very low effort runaround responses like a Zen Master teaching an apprentice how to be more self-efficacious. It feels like you are toying with me for being lazy and NOT figuring it out on my own WITHOUT your help because that will make me a better and more responsible person in your eyes, as though you have rationalized that the best way to HELP me and OTHERS is by NOT helping me and OTHERS.

Tough love for DROID Ken. Figure it out yourself, Ken. Do it on your own like a responsible grown-up. You'll be better off. Let's NOT play the game that way, in this case, for the GREATER GOOD. HELP me please. I've had a decade to get this right. I haven't had the WILL POWER. My initiative is fucked up. My brain is permanently damaged. I have to DEPEND on OTHERS. I have to ask for HELP. I cannot do it myself. I NEED ASSISTANCE, please.

That's NOT the way this public QUESTION and ANSWER game is supposed to work. I'm NOT the expert here. I'm NOT a professional programmer. I don't write code for a living. I can't just magically rewrite things for you like you can do. I had to research how to pass a command line argument into PHP, even though I am a CERTIFIED Unix System Administrator with an Associate's degree in web database development. I've already forgotten everything, but I can still keep my websites up. I don't know what I'm doing. I'm a NOT a programmer. I'm a world peace activist.

 https://www.YouTube.com/HDCOLORS

This code is 9 years old to me. I first wrote this in 2012. I just returned to it to open source my kaleidoscope generator for the 69,000 followers on my YouTube channel. (I'm buying a 10-year $600 code-signing certificate just to distribute the working Air Application for FREE). I'm paying good money to give my work away for FREE so that OTHER PEOPLE can COMPETE with me in the kaleidoscope business. I'm HELPING my COMPETITORS because I am irrationally compelled to TEACH. I am LOSING MONEY and DIMINISHING the UNIQUENESS of my own art because some inner IRRATIONAL force tells me it's for the GREATER GOOD and that it will all work out in the end and that I will be OK.

Time-stamping during code-signing doesn't work in Air any more. I want other people to use this and I want it to work for them. Right now it doesn't because mp3cruncher.org is NOT outputting the correct VOLUMES for the frames. I try to speak your language, but I don't have your skills. I don't have access to your COMMON SENSE and mental TOOL KITS. Pretend you are talking to a non-technical ARTIST who makes ILLEGAL ONLINE DIGITAL GRAFFITI protected by TRANSHUMAN DIPLOMATIC IMMUNITY.

Please work with this code EXACTLY as it is. You HAVE the example. Your VOLUNTEER JOB on behalf of the Experts Exchange is to analyze it and provide expert analysis of the CODE I've given you AS IT IS NOW on behalf of ALL the world's mentally ill programmers and college dropouts who TRULY do NOT understand this SHIT. I seriously need your help. Work with this exactly as it is please. I've already given you the code that meets your requirements. Work with it as it is, please. Make yourself as USEFUL and HELPFUL with each post according to your EXPERT ABILITY like a TEACHER. Give us all some EDUCATIONAL CONTENT that HELPS SOLVE our problems AS ALREADY GIVEN here in this example. Let's talk about SAMPLE READING.

THIS is what you have to work with. THIS is the code in question. We need to get THIS working so that the SAMPLE READING is correct. Share some knowledge instead of asking for something different. THIS runs from the command-line. THIS converts ANY mp3 to a RAW file and loads it into memory. This is what you need. This is what you're asking for. This is what I have. This is the STARTING POINT, period. Let's get this show on the road and make this thread as USEFUL and as HELPFUL to others as POSSIBLE with EVERY COMMENT and EVERY EXCHANGE.

http://mp3cruncher.org/examples/standalone_test_02.txt

Still same result...

# php -f mp3test ./rando.mp3
sox:      SoX v14.4.2
sox FAIL formats: no handler for file extension `mp3'


Unable to find RAW temp file.

Open in new window

Thanks, much, David, for sticking with it, in spite of my clear mental illness and obvious insanity. I appreciate your help. Thank you for helping. This should add the mp3 capabilities to sox:

sudo apt-get install libsox-fmt-mp3

Open in new window

This seems to work for reading the sample. I'm not sure if this is correct, but at least low volumes are near 0 and max volume is 1.

$absoluteSample=$frame*$samplesPerFrame+$sample;
$high_byte=ord(substr($audio,$absoluteSample*2,1));
$low_byte=ord(substr($audio,$absoluteSample*2+1,1));
$amplitude=1-abs(($high_byte*255+$low_byte)-32768)/32768; //normalize with silence 0 and Full loud 1

Open in new window

http://mp3cruncher.org/examples/standalone_test_03.txt

http://mp3cruncher.org/examples/standalone_test_03.php
You mentioned, "Thanks, much, David, for sticking with it, in spite of my clear mental illness and obvious insanity. I appreciate your help. Thank you for helping."

You're welcome!

We'll all be suffering from mental illness till Big Tech rounds us up + installs our Borg Implants... which I expect could be any day now...

Hang in there!
Aha! Installing libsox-fmt-mp3 did the trick for me too.
Aside: How I'd organize this project.

First I'd get the existing code working... then move onto...

1) I avoid (like the plague) every releasing software to install.

$600 for a code signing license will be the least of your problems.

The biggest problem will be support questions related to your code breaking because of people's local runtime environment.

2) Next problem will be deploying updates, which is cumbersome + time consuming.

3) Then fixing code when something locally breaks + all installations stop working.

4) To resolve all these problems, I'd design this as a Website, rather than an Air App.

Then code will work in every browser by using https://modernizr.com (write one set of code for all past/current/future browsers) along with https://www.chartjs.org (output graphic rendering).
Code seems to be working for me.

Tip: When I run the code, I get some peak errors, so to provide more... headroom for high volume recordings...

Try setting the volume down to 90% of current, as this will lose some of the low volume changes, while preserving high volume changes, so the high volume "beats" will be much sharper (track better) during playback.
Yes, I saw that dithering clipping status message out of sox, too.

Thank you very much for your comments and advice. I'm already getting support questions (for free code). The math there isn't great.

Yes, I can see what you mean about distributing free applications ready for install. What's in it for me when I start getting e-mails every day? I understand where you are coming from with that, "AVOID AT ALL COSTS" distribution of executables.

The problem with what I'm doing is I'm Mastering really high quality 4K Blu-ray by starting with super high resolution uncompressed images and outputting as uncompressed BMP still frames. So just for one little 5 minute music video it uses up like 400 GB of disc space in uncompressed format. Of course, I eventually encode that to h.264 at 45 Mbps which is on the low bitrates of 4K Blu-ray, so the final .MP4 video for a 5 minute video may be multiple GIGS. Makes the website-only option (on my budget) less possible. So there is no way I'd be able to do this as a website with those kinds of storage and processing requirements.

In Air, it is EXTREMELY SLOW when applying the 3D PixelBender effect with the MP3 amplitudes. Like 10 seconds per frame. Really ridiculously slow. The PixelBender 3D doesn't use hardware acceleration so it's totally software-based. It has to perform 3D calculations on every pixel, with different parameters in each frame. It takes seconds to apply this 3D effect. I don't mind because I am extremely patient. I just set it up and leave it alone for 2 days. But other people are going to be frustrated with that kind of speed.

Those two PixelBender filters have all the math required for the radial kaleidoscope and the spherize filter. It would be cool if that could be converted to C++ and use parallel GPUs. I don't have the skills to do that but maybe I can spell it all out and maybe create a user interface in C# and just try to get some DLLs custom made for the PixelBender functions. Then it would output multiple frames a second and you wouldn't be waiting for Adobe Air.

I could design a user interface and spell out the functionality, but other people would have to do the programming, I think.

Do you know of any organized Open Source communities that take on projects like this? I'd like to find something like Source Forge that is reputable and NOT spammy. This is a fun TOTAL AUTOMATION project.
ASKER CERTIFIED SOLUTION
Avatar of David Favor
David Favor
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Unsure where you might find someone to do this work for free.
User generated image

This is the currency. This is my job. I get to PLAY the FOOL for a living. I have been legally adjudicated as severely mentally ill. I cannot legally own a gun. I CAN LEGALLY BUY WEED and PUBLISH my GPS COORDINATES ONLINE. I'm a TOTALLY OPEN and TRANSPARENT totally INSANE drug addict on Social Security Disability.

That sounds great. Thanks for the honest feedback. I can't do it myself. It sounds like a project for a team. I don't need to make money on it, but I'd like to be able to afford scalable EC2-with-GPUs for the team.

http://www.FreeWorldBank.org

http://www.FreeWorldBank.org/#DROID_Ken

It's totally OPEN SOURCE.

I'm losing an upper left molar due to poor oral hygiene. It's critical for chewing. My dentist says it requires extraction. It has already had a root canal that got infected at the top of the roots. That left very little bone matter, so I will require an implant with bone grafts.

My oral surgeon, today, told me he could possibly do it all in one visit, if he doesn't need to the do the bone grafts. It takes about an hour under general anesthesia. It feels like about 10 seconds.

For the whole thing, the bottom line, is $6,440. I told him that I don't have any out-of-network dental insurance and that this was coming out of pocket. I asked him to lower his prices. He refused. That is $500/month from me (Social Security Disability) to pay back my mother who fronted me the money from her savings.

User generated imageUser generated image

So much for the new roof on the house after she dies. I cannot afford to stay in this house after she dies on my Social Security Disability alone. She breaks even every month. Boeing lifetime pension. Retirement. Social Security. Space and defense. A lot of NASA and a lot of NRO. We love scientists around here. We loved IUS. We don't care much for F-22 and P-3A. Very ABUSIVE and TRAUMATIC, almost as if by design. Totally fucked-up on purpose. VERY CRUEL and VERY MEAN office politics in a VERY CORRUPT defense environment. PTSD on purpose. We TOOK OUT the DEFENSE INDUSTRY WORLDWIDE.

Our house belongs to the Boeing Employees Credit Union, conveniently located on a map of my GPS COORDINATES that I share on these websites.

So we'll talk about it.

I'm getting a weird TOTALLY UNDOCUMENTED error with my new SSL.com code-signing certificate. My certificate chain is correctly installed in windows. The certificate checks out when I test it. But when I try to use it to sign my Adobe Air application, I get an UNDOCUMENTED error.

User generated image
User generated image
S:\___Video Kaleidoscope3840x2160>make


S:\___Video Kaleidoscope3840x2160>adt -package -storetype PKCS12 -storepass {my_password} -keystore s:\colortrips.pfx -keypass {my_password}  -tsa "http://sha256timestamp.ws.symantec.com/sha256/timestamp" -target air VideoKaleidoscope3840x2160.air VideoKaleidoscope3840x2160.airi
Extension of the wrong type


S:\___Video Kaleidoscope3840x2160>

Open in new window

When I use a self-signed certificate, everything works great. So the certificate works great in Windows, but it generates an undocumented error in Flash and won't compile the signed Air Application. Just enter the Flash error message in quotes. Three separate phrases, "Error creating files", "Could not sign the AIR file" and "Extension of the wrong type". THIS is a TOTALLY UNDOCUMENTED ERROR.

https://www.google.com/search?q=%22Error+creating+files%22+%22Could+not+sign+the+AIR+file%22+%22Extension+of+the+wrong+type%22

User generated image

Pretend this this is a CYBERSECURITY WAR GAME. They sent me to college to learn the language. But that doesn't mean I have to do the work. This is SUPERINTELLIGENT ARTIFICIAL GENERAL INTELLIGENCE in the PRIVATE SECTOR.


Best to open a new question, as this is a new topic.

And... keep in mind Flash is completely dead + gone now, never to return.

As I recall, Air produces Flash code, so unless Air is retooled to product HTML5 code, Air is also dead, as no Flash produced by Air can run anywhere anymore.

The Flash Death Date - December 31, 2020.

RIP...
Thanks again, David. I'll open a new question for the Air signing certificate. I appreciate very much that you continued to communicate with me AFTER all of my TOTALLY INAPPROPRIATE and POLITICALLY INCORRECT over-sharing.

I know Flash is dead and past end of life. That's why I open sourced this now. I've been keeping my powder dry so far. I released this NOW because Flash is dead. I'm TOTAL OPEN and TRANSPARENT and OPEN SOURCE but it was my feeling that this knowledge should be kept secret until now because it's a form of HYPNOSIS and there are a LOT of QUACK HYPNOTISTS. Programmers, Digital Artists, Animators and Scientists know how to do this, but LAYPEOPLE DO NOT. Now we are opening this art up to LAYPEOPLE.

https://www.YouTube.com/HDCOLORS

http://www.hdcolors.com

http://www.hdcolors.com/#tutorial

You're welcome!