-
Notifications
You must be signed in to change notification settings - Fork 0
/
sample-and-hold-processor.worklet.ts
75 lines (60 loc) · 2.42 KB
/
sample-and-hold-processor.worklet.ts
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
import StoppableAudioWorkletProcessor from "./StoppableAudioWorkletProcessor";
import { Parameters } from "./sample-and-hold-processor.types";
class SampleAndHoldProcessor extends StoppableAudioWorkletProcessor {
nextHoldFrame: number[] = [];
value: number[] = [];
static get parameterDescriptors() {
return [
{
name: Parameters.HoldTime,
defaultValue: 0,
minValue: 0,
maxValue: Number.MAX_SAFE_INTEGER,
automationRate: "k-rate" as AutomationRate,
},
];
}
// Samples input and holds value for given holdTime
process(inputs: Float32Array[][], outputs: Float32Array[][], parameters: Record<Parameters, Float32Array>) {
const input = inputs[0];
const output = outputs[0];
for (let channel = 0; channel < input.length; ++channel) {
const sampleFrames = input[channel].length;
// initial value
if (this.value[channel] == null) {
this.value[channel] = input[channel][0];
}
// To keep things simple, let the hold time be at least the buffer length
const holdTimeInFrames = Math.max(
Math.floor(sampleRate / (1 / parameters[Parameters.HoldTime][0])),
sampleFrames
);
const nextHoldFrame = this.nextHoldFrame[channel] ?? holdTimeInFrames;
// Get new sample in current process run
if (nextHoldFrame < currentFrame + sampleFrames) {
const sampleFramesWithCurrentlyHeldValue = nextHoldFrame - currentFrame;
// Copy held value until next hold frame
for (let i = 0; i < sampleFramesWithCurrentlyHeldValue; i++) {
output[channel][i] = this.value[channel];
}
// Sample new value to hold
this.value[channel] = input[channel][sampleFramesWithCurrentlyHeldValue];
// Save next hold frame
this.nextHoldFrame[channel] = nextHoldFrame + holdTimeInFrames;
// Copy new held value until end of buffer
for (let i = sampleFramesWithCurrentlyHeldValue; i < sampleFrames; i++) {
output[channel][i] = this.value[channel];
}
} else {
for (let i = 0; i < sampleFrames; i++) {
output[channel][i] = this.value[channel];
}
}
}
return this.running;
}
}
registerProcessor("sample-and-hold-processor", SampleAndHoldProcessor);
// Fixes TypeScript error TS1208:
// File cannot be compiled under '--isolatedModules' because it is considered a global script file.
export {};