If you’ve used our API before, you’ll know that each track resource contains a
waveform_url that points to a 1800 x 280 pixel PNG of that particular sound. The classic way of coloring this image was to not color it at all. Instead, you would simply stack it on top of two or three absolutely positioned DIVs whose size was adjusted given the loading or playing state of that sound.
So, what’s wrong with this technique? Well, you can’t adjust the outer color of the waveform image. So unless the area around the waveform is #E5E5E5, things are going to look subpar.
I saw the future, and it was Webkit
Webkit browsers can overcome the outer color issue with a new css function called webkit-mask-box-image. This function colors a div to the shape of a provided mask. In this case, our waveform image. Check out the example below:
It’s simple to code and damn powerful. You can combine this function with the element stacking technique above to generate nice waveforms in most environments. But what about non-webkit browsers? HTML 5 to the rescue!
Canvas adoption is rapidly increasing and for good reason - it fucking rules. With
However, there is one caveat: the Cross-Domain Origin Policy. If you’ve developed with
canvas before, you know that accessing and manipulating images from different domains or origins is prohibited.  But, we can get around this by accessing the image via the server, and I wrote a service that does exactly that.
Wave64 exists as an endpoint you pass a SoundCloud
waveform_url to from the client. It will then read that image on the server and return a Base64 encoded text blob  which can be manipulated by
canvas. I combined this endpoint with some jQuery and wrote the $.wave64 plugin which takes a waveform url, height, width, and color and returns the colored waveform.
Problem solved? Never. Programming is a math problem you can only make harder on yourself, and as such Johannes and I sought out to simplify this even more.
Damn Good Waveforms - Eric Wahlforss, CTO of SoundCloud
Johannes had the bright idea to analyze the waveform image’s peaks and store their values in an array of floating points. HUH..? Take a look at the image below:
If every column was considered a point, it’s value would be a floating decimal from 0 to 1 depending on it’s height. So, we wrote a basic server-side script using RMagick to analyze the columns, convert them into 1800 floating points, and cache the result.
Don’t believe me? Here’s Forss - Flickermood.
canvas generated (and interpolated) waveform. Simply provide the container where it will live, an innerColor &&|| outerColor, and the provided waveform data array. Like so:
Psyched? Yeh, me too. And, not only can you pass colors to the inner and outer color, you can also provide functions. Check out a few examples of this technique on waveformjs.org, including the ability to render both the loading and playing progress right into a single Waveform.
Probably not. It would rock if the SoundCloud API provided the waveform array data right from the API so we wouldn’t even need the endpoint. I’ll keep complaining internally until this happens.
 However, there are a few workarounds.
 Thanks to Max Novakovic for the technique.