int bline[]; 0 => int pos; 0 => int count; while ( true ) { drm.hh(); if ( count % 2 == 0 ) { drm.bd(); } if ( count % 4 == 2 ) { drm.sn(); } if ( count % 2 == 0 ) { spork ~ bass.bass( bline[ pos % 4 ]); } if ( count % 2 == 1 ) { spork ~ bass.bass( 12 + bline[ pos % 4 ]); } 1 + count => count; if ( count % 4 == 0 ) { 1 + pos => pos; } 250::ms => now; } "/> int bline[]; 0 => int pos; 0 => int count; while ( true ) { drm.hh(); if ( count % 2 == 0 ) { drm.bd(); } if ( count % 4 == 2 ) { drm.sn(); } if ( count % 2 == 0 ) { spork ~ bass.bass( bline[ pos % 4 ]); } if ( count % 2 == 1 ) { spork ~ bass.bass( 12 + bline[ pos % 4 ]); } 1 + count => count; if ( count % 4 == 0 ) { 1 + pos => pos; } 250::ms => now; } "/>

modularizing chuck files

Nikolaus Gradwohl2009-01-17T13:11:00+01:00

I wrote a simple chuck script that generates a drum loop and a bass-sequence. later i wanted to reuse the sounds and started to search how to modularize the code.

so i started to convert my instrument declarations in classes. The instrument classes don't get connected to 'dac' directly. They have a "connect"-method that can be used by the main script.

to run the loop all the scripts must be given on the commandline

chuck Bass.ck DrumSet.ck loop.ck

The main script (loop.ck) instanciates a DrumSet and a Bass class and connects them to "dac". Than it generates a walking bass and a simple electronic drum loop.

DrumSet drm;
drm.connect( dac );

Bass bass;
bass.connect( dac );

[ 41, 41, 44, 46] @=> int bline[];
0 => int pos;
0 => int count;

while ( true ) {
    drm.hh();
    if ( count % 2 == 0 ) { drm.bd(); }
    if ( count % 4 == 2 ) { drm.sn(); }

    if ( count % 2 == 0 ) { spork ~ bass.bass( bline[ pos % 4 ]); }
    if ( count % 2 == 1 ) { spork ~ bass.bass( 12 + bline[ pos % 4 ]); }


    1 + count => count;
    if ( count % 4 == 0 ) { 1 + pos => pos; }
    250::ms => now;
}

In Bass.ck a simple saw-wave based electronic bass is declared. The notes are triggerd by the "bass"-method. The notes are all played the same length. Therefore this method must be called in a thread otherwise the main loop would wait for the notes to end.

spork ~ bass.bass( 40 )

playes the bass on midinote 40

public class Bass {
    // BASS
    SawOsc sb => LPF filt => ADSR a => Gain g2;
    440 => filt.freq;
    0.3 => filt.Q;
    0.0 => g2.gain;
    (10::ms, 45::ms, 0.5, 40::ms) => a.set; // Set ADSR envelope

    public void connect( UGen u ) {
        g2 => u;
    }

    public void bass( int tone ) {
        Std.mtof( tone ) =>  sb.freq;
        0.3 => g2.gain;
        1 => a.keyOn;
        125::ms => now;
        1=> a.keyOff;
    }
}

In DrumSet.ck three instruments get declared (a basedrum, a snare and a hihat) and each gets a method that can be used to trigger the sounds.

public class DrumSet {
    // define hihat
    Shakers hhs => JCRev r;
    .025 => r.mix;
    Std.mtof( 76 ) => hhs.freq;

    // Define Bassdrum
    SinOsc s => ADSR bda;
    80 => s.freq;
    (0::ms, 10::ms, 0.0, 0::ms ) => bda.set;

    // define snare drum
    Noise n => ADSR sna => Gain g => dac;
    0.3 => g.gain;
    (0::ms, 25::ms, 0.0, 0::ms) => sna.set;


    public void connect( UGen ugen ) {
        r => ugen;
        bda => ugen;
        g => ugen;
    }

    public void hh() {
        1 => hhs.noteOn;
    }

    public void bd() {
        1 => bda.keyOn;
    }

    public void sn() {
        1 => sna.keyOn;
    }
}
Tweet This! submit to reddit Digg!   Tags: | 1 comments | no trackbacks

See also:

music live-coding environments - my first impressions
volca ardour3 jam
how to create launchpad light effects with chuck
osc sequencer in ruby
Chuck iControl Projectpage

Trackbacks

Comments

Leave a response

  1. XRF 2009-12-23T07:22:42+01:00

    Hi, Very good post article is very informative...thanks for sharing with us....

Leave a comment