12 takter ChucK
Publicerad 2005-01-06 12:00. Taggat music, hack.
ChucK är ett livekodningssystem för musik. Cool!
Här kommer en enkel bluestolva som kodexempel.
Vi börjar med lite definitioner för tidsvärden:
60::second / 125.0 => dur t4;
t4 / 2.0 => dur t8;
t4 / 4.0 => dur t16;
t4 / 8.0 => dur t32;
t4 * 2.0 => dur t2;
t4 * 4.0 => dur t1;
fun void taktpos(dur module, dur offset) {
module - ((now - offset) % module) => now;
}
Eftersom ChucK inte supportar inkludefiler eller något ditåt (än) så använder jag det här som en template, och börjar alla filer som en kopia av det här. Siffran 125 på första raden är antelet slag per minut, ändra det för att byta tempo – men kom ihåg att ändra det i alla filer i projektet!
Rytm
Trummor är ökänt svårt att modellera, så vi gör det enkelt och
använder färdiga ljudfiler. Det ingår några sådana filer i ChucK, i
examples/data
.
Vi börjar med en hihat, den låter på två sätt i det här exemplet, så
vi tar två stycken sndbuf
, chuckar
dem till utgången och
läser in data.
sndbuf open => dac;
sndbuf closed => dac;
"data/hihat-open.wav" => open.read;
(int)(open.length/1::samp) => open.pos;
"data/hihat.wav" => closed.read;
(int)(closed.length/1::samp) => closed.pos;
Raden efter varje read sätter uppspelningspositionen till slutet på den sndbuf jag laddar, för att undvika att varje ljud spelas upp när de laddas.
En enkel loop, en halv takt lång, med öppen och stängd hihat. De öppna slagen är lite före / efter åttondelen, för att ge lite swingkänsla.
while(true) {
taktpos(t2, 0::samp);
0 => closed.pos;
t8 - t64 => now;
0 => open.pos;
t8 + t64 => now;
0 => open.pos;
t8 - t64 => now;
0 => closed.pos;
}
Och så en bas- och en virveltrumma (i separata filer, kom ihåg templaten):
sndbuf kick => dac;
"data/kick.wav" => kick.read;
(int)(kick.length/1::samp) => kick.pos;
0.5 => kick.gain;
while(true) {
taktpos(t1, 0::samp);
0 => kick.pos;
t2 => now;
0 => kick.pos;
t8 => now;
0 => kick.pos;
}
sndbuf snare => dac;
"data/snare.wav" => snare.read;
(int)(snare.length/1::samp) => snare.pos;
while(true) {
taktpos(t1, t1 - t8);
0 => snare.pos;
t16 => now;
0 => snare.pos;
t16 + t4 => now;
0 => snare.pos;
t2 => now;
0 => snare.pos;
}
Basloop
Gör en global variabel för grundtonen, och skriv en funktion som loopar en treklang:
0 => int fundamental;
fun void bassloop() {
Rhodey instr => dac;
0.7 => instr.gain;
while(true) {
taktpos(t1, 0::samp);
std.mtof((float)(2*12 + fundamental + 0)) => instr.freq;
0.8 => instr.noteOn;
t4 + t8 => now;
std.mtof((float)(2*12 + fundamental + 4)) => instr.freq;
0.6 => instr.noteOn;
t8 => now;
std.mtof((float)(2*12 + fundamental + 7)) => instr.freq;
0.7 => instr.noteOn;
t4 => now;
std.mtof((float)(2*12 + fundamental + 4)) => instr.freq;
0.6 => instr.noteOn;
}
}
Sporka av treklangsfunktionen och låte en loop byta grundton vid lämpliga tillfällen för en vanlig bluestolva.
taktpos(t1, t1 - 2::samp);
spork ~ bassloop();
while(true) {
7 + 0 => fundamental;
t1 * 4.0 => now;
7 + 5 => fundamental;
t1 * 2.0 => now;
7 + 0 => fundamental;
t1 * 2.0 => now;
7 + 7 => fundamental;
t1 => now;
7 + 5 => fundamental;
t1 => now;
7 + 0 => fundamental;
t1 * 2.0 => now;
}
Offseten på 2::samp
är för att vara säker på att vara säker på att
ändringen av grundton händer innan den första tonen i treklangen
spelas.
Kommentarer
Det här inlägget är 19 år gammalt, det kan inte längre kommenteras.