or

How I gave my code fixes to BBC

Introduction

I am working on a larger project, wherein I needed to visualise audio waveforms. Surprisingly, there are not that many programs able to do this. Even the Swiss Army Knife for all things audio, SoX, plots only spectrograms and no waveforms.

But, because I chose the JavaScript library Peaks.js (developed at BBC) to plot waveforms in browser, I quickly found out that there is a utility called audiowaveform from the same authors, which converts audio file to data files, which Peaks.js uses as an input.

There was just one little problem: there were no Windows binaries for audiowaveform available, there was even a related GitHub issue.

So I sat down and put some effort into making audiowaveform compile. I never liked DLL hell, so I aimed at producing static binaries, both 32-bit and 64-bit. My earlier efforts to compile static Windows binaries for tools like tshark, make, sed and sox helped here immensely.

Actually, I achieved what aimed at, on two different ways.

First way of compilation

The first way of compilation uses Docker. The compilation tools are here. You can read more about the setup in the README.md file.

In short: The Dockerfile compiles all dependencies (meaning: iconv, zlib, libmad, libid3tag, libogg, libvorbis, flac, libsndfile, libpng, libimagequant, freetype2, expat, fontconfig, libgd and parts of boost) as static MinGW libraries, and then compiles audiowaveform for Win32. Then the directories are cleaned and another binaries for Win64 are recompiled. All resulting binaries, as well as .h and .a files, are compressed to ZIP archives, as Windows can unpack them without using external tool, and copied to the host system using the docker cp command. Executing the script

./compile_audiowaveform.sh

automates the whole process.

Second way of compilation

There is a MinGW cross-compilation environment for free libraries called MXE. It is simple (essentially, a single Makefile), well-maintained (here) and contains all (mentioned previously) dependencies already, so it was a natural choice.

The script (as well as the patch) for compilation using MXE also reside in this repository. Just copy both files to the machine with MXE and execute the script

./compile_audiowaveform_mxe.sh

Specify the path of MXE in the environment variable MXE and the amount of parallel jobs in the variable JOBS. So, compile audiowaveform with dependencies using MXE in the directory /opt/mxe on a quad-core CPU with command

MXE=/opt/mxe JOBS=4 ./compile_audiowaveform_mxe.sh

After a while (because MXE compiles all parts of boost, additionally to the required ones) you will have two static Windows binaries, audiowaveform-win32.exe and audiowaveform-win64.exe, in the same directory as the script.

Results

We have now two ways to compile audiowaveform: through Docker or through MXE. Both ways yield both Win32 and Win64 binaries.

The single compilation problem fixed was the difference between filename container types — std::string on POSIX and std::wstring on Windows. After testing both ways of compilation, I contacted the main developer of audiowaveform, Chris Needham, and asked him about merging my code into the main repository. His reaction was very affirming, hence I made a pull request, and he merged it.

The BBC has my code fixes. I am positively excited.