function BaseSound( context ) {
    /**
     * Web Audio API's AudioContext. If the context passed to the constructor is an AudioContext, a new one is created here.
     *
     * @property audioContext
     * @type AudioContext
     */
    if ( context === undefined || context === null ) {
        log.debug( 'Making a new AudioContext' );
        this.audioContext = new SafeAudioContext();
    } else {
        this.audioContext = context;
    }

    bootAudioContext( this.audioContext );

    /**
     * Number of inputs
     *
     * @property numberOfInputs
     * @type Number
     * @default 0
     */
    this.numberOfInputs = 0;

    /**
     * Number of outputs
     *
     * @property numberOfOutputs
     * @type Number
     * @default 0
     */
    Object.defineProperty( this, 'numberOfOutputs', {
        enumerable: true,
        configurable: false,
        get: function () {
            return this.releaseGainNode.numberOfOutputs;
        }
    } );

    /**
     *Maximum number of sources that can be given to this Sound
     *
     * @property maxSources
     * @type Number
     * @default 0
     */
    var maxSources_ = 0;
    Object.defineProperty( this, 'maxSources', {
        enumerable: true,
        configurable: false,
        set: function ( max ) {
            if ( max < 0 ) {
                max = 0;
            }
            maxSources_ = Math.round( max );
        },
        get: function () {
            return maxSources_;
        }
    } );

    /**
     *Minimum number of sources that can be given to this Sound
     *
     * @property minSources
     * @type Number
     * @default 0
     */
    var minSources_ = 0;
    Object.defineProperty( this, 'minSources', {
        enumerable: true,
        configurable: false,
        set: function ( max ) {
            if ( max < 0 ) {
                max = 0;
            }
            minSources_ = Math.round( max );
        },
        get: function () {
            return minSources_;
        }
    } );

    /**
     * Release Gain Node
     *
     * @property releaseGainNode
     * @type GainNode
     * @default Internal GainNode
     * @final
     */
    this.releaseGainNode = this.audioContext.createGain();
    this.releaseGainNode.gain.prevEndTime = 0;

    /**
     *  If Sound is currently playing.
     *
     * @property isPlaying
     * @type Boolean
     * @default false
     */
    this.isPlaying = false;

    /**
     *  If Sound is currently initialized.
     *
     * @property isInitialized
     * @type Boolean
     * @default false
     */
    this.isInitialized = false;

    /**
     * The input node that the output node will be connected to. <br />
     * Set this value to null if no connection can be made on the input node
     *
     * @property inputNode
     * @type Object
     * @default null
     **/
    this.inputNode = null;

    /**
     * Set of nodes the output of this sound is currently connected to.
     *
     * @property destinations
     * @type Array
     * @default
     **/
    this.destinations = [];

    /**
     * String name of the model.
     *
     * @property modelName
     * @type String
     * @default "Model"
     **/
    this.modelName = 'Model';

    /**
     * Callback for handling progress events thrown during loading of audio files.
     *
     * @property onLoadProgress
     * @type Function
     * @default null
     */
    this.onLoadProgress = null;

    /**
     * Callback for when loading of audio files is done and the the model is initalized.
     *
     * @property onLoadComplete
     * @type Function
     * @default null
     */
    this.onLoadComplete = null;

    /**
     * Callback for when the audio is about to start playing.
     *
     * @property onAudioStart
     * @type Function
     * @default null
     */
    this.onAudioStart = null;

    /**
     * Callback for the audio is about to stop playing.
     *
     * @property onAudioEnd
     * @type Function
     * @default null
     */
    this.onAudioEnd = null;

    this.isBaseSound = true;

    this.dispatches_ = [];

    this.parameterList_ = [];

    this.connect( this.audioContext.destination );

    function bootAudioContext( context ) {

        var iOS = /(iPad|iPhone|iPod)/g.test( navigator.userAgent );
        var isSafari = /Safari/.test( navigator.userAgent ) && /Apple Computer/.test( navigator.vendor );
        var desiredSampleRate = typeof desiredSampleRate === 'number' ? desiredSampleRate : 44100;

        if ( isSafari ) {
            if ( context.state && context.state === 'suspended' ) {
                context.resume();
            }
        }

        function createDummyBuffer() {
            // actually this does nothing. support for older devices support iOS 8 and below
            var buffer = context.createBuffer( 1, 1, desiredSampleRate );
            var dummy = context.createBufferSource();
            dummy.buffer = buffer;
            dummy.connect( context.destination );
            dummy.start( 0 );
            dummy.disconnect();
            if ( context.state && context.state === 'suspended' ) {
                context.resume();
            }
            log.debug( 'currentTime & state ', context.currentTime, context.state );
            setTimeout( function () {
                if ( context.state && context.state === 'running' ) {
                    log.debug( 'context state', context.state );
                    document.body.removeEventListener( 'touchend', createDummyBuffer );
                }
            }, 0 );

        }
        if ( iOS || isSafari ) {
            if ( !window.liveAudioContexts ) {
                window.liveAudioContexts = [];
            }
            if ( window.liveAudioContexts.indexOf( context ) < 0 ) {
                log.debug( 'audio context created' );
                document.body.addEventListener( 'touchend', createDummyBuffer );
                window.liveAudioContexts.push( context );
            }
        }
    }
}
/**
 * Pseudo AudioNode class the encapsulates basic functionality of an Audio Node. To be extended by all other Sound Models
 *
 * @class BaseSound
 * @constructor
 * @requires AudioContextMonkeyPatch
 * @param {AudioContext} [context] AudioContext in which this Sound is defined.
 */
Pseudo AudioNode class the encapsulates basic functionality of an Audio Node. To be extended by all other Sound Models
@class BaseSound
@constructor
@requires AudioContextMonkeyPatch
@param {AudioContext} [context] AudioContext in which this Sound is defined.
Pseudo AudioNode class the encapsulates basic functionality of an Audio Node . To be extended by all other Sound Models @class BaseSound @constructor @requires AudioContextMonkeyPatch @param { AudioContext } [ context ] AudioContext in which this Sound is defined .
function BaseSound( context ) {
    if ( context === undefined || context === null ) {
        log.debug( 'Making a new AudioContext' );
        this.audioContext = new SafeAudioContext();
    } else {
        this.audioContext = context;
    }
    bootAudioContext( this.audioContext );
    this.numberOfInputs = 0;
    Object.defineProperty( this, 'numberOfOutputs', {
        enumerable: true,
        configurable: false,
        get: function () {
            return this.releaseGainNode.numberOfOutputs;
        }
    } );
    var maxSources_ = 0;
    Object.defineProperty( this, 'maxSources', {
        enumerable: true,
        configurable: false,
        set: function ( max ) {
            if ( max < 0 ) {
                max = 0;
            }
            maxSources_ = Math.round( max );
        },
        get: function () {
            return maxSources_;
        }
    } );
    var minSources_ = 0;
    Object.defineProperty( this, 'minSources', {
        enumerable: true,
        configurable: false,
        set: function ( max ) {
            if ( max < 0 ) {
                max = 0;
            }
            minSources_ = Math.round( max );
        },
        get: function () {
            return minSources_;
        }
    } );
    this.releaseGainNode = this.audioContext.createGain();
    this.releaseGainNode.gain.prevEndTime = 0;
    this.isPlaying = false;
    this.isInitialized = false;
    this.inputNode = null;
    this.destinations = [];
    this.modelName = 'Model';
    this.onLoadProgress = null;
    this.onLoadComplete = null;
    this.onAudioStart = null;
    this.onAudioEnd = null;
    this.isBaseSound = true;
    this.dispatches_ = [];
    this.parameterList_ = [];
    this.connect( this.audioContext.destination );
    function bootAudioContext( context ) {
        var iOS = /(iPad|iPhone|iPod)/g.test( navigator.userAgent );
        var isSafari = /Safari/.test( navigator.userAgent ) && /Apple Computer/.test( navigator.vendor );
        var desiredSampleRate = typeof desiredSampleRate === 'number' ? desiredSampleRate : 44100;
        if ( isSafari ) {
            if ( context.state && context.state === 'suspended' ) {
                context.resume();
            }
        }
        function createDummyBuffer() {
            var buffer = context.createBuffer( 1, 1, desiredSampleRate );
            var dummy = context.createBufferSource();
            dummy.buffer = buffer;
            dummy.connect( context.destination );
            dummy.start( 0 );
            dummy.disconnect();
            if ( context.state && context.state === 'suspended' ) {
                context.resume();
            }
            log.debug( 'currentTime & state ', context.currentTime, context.state );
            setTimeout( function () {
                if ( context.state && context.state === 'running' ) {
                    log.debug( 'context state', context.state );
                    document.body.removeEventListener( 'touchend', createDummyBuffer );
                }
            }, 0 );
        }
        if ( iOS || isSafari ) {
            if ( !window.liveAudioContexts ) {
                window.liveAudioContexts = [];
            }
            if ( window.liveAudioContexts.indexOf( context ) < 0 ) {
                log.debug( 'audio context created' );
                document.body.addEventListener( 'touchend', createDummyBuffer );
                window.liveAudioContexts.push( context );
            }
        }
    }
}
function BaseSound ( context ) { if ( context === undefined || context === null ) { log . debug ( 'Making a new AudioContext' ) ; this . audioContext = new SafeAudioContext ( ) ; } else { this . audioContext = context ; } bootAudioContext ( this . audioContext ) ; this . numberOfInputs = 0 ; Object . defineProperty ( this , 'numberOfOutputs' , { enumerable : true , configurable : false , get : function ( ) { return this . releaseGainNode . numberOfOutputs ; } } ) ; var maxSources_ = 0 ; Object . defineProperty ( this , 'maxSources' , { enumerable : true , configurable : false , set : function ( max ) { if ( max < 0 ) { max = 0 ; } maxSources_ = Math . round ( max ) ; } , get : function ( ) { return maxSources_ ; } } ) ; var minSources_ = 0 ; Object . defineProperty ( this , 'minSources' , { enumerable : true , configurable : false , set : function ( max ) { if ( max < 0 ) { max = 0 ; } minSources_ = Math . round ( max ) ; } , get : function ( ) { return minSources_ ; } } ) ; this . releaseGainNode = this . audioContext . createGain ( ) ; this . releaseGainNode . gain . prevEndTime = 0 ; this . isPlaying = false ; this . isInitialized = false ; this . inputNode = null ; this . destinations = [ ] ; this . modelName = 'Model' ; this . onLoadProgress = null ; this . onLoadComplete = null ; this . onAudioStart = null ; this . onAudioEnd = null ; this . isBaseSound = true ; this . dispatches_ = [ ] ; this . parameterList_ = [ ] ; this . connect ( this . audioContext . destination ) ; function bootAudioContext ( context ) { var iOS = / (iPad|iPhone|iPod) / g . test ( navigator . userAgent ) ; var isSafari = / Safari / . test ( navigator . userAgent ) && / Apple Computer / . test ( navigator . vendor ) ; var desiredSampleRate = typeof desiredSampleRate === 'number' ? desiredSampleRate : 44100 ; if ( isSafari ) { if ( context . state && context . state === 'suspended' ) { context . resume ( ) ; } } function createDummyBuffer ( ) { var buffer = context . createBuffer ( 1 , 1 , desiredSampleRate ) ; var dummy = context . createBufferSource ( ) ; dummy . buffer = buffer ; dummy . connect ( context . destination ) ; dummy . start ( 0 ) ; dummy . disconnect ( ) ; if ( context . state && context . state === 'suspended' ) { context . resume ( ) ; } log . debug ( 'currentTime & state ' , context . currentTime , context . state ) ; setTimeout ( function ( ) { if ( context . state && context . state === 'running' ) { log . debug ( 'context state' , context . state ) ; document . body . removeEventListener ( 'touchend' , createDummyBuffer ) ; } } , 0 ) ; } if ( iOS || isSafari ) { if ( ! window . liveAudioContexts ) { window . liveAudioContexts = [ ] ; } if ( window . liveAudioContexts . indexOf ( context ) < 0 ) { log . debug ( 'audio context created' ) ; document . body . addEventListener ( 'touchend' , createDummyBuffer ) ; window . liveAudioContexts . push ( context ) ; } } } }
Pseudo AudioNode class the encapsulates basic functionality of an Audio Node.
Pseudo AudioNode class the encapsulates basic functionality of an Audio Node .
/**
     * Web Audio API's AudioContext. If the context passed to the constructor is an AudioContext, a new one is created here.
     *
     * @property audioContext
     * @type AudioContext
     */ /**
     * Number of inputs
     *
     * @property numberOfInputs
     * @type Number
     * @default 0
     */ /**
     * Number of outputs
     *
     * @property numberOfOutputs
     * @type Number
     * @default 0
     */ /**
     *Maximum number of sources that can be given to this Sound
     *
     * @property maxSources
     * @type Number
     * @default 0
     */ /**
     *Minimum number of sources that can be given to this Sound
     *
     * @property minSources
     * @type Number
     * @default 0
     */ /**
     * Release Gain Node
     *
     * @property releaseGainNode
     * @type GainNode
     * @default Internal GainNode
     * @final
     */ /**
     *  If Sound is currently playing.
     *
     * @property isPlaying
     * @type Boolean
     * @default false
     */ /**
     *  If Sound is currently initialized.
     *
     * @property isInitialized
     * @type Boolean
     * @default false
     */ /**
     * The input node that the output node will be connected to. <br />
     * Set this value to null if no connection can be made on the input node
     *
     * @property inputNode
     * @type Object
     * @default null
     **/ /**
     * Set of nodes the output of this sound is currently connected to.
     *
     * @property destinations
     * @type Array
     * @default
     **/ /**
     * String name of the model.
     *
     * @property modelName
     * @type String
     * @default "Model"
     **/ /**
     * Callback for handling progress events thrown during loading of audio files.
     *
     * @property onLoadProgress
     * @type Function
     * @default null
     */ /**
     * Callback for when loading of audio files is done and the the model is initalized.
     *
     * @property onLoadComplete
     * @type Function
     * @default null
     */ /**
     * Callback for when the audio is about to start playing.
     *
     * @property onAudioStart
     * @type Function
     * @default null
     */ /**
     * Callback for the audio is about to stop playing.
     *
     * @property onAudioEnd
     * @type Function
     * @default null
     */ // actually this does nothing. support for older devices support iOS 8 and below