Fix audio backend

This commit is contained in:
Evan Pratten 2020-04-18 15:54:23 -04:00
parent 020973c732
commit 44944626ef
No known key found for this signature in database
GPG Key ID: 93AC7B3D071356D3
5 changed files with 10 additions and 171 deletions

4
docs/assets/js/howler/howler.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -1,164 +0,0 @@
/**
* This file contains classes for playing sounds.
* The SoundContext works by providing multiple audio channels,
* just like an old ATARI, or even GameBoy sound system. Each
* channel can be controlled individually.
*
* ---- Usage ----
*
* // Load all sounds
* preCacheSounds(()=>{
* // Code can be run here as soon as all sounds are loaded
* // ...
* });
*
* // Play a sound using channels
* globalSoundContext.playSound(globalSoundContext.channels.<channel>, sounds.<soundname>);
*
* // Just play a sound now
* globalSoundContext.playSoundNow(sounds.<soundname>);
*
* // Stop a channel
* globalSoundContext.mute(globalSoundContext.channels.<channel>);
*/
/**
* A sound channel can play 1 sound at a time, and supports sound queueing
*/
class _SoundChannel {
/**
* Create a sound channel
* @param {number} max_queue_size Maximum number of sounds that can be queued before sounds are skipped
*/
constructor(max_queue_size) {
this.max_size = max_queue_size
this.sound_queue = []
}
/**
* Add a snippet to the queue
* @param {SoundSnippet} snippet
*/
enqueue(snippet) {
console.log(this.sound_queue)
// If the queue is full, cut out the next sound in the queue to make room
// if (this.sound_queue.length > this.max_size) {
// this.sound_queue.splice(1, 1);
// }
// Append the sound to the queue
this.sound_queue.push(snippet);
// If this is the first sound in the queue, spawn a watcher job, and play it
if (this.sound_queue.length == 1) {
this.sound_queue[0].play();
this._spawnWatcher(this.sound_queue[0]);
}
}
/**
* Start a job to run when the sound finishes to remove the sound from the queue
* @param {SoundSnippet} snippet
*/
_spawnWatcher(snippet) {
// Read the snippet length
let length = snippet.getLengthSeconds();
// Spawn a clean action for that time in the future
setTimeout(() => {
this._cleanQueue(snippet);
}, length * 1000);
}
/**
* This should be run when every sound finishes. This will remove that
* sound from from the queue, start the next sound, and spawn a
* new watcher for that sound.
* @param {SoundSnippet} snippet
*/
_cleanQueue(snippet) {
// Get the snippet hash
let hash = snippet.getHash();
// Make sure there are actually sounds playing
if (this.sound_queue.length > 0) {
// If the first snippet in the queue matches this hash, remove it.
// If not, something must have happened. Just ignore it, and move on
if (this.sound_queue[0].getHash() == hash) {
// Popoff the snippet
this.sound_queue.shift();
}
// Spawn a watcher for the next sound & play it
if (this.sound_queue.length > 0) {
this.sound_queue[0].play();
this._spawnWatcher(this.sound_queue[0]);
}
}
}
/**
* Clear the entire queue, and stop all sounds
*/
clear() {
// Stop every sound
this.sound_queue.forEach((sound) => {
sound.stop();
})
// Clear the queue
this.sound_queue = [];
}
}
class _SoundContext {
constructor() {
// Define all sound channels
this.channels = {
bgm: new _SoundChannel(3)
}
}
/**
* Play a sound in a channel
* @param {*} channel
* @param {SoundSnippet} snippet
*/
playSound(channel, snippet) {
console.log(`[SoundContext] Playing snippet: ${snippet.getName()}`);
channel.enqueue(snippet);
}
/**
* Play a sound right now
* @param {SoundSnippet} snippet
*/
playSoundNow(snippet) {
snippet.play();
}
/**
* Stop all sounds in a channel
* @param {*} channel
*/
mute(channel) {
channel.clear();
}
}
// The global context for sounds
let globalSoundContext = new _SoundContext();

View File

@ -12,7 +12,7 @@
// A mapping of asset names to their files
// This exists to give nicer names to files
let soundAssetMap = {
"debug-ding":"/assets/sounds/debug-ding.mp3"
"debug-ding":"./assets/sounds/debug-ding.mp3"
}
// All available sounds

View File

@ -20,9 +20,6 @@ class SoundSnippet {
// Read actual asset path
this.assetPath = soundAssetMap[asset_name];
// Set up the audio object
this.audio = new Audio();
}
/**
@ -32,10 +29,10 @@ class SoundSnippet {
cache(callback) {
// Set the audio SRC
this.audio.src = this.assetPath;
this.audio = new Howl({src:[this.assetPath]});
// Create a callback for loading finished
this.audio.addEventListener("loadeddata", callback, true);
this.audio.once("load", callback);
}

View File

@ -24,6 +24,9 @@
<!-- Graphics Library -->
<script src="assets/js/game.js"></script>
<!-- Audio Multichannel Library -->
<script src="assets/js/howler/howler.min.js"></script>
<!-- Crypto -->
<script src="assets/js/crypto/core.min.js"></script>
<script src="assets/js/crypto/md5.js"></script>
@ -52,7 +55,6 @@
<!-- Sounds -->
<script src="assets/js/sounds/soundsnippet.js"></script>
<script src="assets/js/sounds/sounds.js"></script>
<script src="assets/js/sounds/soundcontext.js"></script>
<script src="assets/js/sounds/permissionhandler.js"></script>
<!-- Game -->