Cast my first SuperCollider spell today. The code below spat out an .aiff file. This blogging platform may not allow me to embed that here in a straightforward manner so used VLC to convert it to an .mp3 file (which is what this 2 second clip is).
(
/* 34567890123456789012345678901234567890123456789012345678901234567890123456789
h (h for Hanoi) is a 4 parameter function. f, t and u are are the names of 3
pegs. when h is not called by itself there are n > 0 discs (each of a different
size) on peg f and 0 discs on the other two pegs.
h returns a series of moves such that at the end of the series all the discs
have been shifted from peg f (f for From) to peg t (f for To). during the series
some of the discs may temporarily be shifted to peg u (u for Using).
each move consists of a single disc being moved from peg f to peg t. at no point
is a disc placed on top of a disc of a smaller size. when displaying a move we
don't display the size of the disc being moved (as it doesn't effect the series)
m is a function which moves a single disc from peg f to peg t. a move is
displayed as a pair of sine wave oscillators playing for two seconds. the peg
form which the disc is being removed has its frequency decrease from 100 Hz
above its label to 100 Hz bellow while its amplitude decreases to zero. the
inverse happens for the peg onto which the disc is being moved.
as written all the moves play concurrently, making the solution
incomprehensible. the last line shows the author hasn't understood
SuperCollider's Client vs Server architecture
*/
s.boot;
h = {|n f t u| // tower of hanoi algorithm
if (n > 1,{
h.value(n - 1, f, u, t); // move all but the lowest disc from f to u
h.value(1, f, t, u); // move the lowest disc from f to t
h.value(n - 1, u, t, f); // move all the discs earlier moved to u to t
},{ m.value(f, t);// else move a single disc from f to t
})};
m ={|f t| // sound algorithm
//(f.asString ++ " -> " ++ t.asString).postln; // textual debugging hanoi
// if you delete the rest of this function and un-comment the previous line
// a 'correct solution' is printed.
{[SinOsc.ar( // 1 of 2 channels, increasing frequency and volume
freq:Line.kr(start:t-100, end:t+100, dur:2, doneAction:2),
mul:Line.kr(start:0, end:1, dur:2, doneAction:2)
),SinOsc.ar( // 2 of 2 channels, decreasing frequency and volume
freq:Line.kr(start:f+100, end:f-100, dur:2, doneAction:2),
mul:Line.kr(start:1, end:0, dur:2, doneAction:2)
)]}.play;
while ({s.numSynths != 0;},{2.wait;}); // a pair of conceptual errors
};
s.record;
h.value(1, 600, 1200, 1800);
s.stopRecording;
)
