Question

I’m creating a web application that uses the SoundCloud API to stream tracks of artists. I know how I can get the waveform PNG image (http://w1.sndcdn.com/fxguEjG4ax6B_m.png for example), but I actually need some sort of wave-data (when in the song is it high and when is it low?).

I don’t have access to an audio library like LAME or something like that, because my web hosting doesn’t allow it. Is it possible to

  1. Get this data directly from the SoundCloud API in some way.
  2. Process the waveform PNG image in PHP or JavaScript to retrieve the needed data? (And is there maybe some sort of library available for this kind of processing?)
Was it helpful?

Solution

It's possible to parse the waveform PNG image to translate it to an array of points. The images are vertically symmetrical and to find the peaks you only need to inspect the alpha values to count how many opaque pixels it is from the top of the image. This is how the waveforms are rendered for the widget and on the Next SoundCloud.

In PHP, you could use ImageMagick or the GD Graphics Library to read these values, and in Javascript, it's possible by putting the image onto a canvas object and then inspecting the image data from there. I won't go too much into the details of these, but you could certainly ask another question if you get stuck.

OTHER TIPS

Soundcloud starts to provide the floating points but it’s not official yet. Just a little trick, when you have your PNG:

https://w1.sndcdn.com/XwA2iPEIVF8z_m.png

Change "w1" by "wis" and "png" by "json":

https://wis.sndcdn.com/XwA2iPEIVF8z_m.json

And you get it!

While there is no official way to get the raw waveform data directly from a SoundCloud API request, there is a way to derive the exact same data SoundCloud reveals in the unofficial endpoint (aka: Something like https://wis.sndcdn.com/XwA2iPEIVF8z_m.json) in PHP using this code like this. Simply change the value of $image_file to match whatever SoundCloud 1800 wide by 280 high PNG image you have and you are good to go:

$source_width = 1800;
$source_height = 140;
$image_file = 'https://w1.sndcdn.com/XwA2iPEIVF8z_m.png';
$image_processed = imagecreatefrompng($image_file);
imagealphablending($image_processed, true);
imagesavealpha($image_processed, true);

$waveform_data = array();

for ($width = 0; $width < $source_width; $width++) {

  for ($height = 0; $height < $source_height; $height++) {

    $color_index = @imagecolorat($image_processed, $width, $height);

    // Determine the colors—and alpha—of the pixels like this.
    $rgb_array = imagecolorsforindex($image_processed, $color_index);

    // Peak detection is based on matching a transparent PNG value.
    $match_color_index = array(0, 0, 0, 127);
    $diff_value = array_diff($match_color_index, array_values($rgb_array));
    if (empty($diff_value)) {
      break;
    }

  } // $height loop.

  // Value is based on the delta between the actual height versus detected height.
  $waveform_data[] = $source_height - $height;

} // $width loop.

// Dump the waveform data array to check the values.
echo '<pre>';
print_r($waveform_data);
echo '</pre>';

The benefit of this method is while that https://wis.sndcdn.com/ URL is useful, there is no telling if/when SoundCloud would change the structure of the data coming from it. Deriving the data from the official waveform PNG offers some long term stability since they are not just going to change that PNG image without fair warning to SoundCloud API end users.

Also, note that while the $source_width is 1800 the $source_height is 140 because while the SoundCloud PNG file is 280 pixels high, the bottom half is basically just a flipped/mirrored copy of the top half. So just measuring the values from 0 to 150 will give you the necessary waveform data values.

Sorry to bump an old thread - just in case you are looking for something similar and stumbles across this post: This is now possible as per this link: Waveforms, Let's Talk About Them.

It was published shortly after this thread - so again apologies for bumping an old one.

I'm sorry, but there is no API for that sort of stuff. On soundcloud, the waveform is generated on upload and the data thrown out.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top