svg tag + audio tag = 3D Waveform

November 9th 2009



As always, you just need a bit of practice with a language to start using it in nice ways. Now that I had that little 3D engine working and with the <audio> around, it was time to produce an idea I always had in mine. A 3D interpretation of a waveform.

I'm sure the first thing you would think after checking this experiment would be... What? I didn't know I could analyse the sound signal with the <audio> tag?! ... Well, you can't, if you check the source code (*hint* right click -> view source) you'll see an array of numbers (deltas in fact). These are all the sound level values of the waveform at 30 fps.

I got these values using the library BASS for linux. Unfortunately, my C skills aren't so good (example) and I can't seem to control how to get the values exactly at the fps I want without getting desyncronisations. The first part of the visualisation is spot on, but by the end things aren't that impressive. I'll keep researching on this and update a new array of values whenever I crack it.

Dean McNamee showed me the way. Forget C and BASS. All you need is python, the tune in .wav and 23 lines of magic.

import math
import struct
import wave
import sys

w = wave.open(sys.argv[1], 'rb')
# We assume 44.1k @ 16-bit, can test with getframerate() and getsampwidth().
sum = 0
value = 0;
delta = 0;
amps = [ ]

for i in xrange(0, w.getnframes()):
	# Assume stereo, mix the channels.
	data = struct.unpack('<hh', w.readframes(1))
	sum += (data[0]*data[0] + data[1]*data[1]) / 2
	# 44100 / 30 = 1470
	if (i != 0 and (i % 1470) == 0):
		value = int(math.sqrt(sum / 1470.0) / 10)
		amps.append(value - delta)
		delta = value
		sum = 0

print amps

I've updated the experiment with the new values; now is perfectly in sync all the time. Which makes you appreciate the little sounds at the end much more. Thanks Dean!

As you'll see on the source code, the rest is very simple. Create a couple of cubes, place them one in from on each other, and modify their scaleY depending on the waveform they are related to in that step.

The end result is quite interesting I think and I hope doing more like these. Hopefully more interactive next time.

The factor that turned this from just a nice experiment to an awesome was the fact that the eedl guys allowed me to use their (great) tunes for my experimentation.

Thanks once again!
11 comments written so far...

Hi!
It exist an other solution: using video part for audio spectrum data
http://www.tapper-ware.net/devel/js/JS.VideoViz/index.xhtml

;)
November 9th 2009
Mem's
Uh, how do you make that work? I've tried on Firefox/Chrome/Chromium and the visualisation box is always empty, music plays tho.
November 9th 2009
mr.doob
Cool experiment!
November 9th 2009
Nicolas
I heard EchoNest works fairly well for sound analysis stuff, you can submit your track online and get back an xml file of the sound data. Might fix your framerate issue, no need for C !
http://www.echonest.com

- Karl
November 9th 2009
KC
Nah, it is easier than that. Someone has already told me the proper way (python + .wav). Will update later.
November 9th 2009
mr.doob
@mr.doob: That work on my FF3.5.5 (PC & Mac), but not on webkit (maybe not supported yet)

https://developer.mozilla.org/En/manipulating_video_using_canvas
November 9th 2009
Mem's
Doesn't seem to work on FF3.5.4 (Linux) :(
November 9th 2009
mr.doob
get an error when trying to run the script:

Traceback (most recent call last):
File "/Users/elkraneo/Desktop/test_wav/output.py", line 6, in
w = wave.open(sys.argv[1], 'rb')
IndexError: list index out of range

macosx Python 2.6.4 ...any idea ?
December 16th 2009
elkraneo
Uh, no idea to be honest. Maybe you're not using it properly... I use it like this... python script.py audio.wav > output.txt
December 16th 2009
mr.doob
thx, tried that way and get
File "output.py", line 15, in
data = struct.unpack(' struct.error: unpack requires a string argument of length 4

:(...checking the encoding of the .wav
December 17th 2009
elkraneo
i get the same error elkraneo gets:

Traceback (most recent call last):
File "/Users/elkraneo/Desktop/test_wav/output.py", line 6, in
w = wave.open(sys.argv[1], 'rb')
IndexError: list index out of range

I believe this is because the audio file is not of correct format. Even if it is .wav, there are different ways wavs can be encoded.

mr doob, do you know of one that would work to decode mp3s or be more flexible in terms of getting the audio data for more input media types?
March 7th 2010
josh

Have your say!

Name:

Website:

Comment:

Some of the projects that I worked on.



Some of the HTML5 and Actionscript experiments I've done.