| Author |
Message |
Underwaterbob
Joined: Sep 03, 2008 Posts: 26 Location: Chungju, South Korea
|
Posted: Fri Sep 05, 2008 7:27 am Post subject:
My first ChucK Subject description: help and/or comments please |
 |
|
I found out about this forum and consequently ChucK yesterday.
ChucK seems pretty awesome so I downloaded it this afternoon. This is my first, fairly basic attempt at making something interesting.
| Quote: |
SinOsc s1 => dac; [ 100, 200, 300, 400, 500, 600 ] @=> int foo1[];
SinOsc s2 => dac; [ 125, 250, 375, 500, 625, 750 ] @=> int foo2[];
SinOsc s3 => dac; [ 150, 300, 450, 600, 750, 900 ] @=> int foo3[];
while ( true ) {
44100 => int time1;
44200 => int time2;
44300 => int time3;
Math.rand2f(1, 6) $ int => int note1;
.3 => s1.gain;
Math.rand2f(1, 6) $ int => int note2;
.3 => s2.gain;
Math.rand2f(1, 6) $ int => int note3;
.3 => s3.gain;
foo3[note3] => s3.freq;
time3::samp => now;
foo2[note2] => s2.freq;
time2::samp => now;
foo1[note1] => s1.freq;
time1::samp => now;
}
|
Three different waves slightly out of sync with each other so they change to specific random notes in three made up harmonic series. With a difference of 100 samples per duration they slowly phase in and out with each other changing pitch at regular, slightly different intervals. That was my goal anyway. It almost sounds right, but I'm not entirely clear on how the timing works yet.
It's kind of soothing except for when it hits some nasty dissonance now and again.
Any comments or hints on optimizing my code or how to make all three Ugens start on random notes at the same time? |
|
|
Back to top
|
|
 |
kijjaz

Joined: Sep 20, 2004 Posts: 765 Location: bangkok, thailand
Audio files: 4
|
Posted: Fri Sep 05, 2008 8:56 am Post subject:
|
 |
|
some suggestions on something we can do to the code:
(1)
Math.rand2f(1, 6) $ int
is nice, ..
but actually we can calculate random integer the same way:
Math.rand2(1, 5)
this will generate ramdom integer in the range 1 to 5
(2)
44100 <-- you might refer to the number of sample in one second if the sample rate is 44100
but if you'd like to refer to "second" you can do this with this patch:
second => dur time1;
second + 100::samp => dur time2;
second + 200::samp => dur time3;
.. etc ..
time1 => now;
time2 => now;
time3 => now;
(3) but this can't simultenously automate 3 oscillators independently because
the control of it is in one loop.
if you want the control of each oscillator independent of each one's time,
you might wanna check out "function" and "sporking"
sporking can run a function as a new shred in ChucK virtual machine.
let me do the adjustment to your code to demonstrate.
| Code: | SinOsc s1 => dac; [ 100, 200, 300, 400, 500, 600 ] @=> int foo1[];
SinOsc s2 => dac; [ 125, 250, 375, 500, 625, 750 ] @=> int foo2[];
SinOsc s3 => dac; [ 150, 300, 450, 600, 750, 900 ] @=> int foo3[];
44100 => int time1;
44200 => int time2;
44300 => int time3;
.3 => s1.gain;
.3 => s2.gain;
.3 => s3.gain;
spork ~ UpdateS1();
spork ~ UpdateS2();
spork ~ UpdateS3();
while (true) day => now; // wait forever
fun void UpdateS1()
{
int note1;
while(true)
{
Math.rand2f(1, 6) $ int => note1;
foo1[note1] => s1.freq;
time1::samp => now;
}
}
fun void UpdateS2()
{
int note2;
while(true)
{
Math.rand2f(1, 6) $ int => note2;
foo2[note2] => s2.freq;
time2::samp => now;
}
}
fun void UpdateS3()
{
int note3;
while(true)
{
Math.rand2f(1, 6) $ int => note3;
foo3[note3] => s3.freq;
time3::samp => now;
}
} |
but you see there're some duplications in code,
we can make those update functions better by making it more flexible for all cases.
| Code: | SinOsc s1 => dac; [ 100, 200, 300, 400, 500, 600 ] @=> int foo1[];
SinOsc s2 => dac; [ 125, 250, 375, 500, 625, 750 ] @=> int foo2[];
SinOsc s3 => dac; [ 150, 300, 450, 600, 750, 900 ] @=> int foo3[];
44100 => int time1;
44200 => int time2;
44300 => int time3;
.3 => s1.gain;
.3 => s2.gain;
.3 => s3.gain;
spork ~ Update(foo1, s1, time1::samp);
spork ~ Update(foo2, s2, time2::samp);
spork ~ Update(foo3, s3, time3::samp);
while (true) day => now; // wait forever
fun void Update(int NoteList[], SinOsc s, dur d)
{
int note;
while(true)
{
Math.rand2f(1, 6) $ int => note;
NoteList[note] => s.freq;
d => now;
}
} |
so those are my suggestions on adjusting the code for being able to play more. |
|
|
Back to top
|
|
 |
Kassen
Janitor


Joined: Jul 06, 2004 Posts: 7678 Location: The Hague, NL
G2 patch files: 3
|
Posted: Fri Sep 05, 2008 12:44 pm Post subject:
|
 |
|
Great notes by Kijjaz. I'd add that everything becomes easier if you use some tabs and the occasional extra line of white. Once your programs grow larger this will help you a LOT so it's best to get used to this as soon as possible. _________________ Kassen |
|
|
Back to top
|
|
 |
Underwaterbob
Joined: Sep 03, 2008 Posts: 26 Location: Chungju, South Korea
|
Posted: Fri Sep 05, 2008 5:02 pm Post subject:
|
 |
|
Awesome! Thanks!
A couple comments to see if I understand:
Spork lets me run separate functions simultaneously. So, for example, in the end of the larry, moe and curly tutorial where you are supposed to use command line ChucK to run the separate files simultaneously you would use spork and define larry, moe and curly as separate functions in one file.
In your second reduction. Spork used multiple times acting on the same function with different parameters will make the function run more than once at the same time using each set of parameters. Even when each occurrence of this function is updating at a different time.
Initially I had random, similar times for each SinOsc, but since I had them all in one loop it wasn't doing what I wanted it to do, I moved the goalpost.
I'm coming at this from a Csound perspective where I'm used to manipulating different "instruments" simultaneously.
Yeah, my code badly needs cleaning up.
One more thing:
Is there an output to wave option in miniAudicle or when using command line ChucK, or do I have to record it using some other software? |
|
|
Back to top
|
|
 |
Kassen
Janitor


Joined: Jul 06, 2004 Posts: 7678 Location: The Hague, NL
G2 patch files: 3
|
Posted: Fri Sep 05, 2008 9:26 pm Post subject:
|
 |
|
I could tell :¬), for some reason Csound has a tradition of code without tabs and minimal white space. I respect Csound a lot for it's history but I strongly feel that if you are going to use loops and other more high-level structures you owe it to yourself to use some more formatting. Csound tends towards more straightforward and linear code structures then ChucK. I don't want to tell anybody what to do but I would predict you might thank me in a while if you'd try this; I know I would get lost without those very quickly indeed in larger files :¬).
Also; your summary of sporking seems spot on to me.
In /examples/basic/ you'll find "rec.ck" and "rec-auto.ck". Those will get you started in recording wave files. If you have specific needs and/or get stuck do shout. _________________ Kassen |
|
|
Back to top
|
|
 |
Underwaterbob
Joined: Sep 03, 2008 Posts: 26 Location: Chungju, South Korea
|
Posted: Fri Sep 05, 2008 11:13 pm Post subject:
|
 |
|
Csound code has been around for decades, but due to the disparate nature of the community and the nature of music creation itself, it seems no two coders do it the same. I've been doing it for ten years and I still come across code that makes me go "huh" because of the way people choose to format it. Some of it my own.
I redid my ChucK in the format kijjaz suggested and easily implemented the random durations I initially wanted, even making the code quite a bit shorter:
| Code: |
SinOsc s1 => dac; [ 100, 200, 300, 400, 500, 600 ] @=> int foo1[];
SinOsc s2 => dac; [ 125, 250, 375, 500, 625, 750 ] @=> int foo2[];
SinOsc s3 => dac; [ 150, 300, 450, 600, 750, 900 ] @=> int foo3[];
.3 => s1.gain => s2.gain => s3.gain;
spork ~ Update(foo1, s1);
spork ~ Update(foo2, s2);
spork ~ Update(foo3, s3);
while (true) day => now; // wait forever
fun void Update(int NoteList[], SinOsc s)
{
int note;
while(true)
{
Math.rand2f(800, 1000) $ int => int d;
Math.rand2f(1, 6) $ int => note;
NoteList[note] => s.freq;
d::ms => now;
}
}
|
ChucK's proving itself pretty awesome. There goes my spare time. |
|
|
Back to top
|
|
 |
Kassen
Janitor


Joined: Jul 06, 2004 Posts: 7678 Location: The Hague, NL
G2 patch files: 3
|
Posted: Sat Sep 06, 2008 3:33 am Post subject:
|
 |
|
Yeah, I know. Actually I kinda like that feeling and puzzling it out :¬).
I think, BTW, that I started with Csound not that long after you did but I didn't stick with it for long. Still like The Book as a reference, there's so much in there, and it's nice to be able to read Csound, even if I don't write it.
Your new version looks nice and clean to me. _________________ Kassen |
|
|
Back to top
|
|
 |
kijjaz

Joined: Sep 20, 2004 Posts: 765 Location: bangkok, thailand
Audio files: 4
|
Posted: Sat Sep 06, 2008 7:39 am Post subject:
|
 |
|
I have some suggestions for more adjustments:
(1) the size of an array can be read by its .cap() function.
so you can design the function to be more adaptable to arrays with any size:
original:
Math.rand2f(1, 6) $ int => note;
NoteList[note] => s.freq;
note will be an int in the range 1-5
but i suggest using Math.rand2(0, NoteList.cap() - 1) => note;
NoteList.cap() is the size of the refered array,
for example, if there are 6 members, we can refer to each member as member number 0 to 5
so it's actually 0 to TheArraySize - 1
with this you can initialize each foo array with any size of array you'd like.
(2) something I usually do is to create a master mix gain for overall volumn adjustment.
for example:
SinOsc s1 => Gain master => dac;
SinOsc s2 => master;
SinOsc s3 => master;
.3 => master.gain;
with this it's nice that s1, s2, s3's gain are all 1
(so we can think of the value as the weight of each oscillator's volumn)
and just lower the volumn at the master gain.
hmm that's all for today ^_^.
i'll look forward to seeing more of your patchs ^_^. |
|
|
Back to top
|
|
 |
Underwaterbob
Joined: Sep 03, 2008 Posts: 26 Location: Chungju, South Korea
|
Posted: Sat Sep 06, 2008 9:36 am Post subject:
|
 |
|
| kijjaz wrote: |
original:
Math.rand2f(1, 6) $ int => note;
NoteList[note] => s.freq;
note will be an int in the range 1-5
|
Thanks for that, I didn't realize my random function wasn't hitting every value in the array.
How is the situation in Thailand? I heard things were getting a bit scary for a while. |
|
|
Back to top
|
|
 |
kijjaz

Joined: Sep 20, 2004 Posts: 765 Location: bangkok, thailand
Audio files: 4
|
Posted: Sat Sep 06, 2008 2:47 pm Post subject:
|
 |
|
Hmm.. In Thailand? Usually Thais were always peaceful, even in this kind of situation, they behave okay.
Sometimes these people can be very angry,
but actually they don't mean it deeply.
I see it as fashion lol. |
|
|
Back to top
|
|
 |
Underwaterbob
Joined: Sep 03, 2008 Posts: 26 Location: Chungju, South Korea
|
Posted: Mon Sep 08, 2008 6:13 pm Post subject:
|
 |
|
I'm glad things are OK there. Great country.
I hadn't touched ChucK for a few days but then all of my classes were canceled, so I'm at work and not working and downloaded ChucK on my office machine, luckily it looks like work.
In about ten minutes I turned what's left of my first ChucK into a "Steve Reich Arpeggio Generator". Each of the harmonic series now cycles up and down through each value and the durations are 1::ms apart so it takes around 1:40 for the three arpeggios to phase 360 degrees.
| Code: |
SinOsc s1 => Gain master => dac;
SinOsc s2 => master;
SinOsc s3 => master;
.3 => master.gain;
[ 100, 200, 300, 400, 500, 600, 500, 400, 300, 200 ] @=> int n1[];
[ 125, 250, 375, 500, 625, 750, 625, 500, 375, 250 ] @=> int n2[];
[ 150, 300, 450, 600, 750, 900, 750, 600, 450, 300 ] @=> int n3[];
100 => int t1;
99 => int t2;
98 => int t3;
spork ~ Update(n1, s1, t1::ms);
spork ~ Update(n2, s2, t2::ms);
spork ~ Update(n3, s3, t3::ms);
while (true) day => now; // wait forever
fun void Update(int NoteList[], SinOsc s, dur d)
{
int note;
while(true)
{
NoteList[note] => s.freq;
d => now;
note + 1 => note;
if ( note == 10 ) { 0 => note; }
}
}
|
Since they're letting me go home early today maybe I'll try something new later, but then I can't call it my first ChucK anymore. |
|
|
Back to top
|
|
 |
|