namespace Controllers { export abstract class SoundController extends ControllerBase < Application > { protected _codec : Utils . AudioCodecInfo ; constructor ( parent , codec ) { super ( parent ) ; this . _codec = codec ; $sounds = this ; } protected bufferSounds ( ) { this . bufferSound ( 'stone' ) ; this . bufferSound ( 'pass' ) ; } protected abstract bufferSound ( name ) ; public abstract play ( name ) ; public static initialise ( application ) { if ( ! Utils . isFunction ( Audio ) ) return new NullSoundController ( application , "audio objects not supported" ) ; let audio = new Audio ( ) ; if ( ! audio . canPlayType ) return new NullSoundController ( application , "unable to test audio codecs" ) ; let codec ; for ( let j = 0 ; j < Utils . AudioCodecs . length ; ++ j ) { let support = audio . canPlayType ( Utils . AudioCodecs [ j ] . type ) ; if ( support == 'maybe' ) { codec = Utils . AudioCodecs [ j ] ; } else if ( support == 'probably' ) { codec = Utils . AudioCodecs [ j ] ; break ; } } if ( codec == null ) return new NullSoundController ( application , "no supported audio formats" ) ; let context = WebAudioSoundController . createAudioContext ( ) ; if ( context ) return new WebAudioSoundController ( application , codec , context ) ; else return new ElementSoundController ( application , codec ) ; } protected getSoundURI ( name ) { return "sounds/" + name + this . _codec . extension ; } } class WebAudioSoundController extends SoundController { private _context : AudioContext ; private _soundBank : { [ name ] : AudioBuffer ; } ; constructor ( parent , codec , context ) { super ( parent , codec ) ; Utils . log ( Utils . LogSeverity . Debug , "Sound Controller: Web Audio API (" + codec . name + ")" ) ; this . _context = context ; this . _soundBank = { } ; this . bufferSounds ( ) ; } public static createAudioContext ( ) { if ( ( < any > window ) . AudioContext ) return new AudioContext ( ) ; else if ( ( < any > window ) . webkitAudioContext ) return new webkitAudioContext ( ) ; else return null ; } protected bufferSound ( name ) { this . _soundBank [ name ] = null ; var xhr = new XMLHttpRequest ( ) ; xhr . open ( 'GET' , this . getSoundURI ( name ) , true ) ; xhr . responseType = 'arraybuffer' ; xhr . onload = ( event ) => this . onRequestLoad ( name , xhr , event ) ; xhr . onerror = ( event ) => this . onRequestError ( name , xhr ) ; xhr . send ( ) ; } private onRequestLoad ( name , xhr , event ) { if ( xhr . status == 200 ) this . _context . decodeAudioData ( xhr . response , ( decodedData ) => this . onAudioDecoded ( name , decodedData ) , ( error ) => this . onAudioDecodeError ( name , error ) ) ; else this . onRequestError ( name , xhr ) ; } private onRequestError ( name , xhr ) { delete this . _soundBank [ name ] ; Utils . log ( Utils . LogSeverity . Error , "Sound Controller: failed to GET sound '" + name + "' (" + xhr . statusText + ")" ) ; } private onAudioDecoded ( name , decodedData ) { this . _soundBank [ name ] = decodedData ; } private onAudioDecodeError ( name , error ) { delete this . _soundBank [ name ] ; Utils . log ( Utils . LogSeverity . Error , "Sound Controller: failed to decode sound '" + name + "'" ) ; } public play ( name ) { let buffer = this . _soundBank [ name ] ; if ( buffer === undefined ) Utils . log ( Utils . LogSeverity . Warning , "Sound Controller: '" + name + "' not found in sound bank" ) ; else if ( buffer == null ) Utils . log ( Utils . LogSeverity . Warning , "Sound Controller: '" + name + "' not buffered" ) ; else { let source = this . _context . createBufferSource ( ) ; source . buffer = buffer ; source . connect ( this . _context . destination ) ; source . start ( 0 ) ; } } } class ElementSoundController extends SoundController { private _soundBank : { [ name ] : HTMLAudioElement ; } ; constructor ( parent , codec ) { super ( parent , codec ) ; Utils . log ( Utils . LogSeverity . Debug , "Sound Controller: HTML 5 Audio (" + codec . name + ")" ) ; this . _soundBank = { } ; this . bufferSounds ( ) ; } protected bufferSound ( name ) { this . _soundBank [ name ] = new Audio ( this . getSoundURI ( name ) ) ; } public play ( name ) { if ( name in this . _soundBank ) { this . _soundBank [ name ] . play ( ) ; } else Utils . log ( Utils . LogSeverity . Warning , "Sound Controller: '" + name + "' not found in sound bank" ) ; } } class NullSoundController extends SoundController { constructor ( parent , warning ) { super ( parent , null ) ; Utils . log ( Utils . LogSeverity . Warning , "Sound Controller not initialised: " + warning ) ; } protected bufferSound ( name ) { } ; public play ( name ) { } } } declare var $sounds ;