You've already forked torvalds-GuitarPedal
mirror of
https://github.com/torvalds/GuitarPedal.git
synced 2026-08-17 04:59:59 +00:00
Every cookbook constructor in biquad.h places its poles and zeros with -2*cos(w0), so what it needs out of the sine table is an angle. Cos is the worst possible way to ask for one at the bottom of the range. fastsincos() interpolates 256 entries a quarter linearly. Near zero phase the sine is straight and the chord is nearly exact - the error at 30Hz measures 1.4e-08 - while the cosine is at its maximum, where the chord sits furthest under the arc, and the error is 3.8e-06. That would be a rounding error if cos were a number. It is an angle, and d(cos)/dw = -sin(w0) vanishes exactly where the error is worst, so what comes back is off by err/sin(w0): asked built error 20 30.68 Hz +53% 30 37.49 Hz +25% 60 63.58 Hz +6% 100 101.27 Hz +1.3% 4000 4000.06 Hz 0.001% At the Q of about 1 everything currently uses, a band is more than an octave wide and none of that is audible. It is fatal for anything narrow: a Q of 20 at 60Hz is a 3Hz notch and the error is 3.6Hz, so it attenuates 60Hz by 0.7dB instead of 37. Take the half angle instead, whose sine is the well-behaved one, and come back with the double-angle identities. Both fall out of the one table lookup that was happening anyway, so it costs two multiplies and no accuracy anywhere else - 4kHz moves from +0.001% to -0.0004%. single-pole.h already asks for the same half angle for its own reasons. test-biquad.py is the sweep, and it is not a check that 60Hz got better. It asks all nine constructors, every semitone from 20Hz to 20kHz, at six Q values and four gains, where the filter actually ended up - from the response, by the definition of each filter's own characteristic frequency, never by rearranging the coefficients. 13068 filters; 6464 of them were outside the bound before this and none are after. The bound is a model rather than a percentage, because the residual is now float32 itself: at 20Hz, 1-cos(w0) is 3.4e-06, so a single ulp is 1.7% of the whole quantity carrying the angle. Nothing built this way can do better, and that floor falls to 0.05% by 60Hz - a flat tolerance loose enough for 20Hz would sleep through a hundredfold error at 1kHz. The app has drawn the correct curve all along, in float64, so this also closes a disagreement between the graph and the pedal that was 53% wide at the bottom of the EQ's range. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
7 lines
69 B
Plaintext
7 lines
69 B
Plaintext
test-fft
|
|
__pycache__
|
|
test-midi-cin
|
|
bench/bench
|
|
bench/coeff
|
|
bench/gen
|