Morph 블로그
엔지니어링

우리가 브라우저에서 DAW를 어떻게 구축했는지 입니다.

Soundbend는 WebAssembly, Web Audio API, 25년간의 DSP 연구를 기반으로 클라이언트 측에서 실행됩니다 — 전체 엔지니어링 스토리: 오디오 그래프, 워크릿, Airwindows 포트, 진정한 피크 리미터, 플러그인 호스트.

하이든 시머리에 의한12분 읽기2026년 4월 업데이트

이것은 Morph의 Soundbend에 대한 기술적 설명으로, 완전한 디지털 오디오 작업대(5개의 네이티브 악기, FX 체인과 AUX 송신이 있는 믹서, 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. 오디오 그래프

Soundbend의 모든 트랙은 다음 체인을 통해 라우팅됩니다: 악기 → 트랙 FX 체인 → 보조 송신 → 믹서 스트립 → 마스터 버스 → 리미터 → 대상. 각 화살표는 Web Audio AudioNode 연결을 나타냅니다.

Web Audio는 AudioContext, GainNode, BiquadFilterNode, ConvolverNode, AnalyserNode 및 기타를 제공합니다. 이들은 브라우저 엔진(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의 Airwindows는 MIT 라이선스를 받은 2,500개 이상의 오디오 플러그인으로, 전설적으로 맛있는 DSP로 유명합니다. 우리는 Soundbend의 Wave 12 출시를 위해 5개를 브라우저 AudioWorklets로 포트했습니다:

각 포트는 AudioWorkletProcessor에서 수학 약 30-80 LOC입니다. 포트는 Airwindows와 비트 단위로 일치하지 않습니다(다른 C++와 JS 수치 엔진에서 FMA/비정규 처리가 다름), 그러나 소닉적으로 일치합니다. Null-tests는 출력을 금속 기준에 비해 ≤ -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 → 오디오로 전파되어야 하며, 오디오가 끊기지 않아야 합니다.

웹 오디오의 AudioParam는 표준 매개변수(GainNode gain, BiquadFilterNode frequency)에 대해 내장으로 처리합니다. 사용자 정의 워크릿 매개변수의 경우, UI 메시지에 MessagePort와 구조화 복제를 사용하고, 고속 자동화 데이터에는 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 합성 — DX7 / Operator를 기반으로 한 6연산자 FM 합성. 알고리즘 시각화 도구 + 전체 변조 매트릭스. UI는 약 800 LOC JS, 음성 할당기에는 약 300 LOC 워크릿이 사용되었습니다.

웨이블테이블 싱스 — 웨이블테이블 간 변환 합성. 스펙트럴 왜곡 + 유니슨 + 스테레오 디튠. 30개 이상의 공장 웨이블테이블. ConvolverNode를 사용하여 오디오 속도에서 웨이블테이블 크로스페이드를 구현합니다.

아날로그 서브트랙티브 — 2오실레이터 폴리신스와 Cytomic SVF 필터. Cytomic은 상태-변수 필터 구조로, 올바른 소리를 내며, 단순한 SVF는 fc > SR/6 이상에서 앨리어싱 문제를 일으킵니다. Cytomic 포트는 제로 딜레이 피드백 수학을 통해 이를 처리합니다.

DrumRack + Sampler — 패드 기반 샘플 재생으로 각 패드의 피치/필터/앰프 익스프레션을 조절합니다. 샘플은 IndexedDB에 저장되어 빠른 재호출이 가능합니다. 5가지 장르별 팩토리 킷 (부엄밥, 트랩, 하우스, DNB, 아프로비트).

SeedSynth + Geist (구 AudioStudioEngine에서 사용되던 기능 — Wave 14부터 Soundbend으로 통합됨) — 유전적 패치 생성기(Synplant 2-클래스)와 Geist 스타일 드럼 머신입니다. 이는 통합 이념을 큰 이슈로 만든 특허 기술로, 3만 줄의 병합 과정에서 비트 정확한 동작을 유지해야 했습니다. 병합 후 100개 시드 null 테스트 통과.

6. 믹서 + 보조 출력

적절한 믹서 — 트랙별 볼륨 조절이 아닌 트랙별 FX 삽입, 사전/사후 볼륨 조절 보조 송신, 마스터 버스를 갖춘 믹서는 DAW와 시퀀서를 구분합니다. Soundbend의 믹서 클래스는 약 655 LOC (src/audio/mixer.js)입니다. 각 트랙은 삽입 슬롯, 송신 탭 포인트, 미터링을 갖춘 AudioNode 그래프입니다.

어려운 부분은 프리페이더와 포스트페이더 어시스턴트 송신입니다. 프리페이더는 트랙 볼륨과 무관하게 리버브 버스로 보냅니다(전통적인 사용: 트랙 페이드 시에도 유지되는 병렬 리버브). 포스트페이더는 트랙 볼륨에 따라 조정됩니다. 둘 다 제공됩니다.

7. MIDI + WAM 플러그인 호스트

WebMIDI가 성숙했습니다 — USB-MIDI 키보드에서 어떤 컨트롤러 입력도 즉시 작동합니다. MIDI 랙(아르페지에이터, 스케일, 코드)은 컨트롤러와 악기 사이에 위치하여 노트 스트림을 변환합니다.

플러그인을 위해 우리는 Web Audio Modules v2 (WAM)을 호스팅합니다 — 브라우저 내장 플러그인입니다. VST(25년의 선두 주자)보다 생태계가 작지만 성장 중입니다. WAM을 로드하는 방법은 getWamHost().load(wamUri)로, 이는 AudioNode를 반환하며 이를 어떤 체인에도 삽입할 수 있습니다.

WAM은 각 경로별 CSP를 요구합니다. 사용자 제공 JS를 불러오기 때문입니다. 우리의 _headers/soundbend에 대해 script-src 허용 목록을 사용하여 CSP를 엄격하게 제한합니다. 이 목록에는 잘 알려진 WAM 레지스트리가 포함됩니다.

8. OfflineAudioContext를 사용한 바운스

내보내기는 OfflineAudioContext를 통해 실행됩니다 — 체인 복잡도에 따라 실시간보다 빠르게(또는 느리게) 정적 AudioBuffer로 렌더링한 후, 브라우저 내 인코더를 사용하여 WAV로 인코딩합니다.

주의: 모든 노드가 OfflineAudioContext에서 작동하지 않습니다. MediaStreamAudioSourceNode는 작동하지 않습니다(오프라인으로 실시간 마이크 녹음은 당연히 불가능합니다). 일부 워크릿은 온라인 → 오프라인 전환 시 주의 깊은 상태 재설정이 필요합니다. 우리는 이 문제를 반복적으로 마주쳤고 이제 Mixer.toJSON() + Mixer.fromJSON(offlineCtx)가 표준 패턴입니다: 믹서 상태를 직렬화하고 오프라인 컨텍스트에서 병렬 믹서를 다시 구축한 후 렌더링합니다.

9. Yjs를 통한 협업

Yjs는 다중 사용자 협업 편집을 자동 충돌 해결과 함께 처리하는 CRDT 라이브러리입니다. 우리의 SoundbendSession 클래스는 트랙별 문서 구조(트랙 메타데이터는 Y.Map, 패턴 단계는 Y.Array, 가사/노트는 Y.Text)를 Yjs로 감싸고 있습니다.

두 명에서 네 명의 프로듀서가 샘플 정확도로 트랙 동기화를 통해 동시에 같은 프로젝트를 편집할 수 있습니다. 이는 오디오 데이터가 텍스트 문서 협업보다 수백만 배 더 크기 때문에 텍스트 문서 협업보다 더 어렵습니다 — 우리는 원본 오디오 대신 메타데이터와 패턴을 Yjs를 통해 공유합니다. 원본 샘플은 로컬에 유지됩니다(사용자별 IndexedDB).

10. 성능 예산

브라우저에서 전체 DAW를 60fps UI + 실시간 오디오 + SharedArrayBuffer + WASM + 여러 워크릿을 사용하여 실행하는 것은 엄청난 예산이 필요합니다. 일부 숫자:

11. Null-테스트 헌드레스

DSP 회귀는 침묵합니다 — 코드 리뷰로는 잡을 수 없는 미세한 방식으로 오디오가 달라 보입니다. Soundbend는 tests/audio-null/에서 Puppeteer 기반 null 테스트 헌치를 제공합니다.

각 효과 × 프리셋 × 테스트 신호에 대해, 헌치는 headless Chromium 내부에서 OfflineAudioContext를 통해 렌더링하고, 결과 WAV를 커밋된 골든 기준과 null 테스트한 후 잔여 피크가 -60 dBFS를 초과하면 빌드를 실패시킵니다.

Wave 14F에서 100개의 SeedSynth 시드 기준과 32개의 Geist 드럼 패턴 골든이 추가되었습니다. Soundbend를 AudioStudio(Wave 14B-G)에 통합할 때, null-test로 인해 기존 프로퍼리어트 도구가 무시되거나 손상되는 것을 방지했습니다. 100개 중 96개의 SeedSynth 시드가 비트 정확하게 통과했습니다. 4개의 실패는 기존 크롬 웹 오디오 퀴크(고-Q 필터 공명 드리프트, OfflineAudioContext 인스턴스 간)로 인한 것이며, 통합 회귀가 아니며 JS에서 수정할 수 없습니다.

DSP 회귀는 조용합니다. 코드 검토는 그 소리를 들을 수 없습니다. null-테스트 헌치는 들을 수 있습니다 — 이것이 왜 CI 차단으로 작동하는지입니다.

12. 브라우저 + 클라이언트 사이드가 옳은 선택이었습니다

네이티브 DAW(ableton, Logic, FL Studio)는 30년 이상의 경쟁력이 있습니다. 기능별로 이기기는 긴 여정이지만, 가격은 다른 아키텍처 선택으로 즉시 승리할 수 있었습니다.

2022-2024년 사이 WebAssembly은 성능 한계를 넘어섰습니다. 같은 시기 Web Audio AudioWorklets이 널리 배포되었습니다. SharedArrayBuffer + COOP/COEP이 안정화되었습니다. 크롬, 파이어폭스, 사파리 모두 필요한 API를 충분한 성능으로 지원합니다.

가격 인과: 오디오 처리가 사용자 기기에서 실행되면, 우리는 그것을 위해 지불하지 않습니다. 우리의 프로 구독자당 변동 비용은 근처 0입니다. 따라서 $4.99/mo는 지속 가능합니다 영원히. 라고스의 2020년 안드로이드 사용자도 샌프란시스코의 사람이 지불하는 것과 동일한 $4.99로 완전한 DAW를 사용할 수 있습니다.

경제학에 대한 가격 체계 에세이를 읽어보세요. DSP의 경우, 이는 대부분의 이야기입니다.

체험해 보세요

Soundbend은 morph.cool/soundbend에서 이용할 수 있습니다. 무료 계정은 가입 없이 작동합니다. $4.99/월 Pro는 마스터링 체인 + 진정한 피크 리미터 + 추가 프리셋을 제공합니다. WebMIDI 키보드는 환영하지만 필수는 아닙니다.

Soundbend 열기

— 하이든 및 Morph 에이전트 팀
2026년 4월 22일