|
|
|
@ -3,46 +3,19 @@ name: 'fft_freeze',
|
|
|
|
func: {
|
|
|
|
func: {
|
|
|
|
| buf |
|
|
|
|
| buf |
|
|
|
|
|
|
|
|
|
|
|
|
// Входной звук → FFT → freeze magnitude (PV_Freeze) + phase-jitter
|
|
|
|
|
|
|
|
// (PV_PhaseShift с шумом) → IFFT.
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
// FFT-буфер передаётся снаружи через \fftBufnum — это позволяет
|
|
|
|
|
|
|
|
// распределять буферы в скетче (s.options.numBuffers) и переиспользовать
|
|
|
|
|
|
|
|
// между перезапусками синта.
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
// Почему не кастомная пересборка chain из magnitude/phase: готовых
|
|
|
|
|
|
|
|
// PV_* UGen для неё нет, а PV_Chain не имеет метода .polar.
|
|
|
|
|
|
|
|
// UnpackFFT/PackFFT подходят для поканальной обработки, но не для
|
|
|
|
|
|
|
|
// uniform-операций вроде freeze или jitter. PV_Freeze + PV_PhaseShift
|
|
|
|
|
|
|
|
// дают ближайший готовый результат.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var fftBuf = \fftBufnum.kr(0);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var chain = FFT(
|
|
|
|
var chain = FFT(
|
|
|
|
fftBuf,
|
|
|
|
LocalBuf(2048),
|
|
|
|
buf,
|
|
|
|
buf,
|
|
|
|
\hop.kr(0.25),
|
|
|
|
|
|
|
|
\wintype.kr(1)
|
|
|
|
|
|
|
|
);
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
// PV_Freeze принимает gate trigger: при freezeGate=1 удерживает
|
|
|
|
|
|
|
|
// magnitude, при 0 — пропускает как есть.
|
|
|
|
|
|
|
|
var frozen = PV_Freeze(chain, \freezeGate.tr(0));
|
|
|
|
var frozen = PV_Freeze(chain, \freezeGate.tr(0));
|
|
|
|
|
|
|
|
|
|
|
|
// Phase jitter: случайный сдвиг фазы всех бинов. Субъективно —
|
|
|
|
|
|
|
|
// "дыхание" frozen-спектра.
|
|
|
|
|
|
|
|
var jittered = PV_PhaseShift(frozen, \phaseJitter.kr(0) * TRand.kr(0, 2pi));
|
|
|
|
var jittered = PV_PhaseShift(frozen, \phaseJitter.kr(0) * TRand.kr(0, 2pi));
|
|
|
|
|
|
|
|
var sig = IFFT(jittered, \wintype.kr(1));
|
|
|
|
var rawSig = IFFT(jittered, \wintype.kr(1));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Duck на громкие моменты — общий паттерн для защиты от клиппинга
|
|
|
|
|
|
|
|
var sig = rawSig * (1 - \duckOnLoud.kr(0).clip(0, 1) *
|
|
|
|
|
|
|
|
(Amplitude.kr(rawSig) > \duckThreshold.kr(0.95)).lag(0.05));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sig
|
|
|
|
sig
|
|
|
|
},
|
|
|
|
},
|
|
|
|
inChannels: 2,
|
|
|
|
inChannels: 1,
|
|
|
|
outChannels: 2,
|
|
|
|
outChannels: 1,
|
|
|
|
requiresBuffer: true,
|
|
|
|
requiresBuffer: true,
|
|
|
|
specs: (
|
|
|
|
specs: (
|
|
|
|
phaseJitter: [0, 1, \lin, 0.01, 0.1],
|
|
|
|
phaseJitter: [0, 1, \lin, 0.01, 0.1],
|
|
|
|
|