aboutsummaryrefslogtreecommitdiff
path: root/browser/src/elac.js
blob: fddab1a4129d40d442801f646d3a7fc11d266e89 (plain)
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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
class EQMCData extends Object {
    constructor(obj) {
        super();

        for (let key of Object.keys(obj)) {
            this[key] = obj[key];
        }
    }
}

class EQMCAudioStream extends Object {
    constructor(obj) {
        super();

        for (let key of Object.keys(obj)) {
            this[key] = obj[key];
        }
    }
}

class EQMCError extends Error {
    constructor(props) {
        super(props);
        this.name = "EQMCError";
    }
}

window.EQMC = {
    _base64ToArrayBuffer: (base64) => {
        var binary_string = window.atob(base64);
        var len = binary_string.length;
        var bytes = new Uint8Array(len);
        for (var i = 0; i < len; i++) {
            bytes[i] = binary_string.charCodeAt(i);
        }
        return bytes.buffer;
    },

    isEQMCData: async (data) => {
        return data instanceof EQMCData && data["_eqmc"];
    },

    isEQMCAudioStream: async (data) => {
        return data instanceof EQMCAudioStream && data["data"];
    },

    create: async (file) => {
        try {
            return new EQMCData(JSON.parse(new TextDecoder("utf-8").decode(pako.inflate(new Uint8Array((await (await (await window.fetch(file)).blob()).arrayBuffer()))))));
        } catch (e) {
            console.error(e);
            throw new EQMCError("Failed to construct EQMCData object");
        }
    },

    decodeFile: async (data, file) => {
        if (!await EQMC.isEQMCData(data)) throw new EQMCError("Invalid input, expected EQMCData");

        if (data.files.length - 1 >= file) {
            let s = data.files[file];
            s["data"] = new Blob([pako.inflate(EQMC._base64ToArrayBuffer(s.data))]);
            return new EQMCAudioStream(s);
        } else {
            throw new EQMCError("File index is out of range");
        }
    },

    toAudio: async (data) => {
        if (!await EQMC.isEQMCAudioStream(data)) throw new EQMCError("Invalid input, expected EQMCAudioStream");

        return new Audio(window.URL.createObjectURL(data.data));
    },

    quickAudio: async (url, id) => {
        let eqmc = await EQMC.create(url);
        let file = await EQMC.decodeFile(eqmc, id);
        return await EQMC.toAudio(file);
    }
}