-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path08_cab_sim.js
153 lines (111 loc) · 4.21 KB
/
08_cab_sim.js
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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
// Minimal JS2EEL version of Cockos' 'Convolution Amp/Cab Modeler' (Effects/guitar/amp-model)
config({ description: 'sd_amp_sim', inChannels: 2, outChannels: 2, extTailSize: 32768 });
let fftSize = -1;
let needsReFft = true;
let convolutionSource = new EelBuffer(1, 131072); // 128 * 1024;
let lastAmpModel = -1;
let importedBuffer = new EelBuffer(1, 131072); // 128 * 1024;
let importedBufferChAmount = 0;
let importedBufferSize;
let chunkSize;
let chunkSize2x;
let bufferPosition;
let lastBlock = new EelBuffer(1, 65536); // 64 * 1024
let currentBlock = new EelBuffer(1, 65536); // 64 * 1024
let inverseFftSize;
const interpolationStepCount = 1.0;
let ampModel;
fileSelector(1, ampModel, 'amp_models', 'none', 'Impulse Response');
onSlider(() => {
if (ampModel !== lastAmpModel) {
lastAmpModel = ampModel;
const fileHandle = file_open(ampModel);
let importedBufferSampleRate = 0;
if (fileHandle > 0) {
file_riff(fileHandle, importedBufferChAmount, importedBufferSampleRate);
if (importedBufferChAmount) {
importedBufferSize = file_avail(fileHandle) / importedBufferChAmount;
needsReFft = true;
// FIXME multi dim buffer?
file_mem(
fileHandle,
importedBuffer.start(),
importedBufferSize * importedBufferChAmount
);
}
file_close(fileHandle);
}
}
});
onBlock(() => {
if (needsReFft) {
if (importedBufferSize > 16384) {
importedBufferSize = 16384;
}
fftSize = 32;
while (importedBufferSize > fftSize * 0.5) {
fftSize += fftSize;
}
chunkSize = fftSize - importedBufferSize - 1;
chunkSize2x = chunkSize * 2;
bufferPosition = 0;
inverseFftSize = 1 / fftSize;
let i = 0;
let i2 = 0;
let interpolationCounter = 0;
while (interpolationCounter < min(fftSize, importedBufferSize)) {
const ipos = i;
const ipart = i - ipos;
convolutionSource[0][i2] =
importedBuffer[0][ipos * importedBufferChAmount] * (1 - ipart) +
importedBuffer[0][(ipos + 1) * importedBufferChAmount - 1] * ipart;
convolutionSource[0][i2 + 1] =
importedBuffer[0][ipos * importedBufferChAmount - 1] * (1 - ipart) +
importedBuffer[0][(ipos + 2) * importedBufferChAmount - 1] * ipart;
i += interpolationStepCount;
i2 += 2;
interpolationCounter++;
}
let zeroPadCounter = 0;
while (zeroPadCounter < fftSize - importedBufferSize) {
convolutionSource[0][i2] = 0;
convolutionSource[0][i2 + 1] = 0;
i2 += 2;
zeroPadCounter++;
}
fft(convolutionSource.start(), fftSize);
i = 0;
let normalizeCounter = 0;
while (normalizeCounter < fftSize * 2) {
convolutionSource[0][i] *= inverseFftSize;
i += 1;
normalizeCounter++;
}
needsReFft = false;
}
});
onSample(() => {
if (importedBufferSize > 0) {
if (bufferPosition >= chunkSize) {
lastBlock.swap(currentBlock);
memset(currentBlock.start() + chunkSize * 2, 0, (fftSize - chunkSize) * 2);
// Perform FFT on currentBlock, convolve, and perform inverse FFT
fft(currentBlock.start(), fftSize);
convolve_c(currentBlock.start(), convolutionSource.start(), fftSize);
ifft(currentBlock.start(), fftSize);
bufferPosition = 0;
}
// Save sample
const bufferPosition2x = bufferPosition * 2;
lastBlock[0][bufferPosition2x] = spl0;
lastBlock[0][bufferPosition2x + 1] = 0;
spl0 = currentBlock[0][bufferPosition2x];
spl1 = currentBlock[0][bufferPosition2x + 1];
// Apply overlap-and-add for block continuity
if (bufferPosition < fftSize - chunkSize) {
spl0 += lastBlock[0][chunkSize2x + bufferPosition2x];
spl1 += lastBlock[0][chunkSize2x + bufferPosition2x + 1];
}
bufferPosition += 1;
}
});