diff --git a/tracker/spectrum.go b/tracker/spectrum.go index d7f67e1..5114f7c 100644 --- a/tracker/spectrum.go +++ b/tracker/spectrum.go @@ -77,22 +77,27 @@ func (m *Model) BiquadCoeffs() (coeffs BiquadCoeffs, ok bool) { // in state-space, the filter has the form: // s(n+1) = A*s(n)+B*u, where A = [1 f;-f 1-f*r-f*f] and B = [0;f] // y(n) = C*s(n)+D*u, where - // C = [low band] - // + // C_low = [1 0]*z, C_band = [0 1]*z, C_high = [-1 -f-r], D_high = [1] // The transfer function is then H(z) = C*(zI-A)^-1*B + D // z*I-A = [z-1 -f; f z+f*r+f*f-1] // Invert it: - // (z*I-A)^-1 = 1/det * [z+f*r+f*f-1 f; -f z-1], where det = (z-1)*(z+f*r+f*f-1)+f^2 = z^2 + z * (f*r+f*f−2) + 1-f*r - // (z*I-A)^-1*B = 1/det * [-f*f; f*z-f] + // (z*I-A)^-1 = 1/det * [z+f*r+f*f-1 f; -f z-1], where det = (z-1)*(z+f*r+f*f-1)+f^2 = z*z+z*f*r+z*f*f-z-z-f*r-f*f+1+f^2 = z*z + z*(f*r+f*f-2)-f*r+1 + // (z*I-A)^-1*B = 1/det * f * [f; z-1] + // Low: z * [1,0] * f * [f;z-1] / det = f*f*z / det + // Band: z * [0,1] * f * [f;z-1] / det = (f*z^2-f*z) / det + // High: [-1,-f-r] * f * [f;z-1] / det + 1 = ((-f*f-r*f)*z+r*f)/det + 1 = ((-f*f-r*f)*z+r*f+det)/det = (z^2-2*z+1)/det var a0 float32 = 1 var a1 float32 = r*f + f*f - 2 - var a2 float32 = 1 - r*f + var a2 float32 = 1 - f*r var b0, b1, b2 float32 if p["lowpass"] == 1 { - b2 = -f * f + b1 = f * f } - b2 -= f * float32(p["bandpass"]) - b1 += f * float32(p["bandpass"]) + b0 += f * float32(p["bandpass"]) + b1 -= f * float32(p["bandpass"]) + b0 += float32(p["highpass"]) + b1 += -2 * float32(p["highpass"]) + b2 += float32(p["highpass"]) return BiquadCoeffs{a0: a0, a1: a1, a2: a2, b0: b0, b1: b1, b2: b2}, true case "belleq": f := float32(m.d.Song.Patch[i].Units[u].Parameters["frequency"]) / 128