บทนำ
เสียงเป็นส่วนสําคัญที่ทําให้ประสบการณ์การใช้งานมัลติมีเดียน่าสนใจ หากคุณเคยลองดูภาพยนตร์โดยปิดเสียง คุณอาจสังเกตเห็นสิ่งนี้
เกมก็อยู่ในข้อจำกัดนี้ด้วย ความทรงจำที่ฉันชอบที่สุดเกี่ยวกับวิดีโอเกมคือเพลงและเอฟเฟกต์เสียง หลายเกมที่เล่นเมื่อเกือบ 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 เมื่อคลิกยูนิต
ฟีเจอร์สำคัญอีกอย่างหนึ่งของเอฟเฟกต์เสียงในเกมคืออาจมีเอฟเฟกต์เสียงหลายรายการเล่นพร้อมกัน ลองจินตนาการว่าคุณกำลังอยู่ในฉากการยิงกันโดยมีนักแสดงหลายคนยิงด้วยปืนกล ปืนกลแต่ละกระบอกจะยิงหลายครั้งต่อวินาที ทำให้เอฟเฟกต์เสียงหลายสิบรายการเล่นพร้อมกัน การเล่นเสียงจากแหล่งที่มาหลายแหล่งที่กําหนดเวลาไว้อย่างแม่นยําพร้อมกันเป็นหนึ่งในจุดเด่นของ 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 ไม่มีหน่วย ดังนั้นเราจึงใช้ตัวคูณเพื่อให้เสียงของเดโมดีขึ้น
- เสียงบนเว็บใช้พิกัดคาร์ทีเซียนซึ่ง y ขึ้นด้านบน (ตรงข้ามกับระบบกราฟิกคอมพิวเตอร์ส่วนใหญ่) เราจึงสลับแกน 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]
เอฟเฟกต์และฟิลเตอร์ของห้อง
ในทางปฏิบัติ วิธีที่ผู้คนรับรู้เสียงจะขึ้นอยู่กับห้องที่ได้ยินเสียงนั้นเป็นอย่างมาก ประตูที่ดังเอี๊ยดแบบเดียวกันจะมีเสียงที่ต่างกันมากเมื่ออยู่ในชั้นใต้ดิน เมื่อเทียบกับโถงขนาดใหญ่ที่เปิดโล่ง เกมที่มีมูลค่าการผลิตสูงจะต้องเลียนแบบเอฟเฟกต์เหล่านี้ เนื่องจากการสร้างชุดตัวอย่างแยกต่างหากสำหรับแต่ละสภาพแวดล้อมมีค่าใช้จ่ายสูงมาก และจะทำให้มีชิ้นงานมากขึ้น รวมถึงข้อมูลเกมจำนวนมากขึ้น
กล่าวอย่างคร่าวๆ คำว่าการตอบสนองของแรงกระตุ้นเป็นคำศัพท์ด้านเสียงสำหรับความแตกต่างระหว่างเสียงดิบและเสียงจริง การบันทึกการตอบสนองต่อแรงกระตุ้นเหล่านี้อาจทำได้ยาก แต่จริงๆ แล้วมีเว็บไซต์ที่โฮสต์ไฟล์การตอบสนองต่อแรงกระตุ้นที่บันทึกไว้ล่วงหน้าจำนวนมาก (จัดเก็บเป็นเสียง) เพื่อความสะดวกของคุณ
ดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีสร้างการตอบสนองต่อแรงกระตุ้นจากสภาพแวดล้อมหนึ่งๆ ได้ที่ส่วน "การตั้งค่าการบันทึก" ในส่วนการฟิวชันของข้อมูลจำเพาะ 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 ซึ่งใช้ประโยชน์จากเสียงรอบทิศทางได้อย่างยอดเยี่ยม