Last active
March 1, 2026 11:22
-
-
Save tado/f3ce8673f81ab1f03aa4a1a25dc21c88 to your computer and use it in GitHub Desktop.
Live Coding with SuperCollider (JITlib) + Claude
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // ===================================================================== | |
| // JITLib ライブコーディング | |
| // | |
| // 【JITLib の主要クラス】 | |
| // ProxySpace ─ ~ 変数を NodeProxy として管理する環境 | |
| // Ndef ─ サーバー側シンセの差し替え可能なプロキシ(音源・エフェクト用) | |
| // Pdef ─ イベントパターンの差し替え可能なプロキシ(Pbind 用) | |
| // Tdef ─ ルーティンの差し替え可能なプロキシ(Task/Routine 用) | |
| // | |
| // 【変数の設計】 | |
| // p ─ ProxySpace 本体 | |
| // b ─ 楽器 → リバーブへのルーティングバス(SC グローバル変数) | |
| // t ─ 転調量(半音)を保持するグローバル変数 | |
| // ※ b, t は ~ を使わず SC グローバルに置く | |
| // ProxySpace に入れると NodeProxy 化し整数として使えなくなるため | |
| // | |
| // 【差し替え方法】 | |
| // Ndef(\reverb) の再評価 → fadeTime 秒かけてクロスフェード | |
| // Pdef(\p3) 等の再評価 → 次の小節頭(Pdef.defaultQuant 拍後)に切り替わる | |
| // 転調ブロックの再評価 → t を書き換えて即時に転調 | |
| // | |
| // 【評価順序】 | |
| // [0] → [1] → [2][3][4][5] の順で評価する | |
| // [2][3][4][5] は演奏中に何度でも再評価可能 | |
| // ===================================================================== | |
| Server.killAll; // サーバー上の全シンセを停止してクリーンな状態にする | |
| // ===================================================================== | |
| // [0] ProxySpace 初期化 ── 最初に一度だけ評価する | |
| // ===================================================================== | |
| ( | |
| p = ProxySpace.push(s.boot); | |
| ) | |
| // ===================================================================== | |
| // [1] SynthDef 登録・バス確保・Ndef 起動 ── [0] の後に一度評価する | |
| // ===================================================================== | |
| // fork: s.sync は Routine 内でしか動作しないため、ブロックを Routine として実行する | |
| (fork { | |
| // FM 音源: キャリア + モジュレータによる周波数変調合成 | |
| SynthDef(\myFM, { | |
| |out=0, freq=440, amp=0.5, modRatio=1.5, modIndex=10, | |
| attack=0.01, decay=1.0, sustain=0.3, release=1.5, gate=1| | |
| // 振幅エンベロープ(ADSR) | |
| var ampEnv = EnvGen.kr( | |
| Env.adsr(attack, decay, sustain, release), gate, doneAction: Done.freeSelf); | |
| // modIndex エンベロープ: アタック時は倍音豊富 → ディケイで柔らかくなる | |
| var modEnv = EnvGen.kr( | |
| Env([modIndex, modIndex, modIndex * 0.05], [attack, decay * 2], \exp)); | |
| var carrier = SinOsc.ar(freq + (SinOsc.ar(freq * modRatio) * modEnv)) * amp * ampEnv; | |
| Out.ar(out, carrier.dup); | |
| }).add; | |
| // SuperSaw ベース: 7本のデチューンノコギリ波 → RLPF(減算合成) | |
| SynthDef(\superSawBass, { | |
| |out=0, freq=110, amp=0.5, attack=0.005, decay=0.3, sustain=0.6, release=0.5, | |
| cutoff=800, resonance=0.3, envMod=0.7, detune=1.0, gate=1| | |
| var ampEnv = EnvGen.kr( | |
| Env.adsr(attack, decay, sustain, release), gate, doneAction: Done.freeSelf); | |
| // カットオフエンベロープ: アタック時にフィルターが開く | |
| var filterEnv = EnvGen.kr( | |
| Env.adsr(attack * 0.3, decay * 2.0, sustain * 0.4, release), gate); | |
| var saws = Array.fill(7, { |i| Saw.ar(freq * (1 + ((i - 3) * 0.003 * detune))) }); | |
| var cutoffFreq = (cutoff * (1 + (filterEnv * envMod * 4))).clip(30, 18000); | |
| Out.ar(out, RLPF.ar(Splay.ar(saws) * 0.5, cutoffFreq, resonance.clip(0.01, 0.95)) * amp * ampEnv); | |
| }).add; | |
| // パーカッション: ノイズ + BPF でピッチ成型、SinOsc とのクロスフェードで音色を制御 | |
| // freq → 高域(8000+)= ハイハット的、中域(2000)= スネア的、低域(300)= トム的 | |
| // tone → -1 = ノイズのみ、+1 = サイン波のみ(XFade2 でミックス) | |
| // decay → 打の長さ | |
| SynthDef(\perc, { | |
| |out=0, freq=5000, amp=0.5, decay=0.1, tone=0.0, atk=0.001| | |
| var env = EnvGen.kr(Env.perc(atk, decay, 1, -6), doneAction: Done.freeSelf); | |
| var noise = BPF.ar(WhiteNoise.ar, freq, 0.5) * 4; | |
| var sine = SinOsc.ar(freq); | |
| var sig = XFade2.ar(noise, sine, tone.clip(-1, 1)); | |
| Out.ar(out, (sig * amp * env).dup); | |
| }).add; | |
| s.sync; | |
| // b: 楽器 → リバーブへのルーティングバス | |
| // ProxySpace の外の SC グローバル変数として確保する | |
| b = Bus.audio(s, 2); | |
| // Ndef(\reverb): FreeVerb2 ステレオリバーブ | |
| // バス b からオーディオを読み込み、FreeVerb2 を通してハードウェア出力へ | |
| // 再評価すると fadeTime 秒かけてクロスフェードで差し替わる | |
| Ndef(\reverb, { | |
| var dry = In.ar(b, 2); | |
| FreeVerb2.ar(dry[0], dry[1], 0.2, 0.97, 0.55) * 0.9 | |
| }); | |
| Ndef(\reverb).play; | |
| Ndef(\reverb).fadeTime = 2; // 差し替え時のクロスフェード時間(秒) | |
| // t: 転調量(半音)を保持する SC グローバル変数 | |
| // Pfunc({ t }) でパターンから参照する | |
| t = 0; | |
| // k: スケールを保持する SC グローバル変数 | |
| // Pfunc({ k }) でパターンから参照する | |
| k = Scale.minor; | |
| TempoClock.default.tempo = 132 / 60; // 132 BPM | |
| // Pdef の切り替えタイミング: 4拍(= 1小節)単位で同期 | |
| // Pdef を再評価すると、この拍数後に新しい内容へ切り替わる | |
| Pdef.defaultQuant = 4; | |
| "[ セットアップ完了 ] [2][3][4][5] を評価して再生開始".postln; | |
| }) | |
| // ===================================================================== | |
| // [2] Pdef(\p3): Autechre 風 FM パーカッシブシーケンス | |
| // 再評価 → 次の小節頭(4拍後)にシームレスに差し替わる | |
| // ===================================================================== | |
| ( | |
| Pdef(\p3, Pbind( | |
| \instrument, \myFM, | |
| \out, b, // バス b を経由して Ndef(\reverb) へ | |
| // E(9,16) ユークリッドリズム: 16ステップに9打を均等配置 | |
| \dur, Pseq([0.75, 0.5, 0.25, 0.5, 0.5, 0.25, 0.5, 0.5, 0.25], inf), | |
| // Pstutter でグリッチ的な音の繰り返し | |
| \scale, Pfunc({ k }), | |
| \degree, Pstutter( | |
| Prand([1, 1, 1, 2, 3, 4], inf), | |
| Prand([0, 2, 3, 5, 7, -2, -5, -7], inf) | |
| ), | |
| \octave, Prand([4, 4, 4, 5, 3], inf), | |
| // t は SC グローバル変数なので ProxySpace を経由せず整数として取得できる | |
| \ctranspose, Pfunc({ t }), | |
| // 無理数・超越数に近い modRatio → 非調和的な金属音 | |
| \modRatio, Prand([0.5, 1.41, 1.73, 2.23, 3.14, 4.67, 7.39], inf), | |
| \modIndex, Pbrown(10.0, 120.0, 30.0, inf), | |
| \amp, Pseq([0.5, 0.2, 0.4, 0.15, 0.5, 0.25, 0.35, 0.15], inf) | |
| * Pwhite(1.5, 2.0), | |
| \attack, 0.001, | |
| \decay, Prand([0.04, 0.08, 0.15, 0.3, 0.5], inf), | |
| \release, Prand([0.03, 0.06, 0.1, 0.2, 1.0], inf), | |
| \legato, Prand([0.1, 0.15, 0.3, 0.5, 0.8], inf), | |
| )).play; | |
| ) | |
| // ===================================================================== | |
| // [3] Pdef(\p4): 徐々に激しくなる FM リズムパート | |
| // 再評価 → 次の小節頭(4拍後)にシームレスに差し替わる | |
| // ===================================================================== | |
| ( | |
| Pdef(\p4, Pbind( | |
| \instrument, \myFM, | |
| \out, b, | |
| // E(7,12) ユークリッドリズム: 3拍サイクル | |
| \dur, Pseq([0.5, 0.25, 0.5, 0.5, 0.25, 0.5, 0.5], inf), | |
| \scale, Pfunc({ k }), | |
| \degree, Prand([0, 2, 3, 5, 7, 9, 12, -2], inf), | |
| \octave, Prand([5, 5, 5, 6, 4], inf), | |
| \ctranspose, Pfunc({ t }), | |
| \modRatio, Pwhite(0.3, 12.0), | |
| // modIndex: 8拍周期で calm(500)↔ intense(8000)をサイン波補間で繰り返す | |
| \modIndex, Pseg([500.0, 8000.0, 500.0], [4, 4], \sin, inf) | |
| * Pwhite(0.1, 6.0), | |
| \amp, Pseq([0.4, 0.3, 0.15, 0.4, 0.2, 0.35, 0.1], inf) | |
| * Pwhite(0.7, 1.0), | |
| \attack, Pwhite(0.002, 0.02), | |
| \decay, Prand([0.1, 0.2, 0.3, 0.5, 0.8], inf), | |
| \release, Prand([0.1, 0.2, 0.4, 0.6, 1.2], inf), | |
| \legato, Prand([0.2, 0.3, 0.5, 0.7], inf), | |
| )).play; | |
| ) | |
| // ===================================================================== | |
| // [4] Pdef(\pBass): SuperSaw ベースシーケンス | |
| // 再評価 → 次の小節頭(4拍後)にシームレスに差し替わる | |
| // ===================================================================== | |
| ( | |
| Pdef(\pBass, Pbind( | |
| \instrument, \superSawBass, | |
| \out, b, | |
| // 強拍(1.0)と細かいアクセントを混在させたベースグルーヴ | |
| \dur, Pseq([1, 0.5, 0.5, 0.5, 0.5, 1, 0.75, 0.25, 0.5, 0.5], inf), | |
| // ルート音(degree=0)を高頻度で選びベースらしい安定感を出す | |
| \scale, Pfunc({ k }), | |
| \degree, Prand([0, 0, 0, 3, 5, 7, -2, 0, 5, 7], inf), | |
| \octave, Prand([2, 2, 2, 3, 2, 1], inf), | |
| \ctranspose, Pfunc({ t }), | |
| // Pbrown でカットオフをゆっくり変動 → 有機的なフィルターの動き | |
| \cutoff, Pbrown(200, 1200, 150, inf), | |
| \resonance, Pwhite(0.1, 0.45), | |
| \envMod, Pwhite(0.4, 0.9), | |
| \detune, Pwhite(0.8, 2.0), | |
| \amp, Pseq([1.0, 0.65, 0.55, 0.7, 0.55, 1.0, 0.75, 0.5, 0.6, 0.6], inf) | |
| * Pwhite(0.9, 1.2), | |
| \attack, 0.005, | |
| \decay, Prand([0.15, 0.2, 0.35, 0.5], inf), | |
| \sustain, 0.55, | |
| \release, Prand([0.2, 0.4, 0.6, 1.0], inf), | |
| \legato, Prand([0.3, 0.5, 0.7, 0.9], inf), | |
| )).play; | |
| ) | |
| // ===================================================================== | |
| // [5] Pdef(\pRhythm): パーカッションシーケンス | |
| // 3 種のリズムパターンを小節単位でランダムに切り替える | |
| // Pattern A: 6打 / 4拍 ─ 均等配置の骨格リズム | |
| // Pattern B: 5打 / 4拍 ─ 広い間隔でゆったりとした配置 | |
| // Pattern C: 7打 / 4拍 ─ シンコペーションの多い密な配置 | |
| // freq・tone の組み合わせで、ハイハット・スネア・トム的な音色を横断する | |
| // 再評価 → 次の小節頭(4拍後)にシームレスに差し替わる | |
| // ===================================================================== | |
| ( | |
| Pdef(\pRhythm, Pbind( | |
| \instrument, \perc, | |
| \out, b, | |
| // 3 種のリズムパターンを小節ごとにランダム選択 | |
| // 各 Pseq は 1 回使い切り(Prand が次の小節で再び選ぶ) | |
| \dur, Prand([ | |
| Pseq([0.75, 0.75, 0.5, 0.75, 0.75, 0.5 ], 1), // A: 6打 | |
| Pseq([0.5, 0.75, 1.0, 1.0, 0.75 ], 1), // B: 5打 | |
| Pseq([0.25, 0.5, 0.75, 0.25, 0.5, 0.75, 1.0], 1), // C: 7打 | |
| ], inf), | |
| // freq で打楽器の音域を決める | |
| // 高域 = ハイハット的、中域 = スネア的、低域 = トム・ボディ的 | |
| \freq, Prand([12000, 8000, 6000, 3000, 2000, 1000, 500, 300], inf), | |
| // decay: 短い → カッ、長い → ドスン | |
| \decay, Prand([0.05, 0.08, 0.1, 0.15, 0.25, 0.4], inf), | |
| // tone: -1 = ノイズのみ(ハイハット・スネア)、+1 = サイン波のみ(ピッチ系トム) | |
| \tone, Prand([-0.9, -0.7, -0.5, -0.3, 0.0, 0.3], inf), | |
| // 強弱を付けてダイナミクスを演出 | |
| \amp, Prand([0.6, 0.4, 0.5, 0.3, 0.7, 0.4, 0.5, 0.3], inf) | |
| * Pwhite(0.8, 1.5), | |
| \atk, 0.001, | |
| )).play; | |
| ) | |
| // ===================================================================== | |
| // スケール変更コマンド ── 行を選択して Ctrl+Enter でスケール変更 | |
| // k を書き換えると Pfunc({ k }) を使用する全パターンに即時反映される | |
| // ===================================================================== | |
| k = Scale.minor; // マイナースケール(デフォルト) | |
| k = Scale.major; // メジャースケール | |
| k = Scale.chromatic; // クロマチック(半音階) | |
| k = Scale.dorian; // ドリアンモード | |
| k = Scale.phrygian; // フリジアンモード | |
| k = Scale.lydian; // リディアンモード | |
| k = Scale.mixolydian; // ミクソリディアンモード | |
| k = Scale.minorPentatonic; // マイナーペンタトニック | |
| k = Scale.majorPentatonic; // メジャーペンタトニック | |
| k = Scale.hirajoshi; // 平調子(日本の伝統的なペンタトニック) | |
| // ===================================================================== | |
| // 転調コマンド ── 行を選択して Ctrl+Enter で転調 | |
| // t を書き換えると Pfunc({ t }) を使用する全パターンに即時反映される | |
| // ===================================================================== | |
| t = 0; // ルートに戻す | |
| t = 2; // 長2度上(D) | |
| t = 4; // 長3度上(E) | |
| t = 5; // 完全4度上(F) | |
| t = 7; // 完全5度上(G) | |
| t = 9; // 長6度上(A) | |
| t = -3; // 短3度下(A♭) | |
| t = -5; // 完全4度下(G♭) | |
| t = 18; | |
| t = rrand(-12, 12).postln; // ランダム転調(値を Post window に表示) | |
| // ===================================================================== | |
| // 停止コマンド ── 行を選択して Ctrl+Enter で個別 / 全停止 | |
| // ===================================================================== | |
| Pdef(\p3).stop; // p3 のみ停止 | |
| Pdef(\p4).stop; // p4 のみ停止 | |
| Pdef(\pBass).stop; // ベースのみ停止 | |
| Pdef(\pRhythm).stop; // リズムのみ停止 | |
| Ndef(\reverb).stop; // リバーブのみ停止 | |
| Pdef(\p3).stop; Pdef(\p4).stop; Pdef(\pBass).stop; Pdef(\pRhythm).stop; // 全停止 | |
| // 完全終了(ProxySpace のクリア): | |
| // p.clear; Ndef.clear; s.quit; | |
| // TempoClock.default.tempo = 1; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment