บทนำ
เสียงเป็นส่วนสำคัญที่ทำให้ประสบการณ์มัลติมีเดีย น่าสนใจมาก หากคุณเคยลองดูภาพยนตร์โดยปิดเสียง คุณอาจสังเกตเห็นสิ่งนี้
เกมก็อยู่ในข้อจำกัดนี้ด้วย ความทรงจำเกี่ยวกับวิดีโอเกมที่ฉันชอบที่สุดคือเพลงและเอฟเฟกต์เสียง หลายเกมที่เล่นเมื่อเกือบ 20 ปีก่อนยังคงอยู่ในความทรงจำของฉันเสมอ ไม่ว่าจะผ่านมากี่ปีแล้วก็ตาม ไม่ว่าจะผ่านมากี่ปีแล้วก็ตาม เพลงประกอบของ Koji Kondo ใน Zelda และซาวด์แทร็กของ Matt Uelmen ใน Diablo ยังคงอยู่ในหัวของฉันเสมอ หลักการเดียวกันนี้ยังใช้กับเสียงประกอบได้ด้วย เช่น เสียงตอบกลับเมื่อคลิกยูนิตจาก Warcraft ที่ทุกคนจดจำได้ทันที และซาวด์แทร็กจากเกมคลาสสิกของ Nintendo
เสียงในเกมเป็นปัญหาที่น่าสนใจ หากต้องการสร้างเพลงในเกมที่สมจริง นักออกแบบจะต้องปรับให้เข้ากับสถานะเกมที่ผู้เล่นอาจคาดเดาไม่ได้ ในทางปฏิบัติ เกมบางส่วนอาจเล่นต่อเนื่องไปเป็นเวลานานโดยไม่ทราบแน่ชัด เสียงอาจโต้ตอบกับสภาพแวดล้อมและผสมผสานกันด้วยวิธีที่ซับซ้อน เช่น เสียงสะท้อนในห้องและตำแหน่งเสียงแบบสัมพัทธ์ สุดท้าย อาจมีเสียงจำนวนมากเล่นพร้อมกัน ซึ่งเสียงทั้งหมดต้องฟังดูดีด้วยกันและแสดงผลโดยไม่ทำให้ประสิทธิภาพลดลง
เสียงในเกมบนเว็บ
สำหรับเกมง่ายๆ การใช้แท็ก <audio>
ก็เพียงพอแล้ว อย่างไรก็ตาม เบราว์เซอร์จำนวนมากมีการใช้งานที่ไม่ดี ซึ่งส่งผลให้เกิดข้อบกพร่องของเสียงและเวลาในการตอบสนองที่สูง เราหวังว่านี่จะเป็นปัญหาชั่วคราว เนื่องจากผู้ให้บริการกําลังพยายามปรับปรุงการติดตั้งใช้งานที่เกี่ยวข้อง คุณดูสถานะของแท็ก <audio>
ได้จากชุดทดสอบที่น่าสนใจที่ areweplayingyet.org
อย่างไรก็ตาม เมื่อดูรายละเอียดแท็ก <audio>
อย่างละเอียดแล้ว จะพบว่ามีสิ่งหลายอย่างที่ทําไม่ได้ด้วยแท็กนี้ ซึ่งไม่น่าแปลกใจเนื่องจากแท็กนี้ออกแบบมาเพื่อการเล่นสื่อ ข้อจำกัดบางส่วนมีดังนี้
- ใช้ตัวกรองกับสัญญาณเสียงไม่ได้
- ไม่มีวิธีเข้าถึงข้อมูล PCM ดิบ
- ไม่มีแนวคิดเกี่ยวกับจุดยืนและทิศทางของแหล่งที่มาและผู้ฟัง
- ไม่มีการกำหนดเวลาอย่างละเอียด
ในส่วนที่เหลือของบทความ เราจะเจาะลึกบางหัวข้อเหล่านี้ในบริบทของเสียงในเกมที่เขียนด้วย Web Audio API สำหรับข้อมูลเบื้องต้นเกี่ยวกับ API นี้ โปรดดูที่บทแนะนำการเริ่มต้นใช้งาน
เพลงพื้นหลัง
เกมมักจะมีเพลงเล่นวนซ้ำอยู่เบื้องหลัง
อาจเป็นเรื่องน่ารำคาญหากลูปของคุณสั้นและคาดเดาได้ หากผู้เล่นติดอยู่ในโซนหรือด่านใดด่านหนึ่งและมีเสียงตัวอย่างเดิมเล่นอยู่เบื้องหลังอย่างต่อเนื่อง คุณอาจลองค่อยๆ ปิดแทร็กเพื่อไม่ให้ผู้เล่นรู้สึกหงุดหงิดมากขึ้น อีกกลยุทธ์หนึ่งคือการผสมผสานระดับความรุนแรงที่ค่อยๆ เลือนไปมาเข้าด้วยกัน โดยขึ้นอยู่กับบริบทของเกม
ตัวอย่างเช่น หากผู้เล่นอยู่ในโซนที่มีการต่อสู้กับบอสที่ยิ่งใหญ่ คุณอาจใช้มิกซ์หลายรายการที่สื่ออารมณ์ได้หลากหลายตั้งแต่บรรยากาศ บอกใบ้ ไปจนถึงเข้มข้น ซอฟต์แวร์สังเคราะห์เสียงมักให้คุณส่งออกมิกซ์หลายรายการ (ที่มีความยาวเท่ากัน) โดยอิงตามท่อนเพลงโดยเลือกชุดแทร็กที่จะใช้ในการส่งออก วิธีนี้จะทำให้คุณมีความสม่ำเสมอภายใน และหลีกเลี่ยงไม่ให้มีการเปลี่ยนภาพที่น่าตกใจเมื่อข้ามจากแทร็กหนึ่งไปยังอีกแทร็กหนึ่ง
จากนั้น คุณจะใช้ Web Audio API เพื่อนำเข้าตัวอย่างเพลงทั้งหมดได้โดยใช้สิ่งที่คล้ายกับคลาส BufferLoader ผ่าน XHR (มีรายละเอียดอยู่ในบทความแนะนำ 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;
}
ในวิธีการข้างต้น แหล่งที่มา 2 แหล่งจะเล่นพร้อมกัน และเราจะใช้การเฟดเสียงระหว่างแหล่งที่มาโดยใช้เส้นโค้งกำลังไฟฟ้าที่เท่ากัน (ตามที่อธิบายไว้ในบทนำ)
ลิงก์ที่ขาดหายไป: แท็กเสียงกับ Web Audio
ปัจจุบันนักพัฒนาเกมจำนวนมากใช้แท็ก <audio>
สำหรับเพลงประกอบ เนื่องจากเหมาะกับเนื้อหาสตรีมมิง ตอนนี้คุณนําเนื้อหาจากแท็ก <audio>
ไปไว้ในบริบทเสียงบนเว็บได้แล้ว
เทคนิคนี้มีประโยชน์เนื่องจากแท็ก <audio>
สามารถใช้กับเนื้อหาสตรีมมิงได้ ซึ่งจะช่วยให้คุณเล่นเพลงพื้นหลังได้ทันทีแทนที่จะต้องรอให้ดาวน์โหลดทั้งหมด การนำสตรีมมาไว้ใน Web Audio API จะช่วยให้คุณจัดการหรือวิเคราะห์สตรีมได้ ตัวอย่างต่อไปนี้ใช้ตัวกรอง Low Pass กับเพลงที่เล่นผ่านแท็ก <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);
ดูการพูดคุยที่สมบูรณ์ยิ่งขึ้นเกี่ยวกับการผสานรวมแท็ก <audio>
กับ Web Audio API ได้ที่บทความสั้นๆ นี้
เอฟเฟกต์เสียง
เกมมักจะเล่นซาวด์เอฟเฟกต์เพื่อตอบสนองต่ออินพุตของผู้ใช้หรือการเปลี่ยนแปลงในสถานะของเกม อย่างไรก็ตาม เอฟเฟกต์เสียงอาจทำให้ผู้ชมรู้สึกรำคาญได้อย่างรวดเร็วเช่นเดียวกับเพลงประกอบ วิธีหลีกเลี่ยงปัญหานี้คือการมีกลุ่มเสียงที่คล้ายกันแต่แตกต่างกันไว้เล่น เสียงนี้อาจแตกต่างกันไปตั้งแต่ตัวอย่างเสียงฝีเท้าแบบเล็กน้อยไปจนถึงแบบแตกต่างกันมาก เช่น เสียงที่ได้ยินในซีรีส์ Warcraft เมื่อคลิกยูนิต
ฟีเจอร์สำคัญอีกอย่างหนึ่งของเอฟเฟกต์เสียงในเกมคืออาจมีเอฟเฟกต์เสียงหลายรายการเล่นพร้อมกัน ลองนึกภาพว่าคุณกำลังอยู่ระหว่างการดวลปืนซึ่งมีนักแสดงหลายคนกำลังยิงปืนกล ปืนกลแต่ละปืนจะยิงหลายครั้งต่อวินาที ทำให้มีการเล่นเอฟเฟกต์เสียงหลาย 10 เอฟเฟกต์พร้อมกัน การเล่นเสียงจากแหล่งที่มาหลายแหล่งที่กําหนดเวลาไว้อย่างแม่นยําพร้อมกันเป็นหนึ่งในจุดเด่นของ 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 มีวิธีปรับแต่งตัวอย่างข้างต้นได้ง่ายๆ 2 วิธีดังนี้
- มีการเว้นระยะสั้นๆ ระหว่างที่ยิงของกระสุน
- โดยการเปลี่ยน playbackRate ของตัวอย่างแต่ละรายการ (รวมถึงการเปลี่ยนระดับเสียง) เพื่อจำลองความเป็นแบบสุ่มในชีวิตจริงได้ดียิ่งขึ้น
หากต้องการดูตัวอย่างการใช้งานเทคนิคเหล่านี้ในชีวิตจริง ให้ดูการสาธิตโต๊ะพูล ซึ่งใช้การสุ่มตัวอย่างแบบสุ่มและอัตราการเล่นที่หลากหลายเพื่อให้เสียงลูกบอลกระทบกันน่าสนใจยิ่งขึ้น
เสียงตำแหน่ง 3 มิติ
เกมมักตั้งอยู่ในโลกที่มีสมบัติทางเรขาคณิตบางอย่าง ไม่ว่าจะในแบบ 2 มิติหรือ 3 มิติ ในกรณีดังกล่าว เสียงการวางตำแหน่งสเตอริโอจะเพิ่มความสมจริงของประสบการณ์ได้อย่างมาก แต่โชคดีที่ 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 มีดังนี้
- โดยค่าเริ่มต้น ผู้ฟังจะอยู่ที่จุดเริ่มต้น (0, 0, 0)
- API ตำแหน่งของ Web Audio ไม่มีหน่วย ดังนั้นเราจึงใช้ตัวคูณเพื่อให้เสียงของเดโมดีขึ้น
- Web Audio จะใช้พิกัดแบบรถเข็น y-is-up (ตรงกันข้ามกับระบบกราฟิกของคอมพิวเตอร์ส่วนใหญ่) ผมจึงสลับแกน Y ในตัวอย่างข้างต้น
ขั้นสูง: กรวยเสียง
โมเดลตามตำแหน่งมีประสิทธิภาพสูงและค่อนข้างล้ำสมัย โดยอิงตาม OpenAL เป็นส่วนใหญ่ สำหรับรายละเอียดเพิ่มเติม โปรดดูส่วนที่ 3 และ 4 ของข้อกำหนดที่ลิงก์ด้านบน
มี AudioListener รายการเดียวที่แนบอยู่กับบริบท Web Audio API ซึ่งสามารถกําหนดค่าในพื้นที่ผ่านตําแหน่งและการวางแนว แต่ละแหล่งสามารถส่งผ่าน AudioPannerNode ซึ่งจะเปลี่ยนเสียงอินพุตเป็นเสียงรอบทิศทาง นอตตัวแพนเนอร์มีตําแหน่งและการวางแนว รวมถึงรูปแบบระยะทางและทิศทาง
โมเดลระยะทางจะระบุปริมาณค่าเกนโดยขึ้นอยู่กับระยะใกล้/ไกลจากต้นทาง ในขณะที่โมเดลแบบกำหนดทิศทางกำหนดค่าได้โดยการระบุกรวยด้านในและด้านนอก ซึ่งจะกำหนดปริมาณอัตราขยาย (โดยปกติจะเป็นลบ) หากผู้ฟังอยู่ภายในกรวยด้านใน ระหว่างกรวยด้านในและชั้นนอก หรือนอกกรวยด้านนอก
var panner = context.createPanner();
panner.coneOuterGain = 0.5;
panner.coneOuterAngle = 180;
panner.coneInnerAngle = 0;
แม้ว่าตัวอย่างจะเป็นแบบ 2 มิติ แต่รูปแบบนี้สามารถขยายผลเป็น 3 มิติได้โดยง่าย ดูตัวอย่างเสียงที่วางตำแหน่งใน 3 มิติได้ที่ตัวอย่างตำแหน่งนี้ นอกจากตำแหน่งแล้ว โมเดลเสียงของ Web Audio ยังรวมความเร็วสำหรับการเปลี่ยนแปลง Doppler ด้วย (ไม่บังคับ) ตัวอย่างนี้แสดงเอฟเฟกต์ Doppler โดยละเอียด
อ่านข้อมูลเพิ่มเติมเกี่ยวกับหัวข้อนี้ได้ในบทแนะนำโดยละเอียดเกี่ยวกับ [การผสมเสียงแบบระบุตำแหน่งและ WebGL][webgl]
เอฟเฟกต์และฟิลเตอร์ของห้อง
ในความเป็นจริง วิธีรับรู้เสียงนั้นจะขึ้นอยู่กับห้องที่ได้ยินเสียงนั้นๆ ประตูที่ดังเอี๊ยดแบบเดียวกันจะมีเสียงที่ต่างกันมากเมื่ออยู่ในชั้นใต้ดิน เมื่อเทียบกับโถงขนาดใหญ่ที่เปิดโล่ง เกมที่มีมูลค่าการผลิตสูงจะต้องเลียนแบบเอฟเฟกต์เหล่านี้ เนื่องจากการสร้างชุดตัวอย่างแยกต่างหากสำหรับแต่ละสภาพแวดล้อมมีค่าใช้จ่ายสูงมาก และจะทำให้มีชิ้นงานมากขึ้น รวมถึงข้อมูลเกมจำนวนมากขึ้น
กล่าวอย่างคร่าวๆ ก็คือ การตอบสนองของแรงกระตุ้นเป็นคำศัพท์ด้านเสียงสำหรับความแตกต่างระหว่างเสียงดิบและเสียงจริง การบันทึกการตอบสนองต่อแรงกระตุ้นเหล่านี้อาจทำได้ยาก แต่จริงๆ แล้วมีเว็บไซต์ที่โฮสต์ไฟล์การตอบสนองต่อแรงกระตุ้นที่บันทึกไว้ล่วงหน้าจำนวนมาก (จัดเก็บเป็นเสียง) เพื่อความสะดวกของคุณ
สำหรับข้อมูลเพิ่มเติมเกี่ยวกับวิธีสร้างการตอบสนองด้วยแรงกระตุ้นจากสภาพแวดล้อมหนึ่งๆ โปรดอ่านส่วน "การตั้งค่าการบันทึก" ในส่วน Convolution ของข้อกำหนดของ Web Audio API
ที่สำคัญกว่าสำหรับวัตถุประสงค์ของเราคือ Web Audio API มีวิธีง่ายๆ ในการใช้การตอบสนองต่อแรงกระตุ้นเหล่านี้กับเสียงของเราโดยใช้ ConvolverNode
// 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 รวมถึงตัวอย่างนี้ซึ่งให้คุณควบคุมการผสมเสียงแบบแห้ง (ดิบ) และแบบเปียก (ประมวลผลผ่าน Convolver) ของมาตรฐานเพลงแจ๊สที่ยอดเยี่ยม
การนับถอยหลังครั้งสุดท้าย
คุณได้สร้างเกม กำหนดค่าเสียงตามตำแหน่ง และตอนนี้คุณมี AudioNode จํานวนมากในกราฟที่เล่นพร้อมกันทั้งหมด เยี่ยม แต่ยังมีอีก 1 สิ่งที่ต้องพิจารณา
เนื่องจากเสียงหลายรายการซ้อนทับกันโดยไม่มีการทำให้เป็นมาตรฐาน คุณจึงอาจพบว่าตัวเองอยู่ในสถานการณ์ที่เกินขีดจำกัดความสามารถของลำโพง เช่นเดียวกับรูปภาพที่เกินขอบเขตของผืนผ้าใบ เสียงอาจถูกตัดหากรูปแบบคลื่นเกินเกณฑ์สูงสุด ซึ่งจะทำให้เกิดเสียงที่แตกต่างออกไป รูปแบบคลื่นจะมีลักษณะดังนี้
ต่อไปนี้คือตัวอย่างจริงของการตัด รูปแบบคลื่นดูไม่ดี
คุณควรฟังเสียงที่บิดเบือนอย่างรุนแรง เช่น ตัวอย่างข้างต้น หรือในทางกลับกัน เสียงมิกซ์ที่เบาเกินไปซึ่งบังคับให้ผู้ฟังต้องเพิ่มระดับเสียง หากคุณตกอยู่ในสถานการณ์นี้ คุณจำเป็นต้องแก้ไขจริงๆ!
ตรวจหาการตัด
จากมุมมองทางเทคนิค การตัดจะเกิดขึ้นเมื่อค่าของสัญญาณในช่องใดก็ตามเกินช่วงที่ใช้ได้ ซึ่งก็คือระหว่าง -1 ถึง 1 เมื่อตรวจพบปัญหานี้แล้ว การแสดงผลภาพว่าปัญหานี้เกิดขึ้นจะมีประโยชน์ หากต้องการดำเนินการนี้อย่างน่าเชื่อถือ ให้ใส่ 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
มากเกินไปเพื่อเหตุผลด้านประสิทธิภาพ ในกรณีนี้ การใช้การวัดแบบอื่นอาจสำรวจ RealtimeAnalyserNode
ในกราฟเสียงสำหรับ getByteFrequencyData
ขณะแสดงผลตามที่ requestAnimationFrame
กำหนดไว้ วิธีนี้มีประสิทธิภาพมากกว่า แต่จะไม่จับสัญญาณส่วนใหญ่ (รวมถึงตำแหน่งที่อาจมีการตัดเสียง) เนื่องจากการแสดงผลจะเกิดขึ้นสูงสุด 60 ครั้งต่อวินาที ในขณะที่สัญญาณเสียงจะเปลี่ยนแปลงเร็วกว่ามาก
เนื่องจากการตรวจจับคลิปมีความสำคัญมาก เราจึงอาจเห็นMeterNode
โหนด Web Audio API ในตัวในอนาคต
ป้องกันการตัด
การปรับเกนของ AudioGainNode หลักช่วยให้คุณสามารถลดการมิกซ์ลงให้อยู่ในระดับที่ป้องกันการตัดคลิปได้ อย่างไรก็ตาม ในทางปฏิบัติแล้ว เนื่องจากเสียงที่เล่นในเกมอาจขึ้นอยู่กับหลายปัจจัย จึงอาจเป็นการยากที่จะตัดสินใจเกี่ยวกับค่าเกนหลักที่ป้องกันการตัดของทุกรัฐ โดยทั่วไป คุณควรปรับอัตราขยายสัญญาณเพื่อเตรียมรับมือกับกรณีที่แย่ที่สุด แต่วิธีนี้ต้องใช้ศิลปะมากกว่าวิทยาศาสตร์
ใส่น้ำตาลเล็กน้อย
โดยทั่วไปแล้ว คอมเพรสเซอร์จะใช้ในการผลิตเพลงและเกมเพื่อปรับสัญญาณให้เรียบและควบคุมช่วงที่มีสัญญาณสูงในสัญญาณโดยรวม ฟังก์ชันการทำงานนี้มีอยู่ในโลกของ Web Audio ผ่าน DynamicsCompressorNode
ซึ่งสามารถแทรกลงในกราฟเสียงเพื่อให้เสียงดังขึ้น สมบูรณ์ยิ่งขึ้น และช่วยลดการคลิป
อ้างอิงจากข้อกําหนดเฉพาะโดยตรง โหนดนี้
โดยทั่วไปแล้ว การใช้การบีบอัดไดนามิกจะเป็นความคิดที่ดี โดยเฉพาะในเกม อย่างที่กล่าวไปแล้ว คุณไม่รู้ว่าจะมีเสียงอะไรเล่นและตอนไหน อย่างที่บอกไปแล้ว Plink จาก DinahMoe Labs เป็นตัวอย่างที่ดีในเรื่องนี้ เนื่องจากเสียงที่เล่นจะขึ้นอยู่กับคุณและผู้เข้าร่วมคนอื่นๆ ทั้งหมด คอมเพรสเซอร์มีประโยชน์ในหลายๆ กรณี ยกเว้นบางกรณีที่หายาก ซึ่งคุณจะต้องจัดการกับแทร็กที่ได้รับการมาสเตอร์อย่างพิถีพิถันซึ่งปรับให้เสียง "พอดี" อยู่แล้ว
การใช้งานก็เพียงแค่ใส่ DynamicCompressorNode ในกราฟเสียง โดยปกติจะเป็นโหนดสุดท้ายก่อนปลายทาง
// Assume the output is all going through the mix node.
var compressor = context.createDynamicsCompressor();
mix.connect(compressor);
compressor.connect(context.destination);
ดูรายละเอียดเพิ่มเติมเกี่ยวกับการบีบอัดแบบไดนามิกได้ในบทความนี้ใน Wikipedia
โดยสรุปแล้ว ให้ฟังเสียงอย่างละเอียดเพื่อหาการคลิปและป้องกันโดยการแทรกโหนดการขยายเสียงหลัก จากนั้นทำให้ส่วนผสมทั้งหมดแน่นหนาโดยใช้โหนดไดนามิกคอมเพรสเซอร์ กราฟเสียงอาจมีลักษณะดังนี้
บทสรุป
ทั้งหมดนี้เป็นสิ่งที่เราคิดว่าเป็นประเด็นสำคัญที่สุดในการพัฒนาเสียงของเกมโดยใช้ Web Audio API เทคนิคเหล่านี้จะช่วยให้คุณสร้างประสบการณ์เสียงที่น่าสนใจอย่างแท้จริงได้โดยตรงในเบราว์เซอร์ ก่อนจากกัน เราขอฝากเคล็ดลับเฉพาะเบราว์เซอร์ไว้ให้ อย่าลืมหยุดเสียงชั่วคราวหากแท็บของคุณทำงานอยู่เบื้องหลังโดยใช้ page visibility API ไม่เช่นนั้นผู้ใช้อาจได้รับประสบการณ์การใช้งานที่ไม่น่าพอใจ
ดูข้อมูลเพิ่มเติมเกี่ยวกับเสียงบนเว็บได้ที่บทความเริ่มต้นใช้งานแบบแนะนำเพิ่มเติม และหากมีคำถาม โปรดดูว่าคำถามนั้นได้รับการตอบแล้วในคำถามที่พบบ่อยเกี่ยวกับเสียงบนเว็บหรือไม่ สุดท้าย หากมีข้อสงสัยเพิ่มเติม ให้ถามใน Stack Overflow โดยใช้แท็ก web-audio
ก่อนจากกัน เราขอแชร์การใช้งาน Web Audio API ที่ยอดเยี่ยมในเกมจริงในปัจจุบัน
- Field Runners และบทความเกี่ยวกับรายละเอียดทางเทคนิคบางส่วน
- Angry Birds เพิ่งเปลี่ยนไปใช้ Web Audio API ดูบทความนี้สำหรับข้อมูลเพิ่มเติม
- Skid Racer ซึ่งใช้ประโยชน์จากเสียงรอบทิศทางได้อย่างยอดเยี่ยม