diff --git a/instruments.scd b/instruments.scd index f2a79a4..301101b 100644 --- a/instruments.scd +++ b/instruments.scd @@ -1,9 +1,106 @@ ( ~dict = BmDspAlgs.getDict("spectral/fft_freeze.scd"); +~dict[\defaults] = ( + attack: 0.01, + release: 0.1, + curve: 1 +); +~dict[\sustained] = true; +~dict[\useEnv] = true; ~dict2 = BmDspAlgs.getDict("spectral/fft_freeze_follow.scd"); ~dict.makeBufferProcessingNdef(\freeze1); ~dict.makeBufferProcessingNdef(\freeze2); ~dict2.makeBufferProcessingNdef(\freeze3); "instrumets loaded".postln; -) + +Ndef(\freeze1).set(\in, ~inBus.index); +Ndef(\freeze2).set(\in, ~inBus.index); +Ndef(\freeze3).set(\in, ~inBus.index); + +"inBus setted as NDefs input".postln; + +Ndef(\freeze1).put(10, \filter -> { + |in| + PitchShift.ar( + in, + 0.2, + \shift.kr(2), + 0.01, 0.01 + ); +}); + +Ndef(\freeze2).put(10, \filter -> { + |in| + PitchShift.ar( + in, + 0.2, + \shift.kr(2), + 0.01, 0.01 + ); +}); + +Ndef(\freeze1).set(\wet10, 0); +Ndef(\freeze2).set(\wet10, 0); + +// Динамика: компрессор + нормалайзер + лимитер. +// Сжимает громкое, поднимает тихое, не даёт пробить наушники. +Ndef(\freeze1).put(20, \filter -> { + |in| + // Лёгкая компрессия: сжимаем только то, что выше порога (громкое). + var comp = Compander.ar( + in, in, + thresh: \compThresh.kr(0.5), + slopeBelow: 1.0, + slopeAbove: \compSlope.kr(0.5), + clampTime: \compClamp.kr(0.01), + relaxTime: \compRelax.kr(0.1) + ); + // Нормалайзер: подтягивает тихий сигнал до норм. уровня (flattens dynamics). + var norm = Normalizer.ar(comp, \normLevel.kr(0.5), \normDur.kr(0.05)); + // Лимитер: жёсткий потолок от пробоя наушников. + Limiter.ar(norm, \limLevel.kr(0.002), \limDur.kr(0.01)); +}); + +Ndef(\freeze2).put(20, \filter -> { + |in| + // Лёгкая компрессия: сжимаем только то, что выше порога (громкое). + var comp = Compander.ar( + in, in, + thresh: \compThresh.kr(0.5), + slopeBelow: 1.0, + slopeAbove: \compSlope.kr(0.5), + clampTime: \compClamp.kr(0.01), + relaxTime: \compRelax.kr(0.1) + ); + // Нормалайзер: подтягивает тихий сигнал до норм. уровня (flattens dynamics). + var norm = Normalizer.ar(comp, \normLevel.kr(0.5), \normDur.kr(0.05)); + // Лимитер: жёсткий потолок от пробоя наушников. + Limiter.ar(norm, \limLevel.kr(0.002), \limDur.kr(0.01)); +}); + +// Применяем specs из словарей к Ndef (нужно для GUI и маппинга контроллера). +// TODO(bmSClib): автоматизировать — см. readme.org, секция TODO. +~dict[\specs].keysValuesDo { |k, v| Ndef(\freeze1).addSpec(k, v) }; +~dict[\specs].keysValuesDo { |k, v| Ndef(\freeze2).addSpec(k, v) }; +~dict2[\specs].keysValuesDo { |k, v| Ndef(\freeze3).addSpec(k, v) }; + +// Спек-параметры обёртки processSig (в dict их нет). +[\freeze1, \freeze2, \freeze3].do { |n| + Ndef(n).addSpec(\postAmp, [0, 1, \lin, 0, 1]); + Ndef(n).addSpec(\pan, [-1, 1, \lin, 0, 0]); +}; + +// Огибающая (useEnv) и питчшифтер есть только у freeze1/2. +[\freeze1, \freeze2].do { |n| + Ndef(n).addSpec(\envGate, [0, 1, \lin, 0, 0]); + Ndef(n).addSpec(\attack, [0.001, 4, \exp, 0.001, 0.01]); + Ndef(n).addSpec(\release, [0.001, 4, \exp, 0.001, 0.1]); + Ndef(n).addSpec(\shift, [0.5, 2, \exp, 0.01, 2]); + Ndef(n).addSpec(\wet10, [0, 1, \lin, 0, 0]); +}; + +"FX added".postln; + + +) \ No newline at end of file diff --git a/main.scd b/main.scd index 6631667..4b70de6 100644 --- a/main.scd +++ b/main.scd @@ -1,34 +1,38 @@ ( s.options.memSize_(2.pow(20)); s.waitForBoot({ - ~makeBuffers = { |path, event, mono = false| - var dir = PathName.new(path); - var contents = dir.entries; - if (contents.select({ |n| n.isFile }).size > 0) - { - var files, bufArray; - files = contents.select({ |n| n.isFile }); - files = files.select({ |n| - ["aif", "aiff", "wav"].includesEqual(n.extension) - }); - if (event[dir.folderName.asSymbol] != nil) - { "duplicate subfolder name ignored".warn; } - { - bufArray = files.collect({ |n| - if(mono) - { Buffer.readChannel(s, n.fullPath, channels:[0]) } - { Buffer.read(s, n.fullPath) }; - }); - event[dir.folderName.asSymbol] = bufArray; - }; - }; - if (contents.select({ |n| n.isFolder }).size > 0) - { - var folders = contents.select({ |n| n.isFolder }); - folders.do({ |n| ~makeBuffers.(n.fullPath, event, mono) }); - }; - event; - }; - "instruments.scd".loadRelative; + ~makeBuffers = { |path, event, mono = false| + var dir = PathName.new(path); + var contents = dir.entries; + if (contents.select({ |n| n.isFile }).size > 0) + { + var files, bufArray; + files = contents.select({ |n| n.isFile }); + files = files.select({ |n| + ["aif", "aiff", "wav"].includesEqual(n.extension) + }); + if (event[dir.folderName.asSymbol] != nil) + { "duplicate subfolder name ignored".warn; } + { + bufArray = files.collect({ |n| + if(mono) + { Buffer.readChannel(s, n.fullPath, channels:[0]) } + { Buffer.read(s, n.fullPath) }; + }); + event[dir.folderName.asSymbol] = bufArray; + }; + }; + if (contents.select({ |n| n.isFolder }).size > 0) + { + var folders = contents.select({ |n| n.isFolder }); + folders.do({ |n| ~makeBuffers.(n.fullPath, event, mono) }); + }; + event; + }; + s.sync; + // загрузка тестового сэмпла + "test_init.scd".loadRelative; + s.sync; + "instruments.scd".loadRelative; }); ) diff --git a/scratchpad.scd b/scratchpad.scd index 1a27e49..4f41592 100644 --- a/scratchpad.scd +++ b/scratchpad.scd @@ -1,46 +1,54 @@ -~samples = ~makeBuffers.("/home/dude/code/24_09_2026_gig", ()); -~sample = ~samples[\samples][0]; -~inBus = Bus.audio(s, 1); +Ndef(\testSignal).set(\gain, 0.1); + ( -Ndef(\testSignal, { - var sig, sig2; - sig = BufRd.ar(2, ~sample, Phasor.ar(0, BufRateScale.kr(~sample), 0, BufFrames.kr(~sample))); - Out.ar(~inBus, sig.sum); - sig * \gain.kr(0.01); -}).play; +Ndef(\freeze1).play; +Ndef(\freeze2).play; +Ndef(\freeze3).play; ) -Ndef(\testSignal).ar(2); - -Ndef.clear - -Ndef(\freeze1).set(\in, ~inBus.index); -Ndef(\freeze2).set(\in, ~inBus.index); -Ndef(\freeze3).set(\in, ~inBus.index); - -Ndef(\freeze3).set(\in, ~inBus); - -Ndef(\freeze1).set(\amp, 1.7); -Ndef(\freeze2).set(\amp, 2.6); -Ndef(\freeze3).set(\amp, 10.05); - +// FREEZE1 +( +// Статические параметры. Не меняются +Ndef(\freeze1).set(\attack, 4.0); +Ndef(\freeze1).set(\release, 4.0); +// Динамические параметри. Меняются. +Ndef(\freeze1).set(\amp, 0.3); +Ndef(\freeze1).set(\envGate, 1); +Ndef(\freeze1).set(\pan, 0.0); +// Сброс фриза +Ndef(\freeze1).set(\freezeGate, 0); Ndef(\freeze1).set(\freezeGate, 1); -Ndef(\freeze2).set(\freezeGate, 1); -Ndef(\freeze3).set(\freezeGate, 1); - -Ndef(\freeze3).set(\rel, 0.1); -Ndef(\freeze3).set(\atk, 0.1); -Ndef(\freeze3).set(\ampGate, 0.0001); - -Ndef(\freeze1).set(\pan, 0); -Ndef(\freeze3).set(\amp, 0.1); -Ndef(\freeze1).set(\amp, 0.7); +( +Ndef(\freeze1).set(\freezeGate, 0); +Ndef(\freeze1).set(\freezeGate, 1); +) -Ndef(\freeze1).set(\wipe, 0.3); -Ndef(\freeze1).set(\reshuffle, 0.1); -Ndef(\freeze1).set(\binShift, 0.4); -Ndef(\freeze1).set(\stretch, 0.1); +// Крутим НА САУНДЧЕКЕ!!! +// После не трогать!!! +Ndef(\freeze1).set(\limLevel, 0.003); + +// Настройки питчшифтера +//Рабочие значения (для freeze1 поверх замороженного спектра): + +//Чуть расстроенные (биения между слоями, «расщеплённый» звук): +//- \range1 = 1.0, \range2 = 1.0125 → синтонная комма 81/80, лёгкое «волнение» +//- \range1 = 1.0, \range2 = 1.024 → диезис 128/125 +//- \range1 = 1.0, \range2 = 1.0293 → четвертьтон 2^(1/24) +3 +//Чистые нетемперированные интервалы (классика just intonation, даёт «странный» консонанс/диссонанс): +//- 16/15 = 1.0667 (малая секунда) +//- 25/24 = 1.0417 (хроматический полутон) +//- 21/20 = 1.05 +//- 28/27 = 1.0370 + +//Тричетвертьтон и около: +//- 2^(3/24) = 1.0905 +//- 7/6 = 1.1667, 8/7 = 1.1429 (септимальные интервалы — звучат «не по-нашему») + +Ndef(\freeze1).set(\shift, 2.0); +Ndef(\freeze1).set(\wet10, 1.0); +) ( Ndef(\freeze3).put(10, \filter -> { @@ -68,27 +76,7 @@ Ndef(\freeze3).put(10, \filter -> { ) ( -Ndef(\freeze1).put(10, \filter -> { - |in| - var sig = 0; - var shPitched = PitchShift.ar( - in, - 0.2, - SinOsc.kr(0.1).range(2, 4), - 0.01, - 0.01 - ) * 2.0; - - var shPitched2 = PitchShift.ar( - in, - 0.2, - SinOsc.kr(0.05).range(4, 6), - 0.01, 0.01 - ) * 2.0; - sig = Mix([in, shPitched, shPitched2]) * 0.9; - sig; -}); ) ( @@ -97,12 +85,16 @@ Ndef(\freeze2).stop; Ndef(\freeze3).stop; ) -( -Ndef(\freeze1).play; -Ndef(\freeze2).play; -Ndef(\freeze3).play; -) -Ndef(\testSignal).stop; -Ndef(\testSignal).set(\gain, 1.0); \ No newline at end of file +NdefMixer + +n = NdefMixer(s); + + +// FREEZE3 +// NB! Очень громкий!!! +Ndef(\freeze3).set(\amp, 0.1); +Ndef(\freeze3).set(\freezeGate, 0); +// Ближе к 1 - апекствин +Ndef(\freeze3).set(\ampGate, 0.001);