This is a technical post about how Morph's Soundbend — a full digital audio workstation including 5 native instruments, a Mixer with FX chains and aux sends, 30+ effects (including 5 Airwindows Tier-1 ports and a true-peak limiter), a MIDI effects rack, a WAM v2 plugin host, and a Yjs CRDT collaboration layer — runs entirely in a browser tab.
व्यावहारिक प्रश्न यह है: क्या यह वास्तव में Ableton के साथ प्रतिस्पर्धा करता है? ईमानदार जवाब: अधिकांश प्रोड्यूसर कार्यप्रवाह के लिए, हाँ। गहन Max for Live इंटीग्रेशन के लिए, अभी नहीं। उत्पाद-स्तरीय विश्लेषण के लिए Ableton विकल्प तुलना पढ़ें। यह पोस्ट इंजीनियरिंग है।
स्टैक
- React + Vite फ्रंटएंड
- ऑडियो ग्राफ के लिए Web Audio API
- कस्टम DSP के लिए AudioWorkletProcessor (ऑफ-मेन-थ्रेड)
- WebAssembly के लिए प्रदर्शन-महत्वपूर्ण DSP (कस्टम WASM बिल्ड्स)
- MessagePort + ring buffers for UI ↔ worklet communication
- Yjs for CRDT collaboration
- प्रोजेक्ट संरक्षण + सैंपल स्टोरेज के लिए IndexedDB
- WebMIDI for hardware controller input
- बाउंस/एक्सपोर्ट के लिए OfflineAudioContext
1. The audio graph
Soundbend में हर ट्रैक एक चेन के माध्यम से रास्ता तय करता है: इंस्ट्रूमेंट → ट्रैक FX चेन → ऑक्स सेंड → मिक्सर स्ट्रिप → मास्टर बस → लिमिटर → डेस्टिनेशन. प्रत्येक तीर एक Web Audio AudioNode कनेक्शन है।
वेब ऑडियो हमें AudioContext, GainNode, BiquadFilterNode, ConvolverNode, AnalyserNode, और दोस्त मिलाता है। ये ब्राउज़र इंजन (V8/SpiderMonkey/JSC सभी गहराई से निवेशित) द्वारा अनुकूलित हैं। मानक प्रभावों — EQ, gain automation, मूलभूत फ़िल्टरिंग — के लिए हम मूल नोड्स का उपयोग करते हैं। वे तेज़ और अच्छी तरह परीक्षण किए गए हैं।
कस्टम प्रभावों के लिए — 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। हमने Soundbend के Wave 12 शिप के लिए AudioWorklets में 5 को ब्राउज़र में पोर्ट किया है:
- Pressure6 — ट्रांसपेरेंट कंप्रेशन जो साँस लेता है
- ToTape9 — एनालॉग टेप सैचुरेशन मॉडलिंग
- PurestDrive — कठोर उच्च आवृत्ति के बिना न्यूनतम चरण संतृप्ति
- CreamCoat — गर्मी + हार्मोनिक एक्साइटर
- NotJustAnotherDither — TPDF dither for bit-depth reduction (mastering)
प्रत्येक पोर्ट में गणित के ~30-80 LOC होते हैं एक AudioWorkletProcessor में। पोर्ट Airwindows के बिट-फॉर-बिट मैच नहीं करते (C++ और JS संख्यात्मक इंजन के बीच अलग FMA/डेनॉर्मल संभाल) लेकिन ध्वनि के रूप में मैच करते हैं। नल-टेस्ट्स आउटपुट को सोने के विपरीत ≤ -80 dBFS अवशेष रखते हैं, इसलिए DSP बदलाव पकड़े जाते हैं।
3. ट्रू-पीक लिमिटर
आधुनिक स्ट्रीमिंग प्लेटफॉर्म (Spotify, Apple Music, YouTube) ITU-R BS.1770-5 के अनुसार ट्रू-पीक लाउडनेस नॉर्मलाइज़ेशन लागू करते हैं। सैंपल पीक और इंटर-सैंपल पीक अलग-अलग चीज़ें हैं; एक सिग्नल का सैंपल-आधारित -1 dBFS पीक हो सकता है, लेकिन D/A पुनर्निर्माण के बाद 0 dBFS से अधिक हो सकता है। एक नॉन-ट्रू-पीक लिमिटर DAC में क्लिप करेगा, भले ही आपका DAW इसे साफ दिखाए।
हमारा लिमिटर पूर्ण ITU विनिर्माण को लागू करता है: 4x ओवरसैम्पलिंग, इंटर-सैम्पल-पीक डिटेक्शन, लुकआउट, सॉफ्ट-कनी रिलीज। यह AudioWorklet फॉर्म में public/audio-worklets/true-peak-limiter-processor.js के रूप में आता है। रेफरेंस इम्प्लीमेंटेशन (ऑक्सफ़ोर्ड लिमिटर, 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 LOC JS, वॉयस एलोकेटर के लिए ~300 LOC वर्कलेट।
वेवटेबल सिंथ — मॉर्फ-बीटवीन-टेबल सिंथेसिस। स्पेक्ट्रल वार्पिंग + यूनिसन + स्टेरियो डिट्यून। 30+ फैक्टरी वेवटेबल्स। ConvolverNode का उपयोग ऑडियो रेट पर वेवटेबल क्रॉसफेड के लिए करता है।
एनालॉग सब्ट्रैक्टिव — 2-ऑसिलेटर पॉलीसिंथ जिसमें Cytomic SVF फिल्टर हैं। Cytomic एक स्टेट-वेरिएबल फिल्टर टोपोलॉजी है जो सही आवाज़ देती है; नाइव एसवीएफ में fc > SR/6 के ऊपर एलियसिंग समस्याएँ होती हैं। Cytomic पोर्ट इसे ज़ीरो-डेले फीडबैक मैथ के माध्यम से संभालता है।
ड्रमरैक + सैम्पलर — पैड-आधारित सैम्पल प्लेबैक जिसमें प्रति-पैड पिच/फिल्टर/एम्प एनवलप्स होते हैं। सैम्पल्स IndexedDB में स्टोर होते हैं ताकि तेज़ रिकॉल हो सके। 5 जेनर-विशिष्ट फैक्टरी किट्स (बूमबैप, ट्रैप, हाउस, DNB, अफ्रोबीट)।
SeedSynth + Geist (लीगेसी ऑडियोस्टूडियो इंजन में — अब वेव 14 के बाद Soundbend में मर्ज किया गया) — एक आनुवंशिक पैच-जनरेटर (Synplant 2-क्लास) और एक Geist-शैली का ड्रम मशीन। ये वह प्रॉपराइटरी आईपी हैं जिन्होंने संगठन नीति को एक बड़ा मामला बनाया — हमें 30k लाइन मर्ज के माध्यम से बिट-समान व्यवहार बनाए रखना था। मर्ज के बाद 100-सीड नल-टेस्ट पास हुआ।
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 लौटाता है जिसे आप किसी भी चेन में डाल सकते हैं।
WAMs के लिए प्रत्येक मार्ग के लिए CSP की आवश्यकता होती है क्योंकि वे अनियंत्रित उपयोगकर्ता-प्रदान की गई JS लोड करते हैं। हमारे _headers CSP को /soundbend के लिए एक script-src अनुमति सूची के साथ संकीर्ण रूप से स्कोप करते हैं, जो जाने-माने WAM रजिस्ट्रीज़ के लिए है।
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 + कई वर्कलेट्स के साथ, संकीर्ण बजट की आवश्यकता होती है। कुछ आंकड़े:
- ऑडियो थ्रेड: ~2ms / 48kHz पर 128-सैंपल बफर (सब-फ्रेम)
- मुख्य थ्रेड: 16.6ms / 60fps फ्रेम; ऑडियो हैंडलिंग को प्रति फ्रेम <1ms से कम रहना चाहिए
- Worklet setup: one-time cost ~10-50ms per worklet load (ship 15+ worklets — we batch)
- SharedArrayBuffer आवंटन: प्रत्येक डायनामिक वर्कलेट पैरामीटर के लिए 4KB रिंग बफर
- Soundbend चंक साइज़ (पोस्ट-कंसोलिडेशन): ~496 KB रॉ, ~120 KB gzip
- पूर्ण प्रोजेक्ट लोड (कोल्ड): मध्यम-श्रेणी के लैपटॉप पर ~800ms
- एक्सपोर्ट रेंडर: प्रभाव चेन की जटिलता के आधार पर लगभग 0.3x से 2x तक रियलटाइम
11. नल-टेस्ट हार्नेस
DSP रेग्रेशन्स शांत होते हैं — ऑडियो कोड रिव्यू से पकड़ा नहीं जा सकता है, लेकिन सूक्ष्म तरीके से अलग लगता है। Soundbend में tests/audio-null/ में Puppeteer-चालित नल-टेस्ट हैंच शिप किया गया है।
प्रत्येक प्रभाव × प्रीसेट × परीक्षण सिग्नल के लिए, हैरेस ने OfflineAudioContext का उपयोग करके हेडलेस Chromium में रेंडर किया, परिणामी WAV को एक संवेदनशील सुनिश्चित गोल्डन के विरुद्ध नल-टेस्ट किया, और यदि अवशिष्ट चोटी -60 dBFS से अधिक है तो बिल्ड फेल कर दी।
Wave 14F added 100 SeedSynth seed baselines and 32 Geist drum-pattern goldens. When we merged Soundbend into AudioStudio (Wave 14B-G), the null-test caught anything that would have silently broken the proprietary instruments. 96 of 100 SeedSynth seeds passed bit-identical. The 4 fails were pre-existing Chromium Web Audio quirks (high-Q filter resonance drift between OfflineAudioContext instances) — not merge regressions, and not fixable from JS.
DSP रिग्रेशन्स चुपचाप होते हैं। कोड रिव्यू उन्हें सुन नहीं सकता। नल-टेस्ट हैंगर इन्हें सुन सकता है — इसीलिए यह CI-ब्लॉकिंग है।
12. ब्राउज़र + क्लाइंट-साइड का चुनाव सही था
नेटिव DAWs (Ableton, Logic, FL Studio) के पास 30 साल का सामान्य अंतर है। उनके साथ फीचर-फॉर-फीचर बराबरी करना लंबा सफर है। लेकिन कीमत — यह तुरंत अलग आर्किटेक्चरल बेट्स लेकर जीती जा सकती थी।
वेबएसम्बली का परफॉर्मेंस थ्रेशोल्ड 2022-2024 में पार कर गया। वेब ऑडियो ऑडियोवर्कलेट्स उसी समय व्यापक रूप से लॉन्च हुए। SharedArrayBuffer + COOP/COEP स्थिर हो गया। क्रोमियम + फायरफॉक्स + सफारी सभी आवश्यक API को उचित परफॉर्मेंस के साथ सपोर्ट करते हैं।
मूल्य निर्धारण का प्रभाव: अगर ऑडियो प्रोसेसिंग उपयोगकर्ता के डिवाइस पर चलती है, तो हमें इसके लिए भुगतान नहीं करना पड़ता। हमारा प्रति Pro सदस्य का सीमांत लागत लगभग शून्य है। इसलिए $4.99/mo स्थायी है हमेशा। लागोस में एक बच्चा जिसका 2020 का Android है, एक पूर्ण DAW प्राप्त करता है जिसे सैन फ्रांसिस्को में कोई व्यक्ति $4.99 के समान भुगतान करता है।
लागत विश्लेषण के लिए प्राइसिंग आर्किटेक्चर निबंध पढ़ें। DSP के लिए, यह सबसे बड़ी कहानी है।
आजमाएँ
Soundbend morph.cool/soundbend पर है। फ्री टियर साइनअप के बिना काम करता है। $4.99/महीना Pro में मास्टरिंग चेन + ट्रू-पीक लिमिटर + अतिरिक्त प्रीसेट खुलते हैं। WebMIDI कीबोर्ड स्वागत है, आवश्यक नहीं।
— हेडन + Morph एजेंट टीम
22 अप्रैल, 2026