August 4, 2009

but what does it SOUND like?

Filed under: chuck — aturley @ 7:59 pm

A while back I saw a post about visualizing sorting algorithms. But what do they sound like? I put together a quick Chuck script that does a bubble sort of a list of integers. Each time it compares two values it first converts the values from a MIDI note value to a frequency and then plays two tones with those frequencies.

// what does a bubble sort sound like?

10 => int noteCount;
if (me.args() == 1)
  me.arg(0) => Std.atoi => noteCount;

SqrOsc osc1 => ADSR adsr => Gain g => dac;
SqrOsc osc2 => adsr;

0.5 => g.gain;

// create the unsorted array of MIDI notes

int notes[noteCount];

for (int i; i < noteCount; i++) {
  Std.rand2(40, 90) => notes[i];
 }

fun void bubbleSort(int l[])
{
  for (int i; i < l.cap(); i++) {
    for (int j; j < l.cap() - i - 1; j++) {
      l[j] => Std.mtof => osc1.freq;
      l[j + 1] => Std.mtof => osc2.freq;

      adsr.keyOn();
      0.2::second => now;
      adsr.keyOff();
      if (l[j] > l[j + 1]) {
	l[j + 1] => int temp;
	l[j] => l[j + 1];
	temp => l[j];
      }
    }
  }
}

bubbleSort(notes);

The sound is kind of fun, and because of the way bubble sort works, you end up with some structures that repeat. You might almost call it musical.

Going a little further with the idea of playing the output of a sort, I began to wonder if I could maybe be lazy and just use sorting algorithms that have already been implemented. Most sorting algorithms work by comparing two elements and rearranging them depending on which one is larger. If you are comparing numbers, the criteria for “larger” is fairly well understood. But if you are trying to sort by, oh, let’s say an employee id, and the id is some collection of numbers and letters, and those numbers and letters may mean something special to the way they are sorted, then you want to be able to specify what “larger” actually means. The qsort() function in the C standard library takes a comparison function as an argument. This function knows how to compare two elements in the list that is passed as one of the other arguments to qsort(). That way qsort() doesn’t have to know anything about the elements it is sorting. In Java, there is an interface called Comparable. Objects that implement this interface must provide a method called compareTo() that knows how to compare itself to another object. Each time a sorting function needs to compare one item to another, it uses this compareTo() method.

Can we hijack compareTo()? You bet. Here’s a simple class that implements compareTo():

class Buzz implements Comparable {
    int val;
    public int compareTo(Buzz b) {
	return b.val - this.val;
    }
}

What if, in addition to returning the difference between the two values we also sent the values out of the program to another program that would do something with them? Well, thanks to an OSC library called JavaOSC we can do this fairly easily.

I put together a Groovy program that creates a list of objects that implement Comparable and then sorts the list. Their compareTo() method sends OSC messages to the local host (127.0.0.1) on port 6767. These OSC messages specify which numbers are being compared.

import com.illposed.osc.OSCPortOut;
import com.illposed.osc.OSCMessage;
import java.net.InetAddress;
import java.util.Random;

class Buzz implements Comparable {
    int val;
    OSCPortOut sender;
    public int compareTo(Buzz b) {
	Object[] args = [new Integer(b.val), new Integer(this.val)];
	OSCMessage msg = new OSCMessage("/comparing", args);
	this.sender.send(msg);
	sleep(200);
	return b.val - this.val;
    }
}

OSCPortOut sender = new OSCPortOut(InetAddress.getByName("127.0.0.1"), 6767);

list = [];
rand = new Random();
20.times {
    list << new Buzz(val: 40 + rand.nextInt(51), sender: sender);
}
list.sort();

And here's a Chuck program that listens for the messages and plays the notes

OscRecv recv;
6767 => recv.port;
recv.listen();

recv.event( "/comparing,ii" ) @=> OscEvent oe;

SqrOsc osc1 => ADSR adsr => Gain g => dac;
SqrOsc osc2 => adsr;

0.5 => g.gain;
0.1::second => adsr.attackTime;
0.1::second => adsr.decayTime;
0 => adsr.sustainLevel;

adsr.keyOff();

while ( oe => now ) {
  while ( oe.nextMsg() != 0 ) { 
    adsr.keyOn();
    oe.getInt() => int m1;
    oe.getInt() => int m2;
    <<<"comparing", m1, m2>>>;
    m1 => Std.mtof => osc1.freq;
    m2 => Std.mtof => osc2.freq;
  }
 }

I think the default list sorting algorithm in Java is a quicksort (edit: actually it looks like it is a mergesort, and it may be replaced in the future by timsort), but you can probably find others. And if you can't find anything, you can always write your own. Once you have a sorting algorithm that accepts a collection of Comparable objects, you can use the code I've provided to listen to it.

Update:

Ryan Compton did something similar at UCLA, and he also has graphs to show you what's going on.

12 Comments »

  1. You realize this is going to start up a viral music genre of programmers who try and come up with sequences to recreate actual songs don’t you?

    Comment by slide — August 11, 2009 @ 11:15 am

  2. This sounds really cool. More audio samples please!

    Comment by Rich — August 11, 2009 @ 12:01 pm

  3. [...] This post was Twitted by skravec [...]

    Pingback by Twitted by skravec — August 11, 2009 @ 12:13 pm

  4. I did the same kind of thing with a Minimax search, so you can hear what a computer chess engine is “thinking”.

    http://www.krazydad.com/blog/2009/05/21/musical-chess/

    Comment by Jim Bumgardner — August 11, 2009 @ 2:00 pm

  5. for some reason I now have 8 bit zelda theme in my head!

    Comment by Joshn — August 11, 2009 @ 4:51 pm

  6. I happened to listen to that while also watching a time-scrolling audio spectrum. You can see the sort!

    Comment by Burton MacKenZie — August 11, 2009 @ 5:00 pm

  7. I love this idea. Great, great. Thanks!

    Comment by Joe — August 11, 2009 @ 7:30 pm

  8. You could also sort n random values, making each iteration conform to one waveform (each number is one sample).

    For each iteration, write all the numbers to a byte stream. Then prefix the appropriate .wav or other fileheader.

    The sorting process would go from white noise to a clear sawtooth shape, with intermediate stages exhibiting different kinds of overtones, indicating whether the ordering is currently mostly local or global.

    Comment by Arne D H — August 11, 2009 @ 11:50 pm

  9. Amazing. Would be cool show also the sound of others sort algorithms.

    Comment by Silveira Neto — August 12, 2009 @ 1:45 am

  10. Very, very cool man!

    Comment by cod3fr3ak — August 12, 2009 @ 3:01 am

  11. [...] Chuck writes – A while back I saw a post about visualizing sorting algorithms. But what do they sound like? I put together a quick Chuck script that does a bubble sort of a list of integers. Each time it compares two values it first converts the values from a MIDI note value to a frequency and then plays two tones with those frequencies. [...]

    Pingback by What does a sorting algorithm SOUND like? « adafruit industries blog — August 12, 2009 @ 8:20 pm

  12. I remember a piece of music, way back in the day (say c1982) that was three solutions to the Towers of Hanoi running at different speeds. Different aspects of the model space were mapped onto pitch, timbre, attack, and decay values which drove a synthesizer. I suppose if I weren’t so old and lazy I could go and try to find it on the Web…but I am old and lazy.

    Comment by drbcladd — August 13, 2009 @ 5:32 am

RSS feed for comments on this post. TrackBack URL

Leave a comment

Powered by WordPress

On this site: