Home Identifier Source

src/audiomanager.js



function isIdInTrack(id, track){
    for (let i = 0; i < track.length; i++) {
        if (track[i].id === id){
            return true;
        }
    }
    return false;
}

function getTrackIndexsForId(id, tracks){
    let trackIndexs = [];
    for (let i = 0; i < tracks.length; i++) {
        let track = tracks[i];
        if (isIdInTrack(id, track)){
            trackIndexs.push(i);
        }
    }
    return trackIndexs;
}


class AudioManager {
    constructor(audioCtx){
        this.audioCtx = audioCtx;
        this.tracks = [];
        this.audioNodes = new Map();
        this.audioOutputNodes = [];
    }
        
    createAudioNodeFromTrack(track){
        if (this.audioCtx === undefined){
            // There can only be a max of 6 AudioContexts in most browsers, so only instantiate it here rather than in 
            // constructor as it's genuinley needed. Otherwise having >6 VideoCompositor instances running will break 
            // the browser.
            this.audioCtx = new AudioContext();
        }
        this.tracks.push(track);
        let trackBus = this.audioCtx.createGain();
        this.audioOutputNodes.push(trackBus);
        return trackBus;
    }

    getAudioContext(){
        if (this.audioCtx === undefined){
            // There can only be a max of 6 AudioContexts in most browsers, so only instantiate it here rather than in 
            // constructor as it's genuinley needed. Otherwise having >6 VideoCompositor instances running will break 
            // the browser.
            this.audioCtx = new AudioContext();
        }
        return this.audioCtx;
    }

    removeFromCacheById(id){
        let node = this.audioNodes.get(id);
        node.disconnect();
        this.audioNodes.delete(id);
    }

    clearAudioNodeCache(){
        for (let id of this.audioNodes.keys()){
            this.removeFromCacheById(id);
        }
    }

    update(mediaSources, currentlyPlaying){
        let currentlyPlayingIds = [];
        for (let i = 0; i < currentlyPlaying.length; i++) {
            let mediaSourceRef = currentlyPlaying[i];
            currentlyPlayingIds.push(mediaSourceRef.id);
        }

        if (mediaSources === undefined) return;
        for (let id of mediaSources.keys()) {
            let mediaSource = mediaSources.get(id);
            let trackIndexs = getTrackIndexsForId(id, this.tracks);
            if (trackIndexs.length ===0){
                continue; //No mappings for this id
            }    
            if (!this.audioNodes.has(id)){
                //if an AudioNode for this id does not exist, create it.
                let audioNode;
                try{
                    audioNode = this.audioCtx.createMediaElementSource(mediaSource.element);
                } catch (err) {
                    continue;
                }

                this.audioNodes.set(id, audioNode);
                //make the connections from the audio node to the appropriate output tracks
                for (let i = 0; i < trackIndexs.length; i++) {
                    let trackIndex = trackIndexs[i];
                    audioNode.connect(this.audioOutputNodes[trackIndex]);
                }
            }else {
            }
        }
        //TODO add test to make sure all id's for audio nodes stored in this.audioNodes exist in the current mediaSources, otherwise delete them.
    }
}
export default AudioManager;