benjamin-paine commited on
Commit
ad50952
·
verified ·
1 Parent(s): a7c6486

Upload worklet.js

Browse files
Files changed (1) hide show
  1. worklet.js +86 -0
worklet.js ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /** @module worklet */
2
+
3
+ // Called with `audioWorker.addModule('worklet.js')`
4
+ // Defines the following global variables:
5
+ // - sampleRate
6
+ // - registerProcessor
7
+
8
+ /**
9
+ * The `Processor` class is an AudioWorkletProcessor that resamples the input audio to a target sample rate.
10
+ */
11
+ class Processor extends AudioWorkletProcessor {
12
+ /**
13
+ * @param {object} options - The options object.
14
+ * @param {object} options.processorOptions - The processor options object.
15
+ * @param {number} options.processorOptions.targetSampleRate - The target sample rate.
16
+ */
17
+ constructor(options) {
18
+ super(options);
19
+ this.targetSampleRate = options.processorOptions.targetSampleRate;
20
+ this.inputBuffer = new Float32Array(this.inputFrameSize);
21
+ this.inputBufferSize = 0;
22
+ this.outputBuffer = new Float32Array(this.targetFrameSize);
23
+ }
24
+
25
+ /**
26
+ * The size of the input frame.
27
+ * @type {number}
28
+ */
29
+ get inputFrameSize() {
30
+ return Math.round(sampleRate / 50);
31
+ }
32
+
33
+ /**
34
+ * The size of the target frame.
35
+ * @type {number}
36
+ */
37
+ get targetFrameSize() {
38
+ return Math.round(this.targetSampleRate / 50);
39
+ }
40
+
41
+ /**
42
+ * Flushes the input buffer to the output buffer, resampling the audio.
43
+ * Then sends the output buffer to the main thread using the port.
44
+ */
45
+ async flush() {
46
+ const ratio = sampleRate / this.targetSampleRate;
47
+ this.outputBuffer.fill(0);
48
+ for (let i = 0; i < this.targetFrameSize; i++) {
49
+ const index = i * ratio;
50
+ const left = Math.floor(index);
51
+ const right = Math.min(left + 1, this.targetFrameSize - 1);
52
+ const weight = index - left;
53
+ this.outputBuffer[i] = this.inputBuffer[left] * (1 - weight) + this.inputBuffer[right] * weight;
54
+ }
55
+ await this.port.postMessage(this.outputBuffer);
56
+ }
57
+
58
+ /**
59
+ * Pushes audio to the input buffer.
60
+ * @param {Float32Array} inputArray - The input audio.
61
+ */
62
+ pushAudio(inputArray) {
63
+ const inputLength = inputArray.length;
64
+ const remainingLength = this.inputFrameSize - this.inputBufferSize;
65
+ if (inputLength < remainingLength) {
66
+ this.inputBuffer.set(inputArray, this.inputBufferSize);
67
+ this.inputBufferSize += inputLength;
68
+ return;
69
+ }
70
+ this.inputBuffer.set(inputArray.subarray(0, remainingLength), this.inputBufferSize);
71
+ this.flush();
72
+ this.inputBufferSize = 0;
73
+ this.pushAudio(inputArray.subarray(remainingLength));
74
+ }
75
+
76
+ /**
77
+ * Processes the input audio (the main worklet loop).
78
+ */
79
+ process(inputArray, outputArray, parameters) {
80
+ this.pushAudio(inputArray[0][0]);
81
+ return true;
82
+ }
83
+ }
84
+
85
+ // Registers the processor with the name "hey-buddy".
86
+ registerProcessor("hey-buddy", Processor);