-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdeconvolution.ts
99 lines (73 loc) · 2.58 KB
/
deconvolution.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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
import { Sweep, SweepSettings } from "./sweep";
import { normalizeBuffer } from "./utilities";
export async function deconvolve(
file: File | undefined | null,
setProgress?: (progress: number | null) => void,
settings?: SweepSettings,
) {
if (!file) return;
if (!settings) return;
console.log(file);
console.log(settings);
const startTime = Date.now();
// temporary one just to retrieve num channels and num samples
let context = new OfflineAudioContext({
numberOfChannels: 1,
length: 128,
sampleRate: settings.sampleRate,
});
setProgress?.(0);
let buffer = await context.decodeAudioData(await file.arrayBuffer());
const sweep = new Sweep(settings);
const inverseSweep = new AudioBuffer({
numberOfChannels: 1,
length: sweep.inverseSweep.length,
sampleRate: settings.sampleRate,
});
inverseSweep.copyToChannel(sweep.inverseSweep, 0);
const sweepLength = inverseSweep.length;
let numSamples = buffer.length + sweepLength - 1;
let numChannels = buffer.numberOfChannels;
context = new OfflineAudioContext({
numberOfChannels: numChannels,
length: numSamples,
sampleRate: settings.sampleRate,
});
let source = context.createBufferSource();
source.buffer = buffer;
source.start();
// split into channels
let split = context.createChannelSplitter(numChannels);
let merge = context.createChannelMerger(numChannels);
source.connect(split);
for (let i = 0; i < numChannels; ++i) {
let convolver = context.createConvolver();
convolver.normalize = false;
convolver.buffer = inverseSweep;
split.connect(convolver, i);
convolver.connect(merge, 0, i);
}
merge.connect(context.destination);
const promise = context.startRendering();
let timer: NodeJS.Timeout | undefined;
if (setProgress) {
timer = setInterval(() => {
const progress = ((context.currentTime * context.sampleRate) / numSamples) * 100;
setProgress(progress);
}, 100);
}
let resultBuffer = await promise;
clearInterval(timer);
let cut = new AudioBuffer({
numberOfChannels: numChannels,
length: numSamples - sweepLength,
sampleRate: settings.sampleRate,
});
for (let i = 0; i < numChannels; ++i) {
resultBuffer.copyFromChannel(cut.getChannelData(i), i, sweepLength);
}
normalizeBuffer(cut);
setProgress?.(null);
console.log(`Finished deconvolution - took ${Date.now() - startTime} ms`);
return cut;
}