Este é um post técnico sobre como o Soundbend da Morph — uma estação de trabalho digital de áudio completa com 5 instrumentos nativos, um Mixer com cadeias de efeitos e envios auxiliares, mais de 30 efeitos (incluindo 5 portagens Tier-1 da Airwindows e um limitador de pico verdadeiro), uma rack de efeitos MIDI, um host de plugin WAM v2 e uma camada de colaboração Yjs CRDT — funciona inteiramente em uma aba do navegador.
A pergunta prática é: isso é realmente competitivo com o Ableton? A resposta honesta: para a maioria dos fluxos de trabalho de produtores, sim. Para integrações profundas do Max for Live, ainda não. Leia a comparação de alternativas ao Ableton para uma análise detalhada do produto. Este post é sobre engenharia.
A pilha
- Frontend React + Vite
- Web Audio API para o gráfico de áudio
- AudioWorkletProcessor para DSP personalizado (off-main-thread)
- WebAssembly para processamento crítico de desempenho (builds WASM personalizados)
- MessagePort + buffers de anel para comunicação UI ↔ worklet
- Yjs para colaboração CRDT
- IndexedDB para persistência de projeto + armazenamento de amostras
- WebMIDI para entrada de controlador de hardware
- OfflineAudioContext para bounce/export
1. O gráfico de áudio
Cada faixa no Soundbend passa por uma cadeia: instrumento → cadeia de FX da faixa → envio auxiliar → faixa do mixer → bus principal → limitador → destino. Cada seta é uma conexão Web Audio AudioNode.
O Web Audio nos dá AudioContext, GainNode, BiquadFilterNode, ConvolverNode, AnalyserNode e amigos. Esses são otimizados pelos motores de navegador (V8/SpiderMonkey/JSC todos profundamente investidos). Para efeitos padrão — EQ, automação de ganho, filtragem básica — usamos nós nativos. Eles são rápidos e bem testados.
Para efeitos personalizados — portas do Airwindows, nossa saturação, nosso limitador de verdadeiro pico — nós entramos em AudioWorkletProcessor, que roda na thread de áudio, garantindo prioridade em tempo real, e é o lugar arquitetural correto para DSP não padrão.
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);
Worklets são enviados em public/audio-worklets/*.js e carregados via audioContext.audioWorklet.addModule(path). Uma vez carregados, qualquer parte do gráfico pode instanciar um AudioWorkletNode para esse processador. O processamento ocorre fora da thread principal — animações de UI não prejudicam o áudio.
2. Os 5 ports Tier-1 Airwindows
Chris Johnson's Airwindows é 2.500+ plugins de áudio, licenciados MIT, DSP legendariamente saboroso. Portamos 5 para AudioWorklets do navegador para a ship Wave 12 do Soundbend:
- Pressure6 — compressão transparente que respira
- ToTape9 — modelagem de saturação de fita analógica
- PurestDrive — saturação de fase mínima sem tons agudos duros
- CreamCoat — calor + excitador harmônico
- NotJustAnotherDither — Dither TPDF para redução de profundidade de bits (mastering)
Cada porta é ~30-80 LOC de matemática em um AudioWorkletProcessor. As portas não correspondem bit a bit ao Airwindows (diferentes tratamentos de FMA/denormal entre motores numéricos C++ e JS), mas correspondem sonoramente. Testes nulos mantêm os outputs ≤ -80 dBFS residual contra os goldens, então mudanças no DSP são detectadas.
3. Limitador de pico verdadeiro
Plataformas de streaming modernas (Spotify, Apple Music, YouTube) exigem normalização de loudness true-peak conforme ITU-R BS.1770-5. Picos de amostra e picos interamostragem são coisas diferentes; um sinal pode picoar em -1 dBFS amostralmente, mas exceder 0 dBFS true-peak após reconstrução D/A. Um limitador não-true-peak irá cortar no DAC mesmo que seu DAW mostre que está limpo.
Nosso limitador implementa a especificação completa ITU: 4x oversampling, detecção de pico inter-muestra, lookahead, liberação de knee suave. Ele é enviado na forma de AudioWorklet em public/audio-worklets/true-peak-limiter-processor.js. Medidas contra implementações de referência (Oxford Limiter, iZotope Ozone Maximizer) correspondem dentro de 0,1 dB em LUFS integrado.
4. Comunicação off-main-thread
O gráfico de áudio é executado na thread de áudio. A UI é executada na thread principal. Alterações de parâmetros (girar um controle, suavizar uma faixa) precisam propagar da UI → áudio sem travar o áudio.
O AudioParam do Web Audio manipula isso nativamente para parâmetros padrão (GainNode gain, BiquadFilterNode frequency). Para trabalhos personalizados com worklet, usamos MessagePort com clonagem estruturada para mensagens de interface, e buffers de anel baseados em SharedArrayBuffer para dados de automação de alta taxa.
SharedArrayBuffer requer Cross-Origin-Opener-Policy: same-origin + Cross-Origin-Embedder-Policy: require-corp headers. Esses são definidos em public/_headers para as rotas /soundbend + /pulse. O Tape Delay usa um buffer circular a 96kHz para evitar latência de message-port.
5. Os 5 instrumentos nativos
O Soundbend vem com 5 instrumentos, todos personalizados:
Sintetizador FM — síntese FM de 6 operadores modelada no DX7 / Operator. Visualizador de algoritmo + matriz de modulação completa. ~800 LOC JS para a interface, ~300 LOC para o worklet de alocador de voz.
Sintetizador de Wavetable — síntese morph-between-tables. Warping espectral + unisono + detune estéreo. 30+ wavetables de fábrica. Utiliza ConvolverNode para crossfade de wavetable em taxa de áudio.
Analog Subtractive — polysynth com 2 osciladores e filtros Cytomic SVF. Cytomic é a topologia de filtro de variável de estado que soa certo; o SVF ingênuo tem problemas de aliasing acima de fc > SR/6. A porta Cytomic lida com isso por meio de matemática de feedback de atraso zero.
DrumRack + Sampler — reprodução de amostras baseada em pads com envelopes de pitch/filtro/amp por pad. Amostras armazenadas no IndexedDB para recall rápido. 5 kits de fábrica específicos por gênero (boombap, trap, house, dnb, afrobeat).
SeedSynth + Geist (no legacy AudioStudioEngine — agora fundido no Soundbend a partir da Wave 14) — um gerador de patch genético (Synplant 2-class) e uma máquina de bateria Geist-style. Esses são os direitos autorais proprietários que tornaram a doutrina de consolidação um grande negócio — tivemos que preservar o comportamento bit-idêntico através de uma fusão de 30k linhas. Teste nulo de 100 sementes concluído após a fusão.
6. O Mixer + envios auxiliares
Um Mixer adequado — não apenas faders por faixa, mas inserções de FX por faixa, envios auxiliares pré/pós-fader, bus mestre — é o que separa um DAW de um sequenciador. A classe Mixer do Soundbend tem ~655 LOC (src/audio/mixer.js). Cada faixa é um gráfico AudioNode com slots de inserção, pontos de envio e medição.
A parte complicada é o envio pré-fader versus pós-fader. Envios pré-fader para um bus de reverb independente do volume da faixa (uso clássico: reverb paralela que sobrevive a uma fade de faixa). Pós-fader escala com o volume da faixa. Ambos estão disponíveis.
7. MIDI + WAM plugin host
O WebMIDI está maduro — a entrada de controle de qualquer teclado MIDI USB funciona perfeitamente. A nossa rack MIDI (Arpeggiador, Escala, Acordes) fica entre o controlador e o instrumento, transformando os fluxos de notas.
Para plugins, hospedamos Web Audio Modules v2 (WAM) — plugins nativos do navegador. Ecossistema menor do que VST (25 anos de vantagem) mas em crescimento. Carregar um WAM é getWamHost().load(wamUri), que retorna um AudioNode que você pode inserir em qualquer cadeia.
WAMs requerem CSP por rota porque carregam JS fornecido pelo usuário arbitrário. Nossos _headers escopam o CSP com precisão para /soundbend com uma lista de permissão script-src para registros bem conhecidos de WAM.
8. OfflineAudioContext para bounce
A exportação é executada via OfflineAudioContext — renderiza mais rápido que em tempo real (ou mais lento, dependendo da complexidade da cadeia) para um AudioBuffer estático, depois codifica em WAV usando nosso codificador no navegador.
Aviso: nem todos os nós funcionam em OfflineAudioContext. MediaStreamAudioSourceNode não funciona (não é possível gravar microfone ao vivo offline, obviamente). Certos worklets precisam de reinicialização cuidadosa do estado entre transições online → offline. Encontramos esse problema repetidamente e agora Mixer.toJSON() + Mixer.fromJSON(offlineCtx) é o padrão canônico: serializa o estado do mixer, reconstrói um mixer paralelo no contexto offline, renderiza.
9. Colaboração via Yjs
Yjs é uma biblioteca CRDT que gerencia edição colaborativa multi-usuário com resolução automática de conflitos. Nosso SoundbendSession encapsula o Yjs com estrutura de documento por faixa (Y.Map para metadados de faixa, Y.Array para passos de padrão, Y.Text para letras/notas).
Dois a quatro produtores podem editar o mesmo projeto simultaneamente com sincronização de faixa precisa. Isso é mais difícil do que colaboração em documentos de texto porque os dados de áudio são ordens de magnitude maiores — compartilhamos metadados + padrões via Yjs, não áudio bruto. Amostras brutas permanecem locais (IndexedDB por usuário).
10. Orçamento de desempenho
Executar um DAW completo em um navegador com UI de 60fps + áudio em tempo real + SharedArrayBuffer + WASM + múltiplos worklets requer orçamentos apertados. Algumas números:
- Thread de áudio: ~2ms / buffer de 128 amostras a 48kHz (sub-frame)
- Thread principal: 16,6ms / 60fps por quadro; o tratamento de áudio deve permanecer <1ms por quadro
- Configuração do Worklet: custo único de ~10-50ms por carregamento do worklet (envie 15+ worklets — nós agrupamos)
- Alocação de SharedArrayBuffer: buffers de anel de 4KB por parâmetro de worklet dinâmico
- Tamanho do chunk Soundbend (pós-consolidação): ~496 KB brutos, ~120 KB gzip
- Carregamento completo do projeto (frio): ~800ms em laptop de médio porte
- Exportar render: ~0,3x a 2x em tempo real, dependendo da complexidade da cadeia de efeitos
11. Suíte de teste de null
Regressões de DSP são silenciosas — o áudio soa diferente de maneiras sutis que uma revisão de código não consegue detectar. O Soundbend vem com um conjunto de testes null controlado pelo Puppeteer em tests/audio-null/.
Para cada efeito × pré-configuração × sinal de teste, o sistema renderiza via OfflineAudioContext dentro de um Chromium sem interface, testa nulo o WAV resultante contra um ouro comprometido e falha a construção se o pico residual exceder -60 dBFS.
Wave 14F adicionou 100 seed baselines do SeedSynth e 32 goldens de padrões de bateria Geist. Quando integramos o Soundbend ao AudioStudio (Wave 14B-G), o teste nulo detectou qualquer coisa que poderia ter quebrado silenciosamente os instrumentos proprietários. 96 dos 100 seeds do SeedSynth passaram bit-identicamente. Os 4 falhos eram problemas pré-existentes de quirks do Chromium Web Audio (desvio de ressonância de filtro de alta-Q entre instâncias de OfflineAudioContext) — não regressões de merge, e não passíveis de correção via JS.
Regressões DSP são silenciosas. A revisão de código não consegue ouvi-las. O harness de teste nulo pode — é por isso que ele bloqueia o CI.
12. Por que browser + client-side foi a escolha certa
DAWs nativas (Ableton, Logic, FL Studio) têm uma vantagem de 30 anos. Vencer em termos de funcionalidades é um caminho longo. Mas preço — isso foi algo que podia ser conquistado imediatamente, fazendo apostas arquitetônicas diferentes.
WebAssembly ultrapassou o limiar de desempenho em 2022-2024. Web Audio AudioWorklets foram amplamente lançados aproximadamente na mesma época. SharedArrayBuffer + COOP/COEP estabilizaram. Chromium, Firefox e Safari todos suportam as APIs necessárias com desempenho adequado.
A implicação de preços: se o processamento de áudio ocorre no dispositivo do usuário, não pagamos por isso. Nosso custo marginal por assinante Pro é quase zero. Então $4.99/mo é sustentável para sempre. Uma criança em Lagos com um Android de 2020 obtém um DAW completo que alguém em São Francisco paga o mesmo $4.99 para acessar.
Leia o ensaio sobre a arquitetura de preços para entender a economia. Para o DSP, essa é a maior parte da história.
Experimente
O Soundbend está em morph.cool/soundbend. A versão gratuita funciona sem cadastro. O Pro de $4,99/mês libera a cadeia de masterização + limitador de pico verdadeiro + pré-definidos adicionais. Teclado WebMIDI é bem-vindo, mas não é obrigatório.
— Hayden + a equipe de agentes Morph
22 de abril de 2026