HTML5 <audio> এলিমেন্টের আগে, ওয়েবের নীরবতা ভাঙতে
ফ্ল্যাশ বা অন্য প্লাগ-ইন প্রয়োজন ছিল। ওয়েবে অডিওর জন্য প্লাগ-ইন আর প্রয়োজন না হলেও, অডিও ট্যাগ অত্যাধুনিক গেম ও ইন্টার্যাক্টিভ অ্যাপ্লিকেশন প্রয়োগ করার ক্ষেত্রে
উল্লেখযোগ্য সীমাবদ্ধতা নিয়ে আসে।
Web Audio API হল একটি হাই-লেভেল জাভাস্ক্রিপ্ট API যা ওয়েব অ্যাপ্লিকেশনে অডিও প্রসেস ও সিন্থেসাইজ করার জন্য ব্যবহার করা হয়। এই API-এর লক্ষ্য হল আধুনিক গেম অডিও ইঞ্জিনে পাওয়া যায় এমন ক্ষমতা এবং আধুনিক ডেস্কটপ অডিও প্রোডাকশন অ্যাপ্লিকেশনে পাওয়া যায় এমন কিছু মিক্সিং, প্রসেসিং এবং ফিল্টারিং টাস্ক অন্তর্ভুক্ত করা। এই শক্তিশালী API ব্যবহার করার জন্য একটি সহজ ভূমিকা নিচে দেওয়া হল।
AudioContext ব্যবহার শুরু করা
AudioContext সব সাউন্ড ম্যানেজ ও প্লে করার জন্য ব্যবহার করা হয়। Web Audio API ব্যবহার করে
সাউন্ড তৈরি করতে, এক বা একাধিক সাউন্ড সোর্স তৈরি করুন
এবং AudioContext ইনস্ট্যান্সের মাধ্যমে প্রদান করা সাউন্ড ডেস্টিনেশনের সাথে
সেগুলি কানেক্ট করুন। এই কানেকশন সরাসরি হওয়ার প্রয়োজন নেই এবং এটি যেকোনও সংখ্যক
ইন্টারমিডিয়েট AudioNodes-এর মাধ্যমে হতে পারে যা অডিও সিগন্যালের জন্য
প্রসেসিং মডিউল হিসেবে কাজ করে। এই রাউটিং সম্পর্কে আরও বিস্তারিতভাবে
Web Audio স্পেসিফিকেশন-এ বর্ণনা করা হয়েছে।
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।
AudioNodes তৈরি করা এবং অডিও ফাইল ডেটা ডিকোড করার মতো অনেক আকর্ষণীয় Web Audio API কার্যকারিতা হল AudioContext-এর পদ্ধতি।
সাউন্ড লোড করা হচ্ছে
Web Audio API ছোট থেকে মাঝারি দৈর্ঘ্যের সাউন্ডের জন্য AudioBuffer ব্যবহার করে। সাউন্ড ফাইল ফেচ করার জন্য XMLHttpRequest ব্যবহার করা হল প্রাথমিক পদ্ধতি।
API একাধিক ফর্ম্যাটে অডিও ফাইল ডেটা লোড করতে পারে, যেমন 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() শেষ হয়ে গেলে, এটি একটি কলব্যাক ফাংশনকে কল করে যা
ডিকোড করা PCM অডিও ডেটা 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 ডেভেলপারদের প্লেব্যাক সঠিকভাবে শিডিউল করতে দেয়। এটি দেখানোর জন্য, আসুন একটি সহজ রিদম ট্র্যাক সেট-আপ করি। সম্ভবত সবচেয়ে বেশি পরিচিত ড্রামকিট প্যাটার্ন হল নিম্নলিখিত:
যেখানে প্রতি অষ্টম নোটে হাইহ্যাট বাজানো হয় এবং কিক ও স্নেয়ার প্রতি কোয়ার্টারে অল্টারনেট করে বাজানো হয়, ৪/৪ টাইমে।
ধরা যাক, আমরা 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);
}
ওয়েব অডিও API, RampToValue পদ্ধতির একটি সুবিধাজনক সেট প্রদান করে
যাতে ধীরে ধীরে প্যারামিটারের ভ্যালু পরিবর্তন করা যায়, যেমন
linearRampToValueAtTime এবং exponentialRampToValueAtTime।
ট্রানজিশন টাইমিং ফাংশন বিল্ট-ইন লিনিয়ার এবং এক্সপোনেনশিয়াল (উপরে যেমন দেখানো হয়েছে) থেকে বেছে নেওয়া যেতে পারে, আপনি setValueCurveAtTime ফাংশন ব্যবহার করে ভ্যালুর অ্যারের মাধ্যমে নিজের ভ্যালু কার্ভও নির্দিষ্ট করতে পারেন।
কোনও সাউন্ডে সাধারণ ফিল্টার এফেক্ট প্রয়োগ করা

Web Audio API আপনাকে একটি অডিও নোড থেকে অন্য অডিও নোডে সাউন্ড পাইপ করতে দেয়, আপনার সাউন্ডফর্মে জটিল প্রভাব যোগ করার জন্য প্রসেসরের একটি সম্ভাব্য জটিল চেইন তৈরি করে।
এটি করার একটি উপায় হল আপনার সাউন্ড সোর্স ও ডেস্টিনেশনের মধ্যে BiquadFilterNode প্লেস করা। এই ধরনের অডিও নোড বিভিন্ন ধরনের লো-অর্ডার ফিল্টার করতে পারে যা গ্রাফিক ইকুয়ালাইজার এবং আরও জটিল এফেক্ট তৈরি করতে ব্যবহার করা যেতে পারে, মূলত শব্দের ফ্রিকোয়েন্সি স্পেকট্রামের কোন অংশগুলিতে জোর দিতে হবে এবং কোনগুলি দমন করতে হবে তা বেছে নেওয়ার জন্য।
এই ধরনের ফিল্টার কাজ করে:
- লো পাস ফিল্টার
- হাই পাস ফিল্টার
- ব্যান্ড পাস ফিল্টার
- লো শেল্ফ ফিল্টার
- হাই শেল্ফ ফিল্টার
- পিকিং ফিল্টার
- নচ ফিল্টার
- অল পাস ফিল্টার
এবং সব ফিল্টারে কিছু পরিমাণ গেন, ফিল্টার প্রয়োগ করার ফ্রিকোয়েন্সি এবং কোয়ালিটি ফ্যাক্টর নির্দিষ্ট করার জন্য প্যারামিটার অন্তর্ভুক্ত থাকে। লো-পাস ফিল্টার কম ফ্রিকোয়েন্সি রেঞ্জ বজায় রাখে, কিন্তু বেশি ফ্রিকোয়েন্সি বাদ দেয়। ব্রেক-অফ পয়েন্ট ফ্রিকোয়েন্সি ভ্যালু দ্বারা নির্ধারিত হয়, এবং 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 হল ৪৪০ হার্টজ এবং A5 হল ৮৮০ হার্টজ)। আরও বিবরণের জন্য, উপরে দেওয়া সোর্স কোড লিঙ্কে
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);
আরও শুনুন
আমরা API-এর প্রাথমিক বিষয়গুলি কভার করেছি, যার মধ্যে অডিও স্যাম্পেল লোড করা এবং চালানো অন্তর্ভুক্ত। আমরা গেইন নোড ও ফিল্টার সহ অডিও গ্রাফ তৈরি করেছি এবং কিছু সাধারণ সাউন্ড এফেক্ট চালু করার জন্য সাউন্ড ও অডিও প্যারামিটার টুইক শিডিউল করেছি। এই পর্যায়ে, আপনি কিছু দারুণ ওয়েব অডিও অ্যাপ্লিকেশন তৈরি করার জন্য প্রস্তুত!
আপনি যদি অনুপ্রেরণা খুঁজছেন, তাহলে অনেক ডেভেলপার ইতিমধ্যেই Web Audio API ব্যবহার করে দুর্দান্ত কাজ করেছেন। আমার পছন্দের কিছু জিনিস এর মধ্যে রয়েছে:
- AudioJedit, একটি ইন-ব্রাউজার সাউন্ড স্প্লাইসিং টুল যা SoundCloud পার্মালিঙ্ক ব্যবহার করে।
- ToneCraft, একটি সাউন্ড সিকোয়েন্সার যেখানে 3D ব্লক স্ট্যাক করে সাউন্ড তৈরি করা হয়।
- Plink, ওয়েব অডিও এবং ওয়েব সকেট ব্যবহার করে কোলাবরেটিভ মিউজিক-মেকিং গেম।