Überblick
Eingabe: Der Nutzer gibt Raummaße / Form / Materialien, Lautsprecher- und Hörposition ein — oder die Geometrie wird mit dem AR-Maßband (ohne LiDAR) oder per LiDAR-Scan (RoomPlan) erfasst.
- Lokalisierung früher Reflexionen
- RT60 (gemessen + simuliert) plus EDT / C50 / C80 / D50 (aus der simulierten RIR abgeleitet)
- Liste der Raummoden-Frequenzen
- Panel-Layout (Position, Anzahl, Produkt-SKU)
- 3D-Visualisierung + Reflexionsenergie-Heatmap
- PDF-Export in Montagehandbuch-Qualität
- ESS-Sweep- / Klatsch-Messung auf dem Gerät (internes oder USB-Messmikrofon)
- USB-Messmikrofon-Kalibrierung & SPL-Referenz, Echtzeitspektrum (RTA)
- Frequenzgang-Overlays & Mehrpositions-Mittelung, REW-Austausch, PEQ / Subwoofer-Abgleich, KI-Assistent
Rechteckige, L-, U-förmige und beliebige einfache Polygon-Räume werden unterstützt; Reflexionen 1. Ordnung sowie Flächen-/Enthaltensein-Berechnung nutzen das echte Polygon; Ordnung 2/3 und Raummoden nähern über die Bounding Box (siehe §9).
Akustikmodell
2.1 Sabine RT60
Die klassische Sabine-Formel:
- Raumvolumen (m³); bei Polygonen Shoelace-Fläche × Höhe, abzüglich Hindernissen (Stützen / Träger).
- Fläche × Absorptionsgrad je Fläche. Koeffizienten über 6 Oktavbänder (125 / 250 / 500 / 1k / 2k / 4k Hz).
- = 24·ln(10)/c, mit c = 343 m/s (20 °C).
Die App liefert 4 Ausstattungs-Presets (leerer harter Raum / typisch harte Oberflächen / Möbel / bereits behandelt), je mit Absorptionskurve pro Band; die Einzelwert-RT60-Schätzung und das Panel-Budget nutzen einen Mittel-Hochton-Durchschnittskoeffizienten, die 6-Band-Sabine-Kurve speist die Bandanzeige. Auch das Ziel-RT60 ist eine 6-Band-Kurve, passend zu Normen wie EBU Tech 3276 / THX, die einen längeren Tiefbass-Nachhall zulassen.
2.2 Image-Source-Methode (ISM)
Erste Reflexionen per Spiegelung: Quelle an der Wand spiegeln; der Schnittpunkt der Strecke „Spiegelquelle → Hörer“ mit der Wand ist der Reflexionspunkt.
- Rechteckiger Raum: Spiegelung an allen 6 Ebenen — geschlossene Lösung.
- Nicht rechteckig (
PolygonReflectionCalculator): jedes Wandsegment ausRoomPolygon.walls()spiegeln und Parameter s ∈ [0, 1] prüfen (Boden-/Decken-Reflexionen erfordern zusätzlich Reflexions-XY im Polygon); Pfade 1. Ordnung durchlaufen zudem einen 2D-Verdeckungstest — kreuzt ein Abschnitt Quelle→Punkt→Hörer ein anderes Wandsegment, wird der Pfad verworfen.
Mehrfachreflexionen (Ordnung 1–3) implementiert MultiOrderReflectionCalculator nach dem rekursiven Ansatz von pyroomacoustics:
- Alle Wandsequenzen [s₁, …, sₙ] aufzählen, benachbarte Wände verschieden
- Spiegelquellen-Iteration: S₀ = Quelle, Sₖ = mirror(Sₖ₋₁, sₖ)
- Rückverfolgung vom Hörer: Sₙ → Hörer trifft sₙ in Pₙ; Sₙ₋₁ → Pₙ trifft sₙ₋₁ in Pₙ₋₁; rekursiv zurück
- Jeder Schnittpunkt muss im gültigen Wandbereich liegen und t ∈ (0, 1)
2.3 Pfadenergie
Breitband-Energie als Funktion von Reflexionsanzahl und Distanzdämpfung:
- α wird auf [0, 0.99] begrenzt, damit α = 1 kein log(0) oder pow(negativ, N) = NaN erzeugt
- Distanzdämpfung folgt der sphärischen Ausbreitung 1/r²
- Umrechnung in dB über 10·log₁₀ (Energiedomäne)
Die Energie pro Band wird für die 6 Oktavbänder separat berechnet (Koeffizient aus finishProfile.absorptionByBand).
2.4 RT60-Schätzung (gemessen)
ImpulseResponseEstimator:
- Matched Filtering: der aufgenommene Sweep wird per Inversfilter (ESS / Farina) zu einem Impuls komprimiert; Prozessgewinn ≈ 10·log₁₀(T·B) — etwa +41 dB effektiver SNR bei der 3-s-Telefonvoreinstellung 180 Hz–4 kHz
- rmsEnvelope: gleitende RMS-Hüllkurve
- Schroeder-Rückwärtsintegration: E_back(t) = ∫ₜ^∞ s²(τ) dτ, mit 10·log₁₀ normiert ergibt die EDC-Kurve
- Lineare Steigungsregression: bevorzugt T30 [−5, −35 dB] je SNR, sonst T20 [−5, −25] oder T10 [−5, −15]
- RT₆₀ = −60 / Steigung
RT60 pro Band: auf den gefilterten Samples Bandpass an den nach dem tatsächlichen Sweep-Bereich gewählten ISO-Oktavmitten (Q = √2), dann Schroeder je Band.
2.5 RIR-Simulation
SimulatedRIRGenerator wandelt Mehrfachreflexionspfade in diskrete Impulse in einem 8 kHz × 0,5 s PCM-Puffer:
for path in reflectionPaths:
t = path.totalDistance / speedOfSound
amp = 10^(path.relativeEnergyDB / 20)
impulse[round(t * sampleRate)] += amp
Den Direktschall-Impuls hinzufügen, dann Schroeder-Integration für EDT / RT60 / C50 / C80 / D50.
2.6 Raummoden
Modale Frequenzen eines rechteckigen Raums:
Klassifiziert nach Anzahl der von null verschiedenen nₓ, n_y, n_z: 1 = axial, 2 = tangential, 3 = schräg.
Die Enumeration deckt n ≤ 4 pro Achse bis 300 Hz ab. Nicht rechteckige Räume schätzen Moden über die Bounding Box (exakte Moden brauchen FEM); in der UI ausgewiesen.
Geometriesystem
3.1 Unterstützte Formen
- Rechteck — Breite × Länge × Höhe
- L-Form — eine nw × nl-Kerbe an einer Ecke entfernen
- U-Form — eine nw × nl-Kerbe mittig an einer Wand entfernen
- Benutzerdefiniert — beliebiges einfaches Polygon (≥ 3, ≤ 24 Ecken)
Alle nicht rechteckigen Formen werden über RoomPolygon.from(shape:, bboxWidth:, bboxLength:) zur CCW-Eckenliste. Reflexionen 1. Ordnung, Fläche / Umfang und Enthaltensein nutzen diese Ecken direkt; ein ungültiges eigenes Polygon (< 3 / > 24 Ecken, selbstschneidend, Fläche nahe null) fällt still auf das umschließende Rechteck zurück.
3.2 Polygon-Geometrie-Werkzeuge
- Fläche — Shoelace-Formel
- Umfang — Summe der Kantenlängen
- contains(x, y) — Ray-Casting mit Rand-Epsilon (verhindert Fehler an Ecken)
- clamped(point) — Rechtecke nutzen den schnellen Pfad [0, w] × [0, l]; andere das echte [minₓ, maxₓ] × [min_y, max_y] aus
polygon.boundingBox, prüfen polygon.contains und Binärsuche zum Bbox-Zentrum, falls außerhalb - walls() — zerlegt das Polygon in nach Innennormalen klassifizierte Segmente (leftWall / rightWall / frontWall / backWall), sodass der rechteckige Panel-Empfehler wiederverwendet wird
- PolygonValidator.isSimple — prüft ein nicht selbstschneidendes einfaches Polygon
3.3 RoomPlan-Scan
RoomCaptureSession (iOS-16+-API; die App schaltet das Scannen erst ab iOS 17 frei) wird genutzt; CapturedRoomMapper bildet den Scan auf ScannedRoom ab (wallSegments + openings + furniture). Koordinaten-Mapping:
Scans werden nach Wandanzahl klassifiziert: genau 4 Segmente gelten direkt als Rechteck; alles andere durchläuft RectangularRoomSimplifier.polygonShapeFromScan, das wallSegments zu Polygon-Ecken verkettet. RoomPlan-Endpunkte haben typ. 3–8 cm Fehler; eine 12-Segment-Schleife kann 5 cm akkumulieren, daher 12 cm Schließ-Epsilon. Schließt die Kette nicht, Rückfall auf die Bounding Box und Aufforderung zum erneuten Scan.
3.4 AR-Maßband
Ohne LiDAR übernimmt ARTapeMeasureView (RealityKit-ARView mit World-Tracking): Fadenkreuz auf die Wand richten und per Doppeltipp Start / Ende setzen, nacheinander Breite → Länge → Höhe, dann bestätigen — mit Kamera-Berechtigungsführung und Tracking-Fehler-Hinweisen.
3.5 Freier Vertex-Editor
FreeVertexEditorView erlaubt das Ziehen von Ecken auf einem SwiftUI-Canvas:
- Langes Drücken zum Löschen (bei > 3 Ecken, damit ≥ 3 bleiben)
- Jeder Zieh-Frame wird mit
isSimplevalidiert; eine selbstschneidende Position wird schlicht nicht übernommen (die Ecke bleibt stehen). Tippen auf leere Fläche fügt eine Ecke auf der nächsten Kante ein; dazu kommen ein numerischer Editor je Ecke und ein Reset auf das umschließende Rechteck - 0,05-m-Raster-Einrastung
- Ein Rand von max(0,5, bbox × 0,2) m außerhalb der Bbox erlaubt das Ziehen über die Bbox hinaus (die Elternansicht vergrößert room.width / length automatisch)
Hörzonen & Multi-Listener
AcousticConfiguration.listeners unterstützt 1..N Hörpositionen (bei 0 Hörern wird eine Standard-Primärposition samt Warnung synthetisiert; bei 0 Lautsprechern übernehmen die Vorlagen aus §5.2). Die Analyse führt die Image-Source-Methode je Hörer aus und fügt Reflexionspunkte in ein Array zusammen (primärer Hörer zuerst). Der Empfehler gewichtet jede Wand nach Punktanzahl (cap = max(6, speakerCount × listenerCount)); mehrere Sitze an einer Wand treiben sie ans Budgetlimit.
- In 3D nutzen sekundäre Hörer Opacity 0,45 + Scale 0,75
- Draufsicht (RoomPlanView): primäre Punkte volle Farbe r=5, sekundäre Opacity 0,45 r=3
- Die Liste (RecommendationView) zeigt nur primäre Punkte; Fußnote „+ N Reflexionen bereits berücksichtigt“
Mehrfachreflexionen / RIR / Heatmap werden weiterhin einmal für den primären Hörer berechnet (O(speakers × surfaces³) je Hörer ist zu schwer, RIR ist eine Einzelpunkt-Metrik).
Empfehlungssystem
PanelPlacementRecommender liefert [PanelRecommendation], je mit: Position (links / rechts / Decke / vorn / hinten / Ecke), Anzahl, Priorität (essenziell / stark / empfohlen / optional), effectivenessMultiplier, targetReflectionPointId.
5.1 Proportionale Zuteilung (größter Rest)
Das alte gierige add() ließ Wände verhungern: linke Wand verbrauchte das Budget → rechte 0; bei knappem Budget auch Decke / vorn / hinten. Neu: Methode des größten Rests:
- Raw-Desired je Wand berechnen (Punktanzahl + Raumtiefe + Anwendungsfall)
- floor(raw × budget / total) als Anfangszuteilung
- Wände mit raw > 0 erhalten ≥ 1 Panel; nur wenn das Budget kleiner ist als die Zahl nachgefragter Wände, werden Flächen genullt, niedrigste Priorität zuerst
- falls Summe > Budget, vom kleinsten Bruchrest aufwärts kürzen
- Links/Rechts-Symmetrie: bei raw[0] == raw[1] alloc[0] == alloc[1] erzwingen
- Restbestand nach größtem Bruchteil umverteilen
5.2 Anwendungsfall-Vorlagen
Ohne platzierte Lautsprecher gelten anwendungsspezifische Vorlagen:
- Besprechungsraum: Decke 35 % + Rückwand 20 % + je Seitenwand 12 %
- Podcast: direkt vor dem Mikrofon 25 % + je Seite 18 % + Decke 20 %
- Studio: symmetrische Vier-Wand-Dämpfung + bis zu 4 Eck-Bassfallen im Budget (der echte Budget-Bypass greift nur auf dem Pfad dichter Tieftonmoden aus §5.3)
- Allgemeines Hören: symmetrische Basis + Hinweis, Lautsprecher hinzuzufügen
5.3 Physikalische Muss-Maßnahmen umgehen das Budget
Eck-Bassfallen werden bei dichten 80–150-Hz-Moden auf 4 erzwungen und umgehen das totalPanel-Limit. Grund: In Ecken ist der Schalldruck am höchsten, Bassfallen dort ~1,5× effizienter — physikalische Notwendigkeit.
5.4 Hörnahe Gewichtung
Ein Nachlauf markiert Empfehlungen innerhalb 1,5 m eines Hörers als .nearListener, setzt effectivenessMultiplier ×1,15 und vermerkt dies in Titel / Begründung.
Messung
6.1 ESS-Sweep
ESS-Logarithmus-Sweep (Farina-Methode): vier Voreinstellungen + benutzerdefiniert, Dauer 3 / 6 / 12 s:
- Schnelltest per Telefon: 180 Hz–4 kHz über die interne Ausgabe, 75 Hz–4 kHz über externe Ausgabe (einzige Voreinstellung mit internem Lautsprecher)
- Tieffrequenz / Subwoofer: 15–300 Hz (externe Ausgabe erforderlich)
- Vollbereich: 20 Hz–20 kHz (externe Ausgabe erforderlich)
- Benutzerdefiniert: beliebige Grenzen innerhalb 10 Hz–20 kHz, mindestens eine Oktave (externe Ausgabe erforderlich)
- Inversfilter (
makeInverseSweep) = Zeitumkehr + Amplitudenhüllkurve mit +6 dB/Oktave (mit der Frequenz steigend, gegen das rosa ESS-Spektrum) - Aufnahme via AVAudioRecorder als verlustfreies Linear PCM (16-bit Mono .caf, ~96 dB Dynamik — perceptual Codecs gehören nicht in die Impulsmessung; die Abtastrate folgt der Audio-Session — 44,1 kHz am internen Mikrofon, native 48 kHz bei USB-Messmikrofonen)
- Zurücklesen → Matched Filter → analyzeImpulse
Wiedergabesignal, inverser Sweep und Analyse teilen eine Konfiguration, die oberste Frequenz wird durch die reale Abtastrate begrenzt; die Voreinstellungen Tieffrequenz / Vollbereich / Benutzerdefiniert verweigern ohne externe Ausgabe den Start. Die RT60-Oktavbänder werden nach dem tatsächlichen Sweep-Bereich gewählt; der Frequenzbereich einer Voreinstellung ist die Stimulus-Konfiguration — der vertrauenswürdige Bereich hängt weiterhin von Lautsprecher, Mikrofon und Messqualität ab.
makeInverseSweep(sampleRate:) ist parametrisiert) — das Matched Filtering ist damit immer aktiv, bei 44,1 kHz (internes Mikrofon) wie bei 48 kHz (USB-Messmikrofone).6.2 Klatsch-Impuls
Ohne Wiedergabe — der Nutzer klatscht einmal kräftig in einem 1-s-Fenster; insgesamt 4,5 s aufgenommen (~3,5 s Ausklang). Direkt zu analyzeImpulse (kein Matched Filter nötig; ein Klatschen ist bereits ein schmaler Impuls). Deckt das 125-Hz-Band ab, das die Telefonvoreinstellung (ab 180 Hz) verfehlt.
6.3 Gemessen vs. simuliert
MeasuredVsSimulatedCard nimmt das letzte gemessene RT60 und zeigt die Abweichung zum simulierten RT60:
6.4 Umgebungsrauschen & Kalibrierung
AmbientNoiseEstimator nimmt 3 s Stille auf (je 100 ms an den Enden beschnitten) für das Grundrauschen: Breitband-Mittel / -Spitze in dBFS + 5-stufige Ruhebewertung (dBFS nur relativ, bis eine SPL-Kalibrierung dB SPL liefert). Die Nahfeld-Latenzkalibrierung nutzt denselben ESS-Sweep: Telefon ≤ 30 cm vor den Lautsprecher, Verzögerung Aufnahmestart → Impulsspitze (inkl. bewusstem 250-ms-Vorlauf), idealerweise 2–3 Läufe — Streuung der letzten 3 Messungen < 5 ms = hohe, < 20 ms = mittlere Konfidenz. Die Latenz ist an das aktuelle Paar „Eingang + Ausgaberoute“ gebunden, verfällt bei jeder Änderung und wird bei Fernmessungen automatisch abgezogen.
6.5 Zeitreferenz & Messqualität
- Akustische Zeitreferenz: ein Chirp vor dem Sweep dient als Zeitanker und wird bei jeder Messung neu erkannt; bei Erkennungsfehler Rückfall mit expliziter Phasen-Verlässlichkeit — kein Anspruch auf absolute messübergreifende Ausrichtung.
- Taktdrift: schätzt die Taktdifferenz zwischen Wiedergabe- und Aufnahmepfad und korrigiert sie, wenn die Bedingungen es erlauben.
- Elektrische Loopback-Referenz: USB-Interfaces mit mehreren Eingängen können einen zweiten Kanal als Loopback-Referenz nutzen; bei unerfüllten Bedingungen Rückfall auf die akustische Referenz. Der Mac-Wiedergabehelfer-Pfad nutzt kein lokales elektrisches Loopback.
- Qualitätsfelder: jede Aufzeichnung speichert die verfügbaren Werte für SNR, Rauschgrund, Clipping-Status, IR-Zeitoffset, tatsächlichen Eingang und Abtastrate; was nicht bestimmbar ist, bleibt leer — nichts wird erfunden.
- Clipping-Behandlung: ein Sweep mit erkanntem Clipping wird verworfen und eine Wiederholung empfohlen; Klatsch-Aufzeichnungen werden markiert und angezeigt.
- Abgleich Simulation / Messung: die letzte Messung des Raums wird neben dem RT60 der geometrischen Simulation verglichen, um die Modellgüte einzuschätzen (Schwellen in 6.3).
6.6 USB-Messmikrofone & Ausgaberouting
Die Eingangsauswahl der Messseite listet internes Mikrofon und class-compliant USB-Eingänge (z. B. miniDSP UMIK-1 / UMIK-2); ein routeChangeNotification-Listener fällt aufs interne Mikrofon zurück, wenn das externe verschwindet. Aufnahme- und Sweep-Raten folgen der Session (UMIK-1 = 48 kHz). Frequenzkalibrierdateien im REW- / UMIK-Stil (.txt) lassen sich direkt importieren (Auswertung von Sens Factor und Seriennummer, Interpolation in Log-Frequenz; 90°-Datei für Raummessungen empfohlen). Die Kalibrierung ist an die UID des Eingangsports gebunden — bei nicht passendem Eingang wird die bisherige Kalibrierung nicht angewendet.
Einmalige SPL-Referenzkalibrierung: Schallpegelkalibrator (Standard 94 dB @ 1 kHz) aufs Mikrofon, die App tastet 3 s Pegel ab und leitet den dBFS → SPL-Offset ab; dB SPL wird nur gezeigt, wenn der Eingang passt und eine SPL-Kalibrierung existiert — sonst bleibt es bei dBFS. Kalibrier-Snapshot zum Messzeitpunkt: neue Sweep- / Klatsch-Messungen speichern die damals gültige Kalibrierkurve, Name, Seriennummer, Sens Factor, SPL-Offset und Eingangs-UID — späteres Ersetzen, Löschen oder Neubinden der Kalibrierung ändert die Messwerte dieser Aufzeichnungen nicht mehr; Messdetail, Fenster-Frequenzgang-Vorschau, Frequenzgang-Textexport und PDF nutzen denselben Snapshot. Die Kalibrierung selbst wird pro Eingangsport-UID in ~/Library/Application Support/mic_calibration.json persistiert.
Die Wiedergabe läuft über den System-Routenwähler (AVRoutePickerView-Wrapper, auf den Karten für Sweep / Nahfeld-Kalibrierung); die Session erlaubt AirPlay / Bluetooth A2DP / HFP für Testsignale über externe Lautsprecher, ohne externe Ausgabe wird der Lautsprecher erzwungen. Der Aufnahmeeingang ist immer explizit auf die Nutzerwahl gepinnt (USB-Mikrofon oder intern), damit das Mikrofon eines Bluetooth-Geräts während der Wiedergabe nicht den Eingang kapert und die Messung verunreinigt. Mac-Wiedergabehelfer: findet AcouveroMacSpeaker im LAN per Bonjour, überträgt zuerst das Sweep-WAV auf den Mac und sendet dann den Wiedergabebefehl, während das iPhone aufnimmt — für Mac-Ausgabepfade, die das Audio der Messsession nicht direkt übernehmen können (dieser Pfad nutzt kein lokales elektrisches Loopback).
6.7 REW- & Datei-Interoperabilität
- Frequenzgang-Text-Import / -Export: tolerant gegenüber gängigen Trennzeichen, Kommentarzeilen, wissenschaftlicher Notation und Dezimalformaten, mit Validierung der Frequenzachse beim Import; Dateien ohne Phasenspalte liefern keine Phasendaten.
- Kalibrierungsbewusster Export: Export in dB SPL bei gültigem SPL-Kalibrier-Snapshot, sonst in dBFS — der Header kennzeichnet die Einheit ehrlich.
- IR-Audio-Import: WAV- / AIFF-Impulsantworten werden unterstützt; bei Mehrkanaldateien muss der Kanal explizit gewählt werden.
- Offline-Sweep-Analyse: Export der Stimulusdatei für externe Wiedergabe; nach Import der Aufnahme müssen Anfangs- / Endfrequenz und Dauer vor der Entfaltung angegeben werden — Sweep-Parameter werden nie geraten.
- Audio-Teilexport: verfügbare IRs oder Rohaufnahmen lassen sich als WAV teilen.
- Importierte Ergebnisse lassen sich archivieren und fließen in die passenden Diagramme, Overlays und Analysen; ob sie einer Messgruppe beitreten dürfen, hängt von Datentyp und Vertrauensumfang ab. REW-
.mdat-Projektdateien werden derzeit nicht gelesen.
Messdiagramme & Analyse
Die Messdetailseite zeigt Diagramme entsprechend den tatsächlich vorhandenen Daten jeder Aufzeichnung — fehlende Kurven werden nicht erfunden; Dark / Light Mode, Dynamic Type und Bedienungshilfen-Zusammenfassungen werden unterstützt.
- RT60: Oktavband-Balkendiagramm mit Ziellinie und Statusfarben.
- Schroeder-Abklingen: EDC-Kurve mit T20-Fit-Intervall.
- Frequenzgang: logarithmische Frequenzachse, Oktavglättung und Cursorablesung; Anzeige in dB SPL, solange der Kalibrier-Snapshot gültig ist.
- Impulsantwort: Wellenform mit Zeitnull- und Peak-Markern; Amplitude relativ zum Spitzenwert.
- Phase: Wrapped- / Unwrapped-Ansichten, Polaritätsumkehr, Zeitnull-Feinjustage und Hinweis zur Referenz-Verlässlichkeit.
- Gruppenlaufzeit: Gruppenlaufzeit im gültigen Band, optional mit Minimalphasen- / Exzessphasen-Analyse.
- IR-Fensterung: Peak- oder t=0-Referenz, getrennte linke / rechte Fensterbreiten, Rechteck / Hann / Tukey / Blackman; Original- und gefensterter Frequenzgang nebeneinander in der Vorschau — Fensterung und Phasenjustage wirken nur auf die Vorschau, nie auf die gespeicherte Messung.
- Spektrogramm: Zeit-Frequenz-Abklingen der IR, einstellbare Zeitspanne und Dynamik.
- Wasserfall & RT60 Decay: Visualisierung des Tiefton-Abklingens, Fensterlänge / Zeit / Dynamik einstellbar; Fits unzureichender Qualität werden nicht gezeigt.
- Echtzeitspektrum (RTA): 1/1–1/24-Oktav-Anzeige, A- / C- / Z-Bewertung, Instant- / Fast- / Slow-Ansprechen, Peak-Hold & Clear, Gesamtpegel, Spitzenpegel und dominante Frequenz.
- RTA nutzt die Kalibrierung des passenden Eingangs und ist bis zur SPL-Kalibrierung als dBFS gekennzeichnet; es schließt formelle Messungen gegenseitig aus (beim Betreten wird der Pegelmonitor der Messseite freigegeben, beim Schließen wiederhergestellt), und veraltete Callbacks überschreiben nach Stopp oder Eingangswechsel nie den frischen Zustand.
Verlauf, Mehrpositions-Mittelung & Overlays
- V2-Archiv: Messungen speichern Metadaten, verfügbare Rohaufnahme / IR-Sidecar und Analysedaten; Altaufzeichnungen bleiben schreibgeschützt kompatibel, fehlende Rohdaten werden nicht nachfabriziert.
- Verlaufsverwaltung: Messungen pro Raum ansehen und löschen, Details öffnen oder Aufzeichnungen für weitere Analysen wählen.
- Vorher- / Nachher-Vergleich: zwei beliebige Aufzeichnungen wählen und Gesamt- sowie Band-RT60, überlagerte Frequenzgänge und Unterschiede in den gültigen Bändern vergleichen.
- 2–6 Frequenzgang-Overlays: 1/3–1/48-Oktav-Glättung, Kurven einzeln ein- / ausblendbar, Bereichsvoreinstellungen wie Vollbereich / Tiefton; Pegel unausgerichtet, im Mittelband genullt oder auf die erste Kurve ausgerichtet, Offsets in der Legende; Quelldaten unverändert, und nicht überlagerbare Aufzeichnungen nennen den Grund.
- Messgruppen: Aufzeichnungen tragen Positionslabel, Gewichte und eine Vorher- / Nachher-Phase; Gruppe aus dem Verlauf bilden, einer beitreten oder eine neue Position direkt in eine Gruppe messen.
- Mehrpositions-Mittelung: arithmetischer dB-Mittelwert, RMS-Leistungsmittel und — bei verlässlicher Zeitreferenz und komplexen Spektren — vektorielle komplexe Mittelung; zeigt Mittelkurve, Mitgliedskurven und die frequenzweise min / max räumliche Streuung.
- Gruppenvergleich: vergleicht mittlere Frequenzgänge, räumliche Streuungen und mittlere RT60 zweier Gruppen und schließt auf die räumliche Konsistenz.
PEQ & Subwoofer-Abgleich
9.1 PEQ-Zielabgleich
- Parametrisierte Zielkurve: Zielpegel, Tieftonanhebung, Höhenabfall und Abgleichband.
- Filterbeschränkungen: Filteranzahl, maximale Anhebung / Absenkung und Q-Bereich.
- Vorhersage & Begründung: Messung, Ziel, Filterantworten und vorhergesagtes Ergebnis in einem Diagramm, mit Verbesserungsmetriken und Begründung je Filter.
- Ausschluss tiefer Senken: tiefe Senken durch akustische Auslöschung werden automatisch ausgeschlossen — keine großen Anhebungen auf ein Nullloch.
- Export: Generic-Text, Equalizer APO, miniDSP-Koeffizienten und CamillaDSP-YAML — nur Berechnung und Einstellungsexport; es wird nichts direkt auf Geräte geschrieben.
Es gibt noch keinen manuellen Filtereditor, keine Ziel-Preset-Bibliothek und keine EQ-Ergebnisarchivierung.
9.2 Zweiwege- & Multi-Sub-Abgleich
- Zweiwege-Abgleich: je eine Messung des Referenzlautsprechers und des einstellbaren Subwoofers wählen, die komplexe Summe vorhersagen und Verzögerung, Gain und Polarität lösen; Summenkurve vor und nach dem Abgleich.
- Multi-Sub, Multi-Sitz: 1–4 Subwoofer mit unabhängigen Messungen pro Sitz × Quelle; Optimierung für alle Sitze, Beschränkung durch den schlechtesten Sitz oder explizit nur der Hauptsitz.
- Ergebnisse & Teilen: Einstellungen pro Sub, Verbesserung pro Sitz, mittlere und Worst-Case-Metriken, Einstellungen als Text teilbar.
- Datenvoraussetzungen: Aufzeichnungen ohne Sweep-Konfiguration, verlässliche Zeitreferenz oder IR nennen den Grund ihrer Nichtverfügbarkeit, statt still ausgeschlossen zu werden.
Mehrsitzer-Ergebnisse sind derzeit eine Zahlentabelle ohne Überlagerung der Summenkurven pro Sitz; der Abgleich ist eine Vorhersage, die durch Nachmessen nach Anwendung der Einstellungen verifiziert werden muss; das Mischen von Quellen über Abtastraten hinweg ist noch zu validieren.
KI-Akustikassistent
Die Werkzeugleiste des Messverlaufs bietet einen Chat-Einstieg, der den eigenen Anthropic-API-Key des Nutzers verwendet (im Keychain des Geräts gespeichert); der Assistent sendet die für jede Anfrage nötigen Konversations- und Werkzeugdaten an Anthropic, und die API-Kosten trägt das Konto des Nutzers.
- Chat-Oberfläche: Streaming-Antworten, Werkzeugausführungsstatus, Stopp & Löschen sowie Nutzungs- / Kostenschätzung.
- Messdatenzugriff: Aufzeichnungen, Zusammenfassungen und partielle Frequenzgänge auflisten und Messungen vergleichen.
- Rechenwerkzeuge: ruft exakt dieselben PEQ-Empfehlungs- und Subwoofer-Abgleich-Algorithmen auf wie die manuelle Oberfläche.
- Raum- & Layout-Bewertung: listet Räume, liest Lautsprecher- / Hörerpositionen und Modendaten und sagt — auf einer Projektkopie — die Wirkung von Geräteverschiebungen oder geändertem Absorptionsprofil voraus; gespeicherte Projekte werden nie überschrieben.
- Messung nur nach Bestätigung: die KI schlägt Zweck und Kandidatenräume vor und startet den Sweep erst nach Bestätigung des Nutzers; Ablehnen oder Stoppen bricht die Anfrage ab.
- Geteilte Messeinstellungen: KI und manuelle Messung nutzen denselben Arbeitsbereich und erben Eingang, Mac-Wiedergabehelfer, Sweep-Bereich / -Dauer, Verzögerung und Loopback-Einstellungen; die Chat-Seite zeigt Live-Pegel / Fortschritt mit Abbruch und stellt danach den ursprünglichen Raum- und Messgruppenkontext wieder her.
- Sitzungswiederherstellung: eine aktuelle Sitzung wird gespeichert und kann wiederhergestellt werden, die zuletzt unterbrochene Werkzeugausführung wird markiert; das Löschen der Sitzung entfernt Verlauf und Nutzung zugleich.
Visualisierung & Ausgabe
11.1 3D-Ansicht
Room3DController rendert mit SceneKit: Wände / Boden / Decke / Lautsprecher (dünnes Gehäuse + Akzent + Kanal-Pille) / Hörer (FE-Glyph + Stiel) / Hindernisse (transluzente SCNBox) / empfohlene Panels / Mehrfachreflexions-Pfadsegmente / Reflexionsenergie-Overlay.
11.2 Reflexionsenergie-Heatmap
ReflectionEnergyMapGenerator akkumuliert die Energie jedes Pfads auf das uCells × vCells-Raster der Wand (Standard 12×6). Eine Karte je Wand, in 3D als Energie-Farbschicht (Blau → Cyan → Grün → Gelb → Rot).
EnergyHeatmapRenderer wandelt das Raster in ein UIImage: Block-Zellen à 16 px (keine Interpolation zwischen Zellen, damit Rasterkanten lesbar bleiben; die Glättung an der Wand übernimmt SceneKits bilineare Texturfilterung) + eigener 5-Stufen-Farbverlauf (Blau → Cyan → Grün → Gelb → Rot) + Alpha linear von 0,20 bis 0,85 nach Energieposition auf fester −30…0-dB-Skala (−∞ voll transparent).
11.3 RIR-Faltungs-Vorschau
RIRPreviewPlayer (AVAudioEngine + AVAudioPlayerNode) faltet ein prozedural synthetisiertes Trockensignal (gezupfte Saite / Klatsch-Burst / vokalartige Sprache — keine mitgelieferten Samples) mit dem simulierten RIR — hörbar „unbehandelt vs. behandelt“.
Zeitbereichs-Faltung RIRConvolver.convolve(dry:rir:) direkt O(N × M) (N = trockene Samples, M = RIR), Peak-normiert auf 0,9 gegen Clipping.
11.4 PDF-Montagehandbuch
ReportExporter rendert ein A4-PDF (595 × 842 pt) via UIGraphicsPDFRenderer:
- Raumübersicht + 3D-Schnappschuss
- 6-Band-RT60-Balkendiagramm: Sabine-Schätzung vs. Ziel, bei vorhandenen Messdaten mit Messwerten überlagert
- Reflexionspunkt-Tabelle + Moden-Tabelle + Risikoübersicht
- Empfohlene-Panel-Tabelle (die BOM-Einkaufsliste erscheint in der App, nicht im PDF)
- Bei vorhandenen Messdaten kommen RT60- / EDC- / Frequenzgang- / Spektrogramm- / Wasserfall- / Phasendiagramme sowie eine Mehrpositions-Mittelungsübersicht hinzu; die Frequenzgang-Einheit nutzt den zum Messzeitpunkt gespeicherten Kalibrier-Snapshot (ehrlich als dB SPL oder dBFS gekennzeichnet)
- Geist-Schrift + PingFangSC-Fallback (CoreText cascadeList, damit CJK nicht als □□□ erscheint)
11.5 Projekt-Persistenz
ProjectStore (Actor) schreibt ~/Library/Application Support/Acouvero/projects.json: [RoomProject], je mit Room + Lautsprechern + Hörern + Empfehlungen + panelCountOverrides. Beim ersten Start migrieren Daten automatisch aus dem alten Verzeichnis FindEcho/ (FindEcho ist der interne Codename vor der Umbenennung, in Codesymbolen bewusst beibehalten).
MeasurementStore (Actor) schreibt measurements.json: [MeasurementResult], per roomId mit dem Projekt verknüpft.
Beide nutzen elementweise Decode-Wiederherstellung (Throwable<T>-Wrapper) — ein defekter Datensatz lässt nicht die ganze Liste scheitern.
MicCalibrationStore schreibt ~/Library/Application Support/mic_calibration.json (Wurzelverzeichnis, kein Unterordner): REW-Kalibrierkurve + SPL-Offset, an die Eingangsport-UID gebunden — bei Eingangswechsel ist erneutes Importieren / Kalibrieren nötig.
Engineering-Hinweise
12.1 SwiftUI + @Observable
Das ViewModel (FindEchoViewModel) nutzt Swift 5.9 @Observable — Statusfelder direkt beobachtet, kein Combine. AcousticAnalysis-Ergebnisse werden per Equatable-Vergleich von AcousticConfiguration gecacht:
var analysis: AcousticAnalysis {
let cfg = configuration
if let cached = cachedAnalysis, cachedConfiguration == cfg {
return cached
}
let result = analysisService.analyze(cfg)
cachedConfiguration = cfg
cachedAnalysis = result
return result
}
12.2 Actor-Isolation
ProjectStore und MeasurementStore sind actors, die IO / Async natürlich serialisieren; RoomPlanService ist eine @MainActor-Klasse. Die UI nutzt async / await; der Hauptthread wird nie durch Disk-IO blockiert.
12.3 AVAudio-Lebenszyklus
AudioSessionManager zentralisiert die Session-Kategorie (.playback für RIR-Vorschau, .playAndRecord für Messung). Unterbrechungsschutz gibt es auf beiden Pfaden: messseitig lauscht ein InterruptionMonitor in AudioMeasurementService auf AVAudioSession.interruptionNotification — ein Anruf / Siri während Sweep, Klatschen oder Umgebungsrauschen verwirft das Ergebnis mit Fehler; vorschauseitig hört RIRPreviewPlayer ebenfalls zu und stoppt den Player-Node, isPlaying wird gelöscht. Auch ein Routenwechsel mitten in der Messung verwirft den Lauf.
12.4 Task-Abbruch
Die Faltungs-Wiedergabe ist ein Hintergrund-Task; schnelle Taps lösen pendingPlayTask?.cancel() plus Task.isCancelled-Doppelprüfung aus, um Out-of-order-MainActor-Schreibvorgänge zu verhindern.
12.5 Testabdeckung
AllShapesAndUseCasesTests nutzt das Swift-Testing-Framework für die volle Matrix — jede Form × jeder Anwendungsfall (ein Hörer; Lautsprecher je nach Fall als Stereopaar oder einzeln mittig) — und prüft:
analysis.reflectionPaths.count >= 1analysis.warningsenthält den Näherungshinweis für nicht rechteckige Räume- die empfohlene Panel-Summe ist nicht negativ (totalPanelCount ≥ 0; keine Budget-Assertion)
- selbstschneidende eigene Polygone fallen sicher zurück (kein Crash, Degradierung zum Rechteck)
- Ecken < 3 und weitere Randfall-Rückfälle
12.6 Plattform & Lokalisierung
Deployment-Target iOS 17.0, iPhone + iPad; null Drittanbieter-Abhängigkeiten (keine SPM- / CocoaPods-Pakete) — nur System-Frameworks (SwiftUI / SceneKit / ARKit / RoomPlan / AVFoundation / Accelerate). Lokalisierung per .xcstrings-Katalog: Chinesisch als Quellsprache plus English / Français / Deutsch / Español / Português (Brasil) — 6 Sprachen, in der App oder systemfolgend umschaltbar.
Bekannte Grenzen
- Multi-Order in nicht rechteckigen Räumen via Bounding Box — Flutter-/Slapback-Risiko 2./3. Ordnung nahe konkaven Ecken kann abweichen. Erste Ordnung nutzt das echte Polygon.
- Raummoden in nicht rechteckigen Räumen via Bounding Box geschätzt — exakte Moden brauchen FEM.
- Messung mit iPhone-Mikrofon — unkalibriert; nicht-flacher Frequenzgang / Empfindlichkeit. Zuverlässigkeit immer
.low, als Quervergleich zur geometrischen Schätzung. Mit einem USB-Messmikrofon (miniDSP UMIK-1 / UMIK-2) und geladener REW-Kalibrierdatei werden die Bandpegel gemäß Kalibrierkurve korrigiert; eine einmalige 94-dB-SPL-Referenz zeigt danach Umgebungs- und Messpegel als absolute dB SPL (vorher nur dBFS). - Einzelquellen-ISM-Annahme — ignoriert Gehäusebeugung, Horn-Richtwirkung u. a.
- Keine Bassfallen-Modellierung — Probleme unter 80 Hz liegen außerhalb des Sabine-Modells und brauchen dedizierte Tieftonbehandlung.
- AR-Scan-Genauigkeit — RoomPlan-Endpunkte typ. 3-8 cm Fehler; 12-Segment-Schleife kann 5+ cm akkumulieren. Wanddicke nicht modelliert.
- Grenzen des Analyseumfangs — vektorielle komplexe Mittelung über Abtastraten hinweg wird noch nicht unterstützt; Mehrsitzer-Abgleichsergebnisse sind derzeit eine Zahlentabelle ohne Überlagerung der Summenkurven pro Sitz; Frequenzgang-Overlays fließen noch nicht ins PDF.
- Noch nicht implementierte Profi-Werkzeuge — kein Langzeit-SPL-Logger, keine STI-Sprachverständlichkeit, keine Verzerrungsmessung (THD); Impedanz / Thiele-Small und REST-API fehlen ebenfalls.
- Ausstehende Abnahme auf Gerät — der echte API-Pfad des KI-Assistenten (Streaming mit echtem Key / bestätigte Messung / Aufnahmearchivierung) und die komplette UMIK-Messmikrofon-Kette auf echter Hardware (inkl. UMIK-2 mit 96 kHz) stehen noch aus; Simulator-Erfolge beweisen keinen geschlossenen Audio-Pfad auf dem Gerät.
Referenzen
- Sabine, W. C. (1922). Collected Papers on Acoustics. Harvard University Press.
- Allen, J. B., & Berkley, D. A. (1979). Image method for efficiently simulating small-room acoustics. JASA, 65(4), 943–950.
- Schroeder, M. R. (1965). New method of measuring reverberation time. JASA, 37(3), 409–412.
- Farina, A. (2000). Simultaneous measurement of impulse response and distortion with a swept-sine technique. Audio Engineering Society Convention 108.
- Scheibler, R., Bezzam, E., & Dokmanić, I. (2018). Pyroomacoustics: A Python package for audio room simulation and array processing algorithms. ICASSP 2018.
- EBU Tech 3276. Listening conditions for the assessment of sound programme material.
- ITU-R BS.1116. Methods for the subjective assessment of small impairments in audio systems.
- BB93 — Acoustic design of schools (UK).
- THX Pro Cinema Certification requirements.