playcanvas
Version:
PlayCanvas WebGL game engine
102 lines (99 loc) • 2.79 kB
JavaScript
import { EventHandler } from '../../core/event-handler.js';
import { math } from '../../core/math/math.js';
import { Listener } from './listener.js';
const CONTEXT_STATE_RUNNING = 'running';
const USER_INPUT_EVENTS = [
'click',
'touchstart',
'mousedown'
];
class SoundManager extends EventHandler {
constructor(){
super();
this._context = null;
this.AudioContext = typeof AudioContext !== 'undefined' && AudioContext || typeof webkitAudioContext !== 'undefined' && webkitAudioContext;
if (!this.AudioContext) ;
this._unlockHandlerFunc = this._unlockHandler.bind(this);
this._userSuspended = false;
this.listener = new Listener(this);
this._volume = 1;
}
set volume(volume) {
volume = math.clamp(volume, 0, 1);
this._volume = volume;
this.fire('volumechange', volume);
}
get volume() {
return this._volume;
}
get suspended() {
return this._userSuspended;
}
get context() {
if (!this._context && this.AudioContext) {
this._context = new this.AudioContext();
if (this._context.state !== CONTEXT_STATE_RUNNING) {
this._registerUnlockListeners();
}
}
return this._context;
}
suspend() {
if (!this._userSuspended) {
this._userSuspended = true;
if (this._context && this._context.state === CONTEXT_STATE_RUNNING) {
this._suspend();
}
}
}
resume() {
if (this._userSuspended) {
this._userSuspended = false;
if (this._context && this._context.state !== CONTEXT_STATE_RUNNING) {
this._resume();
}
}
}
destroy() {
this.fire('destroy');
if (this._context) {
this._removeUnlockListeners();
this._context?.close();
this._context = null;
}
}
_resume() {
this._context.resume().then(()=>{
const source = this._context.createBufferSource();
source.buffer = this._context.createBuffer(1, 1, this._context.sampleRate);
source.connect(this._context.destination);
source.start(0);
source.onended = (event)=>{
source.disconnect(0);
this.fire('resume');
};
}, (e)=>{}).catch((e)=>{});
}
_suspend() {
this._context.suspend().then(()=>{
this.fire('suspend');
}, (e)=>{}).catch((e)=>{});
}
_unlockHandler() {
this._removeUnlockListeners();
if (!this._userSuspended && this._context.state !== CONTEXT_STATE_RUNNING) {
this._resume();
}
}
_registerUnlockListeners() {
USER_INPUT_EVENTS.forEach((eventName)=>{
window.addEventListener(eventName, this._unlockHandlerFunc, false);
});
}
_removeUnlockListeners() {
USER_INPUT_EVENTS.forEach((eventName)=>{
window.removeEventListener(eventName, this._unlockHandlerFunc, false);
});
}
}
export { SoundManager };