HTML5 <audio> एलिमेंट से पहले, वेब पर ऑडियो चलाने के लिए Flash या किसी अन्य प्लग इन की ज़रूरत होती थी. वेब पर ऑडियो के लिए अब प्लग इन की ज़रूरत नहीं होती. हालांकि, ऑडियो टैग की वजह से, बेहतर गेम और इंटरैक्टिव ऐप्लिकेशन लागू करने में काफ़ी सीमाएं आती हैं.
Web Audio API, वेब ऐप्लिकेशन में ऑडियो को प्रोसेस और सिंथेसाइज़ करने के लिए, एक हाई-लेवल JavaScript API है. इस एपीआई का मकसद, आधुनिक गेम ऑडियो इंजन में मिलने वाली सुविधाओं को शामिल करना है. साथ ही, आधुनिक डेस्कटॉप ऑडियो प्रोडक्शन ऐप्लिकेशन में मिलने वाले कुछ मिक्सिंग, प्रोसेसिंग, और फ़िल्टर करने वाले टास्क को शामिल करना है. इस दमदार एपीआई को इस्तेमाल करने के बारे में यहां आसान शब्दों में बताया गया है.
AudioContext का इस्तेमाल शुरू करना
AudioContext का इस्तेमाल, सभी ऑडियो को मैनेज करने और चलाने के लिए किया जाता है. Web Audio API का इस्तेमाल करके आवाज़ जनरेट करने के लिए, एक या उससे ज़्यादा साउंड सोर्स बनाएं. इसके बाद, उन्हें AudioContext इंस्टेंस से मिले साउंड डेस्टिनेशन से कनेक्ट करें. यह कनेक्शन डायरेक्ट होना ज़रूरी नहीं है. यह किसी भी संख्या में मौजूद इंटरमीडिएट AudioNodes से होकर गुज़र सकता है. ये ऑडियो सिग्नल के लिए, प्रोसेसिंग मॉड्यूल के तौर पर काम करते हैं. इस रूटिंग के बारे में ज़्यादा जानकारी, वेब ऑडियो की खास बातों में दी गई है.
AudioContext का एक इंस्टेंस, कई साउंड इनपुट और जटिल ऑडियो ग्राफ़ को सपोर्ट कर सकता है. इसलिए, हमें अपने हर ऑडियो ऐप्लिकेशन के लिए, इनमें से सिर्फ़ एक की ज़रूरत होगी.
यहां दिया गया स्निपेट, AudioContext बनाता है:
var context;
window.addEventListener('load', init, false);
function init() {
try {
context = new AudioContext();
}
catch(e) {
alert('Web Audio API is not supported in this browser');
}
}
WebKit पर आधारित पुराने ब्राउज़र के लिए, webkit प्रीफ़िक्स का इस्तेमाल करें, जैसे कि webkitAudioContext.
Web Audio API की कई दिलचस्प सुविधाएं, जैसे कि AudioNodes बनाना और ऑडियो फ़ाइल के डेटा को डिकोड करना, AudioContext के तरीके हैं.
साउंड लोड हो रहे हैं
Web Audio API, कम से लेकर मध्यम अवधि की आवाज़ों के लिए AudioBuffer का इस्तेमाल करता है. साउंड फ़ाइलें फ़ेच करने के लिए, XMLHttpRequest का इस्तेमाल करना सबसे आसान तरीका है.
एपीआई, ऑडियो फ़ाइल के डेटा को कई फ़ॉर्मैट में लोड करने की सुविधा देता है. जैसे, WAV, MP3, AAC, OGG, और अन्य. अलग-अलग ऑडियो फ़ॉर्मैट के लिए, ब्राउज़र की सुविधा अलग-अलग होती है.
यहां दिए गए स्निपेट में, साउंड सैंपल लोड करने का तरीका बताया गया है:
var dogBarkingBuffer = null;
var context = new AudioContext();
function loadDogSound(url) {
var request = new XMLHttpRequest();
request.open('GET', url, true);
request.responseType = 'arraybuffer';
// Decode asynchronously
request.onload = function() {
context.decodeAudioData(request.response, function(buffer) {
dogBarkingBuffer = buffer;
}, onError);
}
request.send();
}
ऑडियो फ़ाइल का डेटा बाइनरी (टेक्स्ट नहीं) होता है. इसलिए, हम अनुरोध के responseType को 'arraybuffer' पर सेट करते हैं. ArrayBuffers के बारे में ज़्यादा जानकारी के लिए, XHR2 के बारे में यह लेख देखें.
ऑडियो फ़ाइल का डेटा (डिकोड नहीं किया गया) मिलने के बाद, उसे बाद में डिकोड करने के लिए सेव करके रखा जा सकता है. इसके अलावा, AudioContext decodeAudioData() तरीके का इस्तेमाल करके, उसे तुरंत डिकोड किया जा सकता है. यह तरीका, request.response में सेव किए गए ऑडियो फ़ाइल डेटा के ArrayBuffer को लेता है और उसे एसिंक्रोनस तरीके से डिकोड करता है. इससे मुख्य JavaScript एक्ज़ीक्यूशन थ्रेड ब्लॉक नहीं होता.
decodeAudioData() के पूरा होने पर, यह एक कॉलबैक फ़ंक्शन को कॉल करता है. यह फ़ंक्शन, डिकोड किए गए पीसीएम ऑडियो डेटा को AudioBuffer के तौर पर उपलब्ध कराता है.
आवाज़ें चलाना
एक या उससे ज़्यादा AudioBuffers लोड होने के बाद, हम साउंड चलाने के लिए तैयार हैं. मान लें कि हमने अभी-अभी कुत्ते के भौंकने की आवाज़ के साथ एक AudioBuffer लोड किया है और लोड होने की प्रोसेस पूरी हो गई है. इसके बाद, हम इस बफ़र को
इस कोड के साथ चला सकते हैं.
var context = new AudioContext();
function playSound(buffer) {
var source = context.createBufferSource(); // creates a sound source
source.buffer = buffer; // tell the source which sound to play
source.connect(context.destination); // connect the source to the context's destination (the speakers)
source.noteOn(0); // play the source now
}
इस playSound() फ़ंक्शन को हर बार तब कॉल किया जा सकता है, जब कोई व्यक्ति कोई बटन दबाता है या माउस से किसी चीज़ पर क्लिक करता है.
noteOn(time) फ़ंक्शन की मदद से, गेम और अन्य ऐप्लिकेशन के लिए सटीक साउंड प्लेबैक शेड्यूल करना आसान हो जाता है. हालांकि, इस शेड्यूलिंग को सही तरीके से काम करने के लिए, पक्का करें कि आपके साउंड बफ़र पहले से लोड हों.
Web Audio API को ऐब्स्ट्रैक्ट करना
ज़ाहिर है कि एक सामान्य लोडिंग सिस्टम बनाना बेहतर होगा, जो इस खास साउंड को लोड करने के लिए हार्ड-कोड न किया गया हो. ऑडियो ऐप्लिकेशन या गेम में इस्तेमाल होने वाली छोटी से लेकर मध्यम अवधि की कई आवाज़ों को मैनेज करने के कई तरीके हैं. यहां BufferLoader का इस्तेमाल करने का एक तरीका बताया गया है. यह वेब स्टैंडर्ड का हिस्सा नहीं है.
यहां BufferLoader क्लास को इस्तेमाल करने का उदाहरण दिया गया है.
चलिए, दो AudioBuffers बनाते हैं; और जैसे ही वे लोड हो जाएं,
उन्हें एक साथ चलाते हैं.
window.onload = init;
var context;
var bufferLoader;
function init() {
context = new AudioContext();
bufferLoader = new BufferLoader(
context,
[
'../sounds/hyper-reality/br-jam-loop.wav',
'../sounds/hyper-reality/laughter.wav',
],
finishedLoading
);
bufferLoader.load();
}
function finishedLoading(bufferList) {
// Create two sources and play them both together.
var source1 = context.createBufferSource();
var source2 = context.createBufferSource();
source1.buffer = bufferList[0];
source2.buffer = bufferList[1];
source1.connect(context.destination);
source2.connect(context.destination);
source1.noteOn(0);
source2.noteOn(0);
}
समय के साथ तालमेल बिठाना: लय के साथ आवाज़ें निकालना
Web Audio API की मदद से, डेवलपर ऑडियो चलाने का सटीक शेड्यूल तय कर सकते हैं. इसे दिखाने के लिए, चलिए एक आसान रिदम ट्रैक सेट अप करते हैं. सबसे ज़्यादा जाना जाने वाला ड्रमकिट पैटर्न यह है:
जिसमें हर आठवें नोट पर हाय-हैट बजाया जाता है. साथ ही, किक और स्नेयर को 4/4 टाइम में, हर क्वार्टर में बारी-बारी से बजाया जाता है.
मान लें कि हमने kick, snare, और hihat बफ़र लोड किए हैं, तो ऐसा करने का कोड आसान है:
for (var bar = 0; bar < 2; bar++) {
var time = startTime + bar * 8 * eighthNoteTime;
// Play the bass (kick) drum on beats 1, 5
playSound(kick, time);
playSound(kick, time + 4 * eighthNoteTime);
// Play the snare drum on beats 3, 7
playSound(snare, time + 2 * eighthNoteTime);
playSound(snare, time + 6 * eighthNoteTime);
// Play the hi-hat every eighth note.
for (var i = 0; i < 8; ++i) {
playSound(hihat, time + i * eighthNoteTime);
}
}
यहां हम शीट म्यूज़िक में दिखने वाले अनलिमिटेड लूप के बजाय, सिर्फ़ एक बार रिपीट करते हैं. playSound फ़ंक्शन एक ऐसा तरीका है जो तय समय पर बफ़र को चलाता है. इसके बारे में यहां बताया गया है:
function playSound(buffer, time) {
var source = context.createBufferSource();
source.buffer = buffer;
source.connect(context.destination);
source.noteOn(time);
}
किसी साउंड की आवाज़ को कम या ज़्यादा करना
किसी साउंड में बदलाव करने के लिए, सबसे बुनियादी कामों में से एक है उसकी आवाज़ को कम या ज़्यादा करना. Web Audio API का इस्तेमाल करके, हम अपने सोर्स को AudioGainNode के ज़रिए उसके डेस्टिनेशन पर रूट कर सकते हैं, ताकि वॉल्यूम में बदलाव किया जा सके:

इस कनेक्शन को इस तरह सेट अप किया जा सकता है:
// Create a gain node.
var gainNode = context.createGainNode();
// Connect the source to the gain node.
source.connect(gainNode);
// Connect the gain node to the destination.
gainNode.connect(context.destination);
ग्राफ़ सेट अप होने के बाद, gainNode.gain.value में बदलाव करके, प्रोग्राम के हिसाब से वॉल्यूम को बदला जा सकता है. इसके लिए, यह तरीका अपनाएं:
// Reduce the volume.
gainNode.gain.value = 0.5;
दो साउंड के बीच क्रॉस-फ़ेडिंग
अब मान लें कि हमारे पास थोड़ा ज़्यादा जटिल परिदृश्य है, जहां हम कई ध्वनियां चला रहे हैं, लेकिन उनके बीच क्रॉस फ़ेड करना चाहते हैं. यह डीजे जैसे ऐप्लिकेशन में एक आम मामला है, जहां हमारे पास दो टर्नटेबल होते हैं और हम एक साउंड सोर्स से दूसरे साउंड सोर्स पर पैन करना चाहते हैं.
इसे इस ऑडियो ग्राफ़ की मदद से किया जा सकता है:
इसे सेट अप करने के लिए, हम दो AudioGainNodes बनाते हैं और हर सोर्स को नोड से कनेक्ट करते हैं. इसके लिए, हम इस फ़ंक्शन का इस्तेमाल करते हैं:
function createSource(buffer) {
var source = context.createBufferSource();
// Create a gain node.
var gainNode = context.createGainNode();
source.buffer = buffer;
// Turn on looping.
source.loop = true;
// Connect source to gain.
source.connect(gainNode);
// Connect gain to destination.
gainNode.connect(context.destination);
return {
source: source,
gainNode: gainNode
};
}
इक्वल पावर क्रॉसफ़ेडिंग
सैंपल के बीच पैन करने पर, एक सामान्य लीनियर क्रॉसफ़ेड अप्रोच से आवाज़ कम हो जाती है.
इस समस्या को हल करने के लिए, हम इक्वल पावर कर्व का इस्तेमाल करते हैं. इसमें, संबंधित गेन कर्व नॉन-लीनियर होते हैं और ज़्यादा एंप्लीट्यूड पर इंटरसेक्ट करते हैं. इससे ऑडियो रीजन के बीच वॉल्यूम में होने वाली गिरावट कम हो जाती है. इससे, उन रीजन के बीच ज़्यादा बेहतर क्रॉसफ़ेड होता है जिनके लेवल में थोड़ा अंतर हो सकता है.
प्लेलिस्ट में मौजूद गानों को क्रॉसफ़ेड करना
क्रॉसफ़ेडर का इस्तेमाल, म्यूज़िक प्लेयर ऐप्लिकेशन के लिए भी किया जाता है.
जब कोई गाना बदलता है, तो हम चाहते हैं कि मौजूदा ट्रैक धीरे-धीरे बंद हो जाए और नया ट्रैक धीरे-धीरे शुरू हो, ताकि ट्रांज़िशन में कोई रुकावट न आए. इसके लिए, आने वाले समय में
क्रॉसफ़ेड शेड्यूल करें. हालांकि, इस शेड्यूलिंग के लिए setTimeout का इस्तेमाल किया जा सकता है, लेकिन यह सटीक नहीं है. Web Audio API की मदद से, हम AudioParam इंटरफ़ेस का इस्तेमाल करके, पैरामीटर के लिए आने वाले समय की वैल्यू शेड्यूल कर सकते हैं. जैसे, AudioGainNode की गेन वैल्यू.
इसलिए, किसी प्लेलिस्ट में, हम मौजूदा ट्रैक के खत्म होने से कुछ समय पहले, उसकी आवाज़ को कम करके और अगले ट्रैक की आवाज़ को बढ़ाकर, ट्रैक के बीच ट्रांज़िशन कर सकते हैं:
function playHelper(bufferNow, bufferLater) {
var playNow = createSource(bufferNow);
var source = playNow.source;
var gainNode = playNow.gainNode;
var duration = bufferNow.duration;
var currTime = context.currentTime;
// Fade the playNow track in.
gainNode.gain.linearRampToValueAtTime(0, currTime);
gainNode.gain.linearRampToValueAtTime(1, currTime + ctx.FADE_TIME);
// Play the playNow track.
source.noteOn(0);
// At the end of the track, fade it out.
gainNode.gain.linearRampToValueAtTime(1, currTime + duration-ctx.FADE_TIME);
gainNode.gain.linearRampToValueAtTime(0, currTime + duration);
// Schedule a recursive track change with the tracks swapped.
var recurse = arguments.callee;
ctx.timer = setTimeout(function() {
recurse(bufferLater, bufferNow);
}, (duration - ctx.FADE_TIME) - 1000);
}
Web Audio API, RampToValue के तरीकों का एक सुविधाजनक सेट उपलब्ध कराता है. इससे किसी पैरामीटर की वैल्यू को धीरे-धीरे बदला जा सकता है. जैसे, linearRampToValueAtTime और exponentialRampToValueAtTime.
ट्रांज़िशन टाइमिंग फ़ंक्शन को पहले से मौजूद लीनियर और एक्स्पोनेंशियल फ़ंक्शन (जैसा कि ऊपर बताया गया है) से चुना जा सकता है. इसके अलावा, setValueCurveAtTime फ़ंक्शन का इस्तेमाल करके, वैल्यू के कलेक्शन के ज़रिए अपनी वैल्यू कर्व भी तय की जा सकती है.
किसी साउंड पर सामान्य फ़िल्टर इफ़ेक्ट लागू करना

Web Audio API की मदद से, साउंड को एक ऑडियो नोड से दूसरे ऑडियो नोड में भेजा जा सकता है. इससे प्रोसेसर की एक जटिल चेन बन सकती है, जिससे आपके साउंडफ़ॉर्म में जटिल इफ़ेक्ट जोड़े जा सकते हैं.
ऐसा करने का एक तरीका यह है कि साउंड सोर्स और डेस्टिनेशन के बीच BiquadFilterNodes को प्लेस करें. इस तरह का ऑडियो नोड, कई तरह के लो-ऑर्डर फ़िल्टर लागू कर सकता है. इनका इस्तेमाल, ग्राफ़िक इक्वलाइज़र और ज़्यादा जटिल इफ़ेक्ट बनाने के लिए किया जा सकता है. इनका इस्तेमाल, ज़्यादातर यह चुनने के लिए किया जाता है कि किसी साउंड के फ़्रीक्वेंसी स्पेक्ट्रम के किन हिस्सों पर ज़ोर देना है और किन हिस्सों को कम करना है.
इन फ़िल्टर का इस्तेमाल किया जा सकता है:
- लो पास फ़िल्टर
- हाई पास फ़िल्टर
- बैंड पास फ़िल्टर
- लो शेल्फ़ फ़िल्टर
- हाई शेल्फ़ फ़िल्टर
- पीकिंग फ़िल्टर
- नॉच फ़िल्टर
- सभी पास फ़िल्टर
सभी फ़िल्टर में, गेन की कुछ मात्रा, फ़िल्टर लागू करने की फ़्रीक्वेंसी, और क्वालिटी फ़ैक्टर तय करने के लिए पैरामीटर शामिल होते हैं. लो-पास फ़िल्टर, कम फ़्रीक्वेंसी वाली रेंज को बनाए रखता है, लेकिन ज़्यादा फ़्रीक्वेंसी वाली रेंज को हटा देता है. ब्रेक-ऑफ़ पॉइंट, फ़्रीक्वेंसी वैल्यू से तय होता है. साथ ही, Q फ़ैक्टर की कोई यूनिट नहीं होती और यह ग्राफ़ का आकार तय करता है. गेन का असर सिर्फ़ कुछ फ़िल्टर पर पड़ता है, जैसे कि लो-शेल्फ़ और पीकिंग फ़िल्टर. इस लो-पास फ़िल्टर पर इसका असर नहीं पड़ता.
आइए, एक आसान लो-पास फ़िल्टर सेट अप करें, ताकि साउंड सैंपल से सिर्फ़ बेस को अलग किया जा सके:
// Create the filter
var filter = context.createBiquadFilter();
// Create the audio graph.
source.connect(filter);
filter.connect(context.destination);
// Create and specify parameters for the low-pass filter.
filter.type = 0; // Low-pass filter. See BiquadFilterNode docs
filter.frequency.value = 440; // Set cutoff to 440 HZ
// Playback the sound.
source.noteOn(0);
आम तौर पर, फ़्रीक्वेंसी कंट्रोल को लॉगरिद्मिक स्केल पर काम करने के लिए अडजस्ट करना पड़ता है. ऐसा इसलिए, क्योंकि इंसानों के सुनने की क्षमता भी इसी सिद्धांत पर काम करती है. उदाहरण के लिए, A4 440 हर्ट्ज़ है और A5 880 हर्ट्ज़ है. ज़्यादा जानकारी के लिए, ऊपर दिए गए सोर्स कोड के लिंक में मौजूद FilterSample.changeFrequency फ़ंक्शन देखें.
आखिर में, ध्यान दें कि सैंपल कोड की मदद से, फ़िल्टर को कनेक्ट और डिसकनेक्ट किया जा सकता है. इससे AudioContext ग्राफ़ में डाइनैमिक तौर पर बदलाव होता है. node.disconnect(outputNumber) को कॉल करके, हम AudioNodes को ग्राफ़ से डिसकनेक्ट कर सकते हैं.
उदाहरण के लिए, ग्राफ़ को फ़िल्टर से गुज़ारने के बजाय सीधे कनेक्शन पर भेजने के लिए, यह तरीका अपनाया जा सकता है:
// Disconnect the source and filter.
source.disconnect(0);
filter.disconnect(0);
// Connect the source directly.
source.connect(context.destination);
इस बारे में और सुनें
हमने एपीआई की बुनियादी बातों के बारे में बताया है. इसमें ऑडियो सैंपल लोड करने और उन्हें चलाने का तरीका भी शामिल है. हमने गेन नोड और फ़िल्टर के साथ ऑडियो ग्राफ़ बनाए हैं. साथ ही, कुछ सामान्य साउंड इफ़ेक्ट चालू करने के लिए, साउंड और ऑडियो पैरामीटर में बदलाव किए हैं. अब आप कुछ बेहतरीन वेब ऑडियो ऐप्लिकेशन बनाने के लिए तैयार हैं!
अगर आपको प्रेरणा चाहिए, तो कई डेवलपर ने Web Audio API का इस्तेमाल करके, पहले से ही शानदार काम किया है. मेरे कुछ पसंदीदा गेम ये हैं:
- AudioJedit, ब्राउज़र में मौजूद साउंड स्प्लाइसिंग टूल है. यह SoundCloud के स्थायी लिंक इस्तेमाल करता है.
- ToneCraft, एक साउंड सीक्वेंसर है. इसमें 3D ब्लॉक को स्टैक करके साउंड बनाए जाते हैं.
- Plink, एक ऐसा गेम है जिसमें वेब ऑडियो और वेब सॉकेट का इस्तेमाल करके, मिलकर संगीत बनाया जाता है.