de035a8596
git-subtree-dir: sound_algo git-subtree-mainline:b7940d650fgit-subtree-split:38b17c42a0
812 lines
32 KiB
Plaintext
812 lines
32 KiB
Plaintext
// =====================================================================
|
|
// setup.scd -- Verification d'etat + init complete du projet
|
|
//
|
|
// USAGE PRINCIPAL (workflow recommande) :
|
|
// Tout est fait depuis 00_load.scd > bloc "CHARGER TOUT". Ce fichier
|
|
// est charge automatiquement par le loader, qui appelle ~setupAll.()
|
|
// a la fin. Tu n'as PAS besoin de l'ouvrir manuellement en general.
|
|
//
|
|
// USAGE MANUEL (debug ou redemarrage rapide) :
|
|
// Ouvre ce fichier dans l'IDE puis Cmd+Entree sur un bloc :
|
|
// ( ~check.() ) -- rapport d'etat colore
|
|
// ( ~setupAll.() ) -- recharge TOUT (engine + live + ...)
|
|
// ( ~setupLive.() ) -- recharge UNIQUEMENT live/* (rapide)
|
|
// ( ~ensureLive.() ) -- charge ce qui manque seulement
|
|
// ( ~teardown.() ) -- stop tout proprement
|
|
//
|
|
// HELPERS EXPOSES (tous definis dans le 1er bloc -- .load-compatible) :
|
|
// ~check status global colore
|
|
// ~setupAll charge engine + synthdefs + scales + melodies
|
|
// + harmonics + boot serveur + setup live + check
|
|
// ~setupLive recharge UNIQUEMENT les modules live (rapide)
|
|
// ~ensureLive charge live/* paresseusement (seulement absents)
|
|
// ~teardown stop tout proprement
|
|
// ~loadFirstBlock(path) helper interne -- evalue le 1er bloc d'un .scd
|
|
//
|
|
// STRUCTURE
|
|
// Le 1er bloc top-level contient TOUS les helpers : c'est le SETUP
|
|
// HELPERS, evaluable via .load setup.scd (ce que fait CHARGER TOUT).
|
|
// Les blocs suivants sont des exemples Cmd+Entree (pas charges par
|
|
// .load, evaluables manuellement dans l'IDE).
|
|
// =====================================================================
|
|
|
|
|
|
// =====================================================================
|
|
// SETUP HELPERS (1er bloc top-level -- .load-compatible)
|
|
//
|
|
// Definit ~base, ~loadFirstBlock, ~check, ~setupAll, ~setupLive,
|
|
// ~ensureLive, ~teardown. Ce bloc est execute par .load setup.scd
|
|
// depuis le bloc CHARGER TOUT de 00_load.scd.
|
|
// =====================================================================
|
|
(
|
|
// --- BASE PATH (auto-detection si pas deja defini) -------------------
|
|
~base = ~base ?? { "/Users/electron/Documents/Projets_Creatifs/sound_algo-refonte-v2/" };
|
|
"~base = ".post; ~base.postln;
|
|
|
|
|
|
// --- HELPER : ~loadFirstBlock ---------------------------------------
|
|
// Lit un fichier .scd et evalue son PREMIER bloc top-level (...) en
|
|
// comptant les parens balancees. Sert pour les fichiers multi-blocs
|
|
// dont seul le 1er bloc est le SETUP a evaluer (live/*, jump.scd, ...).
|
|
//
|
|
// Robuste : try/protect pour qu'une erreur d'un fichier n'arrete pas
|
|
// les autres. Print clair de chaque etape ([setupAll] ... OK / FAIL).
|
|
// --------------------------------------------------------------------
|
|
~loadFirstBlock = { |path|
|
|
var src, depth = 0, start = nil, firstBlock = nil;
|
|
var label = path.basename;
|
|
var i = 0, n, ch, ch2;
|
|
var inLineComment = false, inBlockComment = false, inString = false;
|
|
if (File.exists(path).not) {
|
|
("[setupAll] " ++ label ++ " ... FAIL (fichier introuvable)").postln;
|
|
} {
|
|
src = File.readAllString(path);
|
|
n = src.size;
|
|
block { |break|
|
|
while { i < n } {
|
|
ch = src[i];
|
|
ch2 = if (i + 1 < n) { src[i + 1] } { $ };
|
|
// ----- gestion des etats -----
|
|
if (inLineComment) {
|
|
if (ch == $\n) { inLineComment = false };
|
|
i = i + 1;
|
|
} {
|
|
if (inBlockComment) {
|
|
if ((ch == $*) and: { ch2 == $/ }) { inBlockComment = false; i = i + 2 }
|
|
{ i = i + 1 };
|
|
} {
|
|
if (inString) {
|
|
if (ch == $\\) { i = i + 2 } // skip escape
|
|
{ if (ch == $") { inString = false; i = i + 1 } { i = i + 1 } };
|
|
} {
|
|
// ----- pas dans un comment / string -----
|
|
// entree commentaire ligne
|
|
if ((ch == $/) and: { ch2 == $/ }) { inLineComment = true; i = i + 2 }
|
|
// entree commentaire bloc
|
|
{ if ((ch == $/) and: { ch2 == $* }) { inBlockComment = true; i = i + 2 }
|
|
// char literal SC : $( ou $) ou $" -- on saute le caractere suivant
|
|
{ if ((ch == $$) and: { (ch2 == $() or: { (ch2 == $)) or: { ch2 == $" } } }) { i = i + 2 }
|
|
// entree string
|
|
{ if (ch == $") { inString = true; i = i + 1 }
|
|
// parens REELLES
|
|
{ if (ch == $() {
|
|
if (depth == 0) { start = i };
|
|
depth = depth + 1;
|
|
i = i + 1;
|
|
} { if (ch == $)) {
|
|
depth = depth - 1;
|
|
if ((depth == 0) and: { start.notNil }) {
|
|
firstBlock = src.copyRange(start, i);
|
|
break.value;
|
|
};
|
|
i = i + 1;
|
|
} { i = i + 1 } } } } } };
|
|
} } };
|
|
};
|
|
};
|
|
if (firstBlock.isNil) {
|
|
("[setupAll] " ++ label ++ " ... FAIL (aucun bloc trouve)").postln;
|
|
} {
|
|
("[setupAll] " ++ label ++ " ... loading [" ++ firstBlock.size ++ " chars]").post;
|
|
try {
|
|
firstBlock.interpret;
|
|
" OK".postln;
|
|
} { |err|
|
|
" FAIL".postln;
|
|
(" " ++ err.errorString).postln;
|
|
};
|
|
};
|
|
};
|
|
};
|
|
|
|
|
|
// --- HELPER : ~loadAllBlocks ----------------------------------------
|
|
// Comme ~loadFirstBlock mais charge TOUS les blocs top-level d'un
|
|
// fichier. Utile pour fichiers comme sequences.scd qui ont leurs
|
|
// helpers en bloc 1 puis ~seqIntro/Buildup/Drop en blocs separes.
|
|
// Ignore comments / strings / char literals.
|
|
// --------------------------------------------------------------------
|
|
~loadAllBlocks = { |path|
|
|
var src, depth = 0, start = nil, blocks = List.new;
|
|
var label = path.basename;
|
|
var i = 0, n, ch, ch2;
|
|
var inLineComment = false, inBlockComment = false, inString = false;
|
|
if (File.exists(path).not) {
|
|
("[setupAll] " ++ label ++ " ... FAIL (fichier introuvable)").postln;
|
|
} {
|
|
src = File.readAllString(path);
|
|
n = src.size;
|
|
while { i < n } {
|
|
ch = src[i];
|
|
ch2 = if (i + 1 < n) { src[i + 1] } { $ };
|
|
if (inLineComment) {
|
|
if (ch == $\n) { inLineComment = false }; i = i + 1;
|
|
} {
|
|
if (inBlockComment) {
|
|
if ((ch == $*) and: { ch2 == $/ }) { inBlockComment = false; i = i + 2 } { i = i + 1 };
|
|
} {
|
|
if (inString) {
|
|
if (ch == $\\) { i = i + 2 } { if (ch == $") { inString = false; i = i + 1 } { i = i + 1 } };
|
|
} {
|
|
if ((ch == $/) and: { ch2 == $/ }) { inLineComment = true; i = i + 2 }
|
|
{ if ((ch == $/) and: { ch2 == $* }) { inBlockComment = true; i = i + 2 }
|
|
{ if ((ch == $$) and: { (ch2 == $() or: { (ch2 == $)) or: { ch2 == $" } } }) { i = i + 2 }
|
|
{ if (ch == $") { inString = true; i = i + 1 }
|
|
{ if (ch == $() {
|
|
if (depth == 0) { start = i };
|
|
depth = depth + 1; i = i + 1;
|
|
} { if (ch == $)) {
|
|
depth = depth - 1;
|
|
if ((depth == 0) and: { start.notNil }) {
|
|
blocks.add(src.copyRange(start, i));
|
|
start = nil;
|
|
};
|
|
i = i + 1;
|
|
} { i = i + 1 } } } } } };
|
|
} } };
|
|
};
|
|
("[setupAll] " ++ label ++ " ... " ++ blocks.size ++ " blocs ").post;
|
|
try {
|
|
blocks.do { |b| b.interpret };
|
|
" OK".postln;
|
|
} { |err|
|
|
" FAIL".postln;
|
|
(" " ++ err.errorString).postln;
|
|
};
|
|
};
|
|
};
|
|
|
|
|
|
// --- HELPER : ~check ------------------------------------------------
|
|
// Affiche un rapport coloree (postln) listant l'etat de chaque
|
|
// module. Utilise des prefixes ASCII :
|
|
// [OK] = tout est la
|
|
// [!!] = certains helpers manquent (action recommandee)
|
|
// [--] = pas initialise (optionnel : MIDI, jump)
|
|
// --------------------------------------------------------------------
|
|
~check = {
|
|
var sd = SynthDescLib.global.synthDescs;
|
|
var hasSd = { |sym| sd[sym].notNil };
|
|
var hasV = { |sym| currentEnvironment[sym].notNil };
|
|
var allSd = { |list| list.every { |s| hasSd.(s) } };
|
|
var allV = { |list| list.every { |s| hasV.(s) } };
|
|
var missingSd = { |list| list.select { |s| hasSd.(s).not } };
|
|
var missingV = { |list| list.select { |s| hasV.(s).not } };
|
|
var actions = List.new;
|
|
var line = { |label, status, msg|
|
|
("[" ++ label ++ "]").padRight(13).post;
|
|
status.post; " ".post; msg.postln;
|
|
};
|
|
|
|
"".postln;
|
|
"=== sound_algo STATUS ===".postln;
|
|
|
|
// ----- Server -----
|
|
if (s.serverRunning) {
|
|
("[server] running, " ++ s.numSynths ++ " synths, "
|
|
++ s.avgCPU.round(0.1) ++ "% CPU").postln;
|
|
} {
|
|
"[server] [--] pas demarre (lance ~setupAll ou s.boot)".postln;
|
|
actions.add("Lance ~setupAll.() pour booter le serveur");
|
|
};
|
|
|
|
// ----- engine.scd -----
|
|
block { |b|
|
|
var engineSd = [\kick, \hat, \snare, \clap, \acid, \lead, \pad, \pluck,
|
|
\fmBell, \stab, \saw3, \openHat, \crash, \tom, \rim,
|
|
\cowbell, \reese, \bass808, \impact, \riser, \sweep,
|
|
\vinyl, \masterLim];
|
|
var engineHelpers = [\reload, \bpm, \kickAmp, \melodyAmp, \melodyNotes,
|
|
\kickSteps, \scBus, \masterLim];
|
|
var miss = missingSd.(engineSd) ++ missingV.(engineHelpers);
|
|
if (miss.isEmpty) {
|
|
line.("engine", "[OK]", engineSd.size.asString
|
|
++ " SynthDefs + ~reload + ~scBus + ~masterLim");
|
|
} {
|
|
line.("engine", "[!!]", "manquant : " ++ miss);
|
|
actions.add("CHARGER TOUT depuis 00_load.scd (engine + synthdefs + scales + melodies + harmonics)");
|
|
};
|
|
};
|
|
|
|
// ----- synth/_index.scd : asia palette -----
|
|
block { |b|
|
|
var asia = [\koto, \erhu, \pipa, \gong, \growl, \reeseHard];
|
|
var miss = missingSd.(asia);
|
|
if (miss.isEmpty) { line.("asia", "[OK]", asia.size.asString ++ " SynthDefs"); }
|
|
{ line.("asia", "[!!]", "manquant : " ++ miss); };
|
|
};
|
|
|
|
// ----- synth/_index.scd : extra palette -----
|
|
block { |b|
|
|
var extra = [\squareLead, \fmLead, \organLead, \hardLead, \warmPad,
|
|
\strings, \choir, \fmBass, \subBoom, \handpan, \flute, \drone];
|
|
var miss = missingSd.(extra);
|
|
if (miss.isEmpty) { line.("extra", "[OK]", extra.size.asString ++ " SynthDefs"); }
|
|
{ line.("extra", "[!!]", "manquant : " ++ miss); };
|
|
};
|
|
|
|
// ----- synth/_index.scd : authentic palette -----
|
|
block { |b|
|
|
var auth = [\kickGabber, \kick808, \snareGated, \reeseDnB, \supersaw,
|
|
\hooverbass, \rhodes, \vocalPad, \didgeridoo, \guzheng,
|
|
\shakuhachi, \taiko, \tabla, \scratch];
|
|
var miss = missingSd.(auth);
|
|
if (miss.isEmpty) { line.("authentic", "[OK]", auth.size.asString ++ " SynthDefs"); }
|
|
{ line.("authentic", "[!!]", "manquant : " ++ miss); };
|
|
};
|
|
|
|
// ----- palette/scales.scd -----
|
|
block { |b|
|
|
var scales = [\scaleMinor, \scaleDorian, \scaleMinorPent, \scaleAcid,
|
|
\scaleHijaz, \scaleVietnam];
|
|
var helpers = [\genMelody, \mutate, \octavate, \transpose, \retrograde,
|
|
\densify, \sparsify, \jitter, \genAcidNotes, \genKickPattern,
|
|
\randomTweak];
|
|
var miss = missingV.(scales) ++ missingV.(helpers);
|
|
if (miss.isEmpty) {
|
|
line.("scales", "[OK]", "16 scales + ~genMelody/mutate/octavate/...");
|
|
} {
|
|
line.("scales", "[!!]", "manquant : " ++ miss);
|
|
actions.add("CHARGER TOUT (scales = source unique helpers melodiques)");
|
|
};
|
|
};
|
|
|
|
// ----- palette/melodies/* -----
|
|
block { |b|
|
|
var probes = [\m1, \m78, \ml1, \ml30, \mxl1, \mxl15, \mepic1, \mepic10,
|
|
\melodyBank, \useMelody, \melodyByGenre, \chainPatterns, \buildArc];
|
|
var miss = missingV.(probes);
|
|
if (miss.isEmpty) {
|
|
line.("melodies", "[OK]",
|
|
"~m1..78, ~ml1..30, ~mxl1..15, ~mepic1..10 + ~useMelody/byGenre");
|
|
} {
|
|
line.("melodies", "[!!]", "manquant : " ++ miss);
|
|
actions.add("CHARGER TOUT (charge palette/melodies/index.scd)");
|
|
};
|
|
};
|
|
|
|
// ----- palette/harmonics/* -----
|
|
block { |b|
|
|
var probes = [\enableHarmony, \genThirdHarmony, \genFifthHarmony,
|
|
\genCounterMelody, \genArpFromChords];
|
|
var miss = missingV.(probes);
|
|
if (miss.isEmpty) {
|
|
line.("harmonics", "[OK]", "~enableHarmony + 4 helpers");
|
|
} {
|
|
line.("harmonics", "[!!]", "manquant : " ++ miss);
|
|
actions.add("CHARGER TOUT (charge palette/harmonics/index.scd)");
|
|
};
|
|
};
|
|
|
|
// ----- palette/melodies/tracks.scd (multi-pistes) -----
|
|
block { |b|
|
|
var probes = [\mel, \melTrackAdd, \melTrackOn, \melTrackOff, \melTrackSet,
|
|
\melTrackList, \melTrackSolo];
|
|
var miss = missingV.(probes);
|
|
if (miss.isEmpty) {
|
|
line.("mel-track", "[OK]", "~mel + ~melTrackAdd/On/Off/Set/...");
|
|
} {
|
|
line.("mel-track", "[!!]", "manquant : " ++ miss);
|
|
};
|
|
};
|
|
|
|
// ----- live API wrappers (~kk / ~mm / ~ff / ~cc / ~p) -----
|
|
// Ces wrappers (live/_load.scd) remplacent fonctionnellement les
|
|
// ~kK1, ~clC1, ~pcP1 des palette/rhythm/* (qui sont multi-blocs).
|
|
block { |b|
|
|
var probes = [\kk, \kPat, \kTim, \kList,
|
|
\mm, \mShort, \mLong, \mEpic, \mGen, \mList,
|
|
\ff, \fxSnd, \fxSt, \fxDrop, \fxList,
|
|
\chIntro, \chDrop, \chBuildup, \chList,
|
|
\pKit, \pGenre, \pHat, \pList];
|
|
var miss = missingV.(probes);
|
|
if (miss.isEmpty) {
|
|
line.("live-api", "[OK]", "~kk ~mm ~ff ~chIntro ~pKit + 19 wrappers");
|
|
} {
|
|
line.("live-api", "[!!]", "manquant : " ++ miss);
|
|
actions.add("Lance (~base++\"live/_load.scd\").load (charge les 5 wrappers live)");
|
|
};
|
|
};
|
|
|
|
// ----- palette/rhythm/fills.scd (~snareFill / ~tomFill) -----
|
|
block { |b|
|
|
var probes = [\snareFill, \tomFill];
|
|
var miss = missingV.(probes);
|
|
if (miss.isEmpty) {
|
|
line.("fills", "[OK]", "~snareFill / ~tomFill");
|
|
} {
|
|
line.("fills", "[!!]", "~snareFill et/ou ~tomFill manquent");
|
|
actions.add("Lance ~setupAll.() (charge palette/rhythm/fills.scd)");
|
|
};
|
|
};
|
|
|
|
// ----- palette/rhythm/sequences.scd (~seqPlay / ~seqIntro / ...) -----
|
|
block { |b|
|
|
var probes = [\seqPlay, \seqStop, \seqIntro, \seqBuildup, \seqDrop];
|
|
var miss = missingV.(probes);
|
|
if (miss.isEmpty) {
|
|
line.("sequences", "[OK]", "~seqPlay / ~seqIntro / ~seqBuildup / ~seqDrop / ...");
|
|
} {
|
|
line.("sequences", "[!!]", "manquant : " ++ miss);
|
|
actions.add("Lance ~setupAll.() (charge palette/rhythm/sequences.scd)");
|
|
};
|
|
};
|
|
|
|
// ----- palette/chords_progressions.scd -----
|
|
block { |b|
|
|
var probes = [\progDetroit, \progTrance, \progDnB, \chordsToMelody];
|
|
var miss = missingV.(probes);
|
|
if (miss.isEmpty) {
|
|
line.("chords", "[OK]", "~progXxx + ~chordsToMelody/Harmony");
|
|
} {
|
|
line.("chords", "[--]", "non charge (optionnel) : " ++ miss);
|
|
};
|
|
};
|
|
|
|
// ----- live/live.scd -----
|
|
block { |b|
|
|
var probes = [\lfoTo, \vcfOn, \drop, \breakdown, \stutter, \glitch,
|
|
\freeze, \addFx, \compOn, \satOn];
|
|
var miss = missingV.(probes);
|
|
if (miss.isEmpty) {
|
|
line.("live", "[OK]", "~lfoTo / ~vcfOn / ~drop / ~stutter / ~addFx / ~compOn / ...");
|
|
} {
|
|
line.("live", "[!!]", "manquant : " ++ miss);
|
|
actions.add("Lance ~setupAll.() (charge live/live.scd)");
|
|
};
|
|
};
|
|
|
|
// ----- live/mixer.scd -----
|
|
block { |b|
|
|
var probes = [\setVol, \mute, \solo, \mixPreset, \mixMaster, \mix];
|
|
var miss = missingV.(probes);
|
|
if (miss.isEmpty) {
|
|
line.("mixer", "[OK]", "~setVol / ~mute / ~solo / ~mixPreset / ~mixMaster");
|
|
} {
|
|
line.("mixer", "[!!]", "manquant : " ++ miss);
|
|
actions.add("Lance ~setupAll.() (charge live/mixer.scd)");
|
|
};
|
|
};
|
|
|
|
// ----- live/fx_bus.scd -----
|
|
block { |b|
|
|
var probes = [\fxFx, \fxBuses, \send, \setFx, \lfo, \fxPreset, \tap];
|
|
var miss = missingV.(probes);
|
|
if (miss.isEmpty) {
|
|
line.("fx_bus", "[OK]", "9 bus FX + ~send / ~setFx / ~lfo / ~fxPreset / ~tap");
|
|
} {
|
|
line.("fx_bus", "[!!]", "manquant : " ++ miss);
|
|
actions.add("Lance ~setupAll.() (charge live/fx_bus.scd EN PREMIER)");
|
|
};
|
|
};
|
|
|
|
// ----- live/scenes.scd -----
|
|
block { |b|
|
|
var probes = [\saveScene, \loadScene, \listScenes];
|
|
var miss = missingV.(probes);
|
|
if (miss.isEmpty) {
|
|
line.("scenes", "[OK]", "~saveScene / ~loadScene / ~listScenes");
|
|
} {
|
|
line.("scenes", "[!!]", "manquant : " ++ miss);
|
|
actions.add("Lance ~setupAll.() (charge live/scenes.scd)");
|
|
};
|
|
};
|
|
|
|
// ----- live/loops.scd -----
|
|
block { |b|
|
|
var probes = [\loopOn, \loopOff, \loopRepeat, \loopProgress, \loopList];
|
|
var miss = missingV.(probes);
|
|
if (miss.isEmpty) {
|
|
line.("loops", "[OK]", "~loopOn / ~loopOff / ~loopRepeat / ~loopProgress");
|
|
} {
|
|
line.("loops", "[!!]", "manquant : " ++ miss);
|
|
actions.add("Lance ~setupAll.() (charge live/loops.scd)");
|
|
};
|
|
};
|
|
|
|
// ----- live/memory_guard.scd -----
|
|
block { |b|
|
|
var probes = [\killAllOrphans, \memReport, \watchdogOn, \watchdogOff];
|
|
var miss = missingV.(probes);
|
|
if (miss.isEmpty) {
|
|
line.("guard", "[OK]", "~killAllOrphans / ~memReport / ~watchdogOn / ~watchdogOff");
|
|
} {
|
|
line.("guard", "[!!]", "manquant : " ++ miss);
|
|
actions.add("Lance ~setupAll.() (charge live/memory_guard.scd)");
|
|
};
|
|
};
|
|
|
|
// ----- control/midi.scd (optionnel) -----
|
|
block { |b|
|
|
if (~midiFuncs.notNil and: { ~midiFuncs.size > 0 }) {
|
|
line.("midi", "[OK]", "~midiFuncs (" ++ ~midiFuncs.size ++ " mappings)");
|
|
} {
|
|
line.("midi", "[--]", "pas init (optionnel) -- ouvre control/midi.scd");
|
|
};
|
|
};
|
|
|
|
// ----- control/playlist.scd (optionnel) -----
|
|
block { |b|
|
|
if (hasV.(\playPlaylist)) {
|
|
line.("playlist", "[OK]", "~playPlaylist pret");
|
|
} {
|
|
line.("playlist", "[--]", "pas charge (optionnel) -- ouvre control/playlist.scd");
|
|
};
|
|
};
|
|
|
|
// ----- control/jump.scd -----
|
|
block { |b|
|
|
if (hasV.(\jumpTo) and: { hasV.(\sections) }) {
|
|
var nbTracks = ~sections.size;
|
|
line.("jump", "[OK]", "~jumpTo + ~sections (" ++ nbTracks ++ " tracks chargees)");
|
|
} {
|
|
line.("jump", "[!!]", "pas init");
|
|
actions.add("Lance ~setupAll.() (charge control/jump.scd)");
|
|
};
|
|
};
|
|
|
|
"=== fin status ===".postln;
|
|
|
|
if (actions.size > 0) {
|
|
"".postln;
|
|
"ACTIONS RECOMMANDEES :".postln;
|
|
actions.do { |a| (" - " ++ a).postln };
|
|
} {
|
|
"".postln;
|
|
"Tout est OK -- pret a jouer.".postln;
|
|
};
|
|
"".postln;
|
|
};
|
|
|
|
|
|
// --- HELPER : ~setupAll ---------------------------------------------
|
|
// Charge engine + synthdefs + scales + melodies + harmonics, attend
|
|
// le boot du serveur (skip si deja boote), puis evalue le 1er bloc
|
|
// (SETUP) de chaque module live + rhythm/fills + rhythm/sequences +
|
|
// control/jump. Termine par ~check.()
|
|
//
|
|
// Print clair de chaque etape via ~loadFirstBlock (qui catche les
|
|
// erreurs : un fichier qui plante n'arrete PAS les autres).
|
|
//
|
|
// Ordre d'init des modules live :
|
|
// 1. fx_bus.scd (alloue les bus FX, doit etre en PREMIER)
|
|
// 2. live.scd (LFO/VCF/tricks/SynthDefs additionnels)
|
|
// 3. mixer.scd (~mix / ~setVol / ~mute / ~solo)
|
|
// 4. scenes.scd (~saveScene / ~loadScene)
|
|
// 5. loops.scd (~loopOn / ~loopOff / ~loopRepeat)
|
|
// 6. rhythm/fills.scd (~snareFill / ~tomFill)
|
|
// 7. rhythm/sequences.scd (~seqPlay / ~seqIntro / ~seqDrop / ...)
|
|
// 8. control/jump.scd (~jumpTo + ~sections)
|
|
//
|
|
// PAS init automatiquement :
|
|
// - control/midi.scd (init MIDI -- a faire manuellement)
|
|
// - control/playlist.scd (juste un helper, charge a la demande)
|
|
// - live/tweaks.scd (one-liners, pas de SETUP)
|
|
// --------------------------------------------------------------------
|
|
~setupAll = {
|
|
var liveSetup = {
|
|
"".postln;
|
|
"=== ~setupAll : init modules live ===".postln;
|
|
|
|
// Ordre critique : fx_bus.scd EN PREMIER (alloue ~fxBuses / ~fxFx
|
|
// que les autres modules peuvent referencer)
|
|
~loadFirstBlock.(~base ++ "live/fx_bus.scd");
|
|
~loadFirstBlock.(~base ++ "live/live.scd");
|
|
~loadFirstBlock.(~base ++ "live/mixer.scd");
|
|
~loadFirstBlock.(~base ++ "live/scenes.scd");
|
|
~loadFirstBlock.(~base ++ "live/loops.scd");
|
|
~loadFirstBlock.(~base ++ "live/memory_guard.scd");
|
|
(~base ++ "palette/rhythm/_index.scd").load; // fills + sequences (auto-discovery)
|
|
~loadAllBlocks.(~base ++ "palette/chords_progressions.scd");
|
|
~loadFirstBlock.(~base ++ "control/jump.scd");
|
|
|
|
// 5 wrappers API live (~kk / ~mm / ~ff / ~cc / ~p) -- 1er bloc
|
|
// chacun contient les definitions ; les blocs suivants sont des
|
|
// exemples interactifs Cmd+Entree qu'on ne veut PAS executer au boot.
|
|
~loadFirstBlock.(~base ++ "live/kicks.scd");
|
|
~loadFirstBlock.(~base ++ "live/melodies.scd");
|
|
~loadFirstBlock.(~base ++ "live/fx.scd");
|
|
~loadFirstBlock.(~base ++ "live/chains.scd");
|
|
~loadFirstBlock.(~base ++ "live/patterns.scd");
|
|
|
|
s.sync;
|
|
|
|
// Hook CmdPeriod : chaque Cmd-. declenche aussi ~killAllOrphans
|
|
// pour eviter l'accumulation de Routines/Bus apres un panic stop.
|
|
~guardCmdPeriodOn !? { ~guardCmdPeriodOn.value };
|
|
|
|
"".postln;
|
|
"=== setupAll DONE ===".postln;
|
|
"".postln;
|
|
~check.value;
|
|
};
|
|
|
|
"=== ~setupAll : start ===".postln;
|
|
~base = ~base ?? { "/Users/electron/Documents/Projets_Creatifs/sound_algo-refonte-v2/" };
|
|
|
|
// --- 1. Charge tous les fichiers .load-compatibles ---
|
|
"[setupAll] engine.scd ... loading".postln;
|
|
(~base ++ "engine.scd").load;
|
|
"[setupAll] synth/_index.scd ... loading".postln;
|
|
(~base ++ "synth/_index.scd").load;
|
|
"[setupAll] fx/_index.scd ... loading".postln;
|
|
(~base ++ "fx/_index.scd").load;
|
|
"[setupAll] palette/scales.scd ... loading".postln;
|
|
(~base ++ "palette/scales.scd").load;
|
|
"[setupAll] palette/melodies/index.scd ... loading".postln;
|
|
(~base ++ "palette/melodies/index.scd").load;
|
|
"[setupAll] palette/harmonics/index.scd ... loading".postln;
|
|
(~base ++ "palette/harmonics/index.scd").load;
|
|
|
|
// --- 2. Boot serveur (skip si deja boote) puis init modules live ---
|
|
// Augmente maxSynthDefs (defaut 1024) car le projet en charge >1100
|
|
// (1060 dans synth/ + ~40 dans fx/ + inline). A passer en option scsynth
|
|
// AVANT s.boot, sinon les SynthDef au-dela de 1024 echouent
|
|
// silencieusement avec "Could not add SynthDef X".
|
|
s.options.maxSynthDefs = 4096;
|
|
if (s.serverRunning) {
|
|
"=== ~setupAll : serveur deja boote, skip waitForBoot ===".postln;
|
|
liveSetup.value;
|
|
} {
|
|
"=== ~setupAll : boot serveur en cours... ===".postln;
|
|
s.waitForBoot {
|
|
s.sync;
|
|
"=== ~setupAll : boot OK ===".postln;
|
|
liveSetup.value;
|
|
};
|
|
};
|
|
};
|
|
|
|
|
|
// --- HELPER : ~setupLive --------------------------------------------
|
|
// Charge UNIQUEMENT les modules live (ne touche pas engine /
|
|
// synthdefs / scales / melodies / harmonics). Pour redemarrage
|
|
// rapide quand le serveur tourne deja avec engine charge.
|
|
// --------------------------------------------------------------------
|
|
~setupLive = {
|
|
~base = ~base ?? { "/Users/electron/Documents/Projets_Creatifs/sound_algo-refonte-v2/" };
|
|
if (s.serverRunning.not) {
|
|
"!! ~setupLive : serveur pas demarre. Lance ~setupAll a la place.".postln;
|
|
} {
|
|
"=== ~setupLive : init modules live seulement ===".postln;
|
|
~loadFirstBlock.(~base ++ "live/fx_bus.scd");
|
|
~loadFirstBlock.(~base ++ "live/live.scd");
|
|
~loadFirstBlock.(~base ++ "live/mixer.scd");
|
|
~loadFirstBlock.(~base ++ "live/scenes.scd");
|
|
~loadFirstBlock.(~base ++ "live/loops.scd");
|
|
~loadFirstBlock.(~base ++ "live/memory_guard.scd");
|
|
(~base ++ "palette/rhythm/_index.scd").load; // fills + sequences (auto-discovery)
|
|
~loadAllBlocks.(~base ++ "palette/chords_progressions.scd");
|
|
~loadFirstBlock.(~base ++ "control/jump.scd");
|
|
// 5 wrappers API live (~kk / ~mm / ~ff / ~cc / ~p)
|
|
~loadFirstBlock.(~base ++ "live/kicks.scd");
|
|
~loadFirstBlock.(~base ++ "live/melodies.scd");
|
|
~loadFirstBlock.(~base ++ "live/fx.scd");
|
|
~loadFirstBlock.(~base ++ "live/chains.scd");
|
|
~loadFirstBlock.(~base ++ "live/patterns.scd");
|
|
"=== ~setupLive : OK ===".postln;
|
|
~check.value;
|
|
};
|
|
};
|
|
|
|
|
|
// --- HELPER : ~ensureLive -------------------------------------------
|
|
// Helper paresseux : detecte ce qui manque dans live/* + fills +
|
|
// sequences + jump et charge SEULEMENT les modules absents.
|
|
// Idempotent : peut etre appele plusieurs fois sans rien recharger.
|
|
// --------------------------------------------------------------------
|
|
~ensureLive = {
|
|
var loaded = 0;
|
|
~base = ~base ?? { "/Users/electron/Documents/Projets_Creatifs/sound_algo-refonte-v2/" };
|
|
if (s.serverRunning.not) {
|
|
"!! ~ensureLive : serveur pas demarre. Lance ~setupAll d'abord.".postln;
|
|
} {
|
|
// fx_bus en premier (les autres modules peuvent en dependre)
|
|
if (~fxFx.isNil or: { ~send.isNil }) {
|
|
"ensure : fx_bus.scd".postln;
|
|
~loadFirstBlock.(~base ++ "live/fx_bus.scd");
|
|
loaded = loaded + 1;
|
|
};
|
|
if (~lfoTo.isNil or: { ~vcfOn.isNil }) {
|
|
"ensure : live.scd".postln;
|
|
~loadFirstBlock.(~base ++ "live/live.scd");
|
|
loaded = loaded + 1;
|
|
};
|
|
if (~setVol.isNil or: { ~mixPreset.isNil }) {
|
|
"ensure : mixer.scd".postln;
|
|
~loadFirstBlock.(~base ++ "live/mixer.scd");
|
|
loaded = loaded + 1;
|
|
};
|
|
if (~saveScene.isNil) {
|
|
"ensure : scenes.scd".postln;
|
|
~loadFirstBlock.(~base ++ "live/scenes.scd");
|
|
loaded = loaded + 1;
|
|
};
|
|
if (~loopOn.isNil) {
|
|
"ensure : loops.scd".postln;
|
|
~loadFirstBlock.(~base ++ "live/loops.scd");
|
|
loaded = loaded + 1;
|
|
};
|
|
if (~killAllOrphans.isNil) {
|
|
"ensure : memory_guard.scd".postln;
|
|
~loadFirstBlock.(~base ++ "live/memory_guard.scd");
|
|
loaded = loaded + 1;
|
|
};
|
|
if (~snareFill.isNil or: { ~tomFill.isNil }
|
|
or: { ~seqPlay.isNil } or: { ~seqIntro.isNil }) {
|
|
"ensure : palette/rhythm/_index.scd (fills + sequences)".postln;
|
|
(~base ++ "palette/rhythm/_index.scd").load;
|
|
loaded = loaded + 1;
|
|
};
|
|
if (~jumpTo.isNil) {
|
|
"ensure : jump.scd".postln;
|
|
~loadFirstBlock.(~base ++ "control/jump.scd");
|
|
loaded = loaded + 1;
|
|
};
|
|
if (~progDetroit.isNil or: { ~chordsToMelody.isNil }) {
|
|
"ensure : chords_progressions.scd".postln;
|
|
~loadAllBlocks.(~base ++ "palette/chords_progressions.scd");
|
|
loaded = loaded + 1;
|
|
};
|
|
// 5 wrappers API live (chacun expose un dict + des wrappers env)
|
|
if (~kk.isNil) {
|
|
"ensure : live/kicks.scd".postln;
|
|
~loadFirstBlock.(~base ++ "live/kicks.scd");
|
|
loaded = loaded + 1;
|
|
};
|
|
if (~mm.isNil) {
|
|
"ensure : live/melodies.scd".postln;
|
|
~loadFirstBlock.(~base ++ "live/melodies.scd");
|
|
loaded = loaded + 1;
|
|
};
|
|
if (~ff.isNil) {
|
|
"ensure : live/fx.scd".postln;
|
|
~loadFirstBlock.(~base ++ "live/fx.scd");
|
|
loaded = loaded + 1;
|
|
};
|
|
if (~cc.isNil) {
|
|
"ensure : live/chains.scd".postln;
|
|
~loadFirstBlock.(~base ++ "live/chains.scd");
|
|
loaded = loaded + 1;
|
|
};
|
|
if (~p.isNil) {
|
|
"ensure : live/patterns.scd".postln;
|
|
~loadFirstBlock.(~base ++ "live/patterns.scd");
|
|
loaded = loaded + 1;
|
|
};
|
|
if (loaded == 0) {
|
|
"=== ~ensureLive : tout est deja la, rien a charger ===".postln;
|
|
} {
|
|
("=== ~ensureLive : " ++ loaded ++ " module(s) charge(s) ===").postln;
|
|
};
|
|
};
|
|
};
|
|
|
|
|
|
// --- HELPER : ~teardown ---------------------------------------------
|
|
// Stop tout proprement :
|
|
// - ~track et autres routines
|
|
// - tous les Pdef de l'engine
|
|
// - LFO / VCF / loops / playlist / sequences
|
|
// - libere ~masterLim et ~scBus
|
|
// - libere les bus FX et synths FX si presents
|
|
// --------------------------------------------------------------------
|
|
~teardown = {
|
|
"=== ~teardown : stop tout ===".postln;
|
|
|
|
// Watchdog memory_guard et album orchestrateur
|
|
~watchdogOff !? { ~watchdogOff.value };
|
|
~albumRoutine !? { ~albumRoutine.stop; ~albumRoutine = nil };
|
|
|
|
// Routines de track / sweep / loops engine
|
|
~track !? { ~track.stop; ~track = nil };
|
|
~filterSweep !? { ~filterSweep.stop; ~filterSweep = nil };
|
|
~randomLoop !? { ~randomLoop.stop; ~randomLoop = nil };
|
|
~melodyEvolve !? { ~melodyEvolve.stop; ~melodyEvolve = nil };
|
|
~lRotate !? { ~lRotate.stop; ~lRotate = nil };
|
|
|
|
// Tous les Pdef
|
|
[\kickSeq, \hatSeq, \snareSeq, \clapSeq, \percSeq,
|
|
\acidSeq, \melodySeq, \harmonySeq].do { |k| Pdef(k).stop };
|
|
|
|
// LFO live (live.scd)
|
|
~lfoStopEverything !? { ~lfoStopEverything.value };
|
|
|
|
// LFO fx_bus (fx_bus.scd)
|
|
~lfoStopAll !? { ~lfoStopAll.value };
|
|
|
|
// VCF master
|
|
~vcfOff !? { ~vcfOff.value };
|
|
|
|
// Loops live
|
|
~loopOffAll !? { ~loopOffAll.value };
|
|
|
|
// Sequences (palette/rhythm/sequences.scd)
|
|
~seqStop !? { ~seqStop.value };
|
|
|
|
// Auto-fx (autoPan / tremolo)
|
|
~stopAutoFx !? {
|
|
[\kick, \hat, \snare, \clap, \perc, \acid, \melody, \harmony]
|
|
.do { |v| ~stopAutoFx.(v) };
|
|
};
|
|
|
|
// Compresseur / saturation master
|
|
~compOff !? { ~compOff.value };
|
|
~satOff !? { ~satOff.value };
|
|
|
|
// Playlist
|
|
~playlist !? { ~playlist.stop; ~playlist = nil };
|
|
|
|
// Free pdef tracks melodiques (multi-pistes)
|
|
~melTrackChoke !? { ~melTrackChoke.value };
|
|
|
|
// Master limiter + sidechain bus
|
|
~masterLim !? { ~masterLim.free; ~masterLim = nil };
|
|
~scBus !? { ~scBus.free; ~scBus = nil };
|
|
|
|
// Bus FX + synths FX
|
|
~fxFx !? {
|
|
~fxFx.do { |syn| syn !? { syn.free } };
|
|
~fxFx = nil;
|
|
};
|
|
~fxBuses !? {
|
|
~fxBuses.do { |b| b !? { b.free } };
|
|
~fxBuses = nil;
|
|
};
|
|
|
|
"=== ~teardown OK ===".postln;
|
|
};
|
|
|
|
"~loadFirstBlock / ~check / ~setupAll / ~setupLive / ~ensureLive / ~teardown prets".postln;
|
|
)
|
|
|
|
|
|
// =====================================================================
|
|
// BLOCS Cmd+Entree -- workflows manuels (executes a la demande)
|
|
//
|
|
// IMPORTANT : ces blocs sont COMMENTES car .load echoue avec >1 bloc
|
|
// top-level. Pour les utiliser : DECOMMENTE la ligne (retire les "//")
|
|
// puis Cmd+Entree dessus dans l'IDE. Ou copie-colle le contenu.
|
|
// =====================================================================
|
|
|
|
// --- VERIF rapide de l'etat ----------
|
|
// ( ~check.(); )
|
|
|
|
// --- INIT COMPLETE (charge tout + boot + setup live + check) ---------
|
|
// ( ~setupAll.(); )
|
|
|
|
// --- INIT LIVE SEULEMENT (serveur deja boote) ------------------------
|
|
// ( ~setupLive.(); )
|
|
|
|
// --- INIT PARESSEUSE (charge ce qui manque seulement) ----------------
|
|
// ( ~ensureLive.(); )
|
|
|
|
// --- ARRET PROPRE ----------------------------------------------------
|
|
// ( ~teardown.(); )
|
|
|
|
// --- COMBO : check d'abord, puis setup auto si besoin ----------------
|
|
// ( ~check.(); ~setupAll.(); )
|
|
|
|
// --- COMBO : teardown puis re-setupAll (full restart sans rebooter) --
|
|
// ( ~teardown.(); ~setupAll.(); )
|