ভূমিকা
মাল্টিমিডিয়া অভিজ্ঞতাকে আকর্ষণীয় করে তোলার ক্ষেত্রে অডিওর ভূমিকা অত্যন্ত গুরুত্বপূর্ণ। আপনি যদি কখনও সাউন্ড বন্ধ করে সিনেমা দেখার চেষ্টা করে থাকেন, তাহলে আপনি সম্ভবত এটি লক্ষ্য করেছেন।
গেমের ক্ষেত্রেও এর ব্যতিক্রম হয় না! ভিডিও গেমের মিউজিক ও সাউন্ড এফেক্ট আমার সবচেয়ে প্রিয় স্মৃতি। এখন, অনেক ক্ষেত্রে আমার প্রিয় গেম খেলার প্রায় দুই দশক পরেও, আমি এখনও কোজি কন্ডো-র জেল্ডা কম্পোজিশন এবং ম্যাট উয়েলমেন-এর অ্যাটমোস্ফেরিক Diablo সাউন্ডট্র্যাক ভুলতে পারি না। সাউন্ড এফেক্টের ক্ষেত্রেও একই ধরনের আকর্ষণীয়তা প্রযোজ্য, যেমন Warcraft-এর তাত্ক্ষণিকভাবে চেনা যায় এমন ইউনিট ক্লিক রেসপন্স এবং Nintendo-এর ক্লাসিক থেকে নেওয়া স্যাম্পেল।
গেম অডিও কিছু আকর্ষণীয় চ্যালেঞ্জ উপস্থাপন করে। গেমের জন্য বিশ্বাসযোগ্য মিউজিক তৈরি করতে, ডিজাইনারদের সম্ভাব্য অপ্রত্যাশিত গেমের অবস্থার সাথে মানিয়ে নিতে হবে যেখানে একজন খেলোয়াড় নিজেকে খুঁজে পায়। বাস্তবে, গেমের কিছু অংশ অনির্দিষ্ট সময় ধরে চলতে পারে, সাউন্ড পরিবেশের সাথে ইন্টার্যাক্ট করতে পারে এবং জটিল উপায়ে মিক্স হতে পারে, যেমন রুম এফেক্ট এবং আপেক্ষিক সাউন্ড পজিশনিং। অবশেষে, একসাথে অনেক সাউন্ড চালানো যেতে পারে, যার সবকটি একসাথে ভালো শোনাতে হবে এবং পারফর্ম্যান্স পেনাল্টি ছাড়াই রেন্ডার করতে হবে।
ওয়েবে গেমের অডিও
সহজ গেমের জন্য, <audio> ট্যাগ ব্যবহার করাই যথেষ্ট হতে পারে। তবে, অনেক
ব্রাউজার খারাপভাবে ইমপ্লিমেন্ট করে, যার ফলে অডিওতে সমস্যা
এবং হাই লেটেন্সি দেখা যায়। আশা করি এটি একটি সাময়িক সমস্যা, কারণ ভেন্ডররা
তাদের নিজ নিজ ইমপ্লিমেন্টেশন উন্নত করার জন্য কঠোর পরিশ্রম করছেন। <audio> ট্যাগের অবস্থা
এক ঝলক দেখার জন্য, areweplayingyet.org-এ
একটি চমৎকার টেস্ট স্যুট আছে।
তবে, <audio> ট্যাগ স্পেসিফিকেশন আরও গভীরভাবে দেখলে, এটি স্পষ্ট হয়ে যায় যে
এমন অনেক কিছু আছে যা এটি দিয়ে করা যায় না,
যা অবাক হওয়ার মতো কিছু নয়, কারণ এটি মিডিয়া প্লেব্যাকের জন্য ডিজাইন করা হয়েছে। কিছু
সীমাবদ্ধতার মধ্যে রয়েছে:
- সাউন্ড সিগন্যালে ফিল্টার প্রয়োগ করার ক্ষমতা নেই
- র PCM ডেটা অ্যাক্সেস করার কোনও উপায় নেই
- সোর্স ও শ্রোতার অবস্থান ও দিকনির্দেশ সম্পর্কে কোনও ধারণা নেই
- কোনও ফাইন-গ্রেনড টাইমিং নেই।
নিবন্ধের বাকি অংশে, আমি Web Audio API-এর মাধ্যমে লেখা গেম অডিওর প্রসঙ্গে এইসব বিষয়ের মধ্যে কিছু বিষয় নিয়ে আলোচনা করব। এই API-এর সংক্ষিপ্ত পরিচিতির জন্য, শুরু করা টিউটোরিয়াল দেখুন।
পটভূমি সঙ্গীত
গেমে প্রায়ই ব্যাকগ্রাউন্ড মিউজিক লুপে চালানো হয়।
আপনার লুপ ছোট এবং অনুমানযোগ্য হলে তা খুব বিরক্তিকর হতে পারে। কোনও প্লেয়ার কোনও এলাকা বা লেভেলে আটকে গেলে এবং ব্যাকগ্রাউন্ডে একই স্যাম্পেল ক্রমাগত চলতে থাকলে, আরও হতাশা এড়াতে ট্র্যাকটি ধীরে ধীরে ফেড আউট করা সার্থক হতে পারে। আরেকটি স্ট্র্যাটেজি হল, গেমের প্রসঙ্গের উপর নির্ভর করে বিভিন্ন ইনটেনসিটির মিক্স ব্যবহার করা যা ধীরে ধীরে একটি থেকে অন্যটিতে ক্রসফেড করে।
যেমন, আপনার প্লেয়ার যদি কোনও এপিক বস ব্যাটেল জোনে থাকে, তাহলে আপনার কাছে পরিবেশ থেকে শুরু করে পূর্বাভাস থেকে তীব্র পর্যন্ত বিভিন্ন আবেগপূর্ণ রেঞ্জের মিক্স থাকতে পারে। মিউজিক সিন্থেসিস সফ্টওয়্যার প্রায়ই আপনাকে এক্সপোর্টে ব্যবহার করার জন্য ট্র্যাকের সেট বেছে নিয়ে কোনও পিসের উপর ভিত্তি করে একাধিক মিক্স (একই দৈর্ঘ্যের) এক্সপোর্ট করার অনুমতি দেয়। এর ফলে, আপনার কাছে কিছু ইন্টার্নাল সামঞ্জস্য থাকে এবং একটি ট্র্যাক থেকে অন্য ট্র্যাকে ক্রস-ফেড করার সময় আপনি জার্কিং ট্রানজিশন এড়াতে পারেন।
তারপর, Web Audio API ব্যবহার করে, আপনি XHR-এর মাধ্যমে BufferLoader ক্লাস-এর মতো কিছু ব্যবহার করে এই সমস্ত স্যাম্পেল ইমপোর্ট করতে পারবেন (এটি Web Audio API-এর ভূমিকামূলক নিবন্ধে বিস্তারিতভাবে কভার করা হয়েছে)। সাউন্ড লোড হতে সময় লাগে, তাই গেমে ব্যবহৃত অ্যাসেটগুলি পৃষ্ঠা লোড হওয়ার সময়, লেভেল শুরু হওয়ার সময় অথবা প্লেয়ার যখন খেলছেন তখন ধীরে ধীরে লোড করা উচিত।
এরপর, আপনি প্রতিটি নোডের জন্য একটি সোর্স এবং প্রতিটি সোর্সের জন্য একটি গেইন নোড তৈরি করেন এবং গ্রাফটি কানেক্ট করেন।
এটি করার পরে, আপনি এইসব সোর্স একসাথে লুপে প্লেব্যাক করতে পারবেন এবং যেহেতু এগুলি একই দৈর্ঘ্যের, তাই Web Audio API গ্যারান্টি দেবে যে এগুলি অ্যালাইন করা থাকবে। ক্যারেক্টারটি ফাইনাল বস ব্যাটেলের যত কাছে বা দূরে যাবে, গেমটি চেনের প্রতিটি নোডের জন্য গেইন ভ্যালু পরিবর্তন করতে পারে। এর জন্য নিম্নলিখিত অ্যালগরিদম ব্যবহার করা হয়:
// Assume gains is an array of AudioGainNode, normVal is the intensity
// between 0 and 1.
var value = normVal - (gains.length - 1);
// First reset gains on all nodes.
for (var i = 0; i < gains.length; i++) {
gains[i].gain.value = 0;
}
// Decide which two nodes we are currently between, and do an equal
// power crossfade between them.
var leftNode = Math.floor(value);
// Normalize the value between 0 and 1.
var x = value - leftNode;
var gain1 = Math.cos(x - 0.5*Math.PI);
var gain2 = Math.cos((1.0 - x) - 0.5*Math.PI);
// Set the two gains accordingly.
gains[leftNode].gain.value = gain1;
// Check to make sure that there's a right node.
if (leftNode < gains.length - 1) {
// If there is, adjust its gain.
gains[leftNode + 1].gain.value = gain2;
}
উপরের পদ্ধতিতে, দুটি সোর্স একসাথে চলে এবং আমরা সমান পাওয়ার কার্ভ (ভূমিকাতে যেমন বর্ণনা করা হয়েছে) ব্যবহার করে তাদের মধ্যে ক্রসফেড করি।
The missing link: Audio tag to Web Audio
আজকাল অনেক গেম ডেভেলপার তাদের ব্যাকগ্রাউন্ড মিউজিকের জন্য <audio> ট্যাগ ব্যবহার করেন, কারণ এটি স্ট্রিমিং কন্টেন্টের জন্য উপযুক্ত। এখন আপনি
<audio> ট্যাগ থেকে কন্টেন্ট নিয়ে এসে ওয়েব অডিও কনটেক্সটে ব্যবহার করতে পারবেন।
এই টেকনিকটি উপযোগী হতে পারে কারণ <audio> ট্যাগ স্ট্রিমিং কন্টেন্টের সাথে কাজ করতে পারে, যা আপনাকে ব্যাকগ্রাউন্ড মিউজিক ডাউনলোড করার জন্য অপেক্ষা করার পরিবর্তে অবিলম্বে তা চালাতে দেয়। Web Audio API-তে স্ট্রিম নিয়ে আসার মাধ্যমে, আপনি স্ট্রিম ম্যানিপুলেট বা বিশ্লেষণ করতে পারবেন। নিম্নলিখিত
উদাহরণে <audio> ট্যাগের মাধ্যমে
চালানো মিউজিকে লো পাস ফিল্টার প্রয়োগ করা হয়:
var audioElement = document.querySelector('audio');
var mediaSourceNode = context.createMediaElementSource(audioElement);
// Create the filter
var filter = context.createBiquadFilter();
// Create the audio graph.
mediaSourceNode.connect(filter);
filter.connect(context.destination);
Web Audio API-এর সাথে <audio> ট্যাগ ইন্টিগ্রেট করার বিষয়ে আরও সম্পূর্ণ আলোচনার জন্য, এই সংক্ষিপ্ত নিবন্ধ দেখুন।
সাউন্ড এফেক্ট
ব্যবহারকারীর ইনপুট বা গেমের স্ট্যাটাসে পরিবর্তনের প্রতিক্রিয়া হিসেবে গেম প্রায়শই সাউন্ড এফেক্ট প্লে করে। তবে, ব্যাকগ্রাউন্ড মিউজিকের মতো সাউন্ড এফেক্টও খুব দ্রুত বিরক্তিকর হয়ে উঠতে পারে। এটি এড়াতে, একই রকম কিন্তু আলাদা আলাদা সাউন্ডের একটি পুল থাকলে তা প্রায়শই কাজে লাগে। এটি ফুটস্টেপ স্যাম্পেলের সামান্য পরিবর্তন থেকে শুরু করে আমূল পরিবর্তন পর্যন্ত হতে পারে, যেমন ইউনিটে ক্লিক করার উত্তরে Warcraft সিরিজে দেখা যায়।
গেমের সাউন্ড এফেক্টের আরেকটি গুরুত্বপূর্ণ ফিচার হল, একই সাথে অনেক সাউন্ড এফেক্ট থাকতে পারে। কল্পনা করুন যে আপনি একাধিক অভিনেতার সাথে বন্দুকের লড়াইয়ের মাঝখানে আছেন যারা মেশিনগান থেকে গুলি ছুড়ছে। প্রতিটি মেশিন গান প্রতি সেকেন্ডে অনেকবার গুলি করে, যার ফলে একই সময়ে কয়েক ডজন সাউন্ড এফেক্ট চালানো হয়। একাধিক, নির্দিষ্ট সময় সেট করা সোর্স থেকে একই সাথে সাউন্ড প্লেব্যাক করা এমন একটি জায়গা যেখানে Web Audio API সত্যিই দারুণ কাজ করে।
নিম্নলিখিত উদাহরণে একাধিক সাউন্ড সোর্স তৈরি করে একাধিক স্বতন্ত্র বুলেট স্যাম্পেল থেকে মেশিন গান রাউন্ড তৈরি করা হয়, যার প্লেব্যাক সময়ের সাথে সাথে পরিবর্তিত হয়।
var time = context.currentTime;
for (var i = 0; i < rounds; i++) {
var source = this.makeSource(this.buffers[M4A1]);
source.noteOn(time + i - interval);
}
এখন, আপনার গেমের সব মেশিন গানের আওয়াজ যদি ঠিক এইরকম হয়, তাহলে সেটা খুবই বিরক্তিকর হবে। অবশ্যই, টার্গেট থেকে দূরত্ব এবং আপেক্ষিক অবস্থানের (এই বিষয়ে পরে আরও আলোচনা করা হবে) উপর ভিত্তি করে শব্দ আলাদা হবে, তবে এমনকি সেটিও যথেষ্ট নাও হতে পারে। সৌভাগ্যবশত, Web Audio API-এর মাধ্যমে উপরের উদাহরণটি দুটি উপায়ে সহজেই পরিবর্তন করা যায়:
- বুলেট ফায়ারিংয়ের মধ্যে সময়ের সূক্ষ্ম পরিবর্তন সহ
- প্রতিটি স্যাম্পেলের playbackRate পরিবর্তন করে (পিচও পরিবর্তন করে) বাস্তব জগতের এলোমেলো ভাব আরও ভালোভাবে সিমুলেট করা।
এইসব টেকনিকের আরও বাস্তবসম্মত উদাহরণ দেখতে, পুল টেবিল ডেমো দেখুন, যা র্যান্ডম স্যাম্পলিং ব্যবহার করে এবং বলের সংঘর্ষের আরও আকর্ষণীয় সাউন্ডের জন্য playbackRate পরিবর্তন করে।
3D পজিশনাল সাউন্ড
গেমগুলি প্রায়শই কিছু জ্যামিতিক বৈশিষ্ট্য সহ একটি জগতে সেট করা হয়, হয় 2D বা 3D তে। এই ধরনের ক্ষেত্রে, স্টিরিও পজিশন করা অডিও, অভিজ্ঞতার ইমারসিভনেস অনেক বাড়িয়ে দিতে পারে। ভাগ্যক্রমে, Web Audio API-তে বিল্ট-ইন হার্ডওয়্যার অ্যাক্সিলারেটেড পজিশনাল অডিও ফিচার আছে যা ব্যবহার করা খুবই সহজ। যাই হোক, নিম্নলিখিত উদাহরণটি বোঝার জন্য আপনার কাছে স্টিরিও স্পিকার (হেডফোন হলে ভালো হয়) আছে কিনা তা নিশ্চিত করুন।
উপরের উদাহরণে, ক্যানভাসের মাঝখানে একজন শ্রোতা (ব্যক্তির আইকন) আছেন এবং মাউস সোর্সের (স্পিকার আইকন) অবস্থানকে প্রভাবিত করে। এই ধরনের এফেক্ট পেতে AudioPannerNode ব্যবহার করার একটি সহজ উদাহরণ উপরে দেওয়া হল। উপরের স্যাম্পেলের মূল উদ্দেশ্য হল অডিও সোর্সের পজিশন সেট করে মাউসের মুভমেন্টে সাড়া দেওয়া, যেমন:
PositionSample.prototype.changePosition = function(position) {
// Position coordinates are in normalized canvas coordinates
// with -0.5 < x, y < 0.5
if (position) {
if (!this.isPlaying) {
this.play();
}
var mul = 2;
var x = position.x / this.size.width;
var y = -position.y / this.size.height;
this.panner.setPosition(x - mul, y - mul, -0.5);
} else {
this.stop();
}
};
ওয়েব অডিওর স্পেশিয়ালাইজেশন ট্রিটমেন্ট সম্পর্কে যা জানা প্রয়োজন:
- ডিফল্ট হিসেবে শ্রোতা অরিজিনে (০, ০, ০) থাকেন।
- Web Audio পজিশনাল API-এর কোনও ইউনিট নেই, তাই ডেমো সাউন্ড আরও ভালো করার জন্য আমি একটি মাল্টিপ্লায়ার যোগ করেছি।
- ওয়েব অডিও y-is-up কার্টেসিয়ান কোঅর্ডিনেট ব্যবহার করে (বেশিরভাগ কম্পিউটার গ্রাফিক্স সিস্টেমের বিপরীত)। সেই জন্যই আমি উপরের স্নিপেটে y-অ্যাক্সিস সোয়্যাপ করছি
উন্নত: সাউন্ড কোন
পজিশনাল মডেলটি খুবই শক্তিশালী এবং বেশ উন্নত, মূলত OpenAL-এর উপর ভিত্তি করে তৈরি। আরও তথ্যের জন্য, উপরে লিঙ্ক করা স্পেসিফিকেশনের ৩ ও ৪ নম্বর বিভাগ দেখুন।
Web Audio API কনটেক্সটের সাথে একটি AudioListener অ্যাটাচ করা আছে যা পজিশন ও ওরিয়েন্টেশনের মাধ্যমে স্পেসে কনফিগার করা যেতে পারে। প্রতিটি সোর্স AudioPannerNode-এর মাধ্যমে পাস করা যেতে পারে, যা ইনপুট অডিওকে স্পেশিয়ালাইজ করে। প্যানার নোডের পজিশন ও ওরিয়েন্টেশন এবং দূরত্ব ও দিকনির্দেশক মডেল আছে।
দূরত্ব মডেল সোর্সের নৈকট্যের উপর নির্ভর করে গেইনের পরিমাণ নির্দিষ্ট করে, যদিও ডিরেকশনাল মডেল ইনার ও আউটার কোণ নির্দিষ্ট করে কনফিগার করা যেতে পারে, যা গেইনের পরিমাণ (সাধারণত নেগেটিভ) নির্ধারণ করে যদি শ্রোতা ইনার কোণের মধ্যে, ইনার ও আউটার কোণের মধ্যে অথবা আউটার কোণের বাইরে থাকেন।
var panner = context.createPanner();
panner.coneOuterGain = 0.5;
panner.coneOuterAngle = 180;
panner.coneInnerAngle = 0;
আমার উদাহরণ 2D-তে হলেও, এই মডেল সহজেই তৃতীয় মাত্রায় সাধারণীকরণ করে। 3D-তে স্পেশিয়ালাইজ করা সাউন্ডের উদাহরণ দেখতে, এই পজিশনাল স্যাম্পেল দেখুন। অবস্থান ছাড়াও, ওয়েব অডিও সাউন্ড মডেলে ডপলার শিফটের জন্য বেগও অন্তর্ভুক্ত থাকে। এই উদাহরণে ডপলার এফেক্ট আরও বিস্তারিতভাবে দেখানো হয়েছে।
এই বিষয়ে আরও জানতে, [পজিশনাল অডিও ও WebGL মিক্স করা][webgl] সংক্রান্ত এই বিস্তারিত টিউটোরিয়াল পড়ুন।
রুম এফেক্ট ও ফিল্টার
বাস্তবে, কোনও শব্দ কেমন শোনাবে তা নির্ভর করে যে ঘরে সেই শব্দ শোনা হচ্ছে তার উপর। একই দরজা খোলার আওয়াজ বেসমেন্টে একরকম শোনাবে, আবার বড় খোলা হলে অন্যরকম শোনাবে। যেসব গেমের প্রোডাকশন ভ্যালু বেশি, সেগুলি এই এফেক্ট নকল করতে চাইবে, কারণ প্রতিটি এনভায়রনমেন্টের জন্য আলাদা স্যাম্পেল তৈরি করা অত্যন্ত ব্যয়বহুল এবং এর ফলে আরও বেশি অ্যাসেট ও গেম ডেটার প্রয়োজন হবে।
সহজ কথায়, অডিওর ক্ষেত্রে, র-সাউন্ড এবং বাস্তবে যেভাবে সাউন্ড শোনা যায়, এই দুটির মধ্যে পার্থক্যকে ইমপালস রেসপন্স বলা হয়। এই ইমপালস রেসপন্সগুলি খুব কষ্ট করে রেকর্ড করা হয় এবং আসলে এমন অনেক সাইট আছে যেগুলি আপনার সুবিধার জন্য এই ধরনের অনেক আগে থেকে রেকর্ড করা ইমপালস রেসপন্স ফাইল (অডিও হিসেবে স্টোর করা) হোস্ট করে।
কোনও পরিবেশ থেকে কীভাবে ইমপালস রেসপন্স তৈরি করা যায় সেই সম্পর্কে আরও তথ্য পেতে, Web Audio API স্পেসিফিকেশনের কনভলিউশন অংশের "রেকর্ডিং সেট-আপ" বিভাগটি পড়ুন।
আমাদের উদ্দেশ্যের জন্য আরও গুরুত্বপূর্ণ হল, ConvolverNode ব্যবহার করে আমাদের সাউন্ডে এইসব ইমপালস রেসপন্স প্রয়োগ করার সহজ উপায় Web Audio API প্রদান করে।
// Make a source node for the sample.
var source = context.createBufferSource();
source.buffer = this.buffer;
// Make a convolver node for the impulse response.
var convolver = context.createConvolver();
convolver.buffer = this.impulseResponseBuffer;
// Connect the graph.
source.connect(convolver);
convolver.connect(context.destination);
এছাড়াও, Web Audio API স্পেসিফিকেশন পৃষ্ঠায় রুম এফেক্টের ডেমো দেখুন এবং এই উদাহরণ দেখুন যা আপনাকে একটি দুর্দান্ত জ্যাজ স্ট্যান্ডার্ডের ড্রাই (র) এবং ওয়েট (কনভলভারের মাধ্যমে প্রসেস করা) মিক্সিংয়ের উপর কন্ট্রোল দেয়।
ফাইনাল কাউন্টডাউন
আপনি একটি গেম তৈরি করেছেন, আপনার পজিশনাল অডিও কনফিগার করেছেন এবং এখন আপনার গ্রাফে প্রচুর সংখ্যক AudioNode আছে, সবগুলি একসাথে প্লেব্যাক হচ্ছে। দারুণ, তবে এখনও একটি বিষয় বিবেচনা করতে হবে:
যেহেতু একাধিক সাউন্ড একে অপরের উপরে স্ট্যাক করা থাকে এবং কোনও নরমালাইজেশন থাকে না, তাই আপনি এমন পরিস্থিতিতে পড়তে পারেন যেখানে আপনার স্পিকারের ক্ষমতার সীমা অতিক্রম করে যেতে পারে। ক্যানভাসের সীমানা ছাড়িয়ে যাওয়া ছবির মতো, ওয়েভফর্ম তার সর্বোচ্চ থ্রেশহোল্ড অতিক্রম করলে সাউন্ডও ক্লিপ করতে পারে, যার ফলে একটি স্বতন্ত্র বিকৃতি তৈরি হয়। ওয়েভফর্মটি দেখতে এইরকম হয়:
ক্লিপিং কীভাবে কাজ করে তার একটি বাস্তব উদাহরণ এখানে দেওয়া হল। ওয়েভফর্ম ঠিক লাগছে না:
উপরে উল্লেখ করা উদাহরণের মতো কর্কশ বিকৃতি বা এর বিপরীতে, খুব মৃদু মিক্স যা আপনার শ্রোতাদের ভলিউম বাড়াতে বাধ্য করে, তা শোনা গুরুত্বপূর্ণ। আপনি যদি এই পরিস্থিতিতে থাকেন, তাহলে আপনাকে সত্যিই এটি ঠিক করতে হবে!
ক্লিপিং শনাক্ত করুন
টেকনিক্যাল দিক থেকে, ক্লিপিং তখনই হয় যখন কোনও চ্যানেলের সিগন্যালের ভ্যালু সঠিক রেঞ্জের বাইরে চলে যায়, অর্থাৎ -১ ও ১-এর মধ্যে থাকে না। এটি শনাক্ত করা হলে, এটি যে ঘটছে তা ভিজ্যুয়াল ফিডব্যাক দেওয়া উপযোগী। এটি নির্ভরযোগ্যভাবে করতে, আপনার গ্রাফে একটি JavaScriptAudioNode রাখুন। অডিও গ্রাফ এইভাবে সেট-আপ করা হবে:
// Assume entire sound output is being piped through the mix node.
var meter = context.createJavaScriptNode(2048, 1, 1);
meter.onaudioprocess = processAudio;
mix.connect(meter);
meter.connect(context.destination);
এবং নিম্নলিখিত processAudio হ্যান্ডলারে ক্লিপিং শনাক্ত করা যেতে পারে:
function processAudio(e) {
var buffer = e.inputBuffer.getChannelData(0);
var isClipping = false;
// Iterate through buffer to check if any of the |values| exceeds 1.
for (var i = 0; i < buffer.length; i++) {
var absValue = Math.abs(buffer[i]);
if (absValue >= 1) {
isClipping = true;
break;
}
}
}
সাধারণত, পারফর্ম্যান্সের কারণে JavaScriptAudioNode-এর অতিরিক্ত ব্যবহার
না করার ব্যাপারে সতর্ক থাকুন। এই ক্ষেত্রে, মিটারিংয়ের বিকল্প প্রয়োগ
getByteFrequencyData-এর জন্য অডিও গ্রাফে RealtimeAnalyserNode পোল করতে পারে,
রেন্ডার করার মোট সময়ে, যেমন requestAnimationFrame-এর দ্বারা
নির্ধারিত হয়। এই পদ্ধতিটি আরও দক্ষ, কিন্তু বেশিরভাগ সিগন্যাল মিস করে (যেসব জায়গায় এটি সম্ভাব্য ক্লিপ করে সেগুলি সহ), কারণ
রেন্ডারিং প্রতি সেকেন্ডে সর্বাধিক ৬০ বার ঘটে, যেখানে অডিও সিগন্যাল
অনেক দ্রুত পরিবর্তিত হয়।
ক্লিপ শনাক্তকরণ অত্যন্ত গুরুত্বপূর্ণ, তাই ভবিষ্যতে আমরা একটি
বিল্ট-ইন MeterNode Web Audio API নোড দেখতে পাব।
ক্লিপিং আটকানো
মাস্টার AudioGainNode-এ গেন অ্যাডজাস্ট করে, আপনি নিজের মিক্সকে এমন লেভেলে সাবডিউ করতে পারবেন যা ক্লিপিং আটকায়। তবে, বাস্তবে, আপনার গেমে যে সাউন্ড বাজানো হয় তা বিভিন্ন বিষয়ের উপর নির্ভর করে, তাই মাস্টার গেইন ভ্যালু নির্ধারণ করা কঠিন হতে পারে যা সব স্টেটের জন্য ক্লিপিং আটকায়। সাধারণত, সবচেয়ে খারাপ পরিস্থিতি অনুমান করার জন্য আপনাকে গেন অ্যাডজাস্ট করতে হবে, তবে এটি বিজ্ঞানের চেয়ে শিল্পের মতো বেশি।
একটু চিনি যোগ করুন
মিউজিক ও গেম প্রোডাকশনে সিগন্যাল স্মুথ করতে ও সামগ্রিক সিগন্যালে স্পাইক কন্ট্রোল করতে
সাধারণত কম্প্রেসর ব্যবহার করা হয়। এই
ফাংশনালিটি ওয়েব অডিওর জগতে DynamicsCompressorNode-এর মাধ্যমে
উপলভ্য, যা আপনার অডিও গ্রাফে যোগ করা যেতে পারে যাতে
আরও জোরে, সমৃদ্ধ ও সম্পূর্ণ সাউন্ড পাওয়া যায় এবং ক্লিপিংয়ের ক্ষেত্রেও সাহায্য করে।
সরাসরি স্পেক কোট করে, এই নোড
ডায়নামিক কম্প্রেশন ব্যবহার করা সাধারণত ভাল আইডিয়া, বিশেষ করে গেম সেটিংয়ে, যেখানে, আগে যেমন আলোচনা করা হয়েছে, আপনি ঠিক জানেন না কোন সাউন্ড কখন বাজবে। DinahMoe ল্যাবসের Plink হল এর একটি দুর্দান্ত উদাহরণ, কারণ যে সাউন্ড প্লেব্যাক করা হয় তা সম্পূর্ণভাবে আপনার এবং অন্যান্য অংশগ্রহণকারীদের উপর নির্ভর করে। বেশিরভাগ ক্ষেত্রেই কম্প্রেসর ব্যবহার করা উপযোগী, তবে কিছু বিরল ক্ষেত্রে, যেখানে আপনি অত্যন্ত যত্ন সহকারে মাস্টার করা ট্র্যাক নিয়ে কাজ করছেন, যেগুলি আগে থেকেই "ঠিকঠাক" সাউন্ড করার জন্য টিউন করা হয়েছে।
এটি প্রয়োগ করার জন্য আপনার অডিও গ্রাফে শুধু একটি DynamicsCompressorNode যোগ করতে হবে, সাধারণত গন্তব্যের আগে শেষ নোড হিসেবে এটি যোগ করা হয়।:
// Assume the output is all going through the mix node.
var compressor = context.createDynamicsCompressor();
mix.connect(compressor);
compressor.connect(context.destination);
ডায়নামিক কম্প্রেশন সম্পর্কে আরও বিস্তারিত জানতে, এই Wikipedia নিবন্ধ খুবই তথ্যপূর্ণ।
সংক্ষেপে বলতে গেলে, ক্লিপিংয়ের জন্য মনোযোগ সহকারে শুনুন এবং মাস্টার গেন নোড যোগ করে এটি প্রতিরোধ করুন। তারপর ডাইনামিক্স কম্প্রেসর Node ব্যবহার করে পুরো মিক্সকে টাইট করা। আপনার অডিও গ্রাফটি দেখতে এরকম হতে পারে:
উপসংহার
Web Audio API ব্যবহার করে গেম অডিও ডেভেলপমেন্টের সবচেয়ে গুরুত্বপূর্ণ দিকগুলি আমি কভার করেছি। এইসব টেকনিকের সাহায্যে, আপনি সরাসরি আপনার ব্রাউজারে সত্যিই আকর্ষণীয় অডিও অভিজ্ঞতা তৈরি করতে পারবেন। আমি বিদায় নেওয়ার আগে, আপনাকে ব্রাউজার-নির্দিষ্ট পরামর্শ দিয়ে যাই: পৃষ্ঠা দৃশ্যমানতা API ব্যবহার করে আপনার ট্যাব ব্যাকগ্রাউন্ডে চলে গেলে, সাউন্ড পজ করতে ভুলবেন না, অন্যথায় আপনি ব্যবহারকারীর জন্য সম্ভাব্য হতাশাজনক অভিজ্ঞতা তৈরি করবেন।
ওয়েব অডিও সম্পর্কে আরও তথ্য পেতে, আরও প্রাথমিক শুরু করা সংক্রান্ত নিবন্ধ দেখুন এবং আপনার কোনও প্রশ্ন থাকলে, ওয়েব অডিও সংক্রান্ত প্রায়শই জিজ্ঞাসিত প্রশ্ন থেকে দেখুন যে সেটির উত্তর আগে থেকেই দেওয়া আছে কিনা। সবশেষে, আপনার আরও প্রশ্ন থাকলে, web-audio ট্যাগ ব্যবহার করে Stack Overflow-এ সেগুলি জিজ্ঞাসা করুন।
বিদায় নেওয়ার আগে, আমি আপনাকে আজকের দিনে আসল গেমে Web Audio API-এর কিছু দুর্দান্ত ব্যবহার সম্পর্কে জানিয়ে যেতে চাই:
- Field Runners এবং কিছু প্রযুক্তিগত বিবরণ সম্পর্কে একটি রাইট-আপ।
- Angry Birds, সম্প্রতি Web Audio API-তে পাল্টে গেছে। আরও তথ্যের জন্য এই লেখাটি দেখুন।
- Skid Racer, যা স্পেশিয়ালাইজড অডিওর দারুণ ব্যবহার করে।