CUADERNO DE SESIÓN · SUPERCOLLIDER 3 · 04 OCT 2026
Del banco de parciales a una textura en movimiento
Tres capas, una trayectoria: fondo aditivo, eventos agudos y memoria espacial. Esquema de lo trabajado hoy y guion temporal para volver a interpretarlo.
La arquitectura de la sesión
01 · MATERIA CONTINUA
~pat
Nueve componentes impares. Pendiente espectral, deformación de frecuencias, saturación y pulso. Splay distribuye el banco en estéreo.
02 · ACONTECIMIENTOS
~blip
Dos voces de notas aleatorias. Disparos de velocidad variable, envolventes percusivas y panoramas lentos independientes.
03 · MEMORIA
~fx
Recibe ambas capas. CombL acumula ecos y resonancias; GVerb amplía el espacio; LPF modela el brillo del retorno.
Las fuentes tienen salida directa y alimentan un retorno paralelo. No hay envío OSC. Este documento reúne las transformaciones en una versión coherente; no es una transcripción literal de todos los bloques alternativos.
Los tiempos de la sesión son orientativos. Se evalúan bloques y líneas por separado en SuperCollider; el HTML no genera audio ni ejecuta sclang.
Preparar el entorno
Arranca el servidor y después activa ProxySpace. Evita recrear el clock y apilar entornos cada vez que cambies una fuente.
// 1. Evaluar y esperar a que termine el arranque.
(
s.options.memSize = 2.pow(20);
s.boot;
)
// 2. Evaluar después del arranque; una vez por sesión.
(
t = TempoClock.new(120/60).permanent_(true);
p = ProxySpace.new(s, clock: t);
p.push;
)
currentEnvironment === p; // true
Componente
Función y consecuencia audible
s.options.memSize
Memoria de tiempo real del servidor, en KiB. 2.pow(20) reserva aproximadamente 1 GiB; es una configuración amplia, no un requisito general del patch. Se aplica al arrancar/rearrancar.
t = TempoClock…
120/60 = 2 beats por segundo. permanent_(true) evita que CmdPeriod elimine el clock. Los Impulse y LFO del patch trabajan en Hz; no quedan sincronizados automáticamente con t.
p.push
Activa ProxySpace como entorno: ~pat, ~blip y ~fx se resuelven como NodeProxy.
fadeTime / lag
fadeTime gobierna el reemplazo de fuentes por crossfade. El segundo argumento de NamedControl .kr suaviza cambios de .set; es un lag exponencial, no una rampa lineal.
~pat · Construir y transformar el fondo
Con MIDI 25 la fundamental es aproximadamente 34,65 Hz. Los nueve multiplicadores son 1, 3, 5, 7, 9, 11, 13, 15 y 17. Antes de la saturación y con stretch = 1 son armónicos impares.
Componente
Función y consecuencia audible
Array.series(9, 1, 2)
Construye nueve multiplicadores empezando en 1, con paso 2. El array expande SinOsc en nueve osciladores.
partials.pow(tilt.neg)
aₙ ∝ n⁻ᵗⁱˡᵗ. tilt positivo atenúa los componentes altos; tilt = 0 iguala amplitudes. .neg cambia el signo del exponente.
normalizeSum
Divide por la suma de amplitudes. Conserva las proporciones; no mantiene constante RMS ni sonoridad.
midi.midicps
Convierte nota MIDI a Hz. El lag antes de midicps suaviza el desplazamiento en unidades MIDI.
partials.pow(stretch)
fₙ = f₀ · nˢᵗʳᵉᵗᶜʰ. Aquí no hay .neg. stretch = 1 conserva relaciones armónicas; valores mayores estiran el banco. La fundamental permanece.
tanh / drive
No linealidad aplicada por componente. drive aumenta la saturación y genera armónicos adicionales. Tras ella ya no hay solo nueve líneas espectrales.
LFPulse / blend
Pulso unipolar entre 0.2 y 1. width fija la fracción alta del ciclo. blend mezcla versión continua y pulsada; con 0.6 el factor efectivo oscila entre 0.52 y 1.
Splay
Distribuye las nueve señales en estéreo. spread controla anchura; la compensación de nivel está activada por defecto.
SinOsc de tilt / breath
El primero mueve la pendiente alrededor del valor base; depth = 0 lo retira. La respiración multiplica por un valor positivo, mezclable con breathMix.
amp / Limiter
amp regula la ganancia; 0.9 es el techo por canal. El limitador no eleva señales débiles y no limita la suma global de todos los proxies.
Ver código completo de pat
(
~pat.fadeTime = 8;
~pat = {
var partials, amps, freqs, sig, tilt, pulse, breath;
partials = Array.series(9, 1, 2);
// Desplazamos la pendiente espectral alrededor de tilt.
tilt = (\tilt.kr(1.5, 3)
+ SinOsc.kr(\lfoRate.kr(0.05, 2))
* \depth.kr(0, 3)).max(0);
amps = partials.pow(tilt.neg).normalizeSum;
freqs = \midi.kr(25, 3).midicps
* partials.pow(\stretch.kr(1, 4));
sig = SinOsc.ar(freqs, 0, amps);
// La saturación actúa sobre cada componente antes de mezclarlos.
sig = (sig * \drive.kr(4, 2)).tanh;
pulse = LFPulse.kr(\pulseRate.kr(8, 1),
width: \width.kr(0.3, 1)).range(0.2, 1);
sig = sig.blend(sig * pulse, \pulseMix.kr(0.6, 2));
sig = Splay.ar(sig, spread: \spread.kr(0.7, 2));
// El control permite introducir la respiración sin reemplazar la fuente.
breath = SinOsc.kr(0.08).range(0.4, 1);
sig = sig * ((1 - \breathMix.kr(0, 2))
+ (breath * \breathMix.kr(0, 2)));
Limiter.ar(sig * \amp.kr(0.2, 2), 0.9);
};
~pat.play;
)
~blip · Dos voces de eventos
No hay una melodía ordenada: cada trigger selecciona una nota del conjunto. Cada voz cambia de frecuencia y redispara su envolvente; no se crea un synth nuevo por nota.
Componente
Función y consecuencia audible
LFNoise1.kr([0.1, 0.1])
Dos procesos aleatorios independientes con interpolación lineal. Nuevos objetivos aproximadamente cada 10 s. No son oscilaciones periódicas.
range(1/3, 5/3) × rate
La velocidad central vuelve a ser modulable. Con rate = 0.3, cada voz recorre de 0.1 a 0.5 Hz.
Impulse.kr(rates)
Dos trenes de triggers. Sus intervalos cambian con rates; no están vinculados al TempoClock.
TChoose
Selecciona una nota por voz entre 66, 78, 80, 83 y 85. La repetición de una nota es posible.
transpose / midicps
Desplazamiento en semitonos antes de convertir a Hz. Cambiar transpose altera también notas que ya están sonando.
Env.perc / EnvGen
Ataque de 2 ms y caída curva -30. release controla la duración del tramo de caída; con esa curva gran parte de la energía se concentra al principio. doneAction: 0 conserva el synth para los siguientes triggers.
drive antes de amp
La saturación actúa sobre el oscilador antes de envolvente y ganancia. En el código previo amp = 0.02 dejaba tanh casi lineal incluso con drive = 4.
Pan2 / Mix
Cada voz produce un par estéreo. Mix suma los pares en L/R; no usar flatten como sustituto de esa suma. Los panoramas de 0.07 y 0.09 Hz tienen ciclos de unos 14.3 y 11.1 s.
× 0.5 / Limiter
Deja margen al sumar las voces y fija un techo de salida. La amplitud final sigue expuesta con amp.
Ver código completo de blip
(
~blip.fadeTime = 4;
~blip = {
var rates, trig, note, freq, env, sig, drive, pan;
// Dos fluctuaciones independientes alrededor de la velocidad central.
rates = LFNoise1.kr([0.1, 0.1]).range(1/3, 5/3)
* \rate.kr(0.3, 2);
trig = Impulse.kr(rates);
note = TChoose.kr(trig, [66, 78, 80, 83, 85]);
freq = (note + \transpose.kr(0)).midicps;
env = EnvGen.ar(
Env.perc(0.002, \release.kr(6), curve: -30),
gate: trig, doneAction: 0
);
// Drive antes de amp: permite saturar sin elevar la salida.
drive = LFNoise1.kr(0.2).exprange(0.7, 4);
sig = (SinOsc.ar(freq) * drive).tanh;
sig = sig * env * \amp.kr(0.02, 1);
pan = SinOsc.kr([0.07, 0.09]).range(-0.8, 0.8);
// Dos pares estéreo se suman en un único par.
sig = Mix(Pan2.ar(sig, pan)) * 0.5;
Limiter.ar(sig, 0.9);
};
~blip.play;
)
~fx · Retardo, espacio y filtrado
Se conserva tu encadenamiento CombL → GVerb → LPF. Se añaden controles de envío y retorno, y se elimina el directo interno de GVerb para evitar duplicarlo.
Componente
Función y consecuencia audible
~blip.ar(2), ~pat.ar(2)
Lee dos canales de cada bus del proxy. sendBlip y sendPat regulan sus aportaciones independientemente.
LFNoise1.kr(0.02)
Nuevo objetivo aleatorio aproximadamente cada 50 s. exprange mueve delaytime entre 0.1 y 0.4 segundos.
CombL
Retardo con feedback e interpolación lineal. maxdelaytime = 0.5 reserva el máximo. decay = 8 fija el tiempo de caída de 60 dB, no una duración exacta hasta el silencio. Variar el retardo mueve resonancias y puede alterar la altura.
blend / combMix
Mezcla la entrada y el resultado de CombL antes de la reverberación. Aumentarlo modifica la memoria y el color.
sig.sum / GVerb
Suma L/R para entrar en GVerb, que produce estéreo. roomsize = 300 y revtime = 5 mantienen tu espacio amplio. drylevel = 0 deja el directo a los proxies fuente.
LPF / cutoffDepth
Filtra después de la reverb: no la sustituye. cutoffDepth se mide aquí en octavas; 1 mueve el corte de la mitad al doble de cutoff. El recorrido tiene ciclo de 25 s.
wet / Limiter
Controla el nivel de toda la cadena del retorno. No es un porcentaje exacto de reverberación: también contiene el carácter del comb.
Ver código completo de fx
(
~fx.fadeTime = 5;
~fx = {
var sig, del, cutoff;
// Envíos independientes: controlamos cuánto aporta cada fuente.
sig = ~blip.ar(2) * \sendBlip.kr(0.3, 2);
sig = sig + (~pat.ar(2) * \sendPat.kr(0.3, 2));
del = LFNoise1.kr(0.02).exprange(0.1, 0.4);
sig = sig.blend(
CombL.ar(sig, 0.5, del, \decay.kr(8, 2)),
\combMix.kr(0.5, 2)
);
// Entrada mono; GVerb devuelve estéreo. El directo sale por las fuentes.
sig = GVerb.ar(sig.sum, 300, 5, drylevel: 0);
// cutoffDepth = 0 mantiene el corte estático.
cutoff = \cutoff.kr(2000, 2)
* (2 ** (SinOsc.kr(0.04) * \cutoffDepth.kr(0, 3)));
sig = LPF.ar(sig, cutoff.clip(100, 12000));
Limiter.ar(sig * \wet.kr(0.3, 2), 0.9);
};
~fx.play;
)
Una sesión de 16 minutos
Es una partitura de decisiones. Espera entre instrucciones; prolonga una fase si todavía está produciendo material musical.
00–02 MIN
Presentación
Establece las dos capas. Escucha el grave y el espacio entre notas antes de transformar.
Escucha: El corte oscila aproximadamente entre 1100 y 4400 Hz. Si se pierde definición, reduce sendPat o decay.
12–14 MIN
Movimiento lento
Retira el pulso e introduce el LFO de tilt. Añade respiración solo después de escucharlo.
~pat.set(\pulseMix, 0);
~pat.set(\tilt, 1.5, \depth, 1, \lfoRate, 0.05);
// Opcional, tras escuchar el movimiento espectral:
~pat.set(\breathMix, 0.5);
Escucha: Un ciclo espectral dura 20 s. No cambies varios parámetros antes de reconocer su efecto.
14–16 MIN
Reposo y cierre
Recupera el material inicial. Después extingue las fuentes y escucha la cola.
~pat.set(\stretch, 1, \tilt, 1.5, \depth, 0, \breathMix, 0);
~blip.set(\rate, 0.3, \release, 6);
// Tras escuchar el reposo, bajar amp corta también la alimentación de fx.
~blip.set(\amp, 0);
~pat.set(\amp, 0);
// Esperar unos 15–20 s y decidir de oído cuándo cerrar el retorno.
~fx.end(8);
// Después del cierre del efecto:
~blip.end(4);
~pat.end(8);
Escucha: stop solo retira el monitor directo; no basta para dejar de alimentar el efecto. end libera la fuente y detiene su escucha.
Qué mantener bajo control
Una causa audible
Cambia primero un parámetro. Distingue brillo, afinación, densidad y volumen antes de combinarlos.
Acumulación
El comb y la reverb mantienen energía. Cuando aumentes drive o densidad, revisa sendPat, decay y wet.
Forma
Alterna actividad y reposo. Recuperar un estado reconocible da sentido a la transformación anterior.
Corrección del cierre anterior: .stop silencia el monitor, pero el bus puede seguir alimentando fx. Para escuchar una cola real, baja amp o los envíos; después usa .end. Los limitadores locales tampoco garantizan un techo común para la mezcla final.
Componente
Función y consecuencia audible
Reemplazar ~pat = { … }
Sustituye el grafo completo. Un bloque nuevo sin saturación elimina la saturación anterior. Los valores ya fijados con .set pueden persistir al reemplazar una fuente.
~proxy.set(…)
Solo actúa sobre controles presentes en el grafo. Si sustituyes rate por un número o por ruido sin control central, pierdes esa intervención.
sig fuera de la función
sig es local: las operaciones sobre ella deben ir dentro del bloque y antes de su expresión final de audio.
0.1!2
Duplica el número en un array; al pasarlo a un UGen se generan dos instancias. Para ruido son procesos independientes.
LFO / modulación aleatoria
SinOsc y LFPulse son periódicos. LFNoise1 es aleatorio interpolado. Todos pueden modular, pero sus trayectorias temporales son distintas.
Reiniciar tras el cierre
Vuelve a evaluar las fuentes si has usado .end, llama a .play y restaura amp: los valores cero enviados con .set pueden seguir almacenados.