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.

pat + blip → escucha directaenvíos → CombL → GVerb → LPF → retorno estéreo

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
ComponenteFunción y consecuencia audible
s.options.memSizeMemoria 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.pushActiva ProxySpace como entorno: ~pat, ~blip y ~fx se resuelven como NodeProxy.
fadeTime / lagfadeTime 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.

ComponenteFunció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.
normalizeSumDivide por la suma de amplitudes. Conserva las proporciones; no mantiene constante RMS ni sonoridad.
midi.midicpsConvierte 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 / driveNo 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 / blendPulso 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.
SplayDistribuye las nueve señales en estéreo. spread controla anchura; la compensación de nivel está activada por defecto.
SinOsc de tilt / breathEl primero mueve la pendiente alrededor del valor base; depth = 0 lo retira. La respiración multiplica por un valor positivo, mezclable con breathMix.
amp / Limiteramp 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.

ComponenteFunció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) × rateLa 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.
TChooseSelecciona una nota por voz entre 66, 78, 80, 83 y 85. La repetición de una nota es posible.
transpose / midicpsDesplazamiento en semitonos antes de convertir a Hz. Cambiar transpose altera también notas que ya están sonando.
Env.perc / EnvGenAtaque 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 ampLa 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 / MixCada 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 / LimiterDeja 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.

ComponenteFunció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.
CombLRetardo 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 / combMixMezcla la entrada y el resultado de CombL antes de la reverberación. Aumentarlo modifica la memoria y el color.
sig.sum / GVerbSuma 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 / cutoffDepthFiltra 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 / LimiterControla 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.

~pat.set(\amp, 0.2, \tilt, 1.5, \stretch, 1,
    \drive, 4, \pulseMix, 0, \depth, 0, \breathMix, 0);
~blip.set(\amp, 0.02, \rate, 0.3, \release, 6);
~fx.set(\wet, 0.2, \combMix, 0.3, \cutoffDepth, 0);
Escucha: ¿Se distinguen las notas del fondo? Ajusta amp o sendPat antes de añadir actividad.
02–04 MIN

Apertura espectral

Reduce tilt. Las frecuencias permanecen; cambia el reparto de amplitudes.

~pat.set(\tilt, 0.8);
// Después de escuchar:
~pat.set(\tilt, 0.3);
Escucha: El brillo y la sonoridad pueden cambiar juntos. normalizeSum no normaliza el volumen percibido.
04–06 MIN

Articulación

Introduce tu pulso de 8 Hz gradualmente.

~pat.set(\pulseRate, 8, \width, 0.3, \pulseMix, 0.6);
Escucha: Escucha el contraste entre continuidad y pulsación. El mínimo efectivo es 0.52 con pulseMix = 0.6.
06–08 MIN

Tensión de afinación

Deforma el banco y vuelve a la serie armónica.

~pat.set(\stretch, 1.02);
// Espera a escuchar el desplazamiento antes de volver:
~pat.set(\stretch, 1);
Escucha: Con stretch distinto de 1 aparecen relaciones inarmónicas; no confundir con un cambio de brillo.
08–10 MIN

Densidad de eventos

Aumenta la velocidad central y acorta las notas. Evalúa cada línea por separado.

~blip.set(\rate, 0.6);
~blip.set(\release, 1.5);
~blip.set(\rate, 1.2);
~pat.set(\tilt, 2.5);
Escucha: Las dos voces siguen siendo monofónicas. El fondo más oscuro deja espacio a los eventos.
10–12 MIN

Memoria y profundidad

Da protagonismo al retardo y abre el retorno, compensando su ganancia.

~fx.set(\combMix, 0.6, \wet, 0.2);
~fx.set(\cutoff, 2200, \cutoffDepth, 1);
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.
ComponenteFunció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ónsig es local: las operaciones sobre ella deben ir dentro del bloque y antes de su expresión final de audio.
0.1!2Duplica el número en un array; al pasarlo a un UGen se generan dos instancias. Para ruido son procesos independientes.
LFO / modulación aleatoriaSinOsc y LFPulse son periódicos. LFNoise1 es aleatorio interpolado. Todos pueden modular, pero sus trayectorias temporales son distintas.
Reiniciar tras el cierreVuelve a evaluar las fuentes si has usado .end, llama a .play y restaura amp: los valores cero enviados con .set pueden seguir almacenados.