Skip to content

#131: das Regelgesetz gegen die Uhrendrift — und was die Messung daran fand - #198

Merged
oe5sos merged 2 commits into
mainfrom
feat/rx-drift-regelgesetz
Oct 5, 2026
Merged

oe5sos merged 2 commits into
mainfrom
feat/rx-drift-regelgesetz

Conversation

@oe5sos

@oe5sos oe5sos commented Oct 5, 2026

Copy link
Copy Markdown
Owner

Setzt den Entwurf aus #131 um — nur das Regelgesetz. Kein Resampler, kein Bus, kein Faden, keine Verdrahtung in den Tonweg. Die kommt getrennt zur Durchsicht, so verlangt es der Entwurf selbst (§4) und CLAUDE.md für Änderungen am Tonweg ohnehin.

Was die Messung fand

Der Entwurf verlangte in §5 genau diesen Prüfstand. Er hat etwas gefunden:

Mit Thetis' Verstärkung 4,0e-6 divergiert der Regelkreis bei Longpaths Aufrufrate.

In der Simulation über 5,5 Stunden schwingt der Füllstand über den ganzen Ring (90 ms Hub bei 100 ms Ring) und läuft eine halbe Million Mal über — auch bei 0 ppm, wo es nichts zu regeln gibt. Hätte der Entwurf die Zahl ungeprüft übernommen, wäre der Ausgleich schlimmer geworden als die Drift, gegen die er gebaut ist.

Mit 4,0e-7 trifft die Regelung den theoretischen Sollwert auf neun Stellen, mit 0,3 ms Hub und ohne einen Über- oder Leerlauf:

Drift gemessenes var theoretisch
0 ppm 1,000000000 1,000000000
+4 ppm 0,999996010 0,999996000
−4 ppm 1,000003990 1,000004000
+100 ppm 0,999900011 0,999900010
−100 ppm 1,000100009 1,000100010

Zweiter Befund: über die Stabilität entscheidet das Produkt aus Verstärkung und Blockgröße, nicht die Verstärkung allein.

Produkt Ergebnis
4,0e-6 × 480 = 1,9e-3 divergiert (Thetis' Zahl)
4,0e-7 × 2048 = 8,2e-4 divergiert
4,0e-7 × 1024 = 4,1e-4 stabil, 4,8 ms Hub
1,0e-7 × 2048 = 2,0e-4 stabil, 4,9 ms Hub
4,0e-7 × 480 = 1,9e-4 stabil, 0,3 ms Hub

Die Vorgabe 4,0e-7 gilt also für Blöcke bis rund 1024 Rahmen. Ein größerer Ring hilft dagegen nicht — das stand zuerst als Abhilfe im Prüfstand und war behauptet, nicht gemessen: mit Block 2048 und 4,0e-7 wird es im 16384er Ring sogar schlimmer (298 ms Hub).

Abweichung von Thetis, ausdrücklich

Thetis ruft control() von beiden Seiten auf und schützt var mit cs_var — einer Sperre, die im Geräterückruf genommen wird. Longpath darf das nicht (CLAUDE.md), und sein Ring ist absichtlich sperrfrei. Hier läuft alles auf dem Erzeugerfaden: keine Sperre, kein Rückruf berührt diese Klasse.

Portiert aus third_party/wdsp/src/rmatch.c (Warren Pratt, NR0V, GPL-2.0-or-later): xmav (:56-69), xaamav (:101-126), control (:256-272), Parameter (:500-526), Verstärkungsskalierung (:147).

Prüfstand

Neun Punkte, davon zwei Gegenproben — ohne sie belegt keiner etwas:

  • die Thetis-Verstärkung muss überlaufen,
  • ohne jede Regelung muss der Ring überlaufen.

Die zweite lief zuerst über 1 Mio Blöcke und war grün, ohne etwas zu zeigen: gemessen läuft der Ring erst nach 3,5 Stunden (1,25 Mio Blöcke) über. Jetzt 1,5 Mio.

Acht simulierte Stunden Drift sind anders nicht zu prüfen als auf einer virtuellen Uhr.

Die Klasse kommt ohne Qt aus (std::int64_t statt qint64). Kein Selbstzweck: so ließ sich das Regelgesetz mit einer Wegwerf-Sonde vermessen — und genau das war nötig, um die Divergenz zu finden.

Was noch fehlt

IAudioBus::queuedFrames(), der varsamp-Resampler und die Verdrahtung je Bus. Dazu die offenen Fragen aus §7 des Entwurfs (Zielverzögerung, auch für den Mithörweg?) — die gehören dir, nicht mir.

🤖 Generated with Claude Code

oe5sos and others added 2 commits October 5, 2026 06:59
…n fand

NUR das Regelgesetz. Kein Resampler, kein Bus, kein Faden, keine
Verdrahtung in den Tonweg -- die kommt getrennt zur Durchsicht, so
verlangt es der Entwurf selbst (2026-09-27-rx-audio-rate-match-design.md
§4) und CLAUDE.md fuer Aenderungen am Tonweg ohnehin.

Portiert aus WDSP/ChannelMaster `rmatch.c` (Warren Pratt, NR0V,
GPL-2.0-or-later): xmav (:56-69), xaamav (:101-126), control (:256-272),
Parameter (:500-526), Verstaerkungsskalierung (:147).

ABWEICHUNG, ausdrueckliche: Thetis ruft `control()` von beiden Seiten
auf und schuetzt `var` mit `cs_var` -- einer Sperre, die im
Geraeterueckruf genommen wird. Longpath darf das nicht (CLAUDE.md), und
sein Ring ist absichtlich sperrfrei. Hier laeuft alles auf dem
Erzeugerfaden: keine Sperre, kein Rueckruf beruehrt diese Klasse.

── WAS DIE MESSUNG FAND ───────────────────────────────────────────────

Der Entwurf verlangte in §5 genau diesen Pruefstand, und er hat etwas
gefunden: MIT THETIS' VERSTAERKUNG 4,0e-6 DIVERGIERT DER REGELKREIS bei
Longpaths Aufrufrate. In der Simulation ueber 5,5 Stunden schwingt der
Fuellstand ueber den GANZEN Ring (90 ms Hub bei 100 ms Ring) und laeuft
eine halbe Million Mal ueber -- auch bei 0 ppm, wo nichts zu regeln ist.
Haette der Entwurf die Zahl ungeprueft uebernommen, waere der Ausgleich
schlimmer geworden als die Drift, gegen die er gebaut ist.

Mit 4,0e-7 trifft die Regelung den theoretischen Sollwert auf neun
Stellen, mit 0,3 ms Hub und ohne einen Ueber- oder Leerlauf:

      0 ppm -> var 1,000000000
     +4 ppm -> var 0,999996010   (theoretisch 0,999996000)
     -4 ppm -> var 1,000003990   (theoretisch 1,000004000)
   +100 ppm -> var 0,999900011   (theoretisch 0,999900010)
   -100 ppm -> var 1,000100009   (theoretisch 1,000100010)

Zweiter Befund: ueber die Stabilitaet entscheidet das PRODUKT aus
Verstaerkung und Blockgroesse, nicht die Verstaerkung allein.

     4,0e-6 x  480 = 1,9e-3   divergiert (Thetis' Zahl)
     4,0e-7 x 2048 = 8,2e-4   divergiert
     4,0e-7 x 1024 = 4,1e-4   stabil, 4,8 ms Hub
     1,0e-7 x 2048 = 2,0e-4   stabil, 4,9 ms Hub
     4,0e-7 x  480 = 1,9e-4   stabil, 0,3 ms Hub

Die Vorgabe 4,0e-7 gilt also fuer Bloecke bis rund 1024 Rahmen. Ein
groesserer RING hilft dagegen NICHT -- das stand hier zuerst als Abhilfe
und war behauptet, nicht gemessen: mit Block 2048 und 4,0e-7 wird es im
16384er Ring sogar schlimmer (298 ms Hub).

── PRUEFSTAND ─────────────────────────────────────────────────────────

Neun Punkte, davon ZWEI Gegenproben, weil ohne sie keiner etwas belegt:
die Thetis-Verstaerkung MUSS ueberlaufen, und ohne jede Regelung MUSS
der Ring ueberlaufen. Letztere lief zuerst ueber 1 Mio Bloecke und war
gruen, ohne etwas zu zeigen -- gemessen laeuft der Ring erst nach
3,5 Stunden (1,25 Mio Bloecke) ueber. Jetzt 1,5 Mio.

Acht simulierte Stunden Drift sind anders nicht zu pruefen als auf einer
virtuellen Uhr.

Die Klasse kommt ohne Qt aus (std::int64_t statt qint64). Das ist kein
Selbstzweck: so laesst sich das Regelgesetz mit einer Wegwerf-Sonde
vermessen, und genau das war noetig, um die Divergenz zu finden.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Die CI-Stufe "Compliance & Provenance" war rot, und zu Recht:
`check-new-ports.py` fand im Kopf der neuen Klasse "NR0V" und keine
Attribution. Der Entwurf hatte das ausdruecklich verlangt ("Port as a
faithful derivative: verbatim rmatch.c header, PROVENANCE rows"), und
ich hatte es uebergangen.

Nachgetragen nach docs/attribution/HOW-TO-PORT.md:

  * der Kopf von third_party/wdsp/src/rmatch.c WOERTLICH, Zeichen fuer
    Zeichen, in beiden Dateien;
  * davor der Longpath-Portierungsblock mit den portierten Stellen
    (control :256-272, xmav :56-69, xaamav :101-126, Parameter
    :500-526, Verstaerkungsumrechnung :147) UND dem, was ausdruecklich
    NICHT portiert ist: varsamp, Ringpuffer, Ausblenden, die beiden
    kritischen Abschnitte;
  * zwei Zeilen in docs/attribution/THETIS-PROVENANCE.md, beide mit
    den Abweichungen im Klartext -- Regelgesetz nur auf der
    Erzeugerseite, und Verstaerkung 4,0e-7 statt 4,0e-6.

Lokal gegengeprueft: check-new-ports.py, verify-thetis-headers.py
(--all-kinds), verify-provenance-sync.py, verify-inline-cites.py,
check-applet-ids.py und verify-no-gui-dsp-access.py laufen sauber
durch. Der Pruefstand bleibt bei 9 von 9.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@oe5sos
oe5sos merged commit 044701b into main Oct 5, 2026
12 checks passed
oe5sos added a commit that referenced this pull request Oct 5, 2026
Zwei Konflikte, zwei verschiedene Antworten -- darum nachgesehen statt
pauschal aufgeloest:

  * handfunke/app.js: beide Stellen sind reine Ergaenzungen, mains Seite
    ist leer -> unsere behalten.
  * tests/CMakeLists.txt: main hat dort den Eintrag fuer
    tst_audio_rate_matcher (#198) ergaenzt, wir die beiden Rotor-Staende
    -> BEIDE behalten. Hier haette "unsere behalten" den Driftausgleich
    aus der Pruefliste geworfen, und niemand haette es gemerkt, weil die
    Datei trotzdem baut.

Danach neu konfiguriert und gegen frische Binaerdateien gemessen:

    tst_rotor_peilung        8
    tst_tci_rotor            9
    tst_audio_rate_matcher   9
    pruefe-rotor            31
    pruefe-spots            43
    pruefe-aufwachen        17

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant