-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathws-opus-codec.mjs
More file actions
107 lines (96 loc) · 2.96 KB
/
ws-opus-codec.mjs
File metadata and controls
107 lines (96 loc) · 2.96 KB
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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
import {channelCount, bitrate, frameSize, voiceOptimization} from './ws-constants.mjs';
import { QueueManager } from 'queue-manager-async';
import { floatTo16Bit } from './convert.mjs';
import { formatSamples } from './format.mjs';
export const makeOpusCodec = (libopus) =>
class WsOpusCodec extends EventTarget {
constructor() {
super();
const readyPromise = libopus.waitForReady();
this.handlemessage = e => {
const {
mode,
sampleRate,
format,
} = e.data;
switch (mode) {
case 'encode': {
const encoderPromise = (async () => {
await readyPromise;
const enc = new libopus.Encoder(channelCount, sampleRate, bitrate, frameSize, voiceOptimization);
return enc;
})();
const queueManager = new QueueManager();
this.handlemessage = async e => {
await queueManager.waitForTurn(async () => {
const enc = await encoderPromise;
if (e.data) {
const samples = floatTo16Bit(e.data);
enc.input(samples);
let output;
while (output = enc.output()) {
output = output.slice();
this.dispatchMessage({
data: output,
timestamp: 0, // fake
duration: 1, // fake
}, [output.buffer]);
}
} else {
this.dispatchMessage({
data: null,
timestamp: 0, // fake
duration: 1, // fake
});
this.close();
}
});
}
break;
}
case 'decode': {
const decoderPromise = (async () => {
await readyPromise;
const dec = new libopus.Decoder(channelCount, sampleRate);
return dec;
})();
const queueManager = new QueueManager();
this.handlemessage = async e => {
await queueManager.waitForTurn(async () => {
const dec = await decoderPromise;
if (e.data) {
dec.input(e.data);
let output;
while (output = dec.output()) {
const formatted = formatSamples(output, format, 'i16');
this.dispatchMessage(formatted, [formatted.buffer]);
}
} else {
this.dispatchMessage(null);
this.close();
}
});
};
break;
}
}
};
}
postMessage(data, transferList) {
this.handlemessage({
data,
transferList,
});
}
dispatchMessage(data, transferList) {
this.dispatchEvent(new MessageEvent('message', {
data,
transferList,
}));
}
close() {
this.dispatchEvent(new MessageEvent('close', {
data: null,
}));
}
}