केस-स्टडी - Chrome के साथ JAM

हमने ऑडियो रॉक कैसे बनाया

शुरुआती जानकारी

Chrome के साथ JAM, वेब पर आधारित एक म्यूज़िकल प्रोजेक्ट है, जिसे Google ने बनाया है. Chrome के साथ JAM, दुनिया भर के लोगों को ब्राउज़र में रीयल टाइम में बैंड बनाने और जैम करने देता है. हमें DinahMoe चैनल पर, इस प्रोजेक्ट का हिस्सा बनने में खुशी हुई. हमारा काम ऐप्लिकेशन के लिए संगीत बनाना, संगीत के कॉम्पोनेंट को डिज़ाइन, और डेवलप करना था. इस गेम में तीन मुख्य चीज़ें शामिल हैं: "म्यूज़िक वर्कस्टेशन". इसमें मिडी प्लेबैक, सॉफ़्टवेयर सैंपलर, ऑडियो इफ़ेक्ट, रूटिंग और मिक्सिंग शामिल है. इसके अलावा, रीयल टाइम में इंटरैक्टिव तरीके से संगीत को कंट्रोल करने वाला म्यूज़िक लॉजिक इंजन; और एक ऐसा सिंक्रोनाइज़ेशन कॉम्पोनेंट जो यह पक्का करता है कि किसी सेशन में सभी खिलाड़ियों को एक ही समय पर संगीत सुनाई दे. यह एक साथ चलाने के लिए एक ज़रूरी चीज़ है.

हमने Web Audio API का इस्तेमाल करने का विकल्प चुना है. ऐसा इसलिए किया गया है, ताकि ज़्यादा से ज़्यादा प्रामाणिकता, सटीक जानकारी, और ऑडियो क्वालिटी बनाई जा सके. इस केस स्टडी में, कुछ ऐसी चुनौतियों के बारे में बताया गया है जो हमारे सामने आईं और उन्हें हल करने का हमारा तरीका क्या है. वेब ऑडियो के साथ शुरुआत करने के लिए यहां HTML5Rocks पर पहले से ही कई बेहतरीन शुरुआती लेख मौजूद हैं, इसलिए हम सीधे पूल के आखिर में जाएंगे.

पसंद के मुताबिक ऑडियो इफ़ेक्ट लिखना

Web Audio API में, खास बातों में कई काम के इफ़ेक्ट शामिल किए गए हैं. हालांकि, हमें Chrome के साथ JAM में शामिल अपने इंस्ट्रुमेंट के लिए, और बेहतर इफ़ेक्ट की ज़रूरत है. उदाहरण के लिए, वेब ऑडियो में नेटिव डिले नोड होता है, लेकिन इसमें कई तरह की देरें होती हैं - स्टीरियो डिले, पिंग पॉन्ग डिले, स्लैपबैक डिले, और सूची चलता रहता है. अच्छी बात यह है कि वेब ऑडियो में इन सभी इफ़ेक्ट को नेटिव इफ़ेक्ट नोड का इस्तेमाल करके और कुछ कल्पना के साथ बनाया जा सकता है.

हम नेटिव नोड और अपने कस्टम इफ़ेक्ट का इस्तेमाल पारदर्शी तरीके से करना चाहते थे. इसलिए, हमने तय किया कि इस लक्ष्य को हासिल करने के लिए, हमें एक रैपर फ़ॉर्मैट बनाना होगा. वेब ऑडियो के नेटिव नोड, नोड को एक साथ लिंक करने के लिए कनेक्ट करने के तरीके का इस्तेमाल करते हैं, इसलिए हमें इसे एम्युलेट करना था. बुनियादी आइडिया ऐसा दिखता है:

var MyCustomNode = function(){
    this.input = audioContext.createGain();
    var output = audioContext.createGain();

    this.connect = function(target){
       output.connect(target);
    };
};

इस पैटर्न के साथ हम वाकई नेटिव नोड के करीब हैं. आइए, देखते हैं कि इसका इस्तेमाल कैसे किया जाता है.

//create a couple of native nodes and our custom node
var gain = audioContext.createGain(),
    customNode = new MyCustomNode(),
    anotherGain = audioContext.createGain();

//connect our custom node to the native nodes and send to the output
gain.connect(customNode.input);
customNode.connect(anotherGain);
anotherGain.connect(audioContext.destination);
कस्टम नोड को रूट करना

हमारे कस्टम नोड और नेटिव नोड में अंतर सिर्फ़ यह है कि हमें कस्टम नोड की इनपुट प्रॉपर्टी से कनेक्ट करना पड़ता है. मुझे यकीन है कि इससे बचने के तरीके हैं, लेकिन यह हमारे मकसद को पूरा करने के लिए काफ़ी था. इस पैटर्न को नेटिव AudioNodes के डिसकनेक्ट करने के तरीकों को सिम्युलेट करने के साथ-साथ, कनेक्ट करते समय उपयोगकर्ता के तय किए गए इनपुट/आउटपुट को शामिल करने के लिए भी बनाया जा सकता है. नेटिव नोड से जुड़ी जानकारी देखने के लिए, खास जानकारी देखें.

कस्टम इफ़ेक्ट बनाने के लिए हमारा बुनियादी पैटर्न तैयार हो गया था. इसलिए, अगला कदम कस्टम नोड को पसंद के मुताबिक बनाने का तरीका देना था. आइए, स्लैपबैक डिले नोड पर नज़र डालते हैं.

आप ज़ोर से बोल रहे हैं

स्लैपबैक डिले को कभी-कभी स्लैपबैक इको भी कहा जाता है. यह एक क्लासिक इफ़ेक्ट है, जिसे 50 के दशक की शैली वाली आवाज़ से लेकर सर्फ़ गिटार तक, कई इंस्ट्रुमेंट पर इस्तेमाल किया जाता है. यह इफ़ेक्ट आने वाली आवाज़ को लेता है और करीब 75 से 250 मिलीसेकंड की देरी के साथ आवाज़ की एक कॉपी चलाता है. इससे थप्पड़ मारने की आवाज़ का एहसास होता है. इसलिए, इस गाने का यह नाम रखा गया. हम इस तरह का इफ़ेक्ट बना सकते हैं:

var SlapbackDelayNode = function(){
    //create the nodes we'll use
    this.input = audioContext.createGain();
    var output = audioContext.createGain(),
        delay = audioContext.createDelay(),
        feedback = audioContext.createGain(),
        wetLevel = audioContext.createGain();

    //set some decent values
    delay.delayTime.value = 0.15; //150 ms delay
    feedback.gain.value = 0.25;
    wetLevel.gain.value = 0.25;

    //set up the routing
    this.input.connect(delay);
    this.input.connect(output);
    delay.connect(feedback);
    delay.connect(wetLevel);
    feedback.connect(delay);
    wetLevel.connect(output);

    this.connect = function(target){
       output.connect(target);
    };
};
स्लैपबैक नोड की इंटरनल रूटिंग

जैसा कि आप में से कुछ लोगों ने पहले ही महसूस किया होगा, इस देरी का इस्तेमाल ज़्यादा देरी वाले समय के साथ भी किया जा सकता है. इस तरह सुझाव के साथ सामान्य मोनो डिले बन जाता है. यहां दिए गए उदाहरण में देरी का इस्तेमाल करके, आपको बताया गया है कि यह आवाज़ कैसी है.

ऑडियो रूटिंग

ऑडियो ऐप्लिकेशन का इस्तेमाल करते समय, अलग-अलग इंस्ट्रुमेंट और म्यूज़िकल पार्ट का इस्तेमाल करते समय, कई लचीले रूटिंग सिस्टम का इस्तेमाल करना ज़रूरी है. इस सिस्टम में, साउंड को बेहतर तरीके से मिक्स और व्यवस्थित किया जा सकता है. Chrome के साथ JAM में, हमने एक ऑडियो बस सिस्टम डेवलप किया है. यह सिस्टम, फ़िज़िकल मिक्सिंग बोर्ड से मिलता-जुलता है. इससे हम उन सभी वाद्ययंत्रों को जोड़ पाते हैं जिन्हें किसी आम बस या चैनल पर रीवर्ब इफ़ेक्ट की ज़रूरत होती है. इसके बाद, हर अलग-अलग वाद्ययंत्र में रीवर्ब जोड़ने की जगह, उस बस में रीवर्ब जोड़ा जा सकता है. यह एक बड़ा ऑप्टिमाइज़ेशन है. साथ ही, आपको सुझाव दिया जाता है कि ज़्यादा कॉम्प्लेक्स ऐप्लिकेशन पर काम शुरू करने के बाद, जल्द से जल्द इसी तरह का काम करें.

AudioBus का रूटिंग

अच्छी बात यह है कि वेब ऑडियो में ऐसा करना बहुत आसान है. हम असल में उस कंकाल का इस्तेमाल कर सकते हैं जिसे हमने इफ़ेक्ट के लिए तय किया है और इसका इस्तेमाल हम ठीक उसी तरह कर सकते हैं.

var AudioBus = function(){
    this.input = audioContext.createGain();
    var output = audioContext.createGain();

    //create effect nodes (Convolver and Equalizer are other custom effects from the library presented at the end of the article)
    var delay = new SlapbackDelayNode(),
        convolver = new tuna.Convolver(),
        equalizer = new tuna.Equalizer();

    //route 'em
    //equalizer -> delay -> convolver
    this.input.connect(equalizer);
    equalizer.connect(delay.input);
    delay.connect(convolver);
    convolver.connect(output);

    this.connect = function(target){
       output.connect(target);
    };
};

इसका इस्तेमाल इस तरह किया जाएगा:

//create some native oscillators and our custom audio bus
var bus = new AudioBus(),
    instrument1 = audioContext.createOscillator(),
    instrument2 = audioContext.createOscillator(),
    instrument3 = audioContext.createOscillator();

//connect our instruments to the same bus
instrument1.connect(bus.input);
instrument2.connect(bus.input);
instrument3.connect(bus.input);
bus.connect(audioContext.destination);

साथ ही, हमने देरी, समानता, और रीवर्ब (जो परफ़ॉर्मेंस के हिसाब से काफ़ी महंगा है) को लागत से आधा कर दिया है, जैसे कि हम अलग-अलग वाद्ययंत्रों के लिए अलग-अलग इफ़ेक्ट का इस्तेमाल करते. अगर हम बस में कुछ और मसालों को जोड़ना चाहते, तो हम दो नए गेन नोड - प्रीगैन और पोस्टगेन - जोड़ सकते थे. इनसे हम बस की आवाज़ को दो अलग-अलग तरीकों से बंद या फ़ेड कर सकते थे. प्रीगेन को इफ़ेक्ट से पहले रखा जाता है और पोस्टगेन को चेन के आखिर में रख दिया जाता है. अगर हम प्रीगेन को फ़ेड कर देते हैं, तो लाभ के सबसे निचले हिस्से पर पहुंचने के बाद भी प्रभाव अब भी गूंजते रहेंगे.

यहां से कहां जाएं?

मैंने यहां जिन तरीकों के बारे में बताया है उन्हें और बेहतर बनाया जा सकता है और ऐसा किया जा सकता है. कस्टम नोड के इनपुट और आउटपुट और कनेक्ट करने के तरीकों जैसी चीज़ों को प्रोटोटाइप पर आधारित इनहेरिटेंस का इस्तेमाल करके लागू किया जा सकता है या किया जाना चाहिए. इफ़ेक्ट की सूची पास करके, बसों को डाइनैमिक तौर पर इफ़ेक्ट बनाने की सुविधा मिलनी चाहिए.

Chrome के साथ JAM की रिलीज़ का जश्न मनाने के लिए, हमने इफ़ेक्ट के फ़्रेम को ओपन सोर्स बनाने का फ़ैसला किया है. अगर इस छोटे से परिचय से आपको पसंद आया है, तो कृपया एक नज़र डालें और बेझिझक योगदान करें. कस्टम वेब ऑडियो एंटइट के लिए फ़ॉर्मैट का स्टैंडर्ड तय करने के बारे में यहां चर्चा हो रही है. शामिल हों!