-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgoertzel-processor.js
62 lines (61 loc) · 1.78 KB
/
goertzel-processor.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
class GoertzelProcessor extends AudioWorkletProcessor {
constructor (options) {
super();
this.filters = [];
this.frequencies = options.processorOptions.frequencies || [697, 770, 852, 941, 1209, 1336, 1477, 1633]; // DTMF
this.frequencies.forEach(frequency => {
this.filters.push(new GoertzelFilter(frequency, options.processorOptions.blockSize));
}, this);
}
process (inputs, outputs, parameters) {
const input = inputs[0]
const channel = input[0];
let data = this.gather(channel);
if(data)
this.port.postMessage(data);
return true;
}
gather(channel) {
let done = false;
this.filters.forEach(filter => done |= filter.process(channel));
if(!done)
return;
const data = {}
for(let i=0; i<this.filters.length; i++) {
data[this.frequencies[i]] = this.filters[i].magnitude;
}
data.time = this.time;
this.time = new Date().getTime();
if(!data.time)
data.time = this.time;
return data;
}
}
registerProcessor('goertzel-processor', GoertzelProcessor)
class GoertzelFilter {
constructor(targetFrequency, blockSize) {
this.k = 2 * Math.cos(2 * Math.PI * targetFrequency / sampleRate);
this.n = blockSize || 512; // minimum block size with good result
this.q0 = 0;
this.q1 = 0;
this.q2 = 0;
this.j = 0;
}
process(channel) {
let done = false;
for (let i = 0; i < channel.length; i++) {
this.q0 = this.k * this.q1 - this.q2 + channel[i];
this.q2 = this.q1;
this.q1 = this.q0;
if(++this.j >= this.n) {
this.magnitude = (this.q1*this.q1 + this.q2*this.q2 - this.q1*this.q2*this.k) / (this.n*this.n);
this.q0 = 0;
this.q1 = 0;
this.q2 = 0;
this.j = 0;
done = true;
}
}
return done;
}
}