electro-music.com   Dedicated to experimental electro-acoustic
and electronic music
 
    Front Page  |  Articles  |  Radio
 |  Media  |  Forum  |  Wiki  |  Links  |  Store
Forum with support of Syndicator RSS
 FAQFAQ   CalendarCalendar   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   LinksLinks
 RegisterRegister   ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in  Chat RoomChat Room 
 Forum index » DIY Hardware and Software » ChucK programming language
My take on the ctrl_sequencer example
Post new topic   Reply to topic Moderators: Kassen
Page 1 of 1 [1 Post]
View unread posts
View new posts in the last week
Mark the topic unread :: View previous topic :: View next topic
Author Message
chuckles



Joined: Apr 02, 2007
Posts: 72
Location: San Diego, California

PostPosted: Thu May 03, 2007 10:30 am    Post subject: My take on the ctrl_sequencer example Reply with quote  Mark this post and the followings unread

[24 May 2007 -- added a download link for the program -- it shows up at the bottom]

Sort of quiet in this forum lately...what I've been doing is tweaking the example in the ctrl directory called ctrl_sequencer.ck. It wasn't too extensively commented so it was a good exercise in trying to figure out what it was doing.
It was a program that created a mandolin and clarinet "player" and a simple algorithm to play a little two-part "sonata". I finished adding a third voice which had been started, wrote a bunch of comments and experimented with some various code variants.
My thanks to whoever philipd is who I guess wrote the original thing. It's fun to listen to -- for a while!
All comments, changes, improvements, criticism is welcome...
I'm going to add it inline even though it's sort of long; since I personally would rather read the code in a forum than have to download a file. Hope it's not too inconvenient...

chuckles!


Code:
// 05 ctrl_sequencer.ck

// Trio Sonata for Mandolin, Flute and Clarinet
// um, by philipd
// (what is it?)

// based on ctrl_sequencer.ck distributed in the examples\ctrl directory

// This started out as a very cool ChucK program to play an algorithmic
// quasi-Baroque Trio. It's amazingly simple for the good results it gives.

// I took it and added comments, formatting, and fiddled with the code a
// little here and there.

// Runs as one shred
//
// Originally only mandolin and clarinet voices were active; I added some
// code to play the flute voice as well.
//
// NOTE: Beginner zone: this is one of the first things I ever did with
// ChucK. Be kind.
//
// 20070423 tps
// 20070418 tps
// 20070426 tps
// 20070502 tps   
// 20070503 tps

// --------------------------------------------------------------------------
//
// Classes used:
//     Player.connect, .noteOn, .noteOff
//     Note.set, .playOn, .playOnAlt
//     Player -> MandPlayer.noteOn
//     Player -> FlutePlayer.noteOn, .noteOff
//     Player -> ClarPlayer.noteOn, .noteOff
//
// Functions defined:
//     newsequence
//     swap

class Player
{
    UGen @ base;         // thus base is a null reference of type UGen
    fun void connect( UGen target )
    {
        base => target;  // connect one UGen to another?
    }

    fun void noteOn ( float note, float vel ) {}
    fun void noteOff ( float vel ) {}
}

class MandPlayer extends Player
{
    Mandolin m @=> base;

    fun void noteOn ( float note, float vel )
    {
        Std.mtof ( note ) => m.freq;
        vel => m.pluck;
    }
}

class ClarPlayer extends Player
{
    Clarinet c @=> base;
    fun void noteOn ( float note, float vel )
    {
        Std.mtof ( note ) => c.freq;
        vel => c.startBlowing;
    }

// ClarPlayer is monophonic, so .stopBlowing refers to a the note.
// For a polyphonic Player, you'd need to identify the note to stop.

    fun void noteOff ( float vel )
    {
        vel => c.stopBlowing;
    }
}
// 'pears that FlutePlayer hasn't yet been turned on...an exercise
// for the new user...going to make it have some of the same
// characteristics as Clarinet...
// (might be interesting to try the Flute UGen too)

class FlutePlayer extends Player
{
    PercFlut f @=> base;
    fun void noteOn ( float note, float vel )
    {
         Std.mtof ( note ) => f.freq;
         vel => f.noteOn;
    }
       
    fun void noteOff ( float vel )
    {
         vel => f.noteOff;
    }
}

// Note has three methods: .set, .playOn and .playOnAlt

class Note
{
    float note;
    float vel;
    dur length;

    fun void set ( float nt, float vl, dur ln )
    {
        nt => note;
        vl => vel;
        ln => length;
    }

    fun void playOn ( Player p )
    {
        if ( note > 0 )
        {
            p.noteOn( note , vel );
        }
    }

    fun void playOnAlt( Player p, float noff, float vmul )
    // like playOn, but add noff to the note and multiply
    // the velocity by a factor vmul
    {
        p.noteOn( note+noff, vel*vmul );
    }
}
// --------------------------------------------------------------------------

// set up some parameters, scale, note and order arrays...

// sequence is an array of Note objects; 12 of them in this case...
12 => int seqn;
Note sequence[seqn];

// order will be an array of ints which will give us the order in
// which to play the sequence
int order[seqn];

// ok.. a simple two octave pentatonic scale. in C it would map to notes
// C D E G A

[0, 2, 4, 7, 9, 12, 14, 16, 19, 21] @=> int scale[];

// 10 => int nscale; // I think scale.cap() is supposed to be able to do this
                 
scale.cap() => int nscale;

// TODO: make this more flexible re tempo...right now notes can only be
// 1/4, 1/8 or 3/8 sec long

// [0.25::second, 0.125::second, 0.125::second,  0.375::second] @=> dur times[];
// 4 => int ntimes;
// or: let's try it thisaway

// [ (1./4.)::second, (1./8.)::second, (1./.8)::second, (3./8.)::second] @=> dur times[];
// made a typo in the third value (1./.8 rather than 1./8.; thus
// 1.25 sec rather than .125 sec -- made an interesting change

[ (1./4.)::second, (1./8.)::second, (1./8.)::second, (3./8.)::second] @=> dur times[];
times.cap() => int ntimes; // seems to work

//fun initialize ( Note sequence, int n ) { // leftover from something?

// --------------------------------------------------------------------------
// the clever thing is he managed to do this with just a couple of functions
// newsequence and swap

fun void newsequence()
{
    for ( 0 => int i; i <seqn> order[i];      
        55 + scale[Std.rand2(0, nscale - 1)] => int note;
        times[Std.rand2(0, ntimes - 1)] => dur mydur;
        Std.rand2f( 0.75, 0.9 ) => float vel;
        sequence[i].set( note, vel, mydur );
    }
}

// swap is intended to do limited permutations but exchanging
// a couple entries in the order array (maybe rewrite this as
// a function of type int[]?) A minor gyration is gone through
// to make sure a <b> int a;
    ( a + Std.rand2(1, seqn-1) ) % seqn => int b;
    <<< "swapping ", a, " and ", b >>> ;
    order[a] => int tmp;
    order[b] => order[a];
    tmp => order[a];
}

// --------------------------------------------------------------------------

Gain g => JCRev j => Echo e => dac;
0.95 => j.gain;
0.2 => j.mix;

1.15::second => e.max;
1.0::second => e.delay;
0.3 => e.mix;

// Instantiate some Players...
MandPlayer mand;
ClarPlayer clar;
FlutePlayer flutey;

// Hook em all up to the Gain object...
mand.connect(g);
clar.connect(g);
flutey.connect(g); // and our new player too

// 0.6 => g.gain; this seemed to give slightly too low
// a level when I saved this to a file

0.8 => g.gain;

newsequence();

1 => int loop_count;
while ( true )
{
<<< "loop #", loop_count++ >>>;
    for ( 0 => int j ; j <seqn> Note note;
// we can use "note" here again since it's in a different
// scope than the temporary "note" used in the Note class
// definition

// play a mandolin note...
     note.playOn ( mand );
     
// and a clarinet note...
     note.playOnAlt ( clar, 12 , 0.7 );

// that's cool, now let's add the new flute note:
     note.playOnAlt ( flutey, 5 , 0.7 );
   
     note.length * 2.0 => now;

// play a note 7 semitones higher, 0.33 velocity
     note.playOnAlt( mand, 7, 0.33 );
     note.length => now;
    }

// do the swap function between 1 and 2 times.
    for ( Std.rand2(0, 2) => int j ; j > 0 ; j-- ) {
        swap();
    }
    Std.rand2(0, 10) => int newseq;
    if ( newseq > 8 ) {
        <<< "generating a new sequence at time", now >>>;
        newsequence();
    }
}



05 ctrl_sequencer.ck
 Description:
My variation on the ctrl_sequencer.ck example program which came with 1.2.0.8

Download
 Filename:  05 ctrl_sequencer.ck
 Filesize:  6.83 KB
 Downloaded:  185 Time(s)

Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic Moderators: Kassen
Page 1 of 1 [1 Post]
View unread posts
View new posts in the last week
Mark the topic unread :: View previous topic :: View next topic
 Forum index » DIY Hardware and Software » ChucK programming language
Jump to:  

You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum
e-m mkii

Please support our site. If you click through and buy from
our affiliate partners, we earn a small commission.


Forum with support of Syndicator RSS
Powered by phpBB © 2001, 2005 phpBB Group
Copyright © 2003 through 2009 by electro-music.com - Conditions Of Use