Inhalt
Synth-GeneratorEnvelope-Generator
Parameteroptionalität
Generatorverkettung
Funktions-Schachtelung
Range-Wertanpassung
Routine-Komposition
TempoClock-Komposition
Quantisierung
Pbind-Komposition
Sound-Array
OSC-Messages
Supercollider ist eine Entwicklungsumgebung für Soundprogrammierung. Supercollider besteht aus einem Server und einem Interpreter. Zwischen Server und Interpreter wird ausschließlich mit OSC-Messages kommuniziert. Aus diesem Grund lässt sich Supercollider aus anderen Entwicklungsumgebungen wie zum Beispiel Processing vergleichsweise leicht ansteuern. Für Processing gibt es bereits eine Supercollider-Library, die genau diesen Zweck verfolgt. Es ist möglich mit Processing selbst oder mit anderen Libraries wie Minim in einem eingeschränkten Umfang, Sound und Musik zu programmieren – Soundprogrammierung ist jedoch eine rechenintensive und vor allem zeitkritische Angelegenheit. Entwicklungsumgebungen wie Processing, die auf Javascript basieren, liefern weder die nötige stabile Performance noch die Präzision in der Kontrolle von Klangparametern. Supercollider hingegen basiert auf C++. Mit Command-D blenden wir ein Suchfenster ein, um nach Stichworten suchen zu können. Positionieren wir den Cursor auf ein blau markiertes Wort im Code-Editor, erhalten wir mit der Tastaturkombination Command-Shift-D einen passenden Hilfstext im Help Browser angezeigt.
OSC-Messages Bevor wir Sound mit Supercollider erzeugen können, starten wir den Server mit Command-B, der für die Klangerzeugung verantwortlich ist. Den Code tippen wir in den Interpreter. Dieser wandelt im Hintergrund unsere Anweisungen in OSC-Messages um, die vom Server verstanden werden. Im Gegensatz zu Processing können wir bereits Teile des Programmcodes unabhängig vom Rest starten und testen. Live-Coding Supercollider ist an die Struktur von Smalltalk angelegt. Es reicht bereits eine Zeile, die wir mit Command-Return aufrufen, damit wir Sound hören können. Die Klangausgabe stoppen wir wieder mit einem Command-Punkt. Auf Grund der strukturellen Besonderheit der Sprache ist Supercollider ebenfalls für Livecoding geeignet: Wir können Programmteile im laufenden Betrieb hinzufügen oder wieder entfernen und so nach und nach ein Kompositionsstück programmierend aufbauen. Syntaktik Wollen wir einen Codeblock mehrerer Zeilen auf einmal ausführen, setzen wir in der Regel diesen zwischen zwei runde Klammern. Funktionsaufrufe erkennen wir an geschweiften Klammern. Methoden werden mit einem Punkt hinter dem Funktionsnamen notiert. An Methoden übergeben wir Parameter als Zahlen mit Komma getrennt. Zur besseren Verständlichkeit können wir der jeweiligen Zahl ein Schlüsselwort voranstellen und mit einem Doppelpunkt vom Wert trennen. Es werden nur richtig geschriebene Schlüsselwörter zugelassen und mit einer grünen Färbung des Wortes bestätigt. Rufen wir eine Funktion samt Methode ohne Parameter auf, greift Supercollider auf vordefinierte Standardwerte zurück. Welche Parameter wir mit individuellen Werten überschreiben und wie viele davon, bleibt uns überlassen – Supercollider kommt auch mit verkürzten Aufrufen zurecht. Klangerzeugung in drei Stufen Eine einfache Funktion zum Abspielen von Sound klingt zunächst verlockend, weil sie den notwendigen syntaktischen Aufbau im Hintergrund für uns erledigt. Sie schränkt uns gleichzeitig jedoch in möglichen strukturellen Manipulationen des Klangs eIn. Die erweiterte Funktion als Zwischenstufe erlaubt uns genauere Steuermöglichkeiten. Die Synth-Definition mit anschließendem Synth-Aufruf ist der Goldstandard, die größte Flexibilität erlaubend. Sogar das Ansteuern der Klangerzeugung aus anderen Entwicklungsumgebungen ist damit möglich. UGen Im Hintergrund werkeln für uns verschiedene Generatoren – in Supercollidersprache UGen genannt. Es gibt welche zur synthetischen Klangerzeugung, welche zum Abspielen von Samples, Effekt-Generatoren und Hüllkurven-Generatoren. Einer davon ist der Sinus-Oszilator und erzeugt Sinustöne. Der Funktionsname dafür lautet SinOsc. Dem Funktionsnamen folgt meist ein Methodenaufruf mit einem Punkt angehängt. Audiorate und Kontrolrate Klang-Generatoren folgt entweder die Methode ar oder kr – Abkürzungen für Audiorate und Kontrolrate. Die Audiorate ist hochauflösend, erzeugt 44.100 Werte pro Sekunde in der Standardeinstellung, ist dementsprechend performanceintensiv. ar wird für die Ausgabe von Audio verwendet. Die Kontrolrate ist dagegen niedrigauflösend und erzeugt nur einen Bruchteil von Werten pro Sekunde – ein 64tel der 44.100 Werte. kr wird für bevorzugt für Steuerungsaufgaben verwendet wie beispielsweise eine Parameterfahrt für die Frequenz eines Oszillators.
{SinOsc.ar(freq: 440, phase: 0, mul: 0.1, add: 0)}.play
( b = { arg freq = 440, phase = 0; var sig; sig = SinOsc.ar(freq, phase); sig = sig * 0.1; // 1/10 der Gesamtlautstärke }.play; ) b.set(\freq, 880); // Zugriff auf Synth-Parameter
( SynthDef.new(\sinus, { arg freq = 440, phase = 0; var sig; sig = SinOsc.ar(freq, phase); sig = sig * 0.1; // Lautstärke auf 10 Prozent Out.ar(0, sig!2); // Multiple Expansion: Stereosound }).add; // Synth zum Server hinzufügen ) c = Synth.new(\sinus); // Lokale Variable: nur Zeichen c.set(\freq, 880); // Zugriff auf Synth-Parameter c.free; ~sinSynth = Synth.new(\sinus); // Globale Variable: auch Wörter ~sinSynth.set(\freq, 880); // Zugriff auf Synth-Parameter ~sinSynth.free;
( SynthDef.new(\sinus, { arg freq = 440, phase = 0; var sig; sig = SinOsc.ar(freq, phase); sig = sig * 0.1; Out.ar(0, sig!2); }).add; Synth.new(\sinus, [\freq, 220, \phase, 0]);
// Mono {SinOsc.ar(freq: 440, phase: 0, mul: 0.1)}.play // Stereo über Array {SinOsc.ar(freq: [440, 440], phase: 0, mul: 0.1)}.play // Stereo über Faktorierung {SinOsc.ar(freq: 440!2, phase: 0, mul: 0.1)}.play
{SinOsc.ar(freq: 440, phase: 0, mul: 0.1, add: 0)}.play {Saw.ar(freq: 440, phase: 0, mul: 0.1, add: 0)}.play {Pulse.ar(freq: 440, phase: 0, mul: 0.1, add: 0)}.play {ImPulse.ar(freq: 440, phase: 0, mul: 0.1, add: 0)}.play
{LFPar.ar(freq: 440, phase: 0, mul: 0.1, add: 0)}.play {LFSaw.ar(freq: 440, phase: 0, mul: 0.1, add: 0)}.play {LFPulse.ar(freq: 440, phase: 0, mul: 0.1, add: 0)}.play {LFTri.ar(freq: 440, phase: 0, mul: 0.1, add: 0)}.play
zurück zur Übersicht
Eine individuelle Hüllkurve besteht aus drei Teilen. level gibt Amplitudenhöhen zwischen 0 und 1 vor, times die Zeiten in Sekunden dazwischen und curve die Biegung der Verbindungslinie zwischen zwei Amplitudenhöhen. Die Anzahl der Level ist frei wählbar, sinnvoll ab drei Werten. Die Anzahl der Zeiten dazwischen ist immer eins weniger als die Anzahl der Level, ebenso die Anzahl der curve-Angaben. level, times und curve werden als Arrays angegeben. Arrays werden mit eckigen Klammern zusammengefasst. Die optionale Angabe eines doneAction-Status bestimmt, was nach Abspielen der Hüllkurve passieren soll. Bei 2 wird der Hüllkurvengenerator vom Server gelöscht, sobald die Hüllkurve abgespielt ist. Diese Angabe ist ein sinnvoller ressourcensparender Umgang mit der Performance-Power des Rechners.
{SinOsc.ar(freq: 440, phase: 0, mul: EnvGen.kr(Env.new), add: 0)}.play;
{SinOsc.ar(freq: 440!2, phase: 0, mul: EnvGen.kr(Env.new), add: 0)}.play; {SinOsc.ar(freq: 440!2, phase: 0, mul: EnvGen.kr(Env.perc), add: 0)}.play; {SinOsc.ar(freq: 440!2, phase: 0, mul: EnvGen.kr(Env.sine), add: 0)}.play; {SinOsc.ar(freq: 440!2, phase: 0, mul: EnvGen.kr(Env.triangle), add: 0)}.play; {SinOsc.ar(freq: 440!2, phase: 0, mul: EnvGen.kr(Env.linen), add: 0)}.play;
( p = { arg freq = 440, phase = 0; var sig, env; env = EnvGen.kr(Env.perc, doneAction: 2); // nach Verstummen löschen sig = SinOsc.ar(freq, phase); sig = sig * env; }.play; )
( SynthDef.new(\env, { arg freq = 440, phase = 0; var sig, env, amp = 0.1; env = EnvGen.kr(Env.perc, doneAction: 2); // Verschachtelung von Funktionen sig = SinOsc.ar(freq, phase); sig = sig * amp * env; Out.ar(0, sig!2); }).add; ) d = Synth.new(\env); d.set(\freq, 880); d.free;
( p = { arg freq = 440, phase = 0; var sig, env, amp = 0.1; env = EnvGen.kr(Env(levels: [0,1,0], times: [1,1], curve: [0,0]), doneAction: 2); sig = SinOsc.ar(freq!2, phase); sig = sig * amp * env; }.play; )
( SynthDef.new(\env, { arg freq = 440, phase = 0; var sig, env, amp = 0.1; env = EnvGen.kr(Env(levels: [0,1,0], times: [1,1], curve: [0,0]), doneAction: 2); sig = SinOsc.ar(freq, phase); sig = sig * amp * env; Out.ar(0, sig!2); }).add; ) Synth.new(\env);
zurück zur Übersicht
( SynthDef.new(\sinusA, { arg freq = 440, phase = 0, mul = 0.1, add = 0; var sig; sig = SinOsc.ar(freq, phase, mul, add); Out.ar(0, sig!2); }).add; ) Synth.new(\sinusA); ( SynthDef.new(\sinusB, { arg freq = 440; var sig; sig = SinOsc.ar(freq); Out.ar(0, sig!2); }).add; ) Synth.new(\sinusB); ( SynthDef.new(\sinusC, { arg freq = 440; var sig; sig = SinOsc.ar(freq); sig = sig * 0.1; Out.ar(0, [sig, sig]); }).add; ) Synth.new(\sinusC); ( SynthDef.new(\sinusD, { arg freq = 440; var sig, amp = 0.1; sig = SinOsc.ar(freq); sig = sig * amp; Out.ar(0, sig!2); }).add; )
( SynthDef.new(\envA, { arg freq = 440, phase = 0, mul = 0.1, add = 0; var sig, env; env = EnvGen.kr(Env.perc, doneAction: 2); sig = SinOsc.ar(freq, phase, mul, add); sig = sig * env; Out.ar(0, sig!2); }).add; ) Synth.new(\envA); ( SynthDef.new(\envB, { arg freq = 440; var sig, evn, amp = 0.1; env = EnvGen.kr(Env.perc, doneAction: 2); sig = SinOsc.ar(freq); sig = sig * amp * env; Out.ar(0, sig!2); }).add; ) Synth.new(\envB);
// mit Schlüsselwörtern {SinOsc.ar(freq: 440, phase: 0, mul: 0.1)}.play // ohne Schlüsselwörter {SinOsc.ar(440, 0, 0.1)}.play
zurück zur Übersicht
> 128 verfügbare Busse bzw Audiokanäle > Bus 0 – 7 reserviert für Audioausgang (min 2, max 8) > Bus 8 – 15 reserviert für Audioeingang (min 2, max 8) > Bus 16 – 127 frei verfügbare Busse > in richtiger Reihenfolge Generatoren verketten > Rangfolge der Ausführung entscheident für Klangerzeugung > Quelle > Effekt > Master > In umgekehrter Reihenfolge aufrufen wie abspielen
// Verbinde Hall-Generator mit Bus 0 (Audioausgang) // Verwende Bus 55 mit zwei Kanälen als Eingang im Hall-Generator a = {Out.ar(0, FreeVerb.ar(In.ar(55, 2)))}.play; // Verbinde Sinus-Generator mit Bus 55 b = {Out.ar(55, SinOsc.ar(100!2, mul: LFPulse.ar(2)))}.play;
// Dynamischer Bus mit zwei Kanälen auf Server s // Command-N für Tilde ~meinBus = Bus.audio(s, 2); // Verbinde Hall-Generator mit Bus 0 (Audioausgang) // Verwende dynamischen Bus mit zwei Kanälen als Hall-Eingang a = {Out.ar(0, FreeVerb.ar(In.ar(~meinBus, 2)))}.play; // Verbinde Sinus-Generator mit dynamischen Bus b = {Out.ar(~meinBus, SinOsc.ar(100!2, mul: LFPulse.ar(2)))}.play; // Genarator b wieder vom Server löschen b.free;
( SynthDef.new(\ton, { arg out; var sig, env, amp = 0.1, freq = 440; env = EnvGen.kr(Env.perc, doneAction: 2); sig = SinOsc.ar(freq); sig = sig * amp * env; Out.ar(out, sig!2); // Ausgangsbus wird extern festgelegt }).add; ) ( SynthDef.new(\hall, { arg in; var sig, out = 0; sig = In.ar(in, 1); // Eingangsbus wird extern festgelegt sig = FreeVerb.ar(sig, mix: 0.5, room: 0.8, damp: 0.1)!2; Out.ar(out, sig); // [0,1] = Audioausgang Computer, [1,2] = Audioeingang Computer }).add; ) // freien Bus auf Server für Hall automatisch generieren ~freierBus = Bus(s, 1); // Zuerst Eingangsbus für Hall-Synth festlegen a = Synth(\hall, [\in, ~freierBus]); // Danach Ausgangsbus für Ton-Synth festlegen b = Synth(\ton, [\out, ~freierBus]);
// Klang-Generatoren definieren ( SynthDef.new(\hit, { arg out; // Ausgangsbus wird extern festgelegt var sig, env, amp = 0.1, freq = 440; env = EnvGen.kr(Env.perc, doneAction: 2); sig = SinOsc.ar(freq); sig = sig * amp * env; Out.ar(out, sig!2); }).add; ) ( SynthDef.new(\crawler, { arg out; // Ausgangsbus wird extern festgelegt var sig, env, amp = 0.1, freq = 55; env = EnvGen.kr(Env.perc, doneAction: 2); sig = SinOsc.ar(freq); sig = sig * amp * env; Out.ar(out, sig!2); }).add; ) ( SynthDef.new(\hall, { arg in, out; // Eingangsbus und Ausgangsbus wird extern festgelegt var sig; sig = In.ar(in, 1); sig = FreeVerb.ar(sig, mix: 0.5, room: 0.8, damp: 0.1)!2; Out.ar(out, sig!2); }).add; ) ( SynthDef.new(\master, { arg in; // Eingangsbus wird extern festgelegt var sig, out = 0; // Ausgangsbus ist intern auf 0 festgelegt sig = In.ar(in, 2); Out.ar(out, sig); }).add; ) // Klang-Generatoren erstellen, Ereignisse abwartend // Signalwege in benannten Bussen vorbereiten ~hallBus = Bus.audio(s, 2); // Zwei Kanäle für Hall ~masterBus = Bus.audio(s,2); // Zwei Kanäle für Audio // Generatoren zu Bussen zuweisen a = Synth(\master, [\in, ~masterBus]); b = Synth(\hall, [\in, ~hallBus]); // OSC-Listener für Hallsound ( OSCdef(\scanhitListener, { c = Synth(\hit, [\out, ~hallBus]); }, "/scanhit"); ) // OSC-Listener für trockenen Sound ( OSCdef(\crawlerListener, { d = Synth(\crawler, [\out, ~masterBus]); }, "/crawlerstep"); )
// Signalwege in benannten Bussen vorbereiten ~hallBus = Bus.audio(s, 2); // Zwei Kanäle für Hall ~masterBus = Bus.audio(s,2); // Zwei Kanäle für Audio // Signalverkettung in Gruppen ~quelleGruppe = Group.new; ~effektGruppe = Group.new(~quelleGruppe, \addAfter); ~masterGruppe = Group.new(~effektGruppe, \addAfter); // Generatoren Gruppen und Bussen zuordnen // Signal einmal trocken und einmal mit Hall a = {Out.ar(~hallBus, SinOsc.ar(freq: 440!2, mul: LFPulse.ar(1)))}.play(target: ~quelleGruppe); b = {Out.ar(~masterBus, Saw.ar(freq: 55!2, mul: LFPulse.ar(2)))}.play(target: ~quelleGruppe); c = {Out.ar(~masterBus, FreeVerb.ar(In.ar(~hallBus, 2), mix: 0.5, room: 0.9))}.play(target: ~effektGruppe); d = {Out.ar(0, In.ar(~masterBus, 2)*0.1)}.play(target: ~masterGruppe);
zurück zur Übersicht
Supercollider baut auf sehr vielen Funktionen auf. Für jede Aufgabe gibt es eine andere Funktion. Oft gibt es für die gleiche Funktion unterschiedliche Varianten mit leicht veränderten Funktionsnamenbezeichnungen. Bevor wir in Supercollider einen eigenen Algorithmus schreiben, sollten wir prüfen, ob es nicht dafür bereits eine Funktion gibt – meistens gibt es eine. Unsere Aufgabe besteht darin, die vielen Funktionen mit ihrem Parameterumfang zu internalisieren. Musikalische und klangliche Gestaltung in Supercollider bedeutet, diese vorhandenen Strukturen zu nutzen und sie vor allem durch Schachtelung von Funktionen zu erweitern. An jeder Stelle eines Parameters einer Funktion lässt sich erneut eine neue Funktion einsetzen – und das in beliebiger Tiefe. Darin liegt die Stärke von Supercollider. Die Verschachtelung von Funktionen wirkt im einfachen Playmodus schnell unübersichtlich. Hier lohnt zumindest der Einsatz einer erweiterten Playfunktion, wenn nicht gar der Synthdefinition. Die zu verschachtelnden Teile können wir in einer Synthdefinition verständlich aufbröseln und benennen. Im Anschluß daran können wir Zeile für Zeile die Einzelteile verketten. Dieses Vorgehen garantiert eine höhere Verständlichkeit und eine bessere Übersicht – Zeile für Zeile. Um Verläufe in Parametern zu erzeugen, stehen uns die Generatoren Line und XLine zur Verfügung. Line erzeugt einen absolut linearen Verlauf, XLine dagegen einen exponentiellen. Der exponentielle Verlauf entspricht eher unserem Gehörempfinden und hört sich richtiger an.
Frequenzmodulation
{SinOsc.ar(freq: SinOsc.kr(5)*500)!2}.play;
Phasenmodulation
{SinOsc.ar(freq: 440!2, phase: SinOsc.kr(5)*5)}.play;
Amplitudenmodulation
{SinOsc.ar(freq: 440!2, phase: 0, mul: SinOsc.kr(5))}.play;
Frequenzmodulation
( a = { var sig, amp; mod = SinOsc.kr(5)*500; sig = SinOsc.ar(freq: mod!2); }.play; )
Phasenmodulation
( b = { var sig, mod; mod = SinOsc.kr(5)*5; sig = SinOsc.ar(freq: 440!2, phase: mod); }.play; )
Amplitudenmodulation
c = { var sig, mod; mod = SinOsc.kr(5); sig = SinOsc.ar(freq: 440!2, phase: 0, mul: mod); }.play; )
Frequenzmodulation
( SynthDef.new (\frequenzmodulation, { var sig, mod; mod = SinOsc.kr(5)*500; sig = SinOsc.ar(freq: mod!2); Out.ar(0, sig); }).add; ) Synth.new(\frequenzmodulation);
Phasenmodulation
( SynthDef.new (\phasenmodulation, { var sig, mod; mod = SinOsc.kr(5)*5; sig = SinOsc.ar(freq: 440!2, phase: mod); Out.ar(0, sig); }).add; ) Synth.new (\phasenmodulation);
Amplitudenmodulation
( SynthDef.new (\amplitudenmodulation, { var sig, mod; mod = SinOsc.kr(5); sig = SinOsc.ar(freq: 440!2, phase: 0, mul: mod); Out.ar(0, sig); }).add; ) Synth.new (\amplitudenmodulation);
Linearer Verlauf
{SinOsc.ar(freq: Line.kr(start: 2000, end: 100, dur: 2)!2, phase: 0, mul: 0.1)}.play;
Exponentieller Verlauf
{SinOsc.ar(freq: XLine.kr(start: 2000, end: 100, dur: 2)!2, phase: 0, mul: 0.1)}.play;
Exponentieller Verlauf
( b = { var sig, mod; mod = XLine.kr(start: 2000, end: 100, dur: 2)!2; sig = SinOsc.ar(freq: mod, phase: 0, mul: 0.5); }.play; )
Exponentieller Verlauf
( SynthDef.new (\exponentiellerVerlauf, { var sig, mod; mod = XLine.kr(start: 2000, end: 100, dur: 2); sig = SinOsc.ar(freq: mod, phase: 0, mul: 0.5); Out.ar(0, sig!2); }).add; ) Synth.new (\exponentiellerVerlauf);
Lineare Frequenzverlaufsmodulation mit XLine
( SynthDef.new (\freqModGradient, { var sig, mod, modmod; modmod = XLine.kr(start: 5, end: 1, dur: 5); mod = SinOsc.kr(modmod)*500; sig = SinOsc.ar(freq: mod, phase: 0, mul: 0.5); Out.ar(0, sig!2); }).add; ) Synth.new (\freqModGradient);
Lineare Phasenverlaufsmodulation mit XLine
( SynthDef.new (\phaseModGradient, { var sig, mod, modmod; modmod = XLine.kr(start: 20, end: 1, dur: 5); mod = SinOsc.kr(modmod)*5; sig = SinOsc.ar(freq: 440, phase: mod, mul: 0.5); Out.ar(0, sig!2); }).add; ) Synth.new(\phaseModGradient);
Lineare Amplitudenverlaufsmodulation mit XLine
( SynthDef.new (\ampModGradient, { var sig, mod, modmod; modmod = XLine.kr(start: 20, end: 1, dur: 5); mod = SinOsc.kr(modmod); sig = SinOsc.ar(freq: 440, phase: 0, mul: mod); Out.ar(0, sig!2); }).add; ) Synth.new(\ampModGradient);
Kontinuierliche Frequenzverlaufsmodulation mit SinOsc
( SynthDef.new (\freqContinousMod, { var sig, mod, modmod; modmod = SinOsc.kr(0.1)*5; mod = SinOsc.kr(modmod)*500; sig = SinOsc.ar(freq: mod, phase: 0, mul: 0.5); Out.ar(0, sig!2); }).add; ) Synth.new (\freqContinousMod);
Kontinuierliche Phasenverlaufsmodulation mit SinOsc
( SynthDef.new (\phaseContinousMod, { var sig, mod, modmod; modmod = SinOsc.kr(0.1)*20; mod = SinOsc.kr(modmod)*5; sig = SinOsc.ar(freq: 440, phase: mod, mul: 0.5); Out.ar(0, sig!2); }).add; ) Synth.new(\phaseContinousMod);
Kontinuierliche Amplitudenverlaufsmodulation mit SinOsc
( SynthDef.new (\ampModGradient, { var sig, mod, modmod; modmod = SinOsc.kr(0.1)*10; mod = SinOsc.kr(modmod); sig = SinOsc.ar(freq: 440, phase: 0, mul: mod); Out.ar(0, sig!2); }).add; ) Synth.new(\ampModGradient);
zurück zur Übersicht
{LFNoise0.kr(freq: 1).poll}.play;
{SinOsc.ar(freq: LFNoise0.kr(freq: 10).range(500, 1500)!2, mul: 0.1)}.play;
Frequenzmodulation mit LFPulse
( SynthDef.new (\freqPulseMod, { var sig, mod; mod = LFPulse.kr(freq: 1).range(100, 200); sig = SinOsc.ar(freq: mod, phase: 0, mul: 0.5); Out.ar(0, sig!2); }).add; ) Synth.new (\freqPulseMod);
Amplitudenmodulation mit LFPulse
( SynthDef.new (\ampPulseMod, { var sig, mod; mod = LFPulse.kr(freq: 1).range(0, 1); sig = SinOsc.ar(freq: 400, phase: 0, mul: mod); Out.ar(0, sig!2); }).add; ) Synth.new (\ampPulseMod);
Phasenmodulation mit LFPulse
( SynthDef.new (\phasePulseMod, { var sig, mod; mod = LFPulse.kr(freq: 50).range(5, 25); sig = SinOsc.ar(freq: 200, phase: mod, mod: 0.5); Out.ar(0, sig!2); }).add; ) Synth.new (\phasePulseMod);
Frequenzmodulation mit LFTri
( SynthDef.new(\freqTriMod, { var sig, mod; mod = LFTri.kr(freq: 1).range(100, 200); sig = SinOsc.ar(freq: mod, phase: 0, mul: 0.5); Out.ar(0, sig!2); }).add; ) Synth.new (\freqTriMod);
Amplitudenmodulation mit LFTri
( SynthDef.new (\ampTriMod, { var sig, mod; mod = LFTri.kr(freq: 1).range(0, 1); sig = SinOsc.ar(freq: 400, phase: 0, mul: mod); Out.ar(0, sig!2); }).add; ) Synth.new (\ampPulseMod);
Phasenmodulation mit LFTri
( SynthDef.new (\phaseTriMod, { var sig, mod; mod = LFTri.kr(freq: 50).range(5, 25); sig = SinOsc.ar(freq: 200, phase: mod, mod: 0.5); Out.ar(0, sig!2); }).add; ) Synth.new(\phasePulseTri);
Frequenzmodulation mit LFSaw
( SynthDef.new (\freqSawMod, { var sig, mod; mod = LFSaw.kr(freq: 1).range(100, 200); sig = SinOsc.ar(freq: mod, phase: 0, mul: 0.5); Out.ar(0, sig!2); }).add; ) Synth.new (\freqSawMod);
Amplitudenmodulation mit LFSaw
( SynthDef.new (\ampSawMod, { var sig, mod; mod = LFSaw.kr(freq: 1).range(0, 1); sig = SinOsc.ar(freq: 400, phase: 0, mul: mod); Out.ar(0, sig!2); }).add; ) Synth.new (\ampSawMod);
Phasenmodulation mit LFSaw
( SynthDef.new (\phaseSawMod, { var sig, mod; mod = LFSaw.kr(freq: 50).range(5, 25); sig = SinOsc.ar(freq: 200, phase: mod, mod: 0.5); Out.ar(0, sig!2); }).add; ) Synth.new (\phaseSawMod);
Frequenzmodulation mit LFPar
( SynthDef.new (\freqParMod, { var sig, mod; mod = LFPar.kr(freq: 1).range(100, 200); sig = SinOsc.ar(freq: mod, phase: 0, mul: 0.5); Out.ar(0, sig!2); }).add; ) Synth.new (\freqParMod);
Amplitudenmodulation mit LFPar
( SynthDef.new (\ampParMod, { var sig, mod; mod = LFPar.kr(freq: 1).range(0, 1); sig = SinOsc.ar(freq: 400, phase: 0, mul: mod); Out.ar(0, sig!2); }).add; ) Synth.new (\ampParMod);
Phasenmodulation mit LFPar
( SynthDef.new (\phaseParMod, { var sig, mod; mod = LFPar.kr(freq: 50).range(5, 25); sig = SinOsc.ar(freq: 200, phase: mod, mod: 0.5); Out.ar(0, sig!2); }).add; ) Synth.new (\phaseParMod);
( SynthDef.new (\ampPulseMod, { var sig, mod, modmod; modmod = SinOsc.kr(freq: 0.1).range(1,10); mod = LFPulse.kr(freq: modmod).range(0, 1); sig = SinOsc.ar(freq: 400, phase: 0, mul: mod); Out.ar(0, sig!2); }).add; ) Synth.new(\ampPulseMod);
( SynthDef.new (\ampMod, { var sig, mod, modmod; modmod = BrownNoise.kr().range(1,10); mod = LFPulse.kr(freq: modmod).range(0, 1); sig = SinOsc.ar(freq: 400, phase: 0, mul: mod); Out.ar(0, sig!2); }).add; ) Synth.new(\ampMod);
zurück zur Übersicht
( SynthDef.new (\ampMod, { arg freq = 1; var sig, mod; mod = LFPulse.kr(freq).range(0, 1); sig = SinOsc.ar(freq: 400, phase: 0, mul: mod); Out.ar(0, sig!2); }).add; ) ( Routine({ x = Synth.new(\ampMod); 64.do({ x.set(\freq, rrand(1,10)); 0.5.wait; }) }).play; )
( SynthDef.new (\ampMod, { arg freq = 1; var sig, mod; mod = LFPulse.kr(freq).range(0, 1); sig = SinOsc.ar(freq: 400, phase: 0, mul: mod); Out.ar(0, sig!2); }).add; ) ( Routine({ x = Synth.new (\ampMod); 64.do({ x.set(\freq, rrand(1,10)); rrand(0.5,1.5).wait; }) }).play; )
( SynthDef.new(\ampMod, { arg freq = 1; var sig, mod; mod = LFPulse.kr(freq).range(0, 1); sig = SinOsc.ar(freq: 400, phase: 0, mul: mod); Out.ar(0, sig!2); }).add; ) ( Routine({ x = Synth.new(\ampMod); 64.do({ x.set(\freq, [1,5,10].choose); 0.5.wait; }) }).play; )
zurück zur Übersicht
Für Zeitplanung in SuperCollider gibt es drei Uhren: TempoClock, SystemClock und AppClock. TempoClock ist für Komposition am Geeignesten. Neben der Standard-TempoClock können wir so viele TempoClocks unterschiedlicher Schnelligkeit anlegen wie wir wollen. Dagegen gibt es nur eine SystemClock und eine AppClock. Wobei die SystemClock genauer ist als die AppClock, weil sie eine höhere Priorität besitzt. TempoClock stellen wir in Beats pro Sekunde eIn. Gewohnt sind wir Angaben in Beats pro Minute. Um von Beats pro Minute in Beats pro Sekunde umzuwandeln, teilen wir die BMP-Zahl durch 60. Beispielsweise entsprechen 120 Beats pro Minute 120/60 also 2 Beats pro Sekunde. Wir können also auch gleich unser Tempo als Bruch in der Form – BPM / 60 – angeben und müssen nicht mehr umdenken. Voreingestellt für tempo in TempoClock ist 1 Beat pro Sekunde (BPS) oder 60 Beats pro Minute (BPM). Mit thisThread.clock erhalten wir Auskunft über den Zeitverlauf einer spezifischen Funktion.
// 1 beats/sek oder 60 BPM TempoClock.default.tempo = 2; // 2 beats/sek oder 120 BPM TempoClock.default.tempo = 2;
// SystemClock SystemClock.sched(5, { "hello".postln }); // TempoClock TempoClock.default.sched(5, { "hello".postln });
( SynthDef.new(\ampMod, { arg freq = 1; var sig, mod; mod = LFPulse.kr(freq).range(0, 1); sig = SinOsc.ar(freq: 800, phase: 0, mul: mod); Out.ar(0, sig!2); }).add; ) r = Routine({ var delta; x = Synth.new(\ampMod); loop { x.set(\freq, [1, 5, 10].choose); delta = rrand(1,3)*0.2; delta.yield; } }); // TempoClock.default.sched(0,r); a = TempoClock(120/60); a.sched(0,r);
( SynthDef.new(\env, { arg freq = 440; var sig, env, amp = 0.5; env = EnvGen.kr(Env.perc, doneAction: 2); sig = SinOsc.ar(freq); sig = sig * amp * env; Out.ar(0, sig!2); }).add; ) r = Routine({ var delta; loop { Synth.new(\env, [\freq, 440]); delta = rrand(1,3)*0.2; delta.yield; } }); a = TempoClock.new(tempo: 120/60); a.sched(0,r);
( SynthDef.new(\ampMod, { arg freq = 1; var sig, mod; mod = LFPulse.kr(freq).range(0, 1); sig = SinOsc.ar(freq: 400, phase: 0, mul: mod); Out.ar(0, sig!2); }).add; ) ( f = { Task({ var delta; x = Synth.new(\ampMod); loop { x.set(\freq, [1, 5, 10].choose); delta = rrand(1,3)*0.2; delta.yield; } }); }; ) t = f.value.play(quant: 4); u = f.value.play(quant:4);
( SynthDef.new(\env, { arg freq = 440; var sig, env, amp = 0.5; env = EnvGen.kr(Env.perc, doneAction: 2); sig = SinOsc.ar(freq); sig = sig * amp * env; Out.ar(0, sig!2); }).add; ) r = Routine({ var delta; loop { Synth.new(\env, [\freq, 440]); delta = 2; delta.yield; } }); a = TempoClock.new(tempo: 120/60); a.sched(0,r);
zurück zur Übersicht
( SynthDef.new(\env, { arg freq = 440; var sig, env, amp = 0.5; env = EnvGen.kr(Env.perc, doneAction: 2); sig = SinOsc.ar(freq); sig = sig * amp * env; Out.ar(0, sig!2); }).add; ) r = Routine({ var delta; loop { Synth.new(\env, [\freq, 440]); delta = 2; delta.yield; } }); m = Routine({ var delta; loop { Synth.new(\env, [\freq, 220]); delta = 4; delta.yield; } }); a = TempoClock.new(tempo: 120/60); ( r.play(a, 0); m.play(a, 0); )
( SynthDef.new(\env, { arg freq = 440; var sig, env, amp = 0.5; env = EnvGen.kr(Env.perc, doneAction: 2); sig = SinOsc.ar(freq); sig = sig * amp * env; Out.ar(0, sig!2); }).add; ) r = Task({ var delta; loop { Synth.new(\env, [\freq, 440]); delta = 2; delta.yield; } }); m = Task({ var delta; loop { Synth.new(\env, [\freq, 220]); delta = 4; delta.yield; } }); a = TempoClock.new(tempo: 120/60); ( r.start(a, 0); m.start(a, 0); )
( SynthDef.new(\tone, { arg freq = 1, pitch = 400; var sig, mod; mod = LFPulse.kr(freq).range(0, 1); sig = SinOsc.ar(freq: pitch, phase: 0, mul: mod); Out.ar(0, sig!2); }).add; ) a = TempoClock.new(tempo: 120/60); a.play({ Synth.new(\tone, [\freq, 1, \pitch, 200]); }); a.play({ Synth.new(\tone, [\freq, 2, \pitch, 400]); }); a.play({ Synth.new(\tone, [\freq, 4, \pitch, 300]); }); a.play({ Synth.new(\tone, [\freq, 8, \pitch, 500]); });
( SynthDef.new(\env, { arg freq = 440; var sig, env, amp = 0.5; env = EnvGen.kr(Env.perc, doneAction: 2); sig = Pulse.ar(freq); sig = sig * amp * env; Out.ar(0, sig!2); }).add; ) t = TempoClock(120/60); Pbind(\instrument, "env", \freq, 400, \dur, 2).play(t, quant: 1); Pbind(\instrument, "env", \freq, 200, \dur, 1).play(t, quant: 1); Pbind(\instrument, "env", \freq, 300, \dur, 0.5).play(t, quant: 1); Pbind(\instrument, "env", \freq, 500, \dur, 0.25).play(t, quant: 1);
zurück zur Übersicht
t = TempoClock(120/60); Pbind(\freq, 400, \dur, 2).play(t, quant: 1); Pbind(\freq, 200, \dur, 1).play(t, quant: 1); Pbind(\freq, 300, \dur, 0.5).play(t, quant: 1); Pbind(\freq, 500, \dur, 0.25).play(t, quant: 1);
t = TempoClock(120/60); ( Pbind(\freq, 400, \dur, 2).play(t); Pbind(\freq, 200, \dur, 1).play(t); Pbind(\freq, 300, \dur, 0.5).play(t); Pbind(\freq, 500, \dur, 0.25).play(t); )
~mySeq = [0.1,0.5,0.5,0.1,0.3]; Pbind(\freq, 440, \dur, Pseq(~mySeq, inf)).play;
~myFreq = [200, 400, 300, 500]; Pbind(\freq, Pseq(~myFreq, inf), \dur, 0.125).play;
~myAkkord = [200, 400, 300]; Pbind(\freq, ~myAkkord, \dur, 0.5).play; ~myAkkorde = [[200, 400, 300], [500, 100, 250]]; Pbind(\freq, Pseq(~myAkkorde, inf), \dur, 0.5).play;
~myFreq = [200, 400, 300, 500]; ~inhalt = Pbind(\freq, Pseq(~myFreq,inf), \dur, 0.125); ~aktion = ~inhalt.play; ~aktion.stop;
( SynthDef.new(\env, { arg freq = 440; var sig, env, amp = 0.5; env = EnvGen.kr(Env.perc, doneAction: 2); sig = SinOsc.ar(freq)*env; sig = sig * amp; Out.ar(0, sig!2); }).add; ) t = TempoClock(120/60); Pbind(\instrument, "env", \freq, 400, \dur, Pwhite(0.1,1)).play(t, quant: 1);
( SynthDef.new(\ampMod, { arg freq = 440; var sig, env, amp = 0.5; env = EnvGen.kr(Env( levels: [0,1,1,0], times: [0,0.05,0], curve: [0,0,0]), doneAction: 2); sig = SinOsc.ar(freq!2); sig = sig * amp * env; Out.ar(0, sig!2); }).add; ) t = TempoClock(120/60); p = Pbind( \instrument, "ampMod", \freq, 400, \dur, Prand([0.15,0.45,0.9], inf)); p.play(t, quant: 1);
( SynthDef.new(\ampMod, { arg freq = 440, sustain = 0.05; var sig, env, amp = 0.5; env = EnvGen.kr(Env( levels: [0,1,1,0], times: [0,sustain,0], curve: [0,0,0]), doneAction: 2); sig = SinOsc.ar(freq!2); sig = sig * amp * env; Out.ar(0, sig!2); }).add; ) t = TempoClock(120/60); Pbind( \instrument, "ampMod", \freq, 400, \dur, ~zufall = Prand([0.3,0.6,0.9], inf), \sustain, if (~zufall == 0.3, { 0.05 }, { 0.1}); ).play(t, quant: 1);
( SynthDef.new(\ampMod, { arg freq = 440, sustain = 0.05; var sig, env, amp = 0.5; env = EnvGen.kr(Env( levels: [0,1,1,0], times: [0,sustain,0], curve: [0,0,0]), doneAction: 2); sig = SinOsc.ar(freq!2); sig = sig * amp * env; Out.ar(0, sig!2); }).add; ) Pbind( \instrument, \ampMod, \freq, Pseq([400, 300, 200, 500], inf), \dur, Pseq([0.5,1,0.5, 2], inf), \sustain, Pseq([0.1, 0.2, 0.1, 0.4], inf) ).play;
( SynthDef.new(\env, { arg freq = 440; var sig, env, amp = 0.5; env = EnvGen.kr(Env.perc, doneAction: 2); sig = Pulse.ar(freq); sig = sig * amp * env; Out.ar(0, sig!2); }).add; ) t = TempoClock(120/60); Pbind(\instrument, "env", \freq, 400, \dur, 2).play(t, quant: 1);
( SynthDef.new(\ton, { arg out; var sig, env, amp = 0.5, freq = 440; env = EnvGen.kr(Env.perc, doneAction: 2); sig = SinOsc.ar(freq); sig = sig * amp * env; Out.ar(out, sig!2); }).add; ) ( SynthDef.new(\hall, { arg in; var sig, out = 0; sig = In.ar(in, 1); sig = FreeVerb.ar(sig, mix: 0.5, room: 2, damp: 0.1)!2; Out.ar(out, sig); }).add; ) ~freierBus = Bus(s, 1); a = Synth(\hall, [\in, ~freierBus]); b = Synth(\ton, [\out, ~freierBus]); t = TempoClock(120/60); Pbind(\instrument, "ton", \freq, 400, \dur, 6).play(t, quant: 1);
zurück zur Übersicht
Array.fill(10, {rrand(1,10)}); Array.fill(10, {arg zaehler; zaehler * 3}); Array.fill(10, {arg zaehler; zaehler + 1 * 440});
Array.series(size: 6, start: 10, step: 3); Array.geom(size: 10, start: 1, grow: 2);
a = [10, 11, 12, 13, 14]; a.at(0); a[0]; a.choose;
a = Array.fill(10, {rrand(440, 880)}); a.do({arg i, z; ("a[" ++ z ++ "] = " ++ i++ " Hz").postln}); a.do({arg i; {SinOsc.ar(i!2, 0, 0.1)}.play});
( SynthDef.new(\ton, { arg freq; var sig, amp = 0.1; sig = SinOsc.ar(freq); sig = sig * amp; Out.ar(0, sig!2); }).add; ) a = Array.fill(10, {rrand(440, 880)}); a.do({arg i; Synth.new(\ton, [\freq, i]) });
( SynthDef.new(\ton, { arg freq; var sig, amp = 0.1; sig = SinOsc.ar(freq); sig = sig * amp; Out.ar(0, sig!2); }).add; ) t = TempoClock.new(tempo: 120/60); a = Array.fill(10, {rrand(440, 880)}); a.do({ arg i; Pbind( \instrument, "ton", \freq, i, \dur, inf).play(t, quant: 1) });
zurück zur Übersicht
In Supercollider SynthDef mit store-Methode
SynthDef.new(\ampMod, { arg outbus = 0, freq = 1; var sig, mod; mod = LFPulse.kr(freq).range(0, 1); sig = SinOsc.ar(freq: 800, phase: 0, mul: mod); Out.ar(outbus, sig!2); }).store;
In Processing OSC-Kommunikation
import supercollider.*; import oscP5.*; Group group; Synth synth; float f; void setup () { size(800, 200); group = new Group(); group.create(); synth = new Synth("ampMod"); synth.set("freq", 1); synth.addToTail(group); } void draw () { background(0); stroke(255); line(mouseX, 0, mouseX, height); } void mouseMoved () { f = map(mouseX, 0, width, 1, 20); synth.set("freq", f); } void exit() { synth.free(); group.free(); super.exit(); }
In Supercollider SynthDef
SynthDef.new(\ampMod, { arg outbus = 0, freq = 1; var sig, mod; mod = LFPulse.kr(freq).range(0, 1); sig = SinOsc.ar(freq: 800, phase: 0, mul: mod); Out.ar(outbus, sig!2); }).store;
In Processing Modulo und OSC
import supercollider.*; import oscP5.*; Group group; Synth synth; float f; int zaehler, index; int[] freq = { 1, 5, 10 }; void setup () { size(800, 200); group = new Group(); group.create(); synth = new Synth("ampMod"); synth.set("freq", 1); synth.addToTail(group); zaehler = 0; } void draw () { background(0); noStroke(); fill(255); line(mouseX, 0, mouseX, height); if (zaehler % 5 == 0) { index = int(random(3)); f = freq[index]; synth.set("freq", f); } zaehler++; rect(0, 0, f * 10, height); } void exit() { synth.free(); group.free(); super.exit(); }
In Supercollider zwei SynthDefs
SynthDef.new(\ampMod, { arg outbus = 0, freq = 1; var sig, mod; mod = LFPulse.kr(freq).range(0, 1); sig = SinOsc.ar(freq: 800, phase: 0, mul: mod); Out.ar(outbus, sig!2); }).store; SynthDef.new(\subbass, { arg outbus = 0, freq = 50; var sig, amp = 0.5; sig = SinOsc.ar(freq: 50); sig = sig * amp; Out.ar(outbus, sig!2); }).store;
In Processing Modulo und OSC
import supercollider.*; import oscP5.*; Group group; Synth synthA, synthB; float f; int zaehler, index; int[] freq = { 1, 5, 10 }; void setup () { size(800, 200); group = new Group(); group.create(); synthA = new Synth("ampMod"); synthA.set("freq", 1); synthA.addToTail(group); synthB = new Synth("subbass"); synthB.set("freq", 50); synthB.addToTail(group); zaehler = 0; } void draw () { background(0); noStroke(); fill(255); line(mouseX, 0, mouseX, height); if (zaehler % 5 == 0) { index = int(random(3)); f = freq[index]; synthA.set("freq", f); } zaehler++; rect(0, 0, f * 10, height); } void exit() { synthA.free(); synthB.free(); group.free(); super.exit(); }
zurück zur Übersicht