JITLib
(Just In Time Library, créé et maintenu par Julian Rhohurber)
- live-coding: le programme n'est plus simplement un outil, mais une construction dynamique, modulable en temps réel.
- La programmation s'inclut dans le processus de la pratique musicale.
- L'exécutant lance des processus, et peut les changer à la volée, en changeant le code.
Cette librairie est destinée à fournir un environnement facilitant le 'livecoding', en donnant des emplacements abstraits (proxies), pouvant êtres remplis, modifiés, utilisés pour le calcul pendant l'exécution. Par exemple, il devient simple de changer la source d'un filtre ou le filtre d'une source en une seule ligne.
JITlib est construit autour de notions fondamentales, comme le proxy, et l'environnement.
- Un proxy est un emplacement dans une structure opérante.
- Cette structure a une validité même si l'emplacement n'est pas occupé.
Les environnements
un environnement (
Environment) est un dictionnaire non ordonné, associant une clef ou entrée unique à une valeur
Il existe par défaut au lancement du langage un Environnement :
currentEnvironment
s = Server.local.boot; // on lance le serveur (l'environnement par défaut)
a = {SinOsc.ar(200,0,0.1)}.play;
~b = {SinOsc.ar(220,0,0.1)}.play;
currentEnvironment.dump;
=> Environment[ (b -> Synth("temp__1867963701" : 1000)) ]
Seule la variable ~b (le tilde est en fait une entrée du dictionnaire) fait partie de l'environnement courant
Si l'on veut maintenant appliquer un effet à ~b, le plus simple est de l'arrêter et de modifier sa définition:
~b.stop; // ne marche pas, il faut arrêter la synthèse (ou arrêter le noeud du graphe en connaissant son index)
s.sendMsg(\n_free, no_index) // la syntaxe devient compliquée
~b = {Clip.ar(SinOsc.ar(220, 0, 0.1), -0.07, 0.07)}.play; // nouvelle définition de ~b
Essayons avec JITLib.
On lance le ProxySpace, propre à JITLib :
n = ProxySpace.push(s);
n.fadeTime_(3); // On peut définir une durée de transition pour les changements
~b = {SinOsc.ar(220,0,0.1)}; // La première définition d'une variable définit si la sortie est mono, stéréo, n-canaux, et son échantillonnage est de type audio (ar) ou contrôle (kr).
~b.play;
~b = {Clip.ar(SinOsc.ar([220,222], 0, 0.1), -0.07, 0.07)};
~b.clear;
~b = {SinOsc.ar([220,222],0,0.1)};
NodeProxy
Le but de l'utilisation d'un proxy dans le cadre du "live coding" est de pouvoir lancer des opérations sans que les membres soit nécessairement existants, autrement dit de créer ou de changer une structure , de la remplir ensuite, et de pouvoir aussi changer ses membres, le tout sans stopper la synthèse .
// boot the server
s.boot;
/* création de deux proxies sur le serveur, vitesse audio, deux canaux.
(note: la vitesse et le nombre de canaux sont les deux paramètres statiques des NodeProxys. Ils ne peuvent plus êtres changés après leur création.)
*/
y = NodeProxy.audio(s, 2);
z = NodeProxy.audio(s, 2);
// calcul sur les proxies
z.play; //z est juste un place holder
z.source = y.sin * 0.2;
y.source = { Saw.ar([300, 301], 4*pi) };
y.source = 0;
y.source = { Pulse.ar([400, 401], 0.1)};
y.source;
//libération des bus
y.clear;
z.clear;
// Un NodeProxy peut contenir plusieurs objets, leur index détermine leur ordre d'exécution sur le serveur.
y = NodeProxy.audio(s, 2);
y.play;
y[0..8] = { Resonz.ar( WhiteNoise.ar(LFClipNoise.kr(8, 10, 10)), exprand(1000, 5000) * LFNoise2.kr(1, {0.1.rand}!2).midiratio, 0.001).softclip}
//on peut utiliser un ProxySpace pour faciliter la création des NodeProxys
y.objects[2];
y.source;
ProxySpace
Un ProxySpace fournit un environnement pouvant contenir, et faciliter la manipulation de plusieurs NodeProxys.
(
s = Server.local;
s.boot;
p = ProxySpace.push(s);
)
Important :
p est un Environement. Après l'instanciation ci-dessus (avec la méthode
.push),il a remplacé
currentEnvironment
p.dump;
currentEnvironment.dump;
//création d'un NodeProxy dans ce contexte;
~out;
NB: le nom
~out est arbitraire, ce pourrait être ~gudule sans autre spécification, sc crée un NodeProxy sans vitesse définie, et sans taille (nombre de canaux) définie;
~out = {SinOsc.ar([300, 302], 0, 0.2)};
~out;
la vitesse et la taille du NodeProxy sont déduits de la fonction :
- la vitesse selon la vitesse du premier UGen de la fonction (ici SinOsc.ar)
- la taille selon le nombre de canaux résultant de l'évaluation de la fonction (ici SinOsc.ar prend un Array de deux éléments comme fréquence -> 2 canaux)
Important: ces caractéristiques ne changeront plus: l'affectation d'une fonction valide à ~out a fixé la vitesse et la taille :
~out = {SinOsc.kr(100, 0 , 0.1)}
~out; // toujours deux canaux, la vitesse kr est traduite pour s'adapter à la vitesse audio
//la suite reprends la structure du fichier "proxyspace examples"
//lancement du 'monitoring
~out.play;
//affectation
~out = { RLPF.ar(Pulse.ar(40), {LFNoise0.kr(8).range(40, 200)}!2).softclip };
~out = { RLPF.ar(Pulse.ar(40*LFNoise0.kr(8, 0.3!2).midiratio, LFNoise0.kr(8).range(0.01, 0.99)), {LFNoise0.kr(8).range(40, 200)}!2).softclip };
~out = { Mix.ar(Pan2.ar(Resonz.ar(PinkNoise.ar(30), ((1..16)*[40, 47.57].choose).scramble[..4], LFNoise0.kr(8).range(0.0001, 0.005)), LFClipNoise.kr(8)) )};
p.fadeTime_(4);
// settings
p.fadeTime_(0);
/*
Les fonctions peuvent prendre des arguments (pour les UGens de vitesse de contrôle, kr), et permettre ainsi des modifications extérieures du graphe.
*/
~out = { | rate=2, nb = 5| Resonz.ar(PinkNoise.ar(6), Hasher.kr(LFSaw.kr(rate, mul: nb).round(1)).range(50, 2000), 0.01)};
~out.set(\rate, 0.5, \nb, 7);
~out.set(\rate, 1, \nb, 3);
~souris = {MouseX.kr(0.2, 2)};
~out.map('rate', ~souris);
~out = {SinOsc.ar(200,mul: 0.1)};
~out.add({SinOsc(220,mul:0.1)});
~out[0] = {SinOsc(600,mul:0.1)}
référencement entre proxies
un NodeProxy peut être intégré dans un autre, en temps qu'UGen, et doit donc prendre une méthode indiquant sa vitesse
~lfo = { LFNoise2.kr(30, 300, 500) };
~out = { SinOsc.ar(~lfo.kr, 0, 0.15) };
~out = { SinOsc.ar(~lfo.kr * [1, 1.2], 0, 0.1) * Pulse.ar(~lfo.kr * [0.1, 0.125], 0.5) };
~lfo = { LFNoise1.kr(30, 40) + SinOsc.kr(0.1, 0, 200, 500) };
~out = { SinOsc.ar(~lfo.kr * [1, 1.2], 0, 0.1) };
~lfo = 410;
opérations sur les proxies
[à continuer]
placeholders in sc jitlib_basic_concepts_01 referencing and environments jitlib_basic_concepts_02 internal structure of node proxy jitlib_basic_concepts_03 timing in node proxy jitlib_basic_concepts_04 tutorials: proxyspace_examples
There are no comments on this page. [Add comment]