Vier Annahmen des Plans vor jedem Implementierungscode geprüft:
A (SMC): Lüftersteuerung bestätigt — F0md/F1md (klein!) als Auto/Manuell-
Umschalter, F0Tg als Ziel, Grenzen aus F0Mn/F0Mx. SMC-Integer sind
little-endian, nicht big-endian wie im verbreiteten Intel-Beispielcode.
Ladelimit: CHWA/CH0B/CH0C/bfE0/bfF0 existieren auf Mac17,9 nicht.
Key noch nicht identifiziert, deshalb smc-diff.sh für eine
Differenzmessung ohne jeden Schreibzugriff.
B (Media): mediaremote-adapter läuft unter 26.6.1, aus dem Quellcode gebaut.
Liefert vollständige Metadaten inkl. Cover aus Google Chrome — der
Fall, den AppleScript nicht erreicht.
C (Audio): Process Tap + privates Aggregate-Device liefern echte Samples
(469 Callbacks/5 s, 0 stille Puffer). Konflikt gefunden: SoundSource
6.1.1 mit ARK.driver ist bereits installiert.
D (Group): App-Group-Container ist aus einem nicht-sandboxed Prozess erreichbar.
Damit trägt die Sandbox-Entscheidung, die Bridge-App entfällt.
Spikes sind Wegwerfcode zur Verifikation, kein Produktionscode.
65 lines
3.1 KiB
Markdown
65 lines
3.1 KiB
Markdown
# Spike C — Core Audio Process Taps auf M5 Pro / macOS 26.6.1
|
|
|
|
Gemessen am 10.08.2026. Werkzeug: `Spikes/audiotap-probe.swift`, signiert mit dem
|
|
Team-Zertifikat. Der Tap lief mit `muteBehavior = .unmuted` — der Spike hört nur zu und
|
|
verändert die Wiedergabe nicht.
|
|
|
|
## Ergebnis: bestätigt
|
|
|
|
| Schritt | Ergebnis |
|
|
|---|---|
|
|
| `kAudioHardwarePropertyProcessObjectList` | 35 Audio-Prozesse, mit PID, Bundle-ID und `IsRunningOutput` |
|
|
| `AudioHardwareCreateProcessTap` | erzeugt, Tap-Objekt 195, Format 48 kHz / 2 Kanäle / 32 bit Float |
|
|
| `AudioHardwareCreateAggregateDevice` (privat) | erzeugt, Device 196 |
|
|
| IOProc über 5 s | 469 Callbacks (93/s), 480 256 Frames, Spitzenpegel 0,4516, **0 stille Puffer** |
|
|
|
|
480 256 Frames ÷ 2 Kanäle ÷ 5 s = 48 025 Hz — deckt sich exakt mit der Abtastrate.
|
|
93 Callbacks/s entsprechen ~512 Frames je Puffer, also rund 10,7 ms Latenz. Für einen
|
|
Lautstärkemixer unkritisch.
|
|
|
|
Der bekannte Fehlerfall „Puffer laufen nach einiger Zeit auf Null" trat im 5-Sekunden-Fenster
|
|
nicht auf. Das widerlegt ihn nicht — der Watchdog aus dem Plan bleibt.
|
|
|
|
**Kein TCC-Dialog erschienen.** Das ist noch kein Freibrief: `.unmuted` ist der harmlose Fall.
|
|
Ob `.mutedWhenTapped` — der Modus, den der Mixer wirklich braucht — eine Berechtigung anfordert,
|
|
muss in Phase 7 gegengeprüft werden.
|
|
|
|
## Fallstrick beim Bauen
|
|
|
|
Die verbreitete Kurzform für Core-Audio-Property-Arrays
|
|
|
|
```swift
|
|
var out = [T](repeating: unsafeBitCast(0 as Int, to: T.self), count: count)
|
|
```
|
|
|
|
**stürzt mit SIGTRAP ab**: `unsafeBitCast` verlangt identische Größen, `Int` hat 8 Byte,
|
|
`AudioObjectID` 4. Da stdout in eine Pipe voll gepuffert ist, kam nicht einmal die erste
|
|
Zeile Ausgabe — der Absturz sah aus wie ein stiller Fehlstart. `MetricsProvider` und
|
|
`AudioProvider` verwenden deshalb die Variante über `UnsafeMutableRawPointer.allocate`
|
|
mit `MemoryLayout<T>.stride`.
|
|
|
|
## Konflikt: SoundSource ist bereits installiert
|
|
|
|
Die Prozessliste zeigt `com.rogueamoeba.soundsource` und `com.rogueamoeba.arkaudiod`,
|
|
dazu liegt `/Library/Audio/Plug-Ins/HAL/ARK.driver` im System. **SoundSource 6.1.1** ist
|
|
Rogue Amoebas Per-App-Lautstärkemixer — funktional genau das, was Phase 7 bauen soll.
|
|
|
|
Zwei Folgen:
|
|
|
|
1. **Doppelung.** Der Mixer aus Phase 7 wäre ein Nachbau einer bereits vorhandenen,
|
|
ausgereiften und bezahlten App.
|
|
2. **Technisches Risiko.** ARK.driver ist ein HAL-Plugin, das Audio abfängt, bevor es das
|
|
Ausgabegerät erreicht. Leitet SoundSource einen Prozess bereits um, sieht ein
|
|
Onyx-Process-Tap auf denselben Prozess unter Umständen nichts mehr — oder beide Ebenen
|
|
schalten sich gegenseitig stumm. Sauber vorhersagen lässt sich das nicht; es müsste
|
|
gemessen werden.
|
|
|
|
Vor Phase 7 zu klären. Bis dahin ist der Befund neutral festgehalten, nicht entschieden.
|
|
|
|
## Nebenbefund
|
|
|
|
`Alcove.app` und `Sapphire.app` sind beide installiert — also die beiden Apps, die als Vorbild
|
|
genannt wurden. Für die Notch-Shell in Phase 1 heißt das: mindestens eine davon greift
|
|
denselben Bildschirmbereich ab. Für die Entwicklung sollten sie beendet sein, sonst überlagern
|
|
sich Hover-Zonen und die Panels streiten sich um dieselbe Fläche.
|