phaser/Phaser/Sound.ts

219 lines
No EOL
4.4 KiB
TypeScript

class SoundManager {
constructor(game:Game) {
this._game = game;
if (game.device.webaudio == true)
{
if (!!window['AudioContext'])
{
this._context = new window['AudioContext']();
}
else if (!!window['webkitAudioContext'])
{
this._context = new window['webkitAudioContext']();
}
if (this._context !== null)
{
this._gainNode = this._context.createGainNode();
this._gainNode.connect(this._context.destination);
this._volume = 1;
}
}
}
private _game: Game;
private _context = null;
private _gainNode;
private _volume: number;
public mute() {
this._gainNode.gain.value = 0;
}
public unmute() {
this._gainNode.gain.value = this._volume;
}
public set volume(value: number) {
this._volume = value;
this._gainNode.gain.value = this._volume;
}
public get volume(): number {
return this._volume;
}
public decode(key: string, callback = null, sound?: Sound = null) {
var soundData = this._game.cache.getSound(key);
if (soundData)
{
if (this._game.cache.isSoundDecoded(key) === false)
{
var that = this;
this._context.decodeAudioData(soundData, function (buffer) {
that._game.cache.decodedSound(key, buffer);
if (sound)
{
sound.setDecodedBuffer(buffer);
}
callback();
});
}
}
}
public play(key:string, volume?: number = 1, loop?: bool = false): Sound {
if (this._context === null)
{
return;
}
var soundData = this._game.cache.getSound(key);
if (soundData)
{
// Does the sound need decoding?
if (this._game.cache.isSoundDecoded(key) === true)
{
return new Sound(this._context, this._gainNode, soundData, volume, loop);
}
else
{
var tempSound: Sound = new Sound(this._context, this._gainNode, null, volume, loop);
// this is an async process, so we can return the Sound object anyway, it just won't be playing yet
this.decode(key, () => this.play(key), tempSound);
return tempSound;
}
}
}
}
class Sound {
constructor(context, gainNode, data, volume?: number = 1, loop?: bool = false) {
this._context = context;
this._gainNode = gainNode;
this._buffer = data;
this._volume = volume;
this.loop = loop;
// Local volume control
if (this._context !== null)
{
this._localGainNode = this._context.createGainNode();
this._localGainNode.connect(this._gainNode);
this._localGainNode.gain.value = this._volume;
}
if (this._buffer === null)
{
this.isDecoding = true;
}
else
{
this.play();
}
}
private _context;
private _gainNode;
private _localGainNode;
private _buffer;
private _volume: number;
private _sound;
loop: bool = false;
duration: number;
isPlaying: bool = false;
isDecoding: bool = false;
public setDecodedBuffer(data) {
this._buffer = data;
this.isDecoding = false;
this.play();
}
public play() {
if (this._buffer === null || this.isDecoding === true)
{
return;
}
this._sound = this._context.createBufferSource();
this._sound.buffer = this._buffer;
this._sound.connect(this._localGainNode);
if (this.loop)
{
this._sound.loop = true;
}
this._sound.noteOn(0); // the zero is vitally important, crashes iOS6 without it
this.duration = this._sound.buffer.duration;
this.isPlaying = true;
}
public stop () {
if (this.isPlaying === true)
{
this.isPlaying = false;
this._sound.noteOff(0);
}
}
public mute() {
this._localGainNode.gain.value = 0;
}
public unmute() {
this._localGainNode.gain.value = this._volume;
}
public set volume(value: number) {
this._volume = value;
this._localGainNode.gain.value = this._volume;
}
public get volume(): number {
return this._volume;
}
}