-
Notifications
You must be signed in to change notification settings - Fork 4
/
filter.go
63 lines (51 loc) · 1.29 KB
/
filter.go
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
package snd
import "math"
// LowPass is a 3rd order IIR filter.
//
// Recursive implementation of the Gaussian filter.
type LowPass struct {
*mono
// normalization factor
b float64
// coefficients
b0, b1, b2, b3 float64
// delays
d1, d2, d3 float64
// TODO eek, temporary
passthrough bool
}
func (lp *LowPass) SetPassthrough(b bool) { lp.passthrough = b }
func (lp *LowPass) Passthrough() bool { return lp.passthrough }
func NewLowPass(freq float64, in Sound) *LowPass {
q := 5.0
s := in.SampleRate() / freq / q
if s > 2.5 {
q = 0.98711*s - 0.96330
} else {
q = 3.97156 - 4.14554*math.Sqrt(1-0.26891*s)
}
q2 := q * q
q3 := q * q * q
// redefined from paper to (1 / b0) to save an op div during prepare.
b0 := 1 / (1.57825 + 2.44413*q + 1.4281*q2 + 0.422205*q3)
b1 := 2.44413*q + 2.85619*q2 + 1.26661*q3
b2 := -(1.4281*q2 + 1.26661*q3)
b3 := 0.422205 * q3
b := 1 - ((b1 + b2 + b3) * b0)
b1 *= b0
b2 *= b0
b3 *= b0
return &LowPass{mono: newmono(in), b: b, b0: b0, b1: b1, b2: b2, b3: b3}
}
func (lp *LowPass) Prepare(uint64) {
for i, x := range lp.in.Samples() {
if lp.off {
lp.out[i] = 0
} else if lp.passthrough {
lp.out[i] = x
} else {
lp.out[i] = lp.b*x + lp.b1*lp.d1 + lp.b2*lp.d2 + lp.b3*lp.d3
}
lp.d3, lp.d2, lp.d1 = lp.d2, lp.d1, lp.out[i]
}
}