All files / ts/controller/assets/sources audioSources.ts

100% Statements 35/35
100% Branches 4/4
100% Functions 12/12
100% Lines 33/33

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 661x             1x         7x 7x       4x       2x 2x 2x 1x   1x 1x         1x 1x 1x   1x       1x 1x 1x 2x 2x 2x 2x 2x   2x 2x   1x 1x 1x 1x 1x 1x 9x         10x    
import { IAudioSource, AudioSource } from "./audioSource.js";
 
export interface IAudioSources extends Map<string, IAudioSource> {
    add(...audios: Array<string>): void;
    remove(...audios: Array<string>): void;
    loadAsync(): Promise<void>;
}
export class AudioSources extends Map<string, IAudioSource> implements IAudioSources {
 
    private readonly _audioPaths: Array<string>;
 
    public constructor() {
        super();
        this._audioPaths = new Array<string>();
    }
 
    public add(...audios: Array<string>): void {
        this._audioPaths.push(...audios);
    }
 
    public remove(...audios: Array<string>): void {
        audios.forEach(audio => {
            const index = this._audioPaths.indexOf(audio);
            if (index < 0 || index >= this._audioPaths.length)
                return;
 
            this._audioPaths.splice(index, 1);
            this.delete(audio);
        });
    }
 
    public async loadAsync(): Promise<void> {
        const audioContext = new AudioContext();
        await Promise.all(this._audioPaths.map(async (audioPath): Promise<void> => {
            await this.loadAudioAsync(audioPath, audioContext);
        }));
        await audioContext.resume();
    }
 
    private async loadAudioAsync(audioPath: string, audioContext: AudioContext): Promise<void> {
        let loaded = false;
        const request = new XMLHttpRequest();
        const onRequestLoaded = (): void => {
            request.removeEventListener("error", onRequestLoaded);
            request.removeEventListener("load", onRequestLoaded);
            const createBuffer = (audioBuffer: AudioBuffer): void => {
                const audioSource = new AudioSource(audioBuffer, audioContext);
                this.set(audioPath.split('/').pop()!, audioSource);
            }
            audioContext.decodeAudioData(request.response, createBuffer);
            loaded = true;
        };
        request.responseType = "arraybuffer";
        request.open("GET", audioPath, true);
        request.addEventListener("error", onRequestLoaded);
        request.addEventListener("load", onRequestLoaded);
        request.send();
        while (!loaded) {
            await this.delay(1);
        }
    }
 
    private delay(ms: number): Promise<unknown> {
        return new Promise((resolve): any => setTimeout(resolve, ms));
    }
}