import AudioContext from "audio-context" ;
declare global {
interface Window { muses : Object ; }
}
/** Create a virtual mixing-console with audio channels */
export class AudioMixer {
/** The audio-context instance used to process audio. */
ctx : AudioContext ;
/** The audio-context instance used to process audio (same as "ctx" property). */
audioContext : AudioContext ;
/** All channels added to the current AudioMixer instance */
channels : AudioChannel[ ] = [ ] ;
/** The node to control the mixer output volume */
inputNode : GainNode ;
/**
* Create a new AudioMixer instance.
* @param {AudioContext} [audioContext] - A custom audio-context to connect the audio-mixer output signal. By default, muses will add a new AudioContext.
* @returns {AudioMixer}
* @example
Standard JavaScript
* ```javascript
* const mixer = new muses.AudioMixer( ) ;
* ```
* @example TypeScript
* ```typescript
* const mixer : AudioMixer = new AudioMixer( ) ;
* ```
*/
constructor( audioContext? : AudioContext ) {
this.ctx = audioContext || AudioContext( ) ;
this.audioContext = this.ctx ;
this.inputNode = this.ctx.createGain( ) ;
this.inputNode.connect( this.ctx.destination ) ;
}
/**
* Due to the constant change in browser security, it is necessary to wait for the user to perform an action within the web page in order to execute the *AudioContext* correctly.
* If necessary, you can execute this method once the user executes the action in order to allow access to the *AudioContext*.
* Basically, this method verify and executes another funtion inside the *AudioContext* object, **AudioContext.resume()**.
* @see https://goo.gl/7K7WLu - For more details about auto-play policy.
* @returns {string} - AudioContext status.
*/
resumeContext( ) : string {
if( this.audioContext.state !== "suspended" ) {
return this.audioContext.state ;
} this.audioContext.resume( ) ;
return this.audioContext.state ;
}
/**
* Add a new channel in the current AudioMixer.
* @param {String} [id] - (Default) The current channel index.
*/
addChannel( id? : string ) : AudioChannel {
const channel = new AudioChannel( this ) ;
channel.id = id || this.channels.length.toString( ) ;
this.channels.push( channel ) ;
return channel ;
}
/**
* Look for a channel with a specific id.
* @param id - The previous defined id on the addChannel( ) method call.
*/
getChannel( id : string ) : AudioChannel | null {
const i = this.channels.findIndex( ( c ) => c.id === id ) ;
return this.channels[ i ] || null ;
}
/** Modify the volume of the current mixer (from 0 to 1) */
set volume( value : number ) {
this.inputNode.gain.value = value ;
}
/** Get the current volume value of the mixer */
get volume( ) : number {
return this.inputNode.gain.value ;
}
} ;
/**
* Create a new audio-mixer to start adding channels with controllers (gain, panning and basic EQ).
* @param {AudioContext} [context] - A custom audio-context to connect the audio-mixer output signal.
*
* @example Standard JavaScript
* ```javascript
* // Import muses globally with