Rasmus.krats.se

English

Skriverier då och då, på webben sedan 1995

12 takter ChucK

Publicerad taggat , .

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.

Skriv en kommentar

Ditt namn (eller en pseudonym).

Publiceras inte, utom som gravatar.

Din hemsida / presentation

Ingen formatering, utom att en tomrad tolkas som styckesbrytning.