[chuck-users] Granular synthesis in ChucK (was: Re: [livecode] granular music recommendations?)

Kassen signal.automatique at gmail.com
Thu May 22 23:37:22 EDT 2008


2008/5/22 AlgoMantra <algomantra at gmail.com>:

> I'm not 100% sure I understand the concept of
>> granular synthesis, and I can't afford a book right now, so I'm asking
>> if you guys got an example/demo of the technique which I could study
>> (preferably in ChucK)?
>>
>
> I would lurrrv an example in Chuck too!
>

Ok, pasted below is a small ChucktudE in grains and blitsaw. First it
synthesises a theme, then it uses grains to manipulate the theme..... Well,
that was the plan. The result is more like "first it synthesises a theme,
then does stuff with it and a ending is bolted on because I got a bit bored
with it and grains are hard to use on themes". :¬)

Still, it demonstrates a few nice tricks with grains and it's a start for
exploration, I hope. I also strongly suspect that requesting and using
voices from LiSa too quickly (a few hundred per second) will crash the whole
VM. Badly. These crashes may also have been caused by some other factor,
there are quite a few variables flying around, after all. Uses some tricks
with time and timing which could be eductational and/or confusing.

==================================
//"A night with LiSa", composed by Kassen
//permision granted to copy for fun and educational value
//No waranties, no refunds; mind your speakers and CPU
//remixing and extending strongly encouraged
<<<"let's pretend we're Bach and base the theme on a name!", "">>>;
float G, E;

43 => Std.mtof => G;
52 => Std.mtof => E;

BlitSaw s => Gain amp => dac;
.8=> s.gain;

dac => LiSa l => dac;
4::second => l.duration;
1 => l.record;

3=> s.harmonics;
3 => amp.op;
SinOsc lfo => amp;
second => lfo.period;


G => s.freq;
second => now;

//use the LFO to cover up clicks in the sound
.25::second => lfo.period;
repeat(8)
    {
    s.harmonics() + 2 => s.harmonics;
    .125::second  => now;
    }


.5::second => lfo.period;

for (0 => int n; n< 4; n++)
    {
    s.harmonics() -3  => s.harmonics;
    if (n%2) G => s.freq;
    else E => s.freq;
    .25::second  => now;
    }
5 => s.harmonics;
2::second => lfo.period;
1::second => now;

//stop recording, disconect blitsaw
0 => l.record;
amp =< dac;



<<<"Now we use simple granualtion to repeat the theme a octave down", "">>>;

100 => int slices;
(l.duration() / slices) / 2 => dur ramprate;
l.rate(0, .5);
l.rate(1, .5);
for (0 => int n; n<slices*2; n++)
    {
    //as one voice ramps up...
    l.rampUp(n%2, ramprate);
    l.playPos(n%2, 0.005 * n * l.duration() );

    //...the other goes down
    l.rampDown(!(n%2), ramprate);
    ramprate => now;
    }

<<<"again, a octave up", "">>>;

l.rate(0, 2);
l.rate(1, 2);
for (0 => int n; n<slices*2; n++)
    {
    l.rampUp(n%2, ramprate);
    l.playPos(n%2, 0.005 * n * l.duration() );
    l.rampDown(!(n%2), ramprate);
    ramprate => now;
    }
l.rampDown(!(slices%2), 20::ms);

<<<"random grains, decreasing density", "">>>;

now + 4::second => time later;
l.rate(0, 1);
l.rate(1, 1);

int free_voice;
float time_past_ratio;
second / G => dur loop_length;
while (now < later)
    {
    (later-now) / 4::second => time_past_ratio;
    //this goes from a chance of "1" to no chance at all over the cource of
the note
    if ( Std.rand2f(0,1) < time_past_ratio)
        {
        l.getVoice() => free_voice;
        l.loopStart(free_voice, Std.rand2f(0, 1) * (l.duration() -
loop_length));
        l.playPos(free_voice, l.loopStart(free_voice) );
        l.loopEnd(free_voice, l.loopStart(free_voice) + loop_length);
        l.rate(free_voice, Std.rand2(1, 2)/ Std.rand2(1, 2));
        l.rampUp(free_voice, loop_length);
        loop_length => now;
        l.rampDown(free_voice, 75::ms);
        loop_length => now;
        }
    else 2::loop_length => now;
    }

//never mind this bit
//it's just here to end "properly"
l.getVoice() => free_voice;
l.rate(free_voice, .5);
l.loop(free_voice, 0);
l.playPos(free_voice, 0::ms);
l.play(free_voice, 1);

<<<"increase it again","">>>;
2::second / E => loop_length;
now + 4::second => later;
while (now < later)
    {
    (later-now) / 4::second => time_past_ratio;
    if ( Std.rand2f(0,1) < 1-time_past_ratio)
        {
        l.getVoice() => free_voice;
        l.loopStart(free_voice, Std.rand2f(0, 1) * (l.duration() -
loop_length));
        l.playPos(free_voice, l.loopStart(free_voice) );
        l.loopEnd(free_voice, l.loopStart(free_voice) + loop_length);
        l.rate(free_voice, Std.rand2(1, 4)/ Std.rand2(1, 4));
        l.rampUp(free_voice, loop_length);
        loop_length => now;
        l.rampDown(free_voice, 75::ms);
        loop_length => now;
        }
    else 2::loop_length => now;
    }

<<<"cheat because endings are hard", "">>>;

 5::second => now;
====================================

Cheers,
Kas.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.cs.princeton.edu/pipermail/chuck-users/attachments/20080523/e5baa6f8/attachment.html>


More information about the chuck-users mailing list