Files
ScarriffleandClaude Opus 5 edb327cabe Kacheln und Fenster sprechen dieselbe Sprache
Alle Kacheln, Popovers und Fenster auf die Designschicht umgestellt: rund
hundert gesetzte Schriftgrößen und 159 gesetzte Abstände und Radien sind jetzt
Token. Übrig bleibt `spacing: 0` — das ist eine Aussage, keine geratene Zahl.

Die Einstellungen bekommen eine Seitenleiste statt sieben Reitern, deren
deutsche Beschriftungen zusammen 880 Punkte brauchten. Panel-Token stehen nicht
mehr in Fenstern: dort gilt Systemsemantik, damit der Hellmodus nicht schwarz
auf schwarz endet.

Neu ist ein Schaufenster, das alle Bauteile nebeneinander zeigt — ohne das
lässt sich eine Änderung an einem Token nur prüfen, indem man die App bedient,
bis jede Kachel einmal zu sehen war.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-05 21:05:51 +02:00

72 lines
3.4 KiB
Swift

import Testing
@testable import AudioProvider
// Der Mixer war an einem Headset völlig still. Nachgemessen am Aggregate-Gerät
// über der „PRO X Wireless Gaming Headset":
//
// MacBook Pro-Lautsprecher Eingang 1 Puffer: 2 Kan. → nur der Tap
// PRO X Headset Eingang 2 Puffer: 1 Kan. | 2 Kan. → Mikrofon, dann Tap
//
// Ein Ausgabegerät, das selbst einen Eingang mitbringt — jedes Headset, jedes
// USB-Interface — schiebt seine eigenen Eingangspuffer vor die des Taps. Wer
// blind Puffer null nimmt, greift das Mikrofon ab statt des Programms: der
// Programmton wird nie ausgegeben, während der Tap das Original stumm hält.
// Die eingebauten Lautsprecher haben keinen Eingang, deshalb fiel es dort nie auf.
@Suite("Wo der Tap im Aggregate-Gerät liegt")
struct TapBufferLayoutTests {
@Test("Reines Ausgabegerät: der Tap liegt vorn")
func outputOnlyDeviceKeepsTapFirst() {
#expect(TapBufferLayout.offset(subDeviceInputBuffers: 0,
aggregateInputChannels: [2],
tapChannels: 2) == 0)
}
@Test("Headset: der eigene Mikrofonpuffer schiebt den Tap nach hinten")
func headsetMicrophoneShiftsTap() {
// Der gemessene Fall. Vorher wurde hier Puffer null genommen — das
// Mikrofon — und der Programmton blieb liegen.
#expect(TapBufferLayout.offset(subDeviceInputBuffers: 1,
aggregateInputChannels: [1, 2],
tapChannels: 2) == 1)
}
@Test("Mehrere Eingangspuffer des Geräts zählen alle")
func severalDeviceInputsCount() {
#expect(TapBufferLayout.offset(subDeviceInputBuffers: 2,
aggregateInputChannels: [1, 1, 2],
tapChannels: 2) == 2)
}
@Test("Passt die Kanalzahl an der erwarteten Stelle nicht, wird nicht geraten")
func mismatchedChannelsAreRefused() {
// Läge der Tap wider Erwarten woanders, wäre die Folge wieder Stille
// bei stummgeschaltetem Original. Dann lieber gar kein Tap: der Aufbau
// fliegt auf, das Programm bleibt hörbar.
#expect(TapBufferLayout.offset(subDeviceInputBuffers: 0,
aggregateInputChannels: [1, 2],
tapChannels: 2) == nil)
}
@Test("Fehlt der Puffer ganz, wird nicht geraten")
func missingBufferIsRefused() {
#expect(TapBufferLayout.offset(subDeviceInputBuffers: 2,
aggregateInputChannels: [1, 2],
tapChannels: 2) == nil)
#expect(TapBufferLayout.offset(subDeviceInputBuffers: 0,
aggregateInputChannels: [],
tapChannels: 2) == nil)
}
@Test("Unsinnige Angaben werden abgewiesen, nicht verrechnet")
func nonsenseIsRefused() {
#expect(TapBufferLayout.offset(subDeviceInputBuffers: -1,
aggregateInputChannels: [2],
tapChannels: 2) == nil)
#expect(TapBufferLayout.offset(subDeviceInputBuffers: 0,
aggregateInputChannels: [2],
tapChannels: 0) == nil)
}
}