Esta es una publicación técnica sobre cómo funciona Soundbend de Morph — un sistema de trabajo digital de audio completo que incluye 5 instrumentos nativos, un mezclador con cadenas de efectos y envíos auxiliares, 30+ efectos (incluyendo 5 puertos de Tier-1 de Airwindows y un limitador de pico verdadero), una rack de efectos MIDI, un host de complementos WAM v2 y una capa de colaboración Yjs CRDT — todo ejecutándose enteramente en una pestaña del navegador.
La pregunta práctica es: ¿es esto realmente competitivo con Ableton? La respuesta sincera: para la mayoría de los flujos de trabajo de productores, sí. Para integraciones profundas de Max for Live, aún no. Lee la comparación de alternativas a Ableton para el desglose a nivel de producto. Esta publicación es la ingeniería.
La pila
- Frontend React + Vite
- Web Audio API para el gráfico de audio
- AudioWorkletProcessor para DSP personalizado (fuera de hilo principal)
- WebAssembly para construcciones WASM personalizadas de alto rendimiento (DSP crítico)
- MessagePort + buffer de anillos para comunicación UI ↔ worklet
- Yjs para colaboración CRDT
- IndexedDB para persistencia de proyectos + almacenamiento de muestras
- WebMIDI para entrada de controladores de hardware
- OfflineAudioContext para rebote/exportar
1. El gráfico de audio
Cada pista en Soundbend pasa por una cadena: instrumento → cadena de efectos de pista → envío auxiliar → strip de mezclador → bus maestro → limitador → destino. Cada flecha es una conexión Web Audio AudioNode.
Web Audio nos da AudioContext, GainNode, BiquadFilterNode, ConvolverNode, AnalyserNode y amigos. Estos están optimizados por los motores del navegador (V8/SpiderMonkey/JSC están profundamente comprometidos). Para efectos estándar — ecualización, automatización de ganancia, filtrado básico — usamos nodos nativos. Son rápidos y bien probados.
Para efectos personalizados — puertos de Airwindows, nuestra saturación, nuestro limitador de verdadero pico — nos introducimos en AudioWorkletProcessor, que se ejecuta en el hilo de audio, garantizando prioridad en tiempo real, y es el lugar arquitectónico correcto para DSP no estándar.
class PurestDriveProcessor extends AudioWorkletProcessor {
process(inputs, outputs) {
const input = inputs[0];
const output = outputs[0];
// Airwindows PurestDrive port — ~30 LOC of saturation math
for (let ch = 0; ch < input.length; ch++) {
for (let i = 0; i < input[ch].length; i++) {
const s = input[ch][i];
// [...tape-saturation math...]
output[ch][i] = processed;
}
}
return true;
}
}
registerProcessor('purest-drive', PurestDriveProcessor);
Los Worklets se envían en public/audio-worklets/*.js y se cargan mediante audioContext.audioWorklet.addModule(path). Una vez cargados, cualquier parte del gráfico puede instanciar un AudioWorkletNode para ese procesador. El procesamiento se ejecuta fuera del hilo principal — las animaciones de la interfaz no interrumpen el audio.
2. Los 5 puertos Tier-1 de Airwindows
Chris Johnson's Airwindows es 2.500+ plugins de audio, licenciados MIT, DSP legendariamente sabroso. Hemos portado 5 a AudioWorklets del navegador para el lanzamiento Wave 12 de Soundbend:
- Pressure6 — compresión transparente que respira
- ToTape9 — modelado de saturación de cinta analógica
- PurestDrive — saturación de fase mínima sin agudos duros
- CreamCoat — Calor + excitador armónico
- NotJustAnotherDither — Dither TPDF para reducción de profundidad de bits (mastering)
Cada puerto es ~30-80 LOC de matemáticas en un AudioWorkletProcessor. Los puertos no coinciden bit a bit con Airwindows (diferente manejo de FMA/denormal entre motores numéricos de C++ y JS) pero coinciden sonoramente. Las pruebas nulas mantienen los resultados ≤ -80 dBFS contra los estándares, por lo que los cambios en DSP se detectan.
3. El limitador de pico verdadero
Las plataformas modernas de transmisión (Spotify, Apple Music, YouTube) aplican la normalización de volumen verdadero pico según ITU-R BS.1770-5. Los picos de muestra y los picos intermuestre son cosas diferentes; una señal puede alcanzar -1 dBFS a nivel de muestra pero exceder 0 dBFS verdadero pico después de la reconstrucción D/A. Un limitador no verdadero pico cortará en el DAC incluso si tu DAW lo muestra limpio.
Nuestro limitador implementa la especificación completa ITU: sobremuestreo 4x, detección de picos intermuestra, lookahead, liberación de suave. Se envía en forma de AudioWorklet en public/audio-worklets/true-peak-limiter-processor.js. Las mediciones contra implementaciones de referencia (Oxford Limiter, iZotope Ozone Maximizer) coinciden dentro de 0.1 dB en LUFS integrado.
4. Comunicación fuera de la línea principal
El gráfico de audio se ejecuta en el hilo de audio. La interfaz de usuario se ejecuta en el hilo principal. Los cambios de parámetros (girar un knob, atenuar una pista) necesitan propagarse desde la interfaz de usuario → audio sin interrumpir el audio.
Web Audio's AudioParam maneja esto nativamente para parámetros estándar (GainNode gain, BiquadFilterNode frequency). Para trabajo personalizado con worklets, usamos MessagePort con clonación estructurada para mensajes de interfaz de usuario, y SharedArrayBuffer-backed ring buffers para datos de automatización de alta tasa.
SharedArrayBuffer requiere Cross-Origin-Opener-Policy: same-origin + Cross-Origin-Embedder-Policy: require-corp encabezados. Estos se establecen en public/_headers para las rutas /soundbend + /pulse. El Tape Delay usa un buffer circular a 96kHz para evitar la latencia del puerto de mensajes.
5. Los 5 instrumentos nativos
Soundbend incluye 5 instrumentos, todos personalizados:
Síntesis FM — Síntesis FM de 6 operadores modelada en DX7 / Operator. Visualizador de algoritmos + matriz de modulación completa. ~800 LOC JS para la interfaz de usuario, ~300 LOC para el worklet de asignación de voz.
Sintetizador de Wavetable — síntesis morph-between-tables. Deformación espectral + unisono + desintonización estéreo. 30+ tablas de onda de fábrica. Usa ConvolverNode para transición cruzada de wavetable a velocidad de audio.
Analog Subtractive — sintetizador polifónico de 2 osciladores con filtros Cytomic SVF. Cytomic es la topología de filtro de variable de estado que suena bien; el SVF ingenuo tiene problemas de aliasing por encima de fc > SR/6. La implementación Cytomic maneja esto mediante matemáticas de retroalimentación de retardo cero.
DrumRack + Sampler — reproducción de muestras basada en pads con envolventes de tono/filtro/volumen por pad. Las muestras se almacenan en IndexedDB para una recuperación rápida. 5 kits de fábrica específicos por género (boombap, trap, house, dnb, afrobeat).
SeedSynth + Geist (en el motor AudioStudioEngine heredado — ahora integrado en Soundbend desde la Ola 14) — un generador de parches genéticos (Synplant 2-clase) y una máquina de batería estilo Geist. Estos son los activos de propiedad intelectual propios que hicieron que la doctrina de consolidación fuera un gran éxito — tuvimos que preservar el comportamiento idéntico a nivel de bits a través de una fusión de 30k líneas. Prueba nula de 100 semillas aprobada después de la fusión.
6. El Mezclador + envíos auxiliares
Un Mixer adecuado — no solo faders por pista sino inserciones de FX por pista, envíos auxiliares pre/post-fader, bus maestro — es lo que separa una DAW de un secuenciador. El Mixer de Soundbend es de ~655 LOC (src/audio/mixer.js). Cada pista es un gráfico AudioNode con ranuras de inserción, puntos de envío y medición.
La parte complicada es la diferencia entre envíos auxiliares pre-fader y post-fader. Los envíos pre-fader se envían a un bus de reverberación sin importar el volumen de la pista (uso clásico: reverberación paralela que sobrevive a un fade de pista). Los post-fader escalan con el volumen de la pista. Ambos están disponibles.
7. MIDI + WAM plugin host
WebMIDI está maduro — la entrada de controladores desde cualquier teclado MIDI USB funciona sin problemas. Nuestro rack MIDI (Arpeggiador, Escala, Acordes) se sitúa entre el controlador e el instrumento, transformando los flujos de notas.
Para plugins, alojamos Web Audio Modules v2 (WAM) — plugins nativos del navegador. Ecosistema más pequeño que VST (25 años de ventaja) pero en crecimiento. Cargar un WAM es getWamHost().load(wamUri), que devuelve un AudioNode que puedes insertar en cualquier cadena.
Los WAM requieren CSP por ruta porque cargan JS proporcionado por el usuario. Nuestros _headers limitan el CSP para /soundbend con un allow-list de script-src para registros de WAM conocidos.
8. OfflineAudioContext para rebote
La exportación se ejecuta mediante OfflineAudioContext — renderiza más rápido que en tiempo real (o más lento, dependiendo de la complejidad de la cadena) a un AudioBuffer estático, luego codifica a WAV mediante nuestro codificador en navegador.
Aviso: no todos los nodos funcionan en OfflineAudioContext. MediaStreamAudioSourceNode no lo hace (no se puede grabar micrófono en vivo sin conexión, obviamente). Algunos worklets necesitan una reinicialización cuidadosa del estado entre transiciones de en línea a sin conexión. Nos encontramos con esto repetidamente y ahora Mixer.toJSON() + Mixer.fromJSON(offlineCtx) es el patrón canónico: serializa el estado del mixer, reconstruye un mixer paralelo en el contexto offline, renderiza.
9. Colaboración mediante Yjs
Yjs es una biblioteca CRDT que maneja la edición colaborativa multiusuario con resolución automática de conflictos. Nuestra clase SoundbendSession encapsula Yjs con una estructura de documento por pista (Y.Map para metadatos de pista, Y.Array para pasos de patrón, Y.Text para letras/notas).
Dos a cuatro productores pueden editar el mismo proyecto simultáneamente con sincronización de pistas precisa a nivel de muestra. Esto es más difícil que la colaboración en documentos de texto porque los datos de audio son de órdenes de magnitud más grandes: compartimos metadatos + patrones mediante Yjs, no audio en bruto. Las muestras en bruto permanecen locales (IndexedDB por usuario).
10. Presupuesto de rendimiento
Ejecutar una DAW completa en un navegador con interfaz de 60fps + audio en tiempo real + SharedArrayBuffer + WASM + múltiples worklets requiere un presupuesto ajustado. Algunos números:
- Hilo de audio: ~2ms / buffer de 128 muestras a 48kHz (sub-frame)
- Hilo principal: 16,6ms / 60fps por fotograma; el manejo de audio debe permanecer <1ms por fotograma
- Configuración de Worklet: costo único de ~10-50 ms por carga de worklet (envío de 15+ worklets — los agrupamos)
- Asignación de SharedArrayBuffer: 4KB de búferes de anillo por parámetro de worklet dinámico
- Tamaño del fragmento de Soundbend (post-consolidación): ~496 KB sin comprimir, ~120 KB gzip
- Carga completa del proyecto (frío): ~800ms en portátil de gama media
- Exportar render: ~0.3x a 2x en tiempo real dependiendo de la complejidad de la cadena de efectos
11. Conjunto de pruebas nulo
Las regresiones de DSP son silenciosas — el audio suena diferente de maneras sutiles que una revisión de código no puede detectar. Soundbend incluye un sistema de pruebas null impulsado por Puppeteer en tests/audio-null/.
Para cada efecto × preajuste × señal de prueba, el sistema de pruebas renderiza mediante OfflineAudioContext dentro de un Chromium sin interfaz, compara el WAV resultante con un golden commitado y falla la compilación si el pico residual supera -60 dBFS.
Wave 14F añadió 100 semillas basales de SeedSynth y 32 patrones de batería Geist dorados. Cuando fusionamos Soundbend en AudioStudio (Wave 14B-G), la prueba nula detectó cualquier cosa que hubiera roto silenciosamente los instrumentos propietarios. 96 de 100 semillas de SeedSynth pasaron bit-identical. Los 4 fallos eran quirks preexistentes de Chromium Web Audio (desplazamiento de resonancia de filtro de alto Q entre instancias de OfflineAudioContext) — no eran regresiones de fusión, y no eran solucionables desde JS.
Las regresiones DSP son silenciosas. La revisión de código no las puede escuchar. El conjunto de pruebas null sí — por eso es bloqueante en CI.
12. Por qué el navegador + cliente-side fue la apuesta correcta
Los DAW nativos (Ableton, Logic, FL Studio) tienen una ventaja de 30 años. Superarlos característica a característica es un largo camino. Pero el precio — eso se podía ganar de inmediato al hacer apuestas arquitectónicas diferentes.
WebAssembly superó el umbral de rendimiento entre 2022 y 2024. Web Audio AudioWorklets se lanzaron ampliamente alrededor de la misma época. SharedArrayBuffer + COOP/COEP se estabilizaron. Chromium, Firefox y Safari admiten todas las API necesarias con rendimiento adecuado.
La implicación de precios: si el procesamiento de audio se ejecuta en el dispositivo del usuario, no lo pagamos. Nuestro costo marginal por suscriptor Pro es casi cero. Por eso $4.99/mo es sostenible para siempre. Un niño en Lagos con un Android de 2020 obtiene una DAW completa que alguien en San Francisco paga el mismo $4.99 para acceder.
Lee el ensayo sobre la arquitectura de precios para entender la economía. Para el DSP, eso es la mayor parte de la historia.
Prueba ahora
Soundbend está en morph.cool/soundbend. La versión gratuita funciona sin registro. El Pro de $4.99/mes desbloquea la cadena de masterización + limitador de pico verdadero + presets adicionales. Se bienvenido el teclado WebMIDI, pero no es obligatorio.
— Hayden + el equipo de agentes de Morph
22 de abril de 2026