UPDATE: After some great comments, I have optimized the performance of this script and made some brief commentary available here. I have also updated any source code links below to the new github project page.
I don’t quite know what gave me the desire to ever generate audio (specifically MP3) waveforms with PHP — it’s not something I’ll likely ever use — but after doing some research and coming up a bit short I decided to make it happen.
A few days of Googling, I did come up with a couple solutions but none seemed to really produce the results I wanted. All I was looking to generate was a simple waveform like that in Cubase or other recording software. I don’t need axis labels or left/right audio splits, just a simple mono waveform from an MP3. I also didn’t want to go through hundreds of audio files and convert them into WAV files just to do this — if I was going to do this as an experiment, I wanted it on the fly. I did come across some interesting links though:
The Sound eXchange (SoX) audio tool kit has a lot of great features that might come in handy later on, including audio effects, but support for MP3 wasn’t built-in and seemed a bit too much work to bother compiling just for a side experiment. SoX can generate spectrograms, but this wasn’t particularly what I was looking for.
I did find this classAudioFile.php, which does support generating waveforms from WAV files, but this seemed a bit more hefty than I really needed — and not as accomplishing as doing it myself. That being said, and though I never bothered testing it out, it does seem (based on the code) to create a simple waveform image that I was aiming to create.
Ultimately, I wanted something flexible: upload MP3s files without pre-converting them, adjust size of the image easily, and change foreground and background colours. The key that makes my script different, and most flexible, is converting the files to WAV on the fly. Though this is time consuming, it’s ultimately a lot easier than batch processing them on my computer first.
The key to making this convenient has been using the LAME MP3 encoder/decoder through the command line (on Windows for my script, I haven’t yet tested with any flavour of Linux). I simply downloaded a windows build of LAME, threw the executable into my script directory and ran the following command:
lame original_file.mp3 -f -m m -b 16 --resample 8 resampled.mp3 && lame --decode resampled.mp3 final_file_for_processing.wav
Because you don’t really need a high quality audio file for generating a waveform, this set of commands will resample the original MP3 to a 16 bit, 8 KHz, mono MP3 file and then turn that into a WAV file for processing the image from. Processing does take some time, but it’s significantly faster than processing a huge 40+ MB WAV file from the start. Also, no amount of research showed a way to directly downsample an MP3 straight to a WAV file, hence the intermediary step.
After that, I used an algorithm I found on the DevShed forums for processing 16 bit WAV files, and used the data it generates to create the waveform (which, ultimately, is pretty simple).
If this is something you have a use for, feel free to use it as you wish and give credit where it’s due (see the source comments for where I pulled some code snippets from to make this work). You may want to fix it up a bit for better error checking and so forth though.
A note of warning: it’s not fast. Far from it. A couple basic tests showed anywhere between 10-30+ seconds to generate the waveforms for an average sized MP3 (decent quality, 2-4 minutes in length). If you will be generating and re-generating waveforms multiple times for the same audio file, you may want to cache the WAV data in a database for future use, as using that data to create the image itself is comparatively quite quick.
I may use this, along with the SoX library, later on to create — simply for fun and discovery — an online audio mixer/editor similar to Cubase, which I’ve been working with quite a lot lately. This would be a great way to create a new web-based interface with a lot of widgets and controls not commonly used, as well as using SoX to add audio effects, mix, combine files, in a multi-layered audio interface. I’ll see if I ever get around to this however.
Environment tested in, your results may vary:
- Windows Server 2003
- PHP 5.2.10
- LAME 3.98.4
I’ve been so kind as to release this code under the Apache License v2.0, which means you’re more than welcome to use, distribute, and modify this code as long as you follow the terms of the license (which includes keeping the license with the modified source code).
This is by far my most popular blog entry — and thus I can assume the most desired piece of code that I’ve so far provided. If this code has been useful to you, and if you can find it in your heart, please donate a dollar or two. If you can buy me a coffee I’d be eternally grateful. Below is a donate button for my PayPal account.