Yes! Shakers are great for this.
The following simple example uses a set of parallel shakers. Each is playing a random harmonic of the current note and is retriggered after a amount of time that's a sub-harmonic of the current pitch. The result is a sort of random-ish noise that still conveys a hint of melody. I added some volume modulation to spice it up. To demonstrate how different sounds can still get a perception of pitch across the sounds used are randomised every time the code is run.
No waranties, no refunds.
Please copy, please remix.
====================
8 => int grains;
64 => int root;
root => int note;
[0, 3, 9, 5, 7] @=> int melody[];
//a different sound every time we play it!
Std.rand2(0,22) => int offset;
now => time start;
repeat(grains) spork ~synth();
me.yield();
while(1)
{
for ( 0=> int n; n < melody.cap(); n++)
{
root + melody[n] => note;
4::second => now;
}
}
fun void synth()
{
Shakers s => dac;
me.id() + offset => s.preset;
while(9)
{
//the "*1.0" is just to force the fraction into becoming a float
Std.mtof(note) * ( (Std.rand2(1,3)* 1.0) / Std.rand2(1, 2) )=> s.freq;
//add volume modulation
s.noteOn( ((now - start)% second) /second);
//the time betwee triggers affects the perception of pitch
Std.rand2(8, 16)::second / Std.mtof(note) => now;
}
}