You've already forked torvalds-GuitarPedal
mirror of
https://github.com/torvalds/GuitarPedal.git
synced 2026-08-14 04:43:53 +00:00
'Software' was the directory everything that was not KiCad ended up in, which stopped describing anything a while ago - Validation and the web app are software too. Worse, it put the shared parts inside the firmware, where they read as the firmware's own. They are not. Effects/ has three consumers built from it: the firmware, Validation's bench, and the web app's controls, all generated from the same POT: comments by gen_effects.py. Audio/ has two - the bench compiles the same biquads, the same envelope followers and the same single_sample(), which is the whole reason a measurement on a workstation says anything about the pedal. Neither belongs under Firmware/, so neither is under it any more: Effects/ one file per effect Audio/ the DSP they are built from, and the audio loop Firmware/ the rest of what runs on the pedal, and the submodules WebMIDI/ the web app scripts/ what the build runs Validation/ unchanged Hardware/, Documentation/, Images/ CMakeLists.txt and the wrapper Makefile move to the top with them, because the build now consumes four of those directories and generates into a fifth. board.local and build/ come along; MIDI_CC_MAP.md is generated into Documentation/ rather than into the old Software/ root. scripts/ goes with the build rather than staying under the firmware, because six of the ten had nothing to do with the firmware: gen_effects.py reads Effects/ and writes to three different places, pow2/log2/quarter_sine generate Audio/'s tables, check-readme.py compares Effects/ against the README, and server.py serves the web app. Four of them are invoked from Validation, which was reaching into Firmware/ for tooling - the same burying this commit is undoing. The four that really are about the firmware are ELF checks the top-level build drives anyway, and a second scripts directory would only be a second place to look. C includes say "Audio/foo.h" and the generated map says "Effects/bar.h", with the repository root on the include path for both the firmware and the bench. Spelling the directory out rather than relying on a bare name is what keeps Audio/cycles.h shimmable: a quoted include searches the including file's own directory first. The submodules are renamed as well as moved. git mv updates their paths but leaves the section names, and 'Software/pico-sdk' surviving in .gitmodules would be the word this commit removes, still load-bearing. That meant the nested modules under pico-sdk too - six .git files pointing into .git/modules/Software - which is why 'git submodule update --init --recursive' is worth running once after pulling this. Verified rather than assumed: a clean configure and build, make check (failing only on the missing-eeprom case it already failed on), check-effects, all four analysis pages reproducing every series and drawing every chart, and a flash to the board that still measures a routed reverb where it did before. One latent bug fell out of it. bench/coeff declared only quarter_sine.h of the three generated math tables, and Audio/util.h includes pow2.h and log2.h as well - so building that target with an empty gen/ could never have worked. 'make bench' builds bench/bench first, which generates all three, so it stayed hidden until this rebuilt everything from nothing. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
95 lines
2.6 KiB
C
95 lines
2.6 KiB
C
//
|
|
// The pedal's biquad coefficients, on a workstation.
|
|
//
|
|
// Same bargain as bench.c and for the same reason: this does not
|
|
// re-derive the cookbook, it calls the pedal's own biquad.h. A second
|
|
// implementation of _biquad_peaking() would be a second opinion, and a
|
|
// second opinion is exactly what you cannot check a filter against.
|
|
//
|
|
// It exists because 'bench --map' cannot see this class of defect. That
|
|
// maps one float through one function; where a biquad lands is a
|
|
// property of how sin(w0) and cos(w0) are combined, which needs the
|
|
// constructor itself and no audio path at all.
|
|
//
|
|
// Lines in on stdin: <type> <freq> <Q> <dB>
|
|
// Lines out on stdout: <type> <freq> <Q> <dB> b0 b1 b2 a1 a2
|
|
//
|
|
// Everything about what those coefficients then mean - where the corner
|
|
// actually is, whether that is near enough - belongs to test-biquad.py
|
|
// on the other end. Nothing here has an opinion about pass or fail.
|
|
//
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <stdint.h>
|
|
#include <stdbool.h>
|
|
#include <string.h>
|
|
|
|
#include "pico/stdlib.h"
|
|
|
|
#include "Audio/types.h"
|
|
#include "Audio/util.h"
|
|
#include "Audio/biquad.h"
|
|
|
|
//
|
|
// db_to_A() lives in util.h and is what every caller of the three gain
|
|
// constructors goes through, so the sweep goes through it too.
|
|
//
|
|
static const struct {
|
|
const char *name;
|
|
void (*fn)(struct biquad_coeff *, float, float);
|
|
} plain[] = {
|
|
{ "lpf", _biquad_lpf },
|
|
{ "hpf", _biquad_hpf },
|
|
{ "notch", _biquad_notch_filter },
|
|
{ "bpf", _biquad_bpf },
|
|
{ "bpf_peak", _biquad_bpf_peak },
|
|
{ "allpass", _biquad_allpass_filter },
|
|
};
|
|
|
|
static const struct {
|
|
const char *name;
|
|
void (*fn)(struct biquad_coeff *, float, float, float);
|
|
} gained[] = {
|
|
{ "peaking", _biquad_peaking },
|
|
{ "loshelf", _biquad_loshelf },
|
|
{ "hishelf", _biquad_hishelf },
|
|
};
|
|
|
|
int main(void)
|
|
{
|
|
char type[32];
|
|
double freq, q, db;
|
|
|
|
while (scanf("%31s %lf %lf %lf", type, &freq, &q, &db) == 4) {
|
|
struct biquad_coeff c;
|
|
bool done = false;
|
|
|
|
for (unsigned i = 0; i < ARRAY_SIZE(plain); i++) {
|
|
if (strcmp(plain[i].name, type))
|
|
continue;
|
|
plain[i].fn(&c, (float)freq, (float)q);
|
|
done = true;
|
|
}
|
|
for (unsigned i = 0; i < ARRAY_SIZE(gained); i++) {
|
|
if (strcmp(gained[i].name, type))
|
|
continue;
|
|
gained[i].fn(&c, (float)freq, (float)q,
|
|
db_to_A((float)db));
|
|
done = true;
|
|
}
|
|
if (!done) {
|
|
fprintf(stderr, "no such filter '%s'\n", type);
|
|
return 1;
|
|
}
|
|
|
|
//
|
|
// %.9e is float32 round-tripped exactly, so the python on
|
|
// the other end is reading the number the pedal has and
|
|
// not a rendering of it.
|
|
//
|
|
printf("%s %g %g %g %.9e %.9e %.9e %.9e %.9e\n",
|
|
type, freq, q, db, c.b0, c.b1, c.b2, c.a1, c.a2);
|
|
}
|
|
return 0;
|
|
}
|