|
|
* Bjornmossa DSP algorythms library
|
|
|
This repo contains SC code for synthesis, processing and analysys algorythms.
|
|
|
* Usage
|
|
|
#+BEGIN_SRC sclang
|
|
|
(
|
|
|
var sin_dict = BmDspAlgs.getDict("synths/distorted_sin.scd");
|
|
|
sin_dict[\postAmp] = true;
|
|
|
sin_dict.makeSourceSynthDef.add();
|
|
|
|
|
|
~synth = ();
|
|
|
~synth[\name] = \synth;
|
|
|
|
|
|
Ndef(~synth[\name]).clear;
|
|
|
Ndef(~synth[\name]).ar(2);
|
|
|
Ndef(~synth[\name]).prime(sin_dict[\name]);
|
|
|
|
|
|
Ndef(~synth[\name]).play;
|
|
|
)
|
|
|
#+END_SRC
|
|
|
|
|
|
* Словари-обработки (Fx-словари) через makeBufferProcessingNdef
|
|
|
#+BEGIN_SRC sclang
|
|
|
(
|
|
|
// Загрузка словаря как buffer-processing Fx.
|
|
|
~dict = BmDspAlgs.getDict("spectral/fft_freeze.scd");
|
|
|
|
|
|
// Вход через Bus — стандартный паттерн: makeBufferProcessingNdef
|
|
|
// передаёт \buf как OSC-параметр (control-rate число = номер bus),
|
|
|
// func получает его первым аргументом.
|
|
|
~inBus = Bus.audio(s, 2);
|
|
|
{ Out.ar(~inBus, SoundIn.ar([0, 1])) }.play;
|
|
|
|
|
|
// Создаём Ndef: name = имя нового Ndef, buf = audio-сигнал.
|
|
|
~dict.makeBufferProcessingNdef(\freezeOnly, ~inBus);
|
|
|
|
|
|
// Параметры func (fftBufnum, freezeGate, phaseJitter) теперь —
|
|
|
// control-параметры SynthDef, доступные через .set / .map.
|
|
|
Ndef(\freezeOnly).set(\fftBufnum, someBuffer);
|
|
|
Ndef(\freezeOnly).set(\freezeGate, 1);
|
|
|
Ndef(\freezeOnly).play;
|
|
|
)
|
|
|
#+END_SRC
|
|
|
|
|
|
** Контракт func для Fx-словарей
|
|
|
|
|
|
Func в Fx-словаре объявляется с одним обязательным первым аргументом — *buf*:
|
|
|
|
|
|
#+BEGIN_SRC sclang
|
|
|
func: {
|
|
|
| buf |
|
|
|
// buf — это audio-сигнал, пришедший через OSC-параметр \buf.
|
|
|
// В скетче он = номер Bus.audio, из которого читает Ndef.
|
|
|
// Остальные параметры объявляются через \name.kr(...) /
|
|
|
// \name.tr(...) и становятся control-параметрами SynthDef.
|
|
|
var sig = ...;
|
|
|
sig;
|
|
|
}
|
|
|
#+END_SRC
|
|
|
|
|
|
Имя первого аргумента (=buf) — это convention, не контракт. Важно,
|
|
|
что func принимает ровно один positional аргумент первым; обёртка
|
|
|
=makeBufferProcessingNdef= делает =SynthDef.wrap(func, prependArgs: [buf])=.
|
|
|
|
|
|
** Цепочки Fx-словарей
|
|
|
|
|
|
Чтобы пропустить выход одного Ndef через другой Fx-словарь,
|
|
|
используется промежуточный Bus:
|
|
|
|
|
|
#+BEGIN_SRC sclang
|
|
|
~midBus = Bus.audio(s, 2);
|
|
|
Ndef(\first)[0] = { Out.ar(~midBus, Ndef(\first).bus.asMap) };
|
|
|
|
|
|
~dict2.makeBufferProcessingNdef(\second, ~midBus);
|
|
|
Ndef(\second).play;
|
|
|
#+END_SRC
|
|
|
|
|
|
Это даёт последовательную обработку: =first → midBus → second=.
|
|
|
|
|
|
** Отличия от нотных словарей
|
|
|
|
|
|
Нотные словари (=makeSourceSynthDef= / =makeSourceNdef=) оборачивают func
|
|
|
с prependArgs =[freq, gate]= и добавляют ADSR-огибающую, panning, amp.
|
|
|
Func должна быть вида =| freq, gate |=.
|
|
|
|
|
|
Fx-словари (=makeBufferProcessingSynthDef= / =makeBufferProcessingNdef=)
|
|
|
оборачивают func с prependArgs =[buf]= и добавляют Pan2 + amp.
|
|
|
Func должна быть вида =| buf |=. Дополнительные обёртки (DetectSilence,
|
|
|
limitDuration через Line) включаются ключами =detectSilence: true= и
|
|
|
=limitDuration: true= в словаре.
|
|
|
|