Building a Patchbay (Gains) in ChucK

posted on 01 Jun 2009 07:19 by achuckaday  in ChucK

long time no chuck ...

i was dreaming of building an easy patchbay in ChucK, but couldn't think of a way to make it.. but thanks to Kassen on www.electro-music.com forum ChucK channel, there is already a very cool workaround i had no idea it's this easy.

here it is: http://wiki.cs.princeton.edu/index.php/Buses

Creating Additive Sinusoid-Partials Waveforms with Gen10

posted on 19 May 2009 04:25 by achuckaday  in ChucK

Wanna generate more waveforms which is the combination of Sine Wave Harmonice easily? Sure! It's very easy with Gen10.

( see http://chuck.cs.princeton.edu/doc/program/ugen_full.html#GenX
http://chuck.cs.princeton.edu/doc/program/ugen_full.html#Gen10 )

This way of creating an oscillator is derived from the table-lookup mechanism dated back to some very classic audio programming languages such as MUSIC-N and Csound. I remember practicing Csound and starting to learn how to use Gen 10 to create a table (array) containing this kind of waveform: "harmonic partials with specified amplitudes" .. "composite waveforms made up of weighted sums of simple sinusoids", you can read more about Gen 10 in Csound at http://www.csounds.com/manual/html/GEN10.html, it feels very classic to me.

After creating a Gen10 and setting the coefficients (.coefs), the values in the table will be "normalized", so the range of the values in the table will always be in this range [-1, 1].

Let's start with the most simple wave form.. A pure sine wave!

Hear out a simple 220hz sine wave:
Phasor phase_generator => Gen10 signal => dac;
[1.0] => signal.coefs;
day => now;

So now, let me explain quickly. When a Gen is created,  we can access the table in two ways:

[1] by using it as a function. by reading its .lookup(float), you can read the value from the table stored in the Gen at the specific phase. For example ..

Gen10 s;
[1.0] => s.coefs;
<<< .25 => s.lookup >>>;

This will output 1.000000 :(float), the value of sine at phase = .25 (90 degree or pi/2 radian).

(or you can use s.lookup(.25) as well.)

[2] by driving it by chucking in a signal. normally a signal in the range [-1, 1] .. but normally we can use Phasor (which has the output range [0, 1]). As in the above example which is playing the sine wave out, the example is (kinda) equivalent to SinOsc s => dac; day => now; (because SinOsc and Phasor both have the same initialized .freq at 220hz).

By driving it with chucking, we can easily use a Gen as an oscillator right away, and by altering the phasor's freq or doing Frequency Modulation (FM) or Phase Modulation (PM) with it, we can also turn a Gen into a FM/PMable oscillator right away.

Let me give an example for using Gen10 to create quite a basic sound: The Electric Organ. Normally, when we think of the electric organ sound, we think of it as the summation of sinusoid harmonic partials. Let's say, if we're playing a 440hz A note, the typical organ will let us mix more harmonics to shape the sound. We can adjust the amplitude of each harmonic by adjusting the drawbars. So we're adding up sine wave at 440hz, 440*2hz, 440*3hz, 440*4hz .. and so on. Yes, this is just like what we can do easily with Gen10!

Example: Randomizing each harmonic's amplitude, playing with the note C below middle C.

Phasor p => Gen10 organ => dac;
48 => Std.mtof => p.freq;
.5 => organ.gain;
float harmonics[8];
while(true)
{
    1.0 => harmonics[0];
    for(int i; i < 7; i++)
    {
        Std.rand2f(0, 2) => harmonics[i + 1];
    }
    
    harmonics => organ.coefs;
    
    second => now;
}

Another Example: The same as above with added vibrato

Phasor p => Gen10 organ => dac;
48 => Std.mtof => p.freq;
.5 => organ.gain;

SinOsc lfo => p;
2 => p.sync; // set p's sync mode to FM to vibrate p's freq
6 => lfo.freq; // vibrato freq
2 => lfo.gain; // vibrato depth in hz

float harmonics[8];
while(true)
{
    1.0 => harmonics[0];
    for(int i; i < 7; i++)
    {
        Std.rand2f(0, 2) => harmonics[i + 1];
    }
   
    harmonics => organ.coefs;
   
    second => now;
}

 Example: Rotating the harmonic partials and the pitch also

Phasor p => Gen10 organ => NRev rev => dac;
.5 => organ.gain;
.04 => rev.mix;

SinOsc lfo => p;
2 => p.sync; // set p's sync mode to FM to vibrate p's freq
6 => lfo.freq; // vibrato freq
2 => lfo.gain; // vibrato depth in hz

float harmonics[8];

int seq;
while(true)
{   
    36 + seq % 12 * 2 => Std.mtof => p.freq;
    for(int i; i < 8; i++)
    {
        .1 => harmonics[i];
    }
    1.0 => harmonics[seq % 8];
   
    harmonics => organ.coefs;
   
    second/8 => now;
    seq++;
}

Example: Using a SinOsc to FM with a Gen10 sound

SinOsc p_fm => ADSR p_fm_env => Phasor p => Gen10 organ => dac;
2 => p.sync;
.5 => organ.gain;

p_fm_env.set(10::ms, 120::ms, .2, 10::ms); // set FM depth ADSR envelope
200 => p_fm_env.gain; // set maximum FM depth

36 => Std.mtof => p_fm.freq;
48 => Std.mtof => p.freq;

[1.0, 0, 0, .7, 0, 0, .4, 0, 0, .3] => organ.coefs; // set harmonic partial aplitudes

while(true)
{
    p_fm_env.keyOn();
    250::ms => now;
    p_fm_env.keyOff();
    250::ms => now;
}

 Example: using a Gen10 to FM a Gen10

Phasor p_p_fm => Gen10 p_fm => ADSR p_fm_env => Phasor p => Gen10 organ => dac;
2 => p.sync;
.5 => organ.gain;

p_fm_env.set(10::ms, 160::ms, .1, 10::ms); // set FM depth ADSR envelope
400 => p_fm_env.gain; // set maximum FM depth

36 => Std.mtof => p_p_fm.freq;
48 => Std.mtof => p.freq;

[1.0, 0, 0, .7, 0, 0, .4, 0, 0, .3] => organ.coefs; // set harmonic partial aplitudes

float harmonics[8];
while(true)
{
    for(int i; i < 8; i++)
    {
        0.0 => harmonics[i];
    }
    1.0 => harmonics[Std.rand2(1, 7)];
    harmonics => p_fm.coefs;
   
    p_fm_env.keyOn();
    250::ms => now;
    p_fm_env.keyOff();
    250::ms => now;
}

I guess that's it for today. As an introduction to Gen10, I hope this can be one of the start point for ChucKers using GenX for the first time or finding general ideas on Gen10. Goodnight guys.

edit @ 19 May 2009 06:20:27 by aChucKaDay

ChucK midi quick guide to opening and reading

posted on 16 May 2009 01:14 by achuckaday

opening a midi device (will exit if there is no midi device with that number):

 

MidiIn min;
MidiMsg msg;
if(!min.open(MIDI_Device_Number)) me.exit();

 

displaying the opened midi device number & name:

 

<<< min.num(), min.name() >>>;

 

waiting for a midi event:

 

min => now;

 

getting the message:

 

while(min.recv(msg))
{
    // what you want to do..
}

 

midi message data:

 

msg.data1, msg.data2, msg.data3 

 

MIDI Message Types (data1, data2, data3):

 

Note On: 144, (note number),  (velocity)
Note Off: 128, (note number), (velocity)
Control Change: 176, (CC number), (value)

edit @ 16 May 2009 01:37:22 by aChucKaDay