Morph 部落格
工程

我們如何在瀏覽器中建構一個DAW

Soundbend 基於 WebAssembly、Web Audio API 和 25 年的 DSP 研究運行 — 全部在客戶端。完整的工程故事:音頻圖、工作區、Airwindows 移植、真正的峰值限制器、外掛主機。

作者:HAYDEN SIMERLY12 分鐘閱讀更新日期:2026 年 4 月

這是一個關於 Morph 的 Soundbend — 一個包含 5 種原生音色、混音器搭配 FX 鏈和輔助輸出、30 多種效果(包括 5 個 Airwindows Tier-1 接口和真正的峰值限制器)、MIDI 效果架、WAM v2 外掛主機,以及 Yjs CRDT 協作層的完整數位音訊工作站 — 在瀏覽器標籤頁中 完全 運行的技術文章。

The practical question is: is this actually competitive with Ableton? The honest answer: for most producer workflows, yes. For deep Max for Live integrations, not yet. Read the Ableton alternative comparison for the product-level breakdown. This post is the engineering.

堆疊

1. The audio graph

Soundbend 中的每條音軌都通過鏈接路由: 樂器 → 音軌 FX 鏈接 → 輔助輸出 → 混音器音軌 → 主總線 → 限制器 → 目的地。每個箭頭代表一個 Web Audio AudioNode 連接。

Web Audio 給我們 AudioContextGainNodeBiquadFilterNodeConvolverNodeAnalyserNode 及其他。這些由瀏覽器引擎優化(V8/SpiderMonkey/JSC 均深度投入)。對於 標準 效果——EQ、增益自動化、基本過濾——我們使用原生節點。它們 快速 且經過充分測試。

自訂效果 — Airwindows移植、我們的飽和度、我們的真正峰值限制器 — 我們會使用AudioWorkletProcessor,它在音頻線程上運行,保證實時優先級,且是處理非標準DSP的正確架構位置。

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 會以 public/audio-worklets/*.js 的形式發佈,並透過 audioContext.audioWorklet.addModule(path) 載入。載入後,圖形中的任何部分均可實例化一個 AudioWorkletNode 來處理該處理器。處理工作在主執行緒之外運行 — UI 動畫不會阻塞音頻。

2. 5 個 Airwindows Tier-1 插件

Chris Johnson's Airwindows 是2,500多個音頻外掛程式,採用MIT授權,以極具品味的DSP聞名。我們已將其中5個移植至Soundbend的Wave 12,以支援瀏覽器AudioWorklets:

每個端口約為 30-80 行數學程式碼在 AudioWorkletProcessor 中。端口並未與 Airwindows 完全匹配(C++ 和 JS 數值引擎之間的 FMA/非規格化處理不同),但音質匹配。Null 測試確保輸出殘留 ≤ -80 dBFS 對應基準,因此 DSP 變更會被捕捉。

3. 真峰值限制器

現代串流平台(Spotify、Apple Music、YouTube)根據ITU-R BS.1770-5強制執行真正峰值音量標準化。樣本峰值與間樣本峰值是不同的概念;信號在樣本層面可能峰值為-1 dBFS,但在D/A轉換後可能超過0 dBFS真正峰值。非真正峰值限制器即使DAW顯示正常,仍可能在DAC中削波。

我們的限制器實現了完整的 ITU 標準:4 倍過取樣、跨樣本峰值檢測、預覽、軟膝釋放。它以 AudioWorklet 格式提供,位於 public/audio-worklets/true-peak-limiter-processor.js。與參考實現(Oxford Limiter、iZotope Ozone Maximizer)的測量結果在 LUFS 積分上相差小於 0.1 dB。

4. 非主執行緒通訊

音頻圖形在音頻執行緒上運行,UI 在主執行緒上運行。參數變更(轉動旋鈕、淡入淡出軌道)需要從 UI → 音頻傳播而不導致音頻中斷。

Web Audio 的 AudioParam 原生處理標準參數(GainNode gain、BiquadFilterNode frequency)。自訂工作器參數則使用 MessagePort 搭配結構化克隆傳遞 UI 訊息,並以 SharedArrayBuffer 支援的環形緩衝區處理高頻率自動化資料。

SharedArrayBuffer 需要 Cross-Origin-Opener-Policy: same-origin + Cross-Origin-Embedder-Policy: require-corp 標頭。這些標頭在 public/_headers 中設置,適用於 /soundbend/pulse 路由。Tape Delay 使用 96kHz 的環形緩衝區以避免訊息埠延遲。

5. 5 種原生音色

Soundbend提供5種自訂樂器:

FM合成 — 6運算元FM合成,模擬DX7 / Operator。演算法可視化 + 完整調製矩陣。UI約800行JS,語音分配器約300行工作區。

波表合成器 — 漢譜間合成。頻譜變形 + 統一音 + 立體聲微調。30+ 廠商預設波表。使用 ConvolverNode 在音頻速率下進行波表交叉淡入。

模擬減法 — 兩振盪器多音色合成器,配備 Cytomic SVF 濾波器。Cytomic 是一種狀態變數濾波器拓撲,聲音效果正確; naïve SVF 在 fc > SR/6 時會有混疊問題。Cytomic 版本透過零延遲反饋數學處理此問題。

DrumRack + Sampler — 以按鍵為基礎的樣本播放,每按鍵可調整音高/濾波器/音量包絡。樣本儲存在 IndexedDB 以快速召回。5 種 Genre 專用預設套件(boombap、trap、house、dnb、afrobeat)。

SeedSynth + Geist(在舊版 AudioStudioEngine 中——現已合併至 Soundbend,自 Wave 14 起)— 一種遺傳補丁生成器(Synplant 2 類)和 Geist 風格鼓機。這些是使整合 doctrine 成為重要事件的專有 IP —— 我們必須在 30k 行合併中保持位元完全一致的行為。合併後通過 100 個種子的 null 測試。

6. 混音器 + 輔助輸出

一個真正的混音器——不只是每軌的推子,而是每軌的FX插入點、前/後推子輔助發送、主總線——才是區分DAW與序列器的關鍵。Soundbend的混音器類別約為655行代碼(src/audio/mixer.js)。每軌是一個AudioNode圖,包含插入槽、發送Tap點和計量。

棘手的部分是預推子與後推子輔助輸出。預推子將訊號送至混響總線,不受軌道音量影響(經典用途:平行混響,即使軌道音量降低仍保留)。後推子則隨軌道音量調整。兩者均內建。

7. MIDI + WAM插件主機

WebMIDI 已經成熟 — USB-MIDI 鍵盤的控制器輸入即刻生效。我們的 MIDI 音頻架(琶音器、調式、和弦)位於控制器和樂器之間,轉換音符流。

對於外掛程式,我們主機提供 Web Audio Modules v2 (WAM) — 瀏覽器原生外掛程式。生態系規模小於 VST(25 年的先發優勢),但正在成長。載入 WAM 的方式是 getWamHost().load(wamUri),會回傳一個 AudioNode,您可以插入任何串流中。

WAMs 需要針對每條路徑設定 CSP,因為它們會載入任意使用者提供的 JS。我們的 _headers 會針對 /soundbend 嚴格設定 CSP,並為知名 WAM 註冊表設定 script-src 允許清單。

8. OfflineAudioContext用於彈跳

匯出透過 OfflineAudioContext 運行——根據鏈複雜度,可比即時更快或更慢地渲染至靜態 AudioBuffer,然後透過瀏覽器內建編碼器轉換為WAV。

注意:並非所有節點都能在OfflineAudioContext中運作。MediaStreamAudioSourceNode不支援(無法離線錄製即時麥克風,顯然)。某些工作區需要在線上→離線轉換時仔細重置狀態。我們反覆遇到此問題,現已採用Mixer.toJSON() + Mixer.fromJSON(offlineCtx)作為標準模式:序列化混音器狀態,在離線上下文中重建平行混音器,然後渲染。

9. 透過 Yjs 協作

Yjs 是一個 CRDT 庫,可處理多人協作編輯並自動解決衝突。我們的 SoundbendSession 類別將 Yjs 包裝為每軌文件結構(Y.Map 用於軌道元數據,Y.Array 用於模式步驟,Y.Text 用於歌詞/註釋)。

兩個到四個製作人可以同時編輯同一個專案,並實現樣本精確的音軌同步。這比文字文件協作更困難,因為音頻數據量大了數個數量級——我們透過 Yjs 共享元數據和模式,而非原始音頻。原始樣本保持在本地(每個使用者的 IndexedDB)。

10. 性能預算

在瀏覽器中執行完整DAW,搭配60fps UI + 即時音訊 + SharedArrayBuffer + WASM + 多個工作線程,需要精確的資源管理。部分數據:

11. 空值測試框架

DSP 回歸問題是靜默的 —— 音頻以微妙的方式聽起來不同,而程式碼審查無法捕捉。Soundbend 隨附 Puppeteer 驅動的空測試工具,位於 tests/audio-null/ 中。

針對每個效果 × 預設 × 測試信號,測試工具會透過 OfflineAudioContext 在無頭 Chromium 內執行,將結果 WAV 與已承諾的黃金標準進行 null 測試,若殘留峰值超過 -60 dBFS 則建構失敗。

Wave 14F新增了100個SeedSynth種子基線和32個Geist鼓點金屬基線。當我們將Soundbend合併到AudioStudio(Wave 14B-G)時,null-test檢測到任何可能靜默破壞專有音軌的問題。100個SeedSynth種子中有96個通過了位元相同測試。4個失敗是預先存在的Chromium Web Audio問題(OfflineAudioContext實例之間高Q濾波器共振漂移)——不是合併回退,且無法從JS中修復。

DSP迴歸是靜音的。程式碼審查聽不到它們。null 測試工具可以——這就是為什麼它會阻斷 CI。

12. 為何瀏覽器 + 用戶端處理是正確的選擇

原生 DAW(Ableton、Logic、FL Studio)有 30 年的先發優勢。要功能對功能地超越它們是漫長的路。但 定價 — 這是在架構上做出不同選擇後立即可贏得的。

WebAssembly 在 2022-2024 年跨過效能門檻。Web Audio AudioWorklets 在相近時間廣泛推出。SharedArrayBuffer + COOP/COEP 穩定化。Chromium、Firefox 和 Safari 均支援所需 API,且效能充足。

定價 implications:如果音頻處理在使用者裝置上執行,我們就不需支付成本。每位 Pro 用戶的邊際成本接近零。因此 $4.99/mo 是可持續的 永久。一個在拉各斯的學生用2020年 Android 手機,可獲得完整的 DAW,與舊金山的用戶支付相同的 $4.99 來使用。

閱讀定價架構論文了解經濟學。對於DSP,這幾乎是全部故事。

立即試用

Soundbend 請至 morph.cool/soundbend。免費方案無需註冊即可使用。$4.99/月 Pro 版解鎖母帶處理鏈 + 真峰值限制器 + 額外預設。WebMIDI 鍵盤歡迎使用,但非必要。

開啟 Soundbend

— Hayden 和 Morph 代理團隊
2026年4月22日