Morph Blog
Engineering

Come abbiamo costruito un DAW nel tuo browser.

Soundbend funziona su WebAssembly, Web Audio API e 25 anni di ricerca su DSP — tutto lato client. La storia tecnica completa: grafo audio, worklets, porting di Airwindows, limitatore true-peak, host per plugin.

DI HAYDEN SIMERLY12 MIN LETTURAAGGIORNATO APRILE 2026

Questa è una pubblicazione tecnica su come Morph's Soundbend — un intero workstation digitale audio completo con 5 strumenti nativi, un Mixer con catene di effetti e invii ausiliari, 30+ effetti (inclusi 5 porting Tier-1 di Airwindows e un true-peak limiter), una rack di effetti MIDI, un host plugin WAM v2 e un layer di collaborazione Yjs CRDT — funziona interamente in una scheda del browser.

La domanda pratica è: questo è effettivamente competitivo con Ableton? La risposta onesta: per la maggior parte dei flussi di lavoro dei produttori, sì. Per le integrazioni profonde con Max for Live, non ancora. Leggi il confronto tra alternative Ableton per una panoramica a livello di prodotto. Questo post è l'ingegneria.

Lo stack

1. Il grafico audio

Ogni traccia in Soundbend passa attraverso una catena: strumento → catena FX traccia → invio aux → striscia del mixer → bus master → limitatore → destinazione. Ogni freccia rappresenta una connessione Web Audio AudioNode.

Web Audio ci offre AudioContext, GainNode, BiquadFilterNode, ConvolverNode, AnalyserNode e amici. Questi sono ottimizzati dai motori del browser (V8/SpiderMonkey/JSC investiti in profondità). Per effetti standard — EQ, automazione del guadagno, filtraggio di base — utilizziamo nodi nativi. Sono veloci e ben testati.

Per effetti personalizzati — porting di Airwindows, la nostra saturazione, il nostro true-peak limiter — passiamo a AudioWorkletProcessor, che funziona sul thread audio, garantendo priorità in tempo reale, e rappresenta il posto architetturale corretto per DSP non standard.

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);

I Worklets vengono distribuiti in public/audio-worklets/*.js e caricati tramite audioContext.audioWorklet.addModule(path). Una volta caricati, qualsiasi parte del grafico può istanziare un AudioWorkletNode per quel processore. L'elaborazione avviene fuori dal thread principale — le animazioni dell'interfaccia utente non interferiscono con l'audio.

2. Le 5 porte Tier-1 Airwindows

Chris Johnson's Airwindows è 2.500+ plugin audio, con licenza MIT, leggendariamente raffinati nel DSP. Abbiamo portato 5 plugin nel browser per AudioWorklets di Soundbend nella versione Wave 12:

Ogni porta è ~30-80 LOC di matematica in un AudioWorkletProcessor. Le porte non corrispondono bit per bit ad Airwindows (diversa gestione FMA/denormal tra motori numerici C++ e JS) ma corrispondono sonoricamente. I test null mantengono le uscite ≤ -80 dBFS rispetto ai riferimenti, quindi i cambiamenti DSP vengono rilevati.

3. Il limitatore di picco vero

Le piattaforme moderne di streaming (Spotify, Apple Music, YouTube) applicano la normalizzazione del livello di volume true-peak secondo ITU-R BS.1770-5. I picchi di campionamento e i picchi inter-campionamento sono cose diverse; un segnale può raggiungere -1 dBFS a livello di campione ma superare 0 dBFS true-peak dopo la ricostruzione D/A. Un limitatore non true-peak clipperà nel DAC anche se il tuo DAW lo mostra pulito.

Il nostro limitatore implementa specifiche complete ITU: 4x oversampling, rilevamento inter-sample-peak, lookahead, rilascio soft-knee. Viene fornito in formato AudioWorklet all'indirizzo public/audio-worklets/true-peak-limiter-processor.js. Le misurazioni rispetto alle implementazioni di riferimento (Oxford Limiter, iZotope Ozone Maximizer) corrispondono entro 0,1 dB su LUFS integrated.

4. Comunicazione fuori dal thread principale

Il grafico audio viene eseguito nel thread audio. L'interfaccia utente viene eseguita nel thread principale. Le modifiche ai parametri (ruotare un quadrante, attenuare una traccia) devono propagarsi dall'interfaccia utente → audio senza interruzioni audio.

Web Audio's AudioParam gestisce questo nativamente per i parametri standard (GainNode gain, BiquadFilterNode frequency). Per lavoro personalizzato, utilizziamo MessagePort con clonazione strutturata per i messaggi UI, e buffer anulari supportati da SharedArrayBuffer per dati di automazione ad alta frequenza.

SharedArrayBuffer richiede Cross-Origin-Opener-Policy: same-origin + Cross-Origin-Embedder-Policy: require-corp headers. Questi sono impostati in public/_headers per le rotte /soundbend + /pulse. Il Tape Delay utilizza un buffer circolare a 96kHz per evitare la latenza delle porte di messaggio.

5. Le 5 strumenti native

Soundbend include 5 strumenti, tutti personalizzati:

Sintesi FM — sintesi FM a 6 operatori modellata su DX7 / Operator. Visualizzatore di algoritmi + matrice completa di modulazione. ~800 LOC JS per l'interfaccia utente, ~300 LOC per il worklet di allocazione vocale.

Sintetizzatore Wavetable — sintesi morph-between-tables. Warping spettrale + unisono + stereo detune. Oltre 30 wavetable factory. Utilizza ConvolverNode per il crossfade wavetable in tempo reale.

Analog Subtractive — polisintetizzatore a 2 oscillatori con filtri Cytomic SVF. Cytomic è la topologia dei filtri a variabile di stato che suona bene; il SVF naive presenta problemi di aliasing per fc > SR/6. La versione Cytomic gestisce questo tramite matematica a feedback a ritardo zero.

DrumRack + Sampler — riproduzione di campioni basata su pad con envelope di pitch/filtro/ampiezza per ogni pad. I campioni sono memorizzati in IndexedDB per un richiamo rapido. 5 kit factory specifici per genere (boombap, trap, house, dnb, afrobeat).

SeedSynth + Geist (nell'engine AudioStudioLegacy — ora integrato in Soundbend a partire dalla Wave 14) — un generatore di patch genetiche (Synplant 2-class) e una macchina ritmica di stile Geist. Questi sono i brevetti proprietari che hanno reso la dottrina di consolidamento un grande successo — abbiamo dovuto preservare il comportamento identico a bit attraverso un merge di 30k linee. Test nullo a 100 semi superato post-merge.

6. Il Mixer + invii ausiliari

Un Mixer adeguato — non solo equalizzatori per traccia ma inserimenti FX per traccia, invii ausiliari pre/post-fader, bus master — è ciò che distingue un DAW da un sequencer. Il Mixer di Soundbend è class ~655 LOC (src/audio/mixer.js). Ogni traccia è un grafico AudioNode con slot di inserimento, punti di tap per invii e misurazione.

La parte difficile è distinguere tra invii aux pre-fader e post-fader. Gli invii pre-fader vengono inviati a un bus di riverbero indipendentemente dal volume della traccia (uso classico: riverbero parallelo che sopravvive a una riduzione del volume della traccia). Gli invii post-fader variano in proporzione al volume della traccia. Entrambi sono disponibili.

7. MIDI + WAM plugin host

WebMIDI è maturo — l'input del controller da qualsiasi tastiera USB-MIDI funziona semplicemente. La nostra rack MIDI (Arpeggiatore, Scala, Accordi) si trova tra il controller e l'strumento, trasformando i flussi di note.

Per i plugin, ospitiamo Web Audio Modules v2 (WAM) — plugin nativi del browser. L'ecosistema è più piccolo rispetto a VST (25 anni di vantaggio) ma in crescita. Il caricamento di un WAM avviene con getWamHost().load(wamUri), che restituisce un AudioNode che puoi inserire in qualsiasi catena.

I WAM richiedono un CSP per route perché caricano JS forniti dall'utente arbitrario. I nostri _headers limitano strettamente il CSP per /soundbend con un allow-list script-src per registri WAM noti.

8. OfflineAudioContext per rimbalzo

L'esportazione avviene tramite OfflineAudioContext — elabora più velocemente del tempo reale (o più lentamente, a seconda della complessità della catena) in un AudioBuffer statico, quindi codifica in WAV tramite il nostro encoder in-browser.

Avvertenza: non tutti i nodi funzionano in OfflineAudioContext. MediaStreamAudioSourceNode non funziona (non è possibile registrare un microfono live offline, ovviamente). Alcuni worklet richiedono una reimpostazione accurata dello stato tra transizioni online → offline. Ci siamo imbattuti ripetutamente in questo problema e ora Mixer.toJSON() + Mixer.fromJSON(offlineCtx) è il modello canonico: serializza lo stato del mixer, ricostruisci un mixer parallelo nel contesto offline, renderizza.

9. Collaborazione tramite Yjs

Yjs è una libreria CRDT che gestisce l'editing collaborativo multi-utente con risoluzione automatica dei conflitti. La nostra classe SoundbendSession avvolge Yjs con una struttura documentale per traccia (Y.Map per i metadati della traccia, Y.Array per i passi del pattern, Y.Text per testi/notes).

Due a quattro produttori possono modificare lo stesso progetto contemporaneamente con sincronizzazione dei tracce accurata a livello di campione. Questo è più difficile che collaborare su documenti testuali perché i dati audio sono di ordini di grandezza più grandi: condividiamo metadati e schemi tramite Yjs, non i dati audio grezzi. I campioni grezzi rimangono locali (IndexedDB per utente).

10. Budget di prestazioni

Eseguire un DAW completo in un browser con interfaccia utente a 60fps + audio in tempo reale + SharedArrayBuffer + WASM + più worklet richiede un bilancio preciso. Alcuni numeri:

11. Test harness di null

Le regressioni DSP sono silenziose — l'audio suona diverso in modi sottili che una revisione del codice non può rilevare. Soundbend include un test harness guidato da Puppeteer in tests/audio-null/.

Per ogni effetto × preset × segnale di test, il sistema genera tramite OfflineAudioContext all'interno di Chromium headless, esegue test null sul risultato WAV confrontandolo con un golden commit, e fallisce la build se il picco residuo supera -60 dBFS.

Wave 14F ha aggiunto 100 baselines SeedSynth e 32 pattern drum Geist goldens. Quando abbiamo integrato Soundbend in AudioStudio (Wave 14B-G), il test null ha rilevato qualsiasi cosa che avrebbe potuto rompere silenziosamente gli strumenti proprietari. 96 su 100 seed SeedSynth hanno superato il test bit-identico. I 4 fallimenti erano già presenti in Chromium Web Audio (drift di risonanza del filtro ad alto Q tra istanze di OfflineAudioContext) — non regressioni di fusione e non risolvibili da JS.

Le regressioni DSP sono silenziose. La revisione del codice non le può sentire. L'ambiente di test null lo può fare — ed è per questo che blocca la CI.

12. Perché browser + client-side è stata la scelta giusta

I DAW nativi (Ableton, Logic, FL Studio) hanno un vantaggio di 30 anni. Sconfiggerli funzionalità per funzionalità è una strada lunga. Ma il prezzo — questo era vincibile immediatamente scegliendo architetture diverse.

WebAssembly ha superato la soglia di prestazioni nel 2022-2024. Web Audio AudioWorklets sono stati distribuiti ampiamente nello stesso periodo. SharedArrayBuffer + COOP/COEP è stato stabilizzato. Chromium, Firefox e Safari supportano tutti le API necessarie con prestazioni adeguate.

L'implicazione sui prezzi: se l'elaborazione audio avviene sul dispositivo dell'utente, non dobbiamo pagare per essa. Il nostro costo marginale per ogni abbonato Pro è vicino allo zero. Quindi $4.99/mo è sostenibile per sempre. Un ragazzo a Lagos con un Android del 2020 ottiene un DAW completo che qualcuno a San Francisco paga lo stesso $4.99 per accedere.

Leggi l'saggio sull'architettura dei prezzi per l'economia. Per il DSP, questa è gran parte della storia.

Provalo

Soundbend è su morph.cool/soundbend. La versione gratuita funziona senza registrazione. $4,99/mese Pro sblocca la catena di mastering + limitatore true-peak + preset aggiuntivi. Tastiera WebMIDI benvenuta, non richiesta.

Apri Soundbend

— Hayden e il team dell'agente Morph
22 aprile 2026