Acouvero
Télécharger
TECHNICAL DOC · v0.5.0

Acoustique des pièces,
de la mesure
au plan.

Acouvero est un outil d'analyse acoustique et de planification de traitement pour iPhone / iPad. Ce document s'adresse aux lecteurs intéressés par l'ingénierie acoustique ou l'implémentation client : algorithmes, système géométrique, méthodes de mesure, moteur de recommandation et notes d'ingénierie.

Bandes d'octave
6bandes
Formes
4géométries
Réflexions
1–3ordres
§ 01

Vue d'ensemble

Entrée : l'utilisateur saisit dimensions / forme / matériaux, positions des enceintes et du point d'écoute — ou la géométrie est mesurée au mètre AR (sans LiDAR) ou capturée par scan LiDAR (RoomPlan).

Sortie
  • Localisation des premières réflexions
  • RT60 (mesuré + simulé) plus EDT / C50 / C80 / D50 (dérivés de la RIR simulée)
  • Liste des fréquences modales
  • Plan d'implantation des panneaux (position, nombre, SKU)
  • Visualisation 3D + carte d'énergie des réflexions
  • Export PDF de niveau manuel d'installation
  • Mesure in situ par balayage ESS / claquement (micro intégré ou micro de mesure USB)
  • Calibration de micro USB de mesure & référence SPL, spectre temps réel (RTA)
  • Superpositions de réponse & moyennes multi-positions, interopérabilité REW, PEQ / alignement de caisson, assistant IA

Pièces rectangulaires, en L, en U et tout polygone simple sont pris en charge ; les réflexions du 1er ordre et les calculs d'aire / d'appartenance utilisent le vrai polygone ; les ordres 2/3 et les modes passent par la boîte englobante (voir §9).

§ 02

Modèle acoustique

VERSION GRAND PUBLIC Ces notions ont chacune une explication grand public : qu’est-ce que le RT60, modes de pièce et ondes stationnaires et la méthode des sources images.

2.1 Sabine RT60

La formule de Sabine classique :

SABINE · RT60RT60=0.161⋅V∑iSiαi RT_{60} = \frac{0.161 \cdot V}{\sum_i S_i \alpha_i}
VV
Volume (m³) ; pour les polygones, aire de Shoelace × hauteur, moins les obstacles (poteaux / poutres).
∑iSiαi\sum_i S_i \alpha_i
Surface × coefficient d'absorption par face. Coefficients sur 6 bandes (125 / 250 / 500 / 1k / 2k / 4k Hz).
0.1610.161
= 24·ln(10)/c, avec c = 343 m/s (20 °C).

L'app fournit 4 préréglages de finition (pièce vide et dure / finition dure typique / mobilier / déjà traité), chacun avec une courbe d'absorption par bande ; l'estimation RT60 mono-valeur et le budget de panneaux utilisent un coefficient moyen médiums-aigus, la courbe Sabine à 6 bandes alimentant l'affichage par bande. Le RT60 cible est aussi une courbe à 6 bandes, conforme aux normes EBU Tech 3276 / THX qui tolèrent une traîne plus longue dans le grave.

2.2 Méthode des sources images (ISM)

Les premières réflexions utilisent le miroir : on reflète la source par rapport au mur ; l'intersection du segment « source miroir → auditeur » avec le mur est le point de réflexion.

  • Pièce rectangulaire : miroir sur les 6 plans (4 murs + sol + plafond) — solution analytique.
  • Non rectangulaire (PolygonReflectionCalculator) : miroir sur chaque segment de RoomPolygon.walls() et validation du paramètre s ∈ [0, 1] (les réflexions sol / plafond exigent en plus un XY dans le polygone) ; les trajets du 1er ordre subissent aussi un test d'occlusion 2D — tout tronçon source→point→auditeur croisant un autre segment de mur est écarté.

Les réflexions multi-ordres (1–3) sont implémentées par MultiOrderReflectionCalculator selon l'approche récursive de pyroomacoustics :

  1. Énumérer toutes les séquences de murs [s₁, …, sₙ], murs adjacents distincts
  2. Itération source-image : S₀ = source, Sₖ = mirror(Sₖ₋₁, sₖ)
  3. Tracé inverse depuis l'auditeur : Sₙ → auditeur coupe sₙ en Pₙ ; Sₙ₋₁ → Pₙ coupe sₙ₋₁ en Pₙ₋₁ ; et ainsi de suite
  4. Chaque intersection doit être dans la plage valide du mur et t ∈ (0, 1)
APPROXIMATION Pour les pièces non rectangulaires, le multi-ordre approxime par la boîte englobante (« réflexions fantômes » près des angles rentrants). L'analyse rejette tout trajet dont le point est > 0,3 m de tout segment réel ; seuls les trajets valides alimentent la détection de flutter / slapback.

2.3 Énergie des trajets

Énergie large bande selon le nombre de réflexions et l'atténuation de distance :

PATH ENERGYErel=(1−αˉ)N⋅ddirect2dtotal2 E_{rel} = (1 - \bar{\alpha})^N \cdot \frac{d_{direct}^2}{d_{total}^2}
  • α est borné à [0, 0.99] pour éviter que α = 1 produise log(0) ou pow(négatif, N) = NaN
  • L'atténuation suit la divergence sphérique 1/r²
  • Conversion en dB via 10·log₁₀ (domaine énergétique)

L'énergie par bande est calculée pour les 6 bandes (coefficient de finishProfile.absorptionByBand).

2.4 Estimation RT60 (mesurée)

ImpulseResponseEstimator :

  • Filtrage adapté : le balayage enregistré est filtré en inverse (ESS / Farina) en une impulsion ; gain de traitement ≈ 10·log₁₀(T·B) — environ +41 dB de SNR effective pour le préréglage téléphone 3 s, 180 Hz–4 kHz
  • rmsEnvelope : enveloppe RMS à fenêtre glissante
  • Intégration inverse de Schroeder : E_back(t) = ∫ₜ^∞ s²(τ) dτ, normalisée en 10·log₁₀ pour la courbe EDC
  • Régression linéaire de pente : T30 [−5, −35 dB] selon SNR, repli T20 [−5, −25] ou T10 [−5, −15]
  • RT₆₀ = −60 / pente

RT60 par bande : sur les échantillons filtrés, passe-bande aux centres d’octave ISO choisis selon la plage de balayage réelle (Q = √2), puis Schroeder par bande.

2.5 Simulation de RIR

SimulatedRIRGenerator convertit les trajets multi-ordres en impulsions discrètes écrites dans un buffer PCM 8 kHz × 0,5 s :

SimulatedRIRGeneratorpseudocode
for path in reflectionPaths:
    t   = path.totalDistance / speedOfSound
    amp = 10^(path.relativeEnergyDB / 20)
    impulse[round(t * sampleRate)] += amp

Ajouter l'impulsion du son direct, puis intégration inverse de Schroeder pour EDT / RT60 / C50 / C80 / D50.

Comparaison avant / après Chaque trajet est atténué par les panneaux des murs traversés, produisant un RIR « traité ». L'UI bascule A/B pour montrer le gain EDT / C50, et AVAudio convolue un signal sec pour comparer à l'oreille.

2.6 Modes propres

Fréquences modales d'une pièce rectangulaire :

ROOM MODESfnx,ny,nz=c2(nxLx)2+(nyLy)2+(nzLz)2 f_{n_x, n_y, n_z} = \frac{c}{2} \sqrt{\left(\frac{n_x}{L_x}\right)^2 + \left(\frac{n_y}{L_y}\right)^2 + \left(\frac{n_z}{L_z}\right)^2}

Classés selon le nombre de nₓ, n_y, n_z non nuls : 1 = axial, 2 = tangentiel, 3 = oblique.

L'énumération couvre n ≤ 4 par axe jusqu'à 300 Hz. Les pièces non rectangulaires estiment les modes via la boîte englobante (les modes exacts exigent un FEM) ; indiqué dans l'UI.

§ 03

Système géométrique

3.1 Formes prises en charge

  • Rectangle — largeur × longueur × hauteur
  • Forme en L — retire une encoche nw × nl à un coin choisi
  • Forme en U — retire une encoche nw × nl au milieu d'un mur
  • Personnalisé — tout polygone simple (≥ 3, ≤ 24 sommets)

Toutes les formes non rectangulaires deviennent une liste de sommets CCW via RoomPolygon.from(shape:, bboxWidth:, bboxLength:). Réflexions du 1er ordre, aire / périmètre et appartenance utilisent ces sommets directement ; un polygone personnalisé invalide (< 3 / > 24 sommets, auto-sécant, aire quasi nulle) se dégrade silencieusement en rectangle englobant.

3.2 Outils de géométrie polygonale

  • Aire — formule de Shoelace
  • Périmètre — somme des longueurs d'arêtes
  • contains(x, y) — lancer de rayon + epsilon de bord (évite les faux négatifs aux coins)
  • clamped(point) — les rectangles utilisent [0, w] × [0, l] ; les autres utilisent le vrai [minₓ, maxₓ] × [min_y, max_y] de polygon.boundingBox, testent polygon.contains, et dichotomie vers le centre si hors polygone
  • walls() — découpe le polygone en segments classés par normale intérieure (leftWall / rightWall / frontWall / backWall), réutilisant le recommandeur rectangulaire
  • PolygonValidator.isSimple — valide un polygone simple non auto-sécant

3.3 Numérisation RoomPlan

RoomCaptureSession (API iOS 16+ ; l'app réserve le scan à iOS 17) est utilisé, et CapturedRoomMapper mappe le scan en ScannedRoom (wallSegments + openings + furniture). Mappage des coordonnées :

ARKit (x, y, z) → y est vertical App (x, y, z) → z est vertical Extrémités de mur (z=0 sol) App.x = ARKit.x App.y = ARKit.z App.z = 0 Centre ouverture / mobilier  App.x = ARKit.x App.y = ARKit.z App.z = ARKit.y

Le scan est classé par nombre de murs : exactement 4 segments = rectangle d'office ; sinon passage par RectangularRoomSimplifier.polygonShapeFromScan, chaînant les wallSegments en sommets. Les extrémités RoomPlan ont une erreur de 3–8 cm ; une boucle de 12 segments peut cumuler 5 cm, d'où un epsilon de fermeture de 12 cm. Si la boucle ne ferme pas, repli sur la boîte englobante et invitation à rescanner.

3.4 Mètre AR

Sans LiDAR, ARTapeMeasureView (ARView RealityKit en suivi du monde) prend le relais : viser le mur avec le réticule et taper deux fois pour marquer début / fin, en chaînant largeur → longueur → hauteur, puis confirmer pour obtenir une pièce rectangulaire — avec guide de permission caméra et alertes de perte de suivi.

3.5 Éditeur de sommets libres

FreeVertexEditorView permet de glisser les sommets sur un Canvas SwiftUI :

  • Appui long pour supprimer (si sommets > 3, pour en garder ≥ 3)
  • Chaque frame de glissement est validée par isSimple ; une position auto-sécante n'est simplement pas appliquée (le sommet reste en place). Toucher une zone vide insère un sommet sur l'arête la plus proche ; s'y ajoutent un éditeur numérique par sommet et une réinitialisation au rectangle englobant
  • Accrochage à la grille de 0,05 m
  • Une marge max(0,5, bbox × 0,2) m hors bbox permet de tirer les sommets au-delà de la bbox (la vue parente agrandit room.width / length)
§ 04

Zones d'écoute & multi-auditeur

AcousticConfiguration.listeners gère 1..N positions d'écoute (sans auditeur, une position principale par défaut est synthétisée avec avertissement ; sans enceinte, les gabarits du §5.2 prennent le relais). L'analyse exécute la méthode des images par auditeur et fusionne les points dans un tableau (l'auditeur principal d'abord). Le recommandeur pondère chaque mur par son nombre de points (cap = max(6, speakerCount × listenerCount)) ; plusieurs sièges partageant un mur le poussent vers le plafond du budget.

Visuel UI
  • En 3D, les auditeurs secondaires : opacité 0,45 + échelle 0,75
  • Vue de dessus (RoomPlanView) : points primaires pleine couleur r=5, secondaires opacité 0,45 r=3
  • La liste (RecommendationView) n'affiche que les points primaires ; note de bas de page « + N réflexions déjà comptées »

Réflexions multi-ordres / RIR / carte sont calculées une fois pour l'auditeur principal (O(speakers × surfaces³) par auditeur est trop lourd, et le RIR est ponctuel).

§ 05

Moteur de recommandation

PanelPlacementRecommender produit [PanelRecommendation], chacun avec : position (mur gauche / droit / plafond / avant / arrière / coin), nombre, priorité (essentiel / fort / recommandé / optionnel), effectivenessMultiplier, targetReflectionPointId.

5.1 Répartition proportionnelle (plus fort reste)

L'ancien add() glouton affamait des murs : le mur gauche vidait le budget → mur droit à 0 ; budget serré, plafond / avant / arrière affamés. La nouvelle version : méthode du plus fort reste :

  • Calculer le « raw desired » par mur (nombre de points + profondeur + cas d'usage)
  • floor(raw × budget / total) comme allocation initiale
  • les murs avec raw &gt; 0 reçoivent ≥ 1 panneau ; ce n'est que si le budget est inférieur au nombre de murs en demande que des surfaces sont remises à zéro, priorité la plus basse d'abord
  • si somme &gt; budget, retrancher en partant du plus petit reste fractionnaire
  • passe de symétrie G/D : si raw[0] == raw[1], forcer alloc[0] == alloc[1]
  • redistribuer le reliquat selon la plus grande fraction

5.2 Modèles par cas d'usage

Sans enceintes placées, des modèles spécifiques s'appliquent :

  • Salle de réunion : plafond 35 % + mur arrière 20 % + chaque mur latéral 12 %
  • Podcast : devant le micro 25 % + chaque côté 18 % + plafond 20 %
  • Studio : amortissement symétrique 4 murs + jusqu'à 4 pièges à graves d'angle dans la limite du budget (le vrai contournement du budget n'a lieu que sur la voie « modes graves denses » du §5.3)
  • Écoute générale : base symétrique + invitation à ajouter des enceintes

5.3 Les nécessités physiques contournent le budget

Les pièges à graves d'angle sont forcés à 4 quand les modes 80–150 Hz sont denses, contournant le plafond totalPanel. Raison : la pression est maximale aux angles et les pièges y sont ~1,5× plus efficaces — une nécessité physique.

5.4 Pondération proche auditeur

Une passe finale marque les recommandations à moins d'1,5 m d'un auditeur en .nearListener, effectivenessMultiplier ×1,15, et l'indique dans le titre / la raison.

§ 06

Mesure

VERSION GRAND PUBLIC Ces trois sujets ont chacun une page en langage clair : la mesure par balayage, le test du claquement et choisir un micro de mesure.

6.1 Balayage ESS

Balayage logarithmique ESS (méthode de Farina) : quatre préréglages + personnalisé, durées de 3 / 6 / 12 s :

  • Test rapide au téléphone : 180 Hz–4 kHz en sortie intégrée, 75 Hz–4 kHz en sortie externe (seul préréglage autorisant le haut-parleur intégré)
  • Graves / caisson : 15–300 Hz (sortie externe requise)
  • Pleine bande : 20 Hz–20 kHz (sortie externe requise)
  • Personnalisé : bornes libres entre 10 Hz et 20 kHz couvrant au moins une octave (sortie externe requise)
  • Filtre inverse (makeInverseSweep) = inversion temporelle + enveloppe d’amplitude de +6 dB/octave (croissante avec la fréquence, pour compenser le spectre rose de l’ESS)
  • Enregistrement via AVAudioRecorder en Linear PCM sans perte (mono 16 bits .caf, ~96 dB de dynamique — les codecs perceptuels n'ont pas leur place en mesure d'impulsion ; le taux suit la session audio — 44,1 kHz au micro intégré, 48 kHz natifs avec un micro de mesure USB)
  • Relecture → filtrage adapté → analyzeImpulse

Signal de lecture, balayage inverse et analyse partagent la même configuration, la fréquence haute étant plafonnée par le taux d’échantillonnage réel ; les préréglages graves / pleine bande / personnalisé refusent de démarrer sans sortie externe. Les bandes d’octave RT60 sont choisies selon la plage de balayage réelle ; la plage d’un préréglage est la configuration du stimulus — la plage fiable dépend toujours de l’enceinte, du micro et de la qualité de mesure.

Alignement d'échantillonnage Le WAV de balayage, le balayage inverse et l'enregistrement sont tous générés au taux d'échantillonnage réel de la session audio (makeInverseSweep(sampleRate:) est paramétré) — le filtrage adapté est toujours actif, à 44,1 kHz (micro intégré) comme à 48 kHz (micros de mesure USB).

6.2 Impulsion par claquement

Sans lecture — l’utilisateur claque fort une fois dans une fenêtre de 1 s ; 4,5 s enregistrées au total (~3,5 s de traîne). Directement vers analyzeImpulse (pas de filtre adapté ; un claquement est déjà une impulsion étroite). Couvre la bande 125 Hz que le préréglage téléphone (dès 180 Hz) rate.

6.3 Mesuré vs simulé

MeasuredVsSimulatedCard récupère le dernier RT60 mesuré et affiche l'écart avec le RT60 simulé :

< 15%modèle et mesure concordent
15–30%écart (mobilier / matériaux non modélisés)
> 30%écart important — vérifier géométrie / matériaux

6.4 Bruit ambiant & calibrage

AmbientNoiseEstimator enregistre 3 s de silence (100 ms rognées à chaque bout) pour le bruit de fond : dBFS moyen / crête large bande + évaluation du calme en 5 niveaux (dBFS relatif tant qu'il n'y a pas de calibration SPL, puis affichage en dB SPL). La calibration de latence en champ proche réutilise le même balayage ESS : téléphone à moins de 30 cm de l'enceinte, délai début d'enregistrement → pic d'impulsion (dont 250 ms de pré-roll délibéré), idéalement 2–3 essais — dispersion des 3 dernières mesures < 5 ms = haute confiance, < 20 ms = moyenne. La latence est liée au couple « entrée + sortie » courant et invalidée dès qu'un côté change ; les mesures lointaines affichent le délai de propagation corrigé.

6.5 Référence temporelle & qualité de mesure

  • Référence temporelle acoustique : un chirp précède le balayage comme ancre temporelle, redétectée à chaque mesure ; en cas d’échec, repli avec indication explicite de la fiabilité de phase — aucune prétention d’alignement absolu entre mesures.
  • Dérive d’horloge : estime l’écart d’horloge entre les chaînes de lecture et d’enregistrement et le corrige quand les conditions le permettent.
  • Référence loopback électrique : les interfaces USB multi-entrées peuvent utiliser un second canal comme référence loopback ; à défaut, repli sur la référence acoustique. Le chemin de l’assistant de lecture Mac n’utilise pas le loopback électrique local.
  • Champs de qualité : chaque relevé conserve le SNR, le plancher de bruit, l’état d’écrêtage, l’offset temporel de l’IR, l’entrée réelle et le taux d’échantillonnage disponibles ; ce qui ne peut être déterminé reste vide, jamais inventé.
  • Gestion de l’écrêtage : un balayage écrêté est invalidé avec invitation à refaire la mesure ; les relevés de claquement sont marqués et signalés.
  • Contraste simulation / mesure : la dernière mesure de la pièce est comparée côte à côte au RT60 de la simulation géométrique pour évaluer l’adéquation du modèle (seuils en 6.3).

6.6 Micros USB de mesure & routage de sortie

Le sélecteur d’entrée de la page de mesure liste le micro intégré et les entrées USB class-compliant (miniDSP UMIK-1 / UMIK-2, par ex.) ; une écoute de routeChangeNotification rebascule sur le micro intégré si le micro externe disparaît. Les taux d’enregistrement et de balayage suivent la session (UMIK-1 = 48 kHz). Les fichiers de calibration fréquentielle .txt de style REW / UMIK s’importent directement (lecture de Sens Factor et du numéro de série, interpolation en fréquence log ; fichier 90° conseillé pour les mesures de pièce). La calibration est liée à l’UID du port d’entrée — sur une entrée non correspondante, l’ancienne calibration n’est pas appliquée.

Calibration SPL de référence unique : placer un calibrateur (94 dB @ 1 kHz par défaut) sur le micro, l’app échantillonne 3 s de niveau pour dériver l’offset dBFS → SPL ; les dB SPL ne s’affichent que si l’entrée correspond et qu’une calibration SPL existe — sinon les mesures restent en dBFS. Instantané de calibration à la mesure : les nouveaux relevés balayage / claquement enregistrent la courbe de calibration, le nom, le numéro de série, le Sens Factor, l’offset SPL et l’UID d’entrée alors en vigueur — remplacer, effacer ou relier la calibration ensuite ne change plus les lectures de ces relevés ; détail de mesure, aperçu de réponse après fenêtrage IR, export texte de la réponse et PDF utilisent le même instantané. La calibration elle-même est persistée par UID de port d’entrée dans ~/Library/Application Support/mic_calibration.json.

La lecture passe par le sélecteur de route système (wrapper AVRoutePickerView, placé sur les cartes balayage / calibration champ proche) ; la session autorise AirPlay / Bluetooth A2DP / HFP pour jouer les signaux via des enceintes externes, avec repli sur le haut-parleur sinon. L’entrée d’enregistrement est toujours explicitement épinglée au choix de l’utilisateur (micro USB ou intégré) pour empêcher le micro d’un appareil Bluetooth de voler l’entrée pendant la lecture et de polluer la mesure. Assistant de lecture Mac : découvre AcouveroMacSpeaker sur le réseau local via Bonjour, transfère d’abord le WAV de balayage vers le Mac puis envoie la commande de lecture, l’iPhone enregistrant — pour les sorties Mac qui ne peuvent pas héberger directement l’audio de la session de mesure (ce chemin n’utilise pas le loopback électrique local).

6.7 Interopérabilité REW & fichiers

  • Import / export texte de réponse : compatible avec les séparateurs courants, lignes de commentaire, notation scientifique et formats décimaux, avec validation de l’axe fréquentiel à l’import ; sans colonne de phase, aucune donnée de phase n’est générée.
  • Export conscient de la calibration : export en dB SPL si un instantané de calibration SPL valide existe, en dBFS sinon — l’en-tête étiquette l’unité honnêtement.
  • Import audio d’IR : réponses impulsionnelles WAV / AIFF prises en charge ; les fichiers multicanaux exigent un choix de canal explicite.
  • Analyse de balayage hors ligne : export du fichier de stimulus pour lecture externe, puis après import de l’enregistrement, les fréquences de début / fin et la durée doivent être déclarées avant la déconvolution — les paramètres du balayage ne sont jamais devinés.
  • Export de partage audio : les IR ou enregistrements bruts disponibles peuvent être partagés en WAV.
  • Les résultats importés peuvent être archivés et alimenter les graphiques, superpositions et analyses applicables ; leur admission dans un groupe de mesure dépend du type de données et du périmètre de confiance. Les fichiers projet REW .mdat ne sont pas lus pour l’instant.
§ 07

Graphiques & analyse de mesure

La page de détail affiche les graphiques selon les données réellement présentes dans chaque relevé — aucune courbe manquante n’est fabriquée ; modes sombre / clair, Dynamic Type et résumés d’accessibilité pris en charge.

  • RT60 : histogramme par bande d’octave avec ligne cible et couleurs d’état.
  • Décroissance de Schroeder : courbe EDC avec l’intervalle d’ajustement T20.
  • Réponse en fréquence : axe logarithmique, lissage par octave et lecture au curseur ; affichée en dB SPL tant que l’instantané de calibration est valide.
  • Réponse impulsionnelle : forme d’onde avec marqueurs de zéro temporel et de pic ; amplitude relative au pic.
  • Phase : vues wrapped / unwrapped, inversion de polarité, ajustement fin du zéro temporel et indication de fiabilité de la référence.
  • Délai de groupe : délai de groupe sur la bande valide, avec option d’analyse phase minimale / phase en excès.
  • Fenêtrage d’IR : référence pic ou t=0, largeurs gauche / droite indépendantes, rectangulaire / Hann / Tukey / Blackman ; réponses originale et fenêtrée en aperçu côte à côte — fenêtrage et ajustement de phase n’affectent que l’aperçu, jamais la mesure enregistrée.
  • Spectrogramme : décroissance temps-fréquence de l’IR, plage temporelle et dynamique réglables.
  • Cascade & RT60 Decay : visualisation de la décroissance des graves, longueur de fenêtre / temps / dynamique réglables ; les ajustements de qualité insuffisante ne sont pas affichés.
  • Spectre temps réel (RTA) : affichage 1/1–1/24 d’octave, pondération A / C / Z, réponse instantanée / Fast / Slow, maintien et effacement des pics, niveau global, niveau de pic et fréquence dominante.
  • Le RTA utilise la calibration de l’entrée correspondante et reste étiqueté dBFS tant qu’aucune calibration SPL n’existe ; il est mutuellement exclusif avec les mesures formelles (entrer libère l’écoute de niveau de la page de mesure, fermer la restaure), et d’anciens rappels n’écrasent jamais l’état frais après un arrêt ou un changement d’entrée.
Conditions de données · DATA GATING Phase, délai de groupe et fenêtrage exigent un balayage et une IR de qualité ; quand la référence temporelle est insuffisante, l’UI parle explicitement de phase relative — aucune prétention d’alignement absolu fiable entre mesures. Le RTA n’a pas encore d’enregistreur SPL longue durée.
§ 08

Historique, moyennes multi-positions & superpositions

  • Archivage V2 : les mesures conservent métadonnées, enregistrement brut / sidecar IR disponibles et données d’analyse ; les anciens relevés restent compatibles en lecture seule, sans fabrication des données brutes manquantes.
  • Gestion de l’historique : parcourir et supprimer les mesures par pièce, ouvrir le détail ou choisir des relevés pour analyse ultérieure.
  • Comparaison avant / après : choisir deux relevés pour comparer RT60 global et par bande, réponses superposées et écarts sur les bandes valides.
  • Superposition de 2–6 réponses : lissage 1/3–1/48 d’octave, affichage individuel par courbe, préréglages de plage pleine bande / graves ; niveaux non alignés, remise à zéro en médian ou alignés sur la première courbe, offsets affichés en légende ; données sources intactes, et les relevés non superposables expliquent pourquoi.
  • Groupes de mesure : les relevés portent étiquette de position, poids et étape avant / après ; créer un groupe depuis l’historique, y adhérer, ou mesurer une nouvelle position directement dans un groupe.
  • Moyennes multi-positions : moyenne arithmétique en dB, moyenne de puissance RMS, et — avec référence temporelle fiable et spectres complexes — moyenne complexe vectorielle ; affiche la courbe moyenne, les courbes membres et l’étendue spatiale min / max par fréquence.
  • Comparaison de groupes : compare réponses moyennes, étendues spatiales et RT60 moyens de deux groupes, avec conclusion sur la cohérence spatiale.
Limites · BOUNDARIES Moyennes et comparaisons de groupes utilisent pour l’instant des dB relatifs ; la moyenne vectorielle entre taux d’échantillonnage n’est pas encore prise en charge. Les superpositions utilisent des préréglages de plage — pas encore de zoom gestuel, de superpositions phase / cascade / décroissance, ni d’export PDF des superpositions.
§ 09

PEQ & alignement de caisson de graves

VERSION GRAND PUBLIC Ces deux sujets ont chacun une page en langage clair : l’égalisation paramétrique et l’alignement du caisson.

9.1 Correspondance de cible PEQ

  • Courbe cible paramétrée : niveau cible, remontée des graves, pente des aigus et bande d’ajustement.
  • Contraintes de filtre : nombre de filtres, gain / atténuation max et plage de Q.
  • Prédiction & justification : mesure, cible, réponses des filtres et résultat prédit sur un même graphique, avec métriques d’amélioration et justification filtre par filtre.
  • Exclusion des creux profonds : les creux profonds dus à l’annulation acoustique sont exclus automatiquement, évitant de gros gains jetés dans un nul.
  • Export : texte Generic, Equalizer APO, coefficients miniDSP et YAML CamillaDSP — calcul et export de réglages uniquement ; rien n’est écrit directement sur les appareils.

Pas encore d’éditeur de filtre manuel, de bibliothèque de cibles ni d’archivage des résultats EQ.

9.2 Alignement deux voies & multi-caissons

  • Alignement deux voies : choisir une mesure d’enceinte de référence et une de caisson réglable, prédire la sommation complexe et résoudre délai, gain et polarité ; courbe sommée affichée avant et après alignement.
  • Multi-caissons, multi-sièges : 1–4 caissons avec mesures indépendantes choisies par siège × source ; optimisation pour tous les sièges, contrainte par le pire siège, ou explicitement le siège principal seul.
  • Résultats & partage : réglages par caisson, amélioration par siège, métriques moyennes et pire cas, réglages partageables en texte.
  • Conditions de données : les relevés sans configuration de balayage, référence temporelle fiable ou IR affichent la raison de leur indisponibilité au lieu d’être silencieusement exclus.

Les résultats multi-sièges sont pour l’instant un tableau numérique sans superposition de courbes sommées par siège ; l’alignement est une prédiction à vérifier en remesurant après application des réglages ; le mélange de sources à différents taux d’échantillonnage reste à valider.

§ 10

Assistant acoustique IA

La barre d’outils de l’historique des mesures propose une entrée de chat utilisant la propre clé API Anthropic de l’utilisateur (stockée dans le Keychain de l’appareil) ; l’assistant envoie à Anthropic la conversation et les données d’outils nécessaires à chaque requête, et les coûts d’API sont à la charge du compte de l’utilisateur.

  • Interface de dialogue : réponses en streaming, état d’exécution des outils, arrêt et effacement, estimation d’usage / de coût.
  • Lecture des données de mesure : lister les relevés, résumés et réponses partielles, et comparer des mesures.
  • Outils de calcul : appelle exactement les mêmes algorithmes de recommandation PEQ et d’alignement de caisson que l’interface manuelle.
  • Évaluation pièce & agencement : liste les pièces, lit les positions enceintes / auditeur et les modes, et prédit — sur une copie du projet — l’effet d’un déplacement d’équipement ou d’un changement de profil d’absorption ; les projets enregistrés ne sont jamais réécrits.
  • Mesure uniquement après confirmation : l’IA propose l’objectif et les pièces candidates et ne lance le balayage qu’après confirmation de l’utilisateur ; refuser ou arrêter annule la requête.
  • Réglages de mesure partagés : IA et mesure manuelle réutilisent le même espace de travail, héritant entrée, assistant de lecture Mac, plage / durée de balayage, délai et loopback ; la page de chat affiche niveau / progression en direct avec annulation, puis restaure le contexte pièce et groupe de mesure d’origine.
  • Restauration de session : une session courante est sauvegardée et restaurable, l’exécution d’outil interrompue étant marquée à la reprise ; effacer la session supprime aussi l’historique et l’usage.
Limites · BOUNDARIES Pas encore de liste multi-sessions ni de modèle local en repli ; l’outil d’agencement ne gère ni ajout / suppression d’équipement, ni modifications de panneaux spécifiées, ni prédiction à partir de la calibration mesurée. La chaîne avec vraie clé API et la boucle audio sur appareil restent à valider.
§ 11

Visualisation & export

11.1 Vue 3D

Room3DController rend via SceneKit : murs / sol / plafond / enceintes (caisson fin + repère + pastille canal) / auditeur (glyphe FE + tige) / obstacles (SCNBox translucide) / panneaux recommandés / segments de trajets multi-ordres / superposition de carte d'énergie.

DESIGN · DESSIN TECHNIQUE Style « dessin technique » (arêtes fines, éclairage constant, sans PBR), distinct du rendu photoréaliste.

11.2 Carte d'énergie des réflexions

ReflectionEnergyMapGenerator accumule l'énergie de chaque trajet sur la grille uCells × vCells du mur (12×6 par défaut). Une carte par mur, superposée en 3D (bleu → cyan → vert → jaune → rouge).

EnergyHeatmapRenderer convertit la grille en UIImage : cellules « block » de 16 px (sans interpolation entre cellules, pour garder les bords lisibles ; le lissage au mur vient du filtrage bilinéaire de texture de SceneKit) + rampe maison à 5 paliers (bleu → cyan → vert → jaune → rouge) + alpha mappé linéairement de 0,20 à 0,85 selon la position de l'énergie sur une échelle fixe −30…0 dB (−∞ totalement transparent).

11.3 Aperçu par convolution RIR

RIRPreviewPlayer (AVAudioEngine + AVAudioPlayerNode) convolue un signal sec synthétisé (corde pincée / claquement / voyelle synthétique — aucun échantillon embarqué) avec le RIR simulé pour l'écoute « non traité vs traité ».

La convolution temporelle RIRConvolver.convolve(dry:rir:) est directe O(N × M) (N = échantillons secs, M = RIR), normalisée à 0,9 pour éviter l'écrêtage.

11.4 Manuel d'installation PDF

ReportExporter rend un PDF A4 (595 × 842 pt) via UIGraphicsPDFRenderer :

  • Aperçu de la pièce + capture 3D
  • Histogramme RT60 6 bandes : estimation Sabine vs cible, valeurs mesurées superposées quand elles existent
  • Tableau des points + tableau des modes + résumé des risques
  • Tableau des panneaux (la nomenclature BOM s'affiche dans l'app, pas dans le PDF)
  • Quand des mesures existent, ajout des graphiques RT60 / EDC / réponse / spectrogramme / cascade / phase et d’un résumé de moyenne multi-positions ; l’unité de la réponse utilise l’instantané de calibration enregistré à la mesure (dB SPL ou dBFS, honnêtement étiqueté)
  • Police Geist + repli PingFangSC (CoreText cascadeList, pour éviter les □□□ en CJK)

11.5 Persistance des projets

ProjectStore (actor) écrit ~/Library/Application Support/Acouvero/projects.json : [RoomProject], chacun avec Room + enceintes + auditeurs + recommandations + panelCountOverrides. Au premier lancement, les données migrent automatiquement depuis l'ancien répertoire FindEcho/ (FindEcho est le nom de code interne d'avant le renommage, conservé volontairement dans les symboles du code).

MeasurementStore (actor) écrit measurements.json : [MeasurementResult], lié au projet par roomId.

Les deux ont une récupération de décodage par élément (wrapper Throwable<T>) — un enregistrement corrompu ne fait pas échouer toute la liste.

MicCalibrationStore écrit ~/Library/Application Support/mic_calibration.json (racine, sans sous-dossier) : courbe de calibration REW + offset SPL, liés à l'UID du port d'entrée — un changement d'entrée exige un nouvel import / calibrage.

§ 12

Notes d'ingénierie

12.1 SwiftUI + @Observable

Le ViewModel (FindEchoViewModel) utilise la macro @Observable de Swift 5.9 — champs observés directement, sans Combine. Les résultats AcousticAnalysis sont mis en cache par comparaison Equatable de AcousticConfiguration :

FindEchoViewModel.analysisswift
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 Isolation par acteur

ProjectStore et MeasurementStore sont des actor, sérialisant l'IO / l'async ; RoomPlanService est une classe @MainActor. L'UI utilise async / await ; le thread principal n'est jamais bloqué par l'IO disque.

12.3 Cycle de vie AVAudio

AudioSessionManager centralise la catégorie de session (.playback pour l'aperçu RIR, .playAndRecord pour la mesure). La protection contre les interruptions couvre les deux voies : côté mesure, un InterruptionMonitor dans AudioMeasurementService écoute AVAudioSession.interruptionNotification — un appel / Siri pendant un balayage, un claquement ou un bruit ambiant invalide le résultat avec une erreur ; côté aperçu, RIRPreviewPlayer écoute aussi et arrête le nœud de lecture en réinitialisant isPlaying. Un changement de route audio en cours de mesure invalide aussi la passe.

12.4 Annulation de tâche

La lecture par convolution est une tâche de fond ; les appuis rapides déclenchent pendingPlayTask?.cancel() + double vérif Task.isCancelled pour éviter des écritures MainActor désordonnées.

12.5 Couverture de tests

AllShapesAndUseCasesTests (framework Swift Testing) exécute la matrice complète — chaque forme × cas d'usage (auditeur unique ; enceintes en paire stéréo ou centrale selon le cas) — en vérifiant :

  • analysis.reflectionPaths.count >= 1
  • analysis.warnings contient la note d'approximation pour les pièces non rectangulaires
  • le total de panneaux recommandés est non négatif (totalPanelCount ≥ 0 ; pas d'assertion budget)
  • les polygones auto-sécants retombent sans crash (dégradation en rectangle)
  • sommets &lt; 3 et autres retombées de cas limites

12.6 Plateforme & localisation

Cible de déploiement iOS 17.0, iPhone + iPad ; zéro dépendance tierce (aucun package SPM / CocoaPods) — frameworks système uniquement (SwiftUI / SceneKit / ARKit / RoomPlan / AVFoundation / Accelerate). Localisation via catalogue .xcstrings : chinois comme langue source, plus English / Français / Deutsch / Español / Português (Brasil) — 6 langues, commutables dans l'app ou au gré du système.

§ 13

Limites connues

  1. Multi-ordre en pièce non rectangulaire = boîte englobante — le risque flutter / slapback d'ordre 2-3 près des angles rentrants peut dévier. Les points d'ordre 1 utilisent le vrai polygone.
  2. Modes en pièce non rectangulaire estimés via boîte englobante — modes exacts = FEM.
  3. Mesure au micro intégré de l'iPhone — non calibré ; réponse / sensibilité non plates. Fiabilité toujours .low, en recoupement de l'estimation géométrique. Avec un micro de mesure USB (miniDSP UMIK-1 / UMIK-2) et son fichier de calibration REW chargé, les niveaux par bande sont corrigés selon la courbe de calibration ; une calibration SPL de référence 94 dB affiche ensuite les niveaux en dB SPL absolus (dBFS seulement avant).
  4. Hypothèse ISM source unique — ignore diffraction du caisson, directivité du pavillon, etc.
  5. Pas de modélisation des pièges à graves — les problèmes sous 80 Hz sortent du modèle de Sabine et exigent un traitement dédié.
  6. Précision du scan AR — extrémités RoomPlan à 3-8 cm près ; boucle de 12 segments peut cumuler 5+ cm. Épaisseur des murs non modélisée.
  7. Limites du périmètre d’analyse — la moyenne complexe vectorielle entre taux d’échantillonnage n’est pas encore prise en charge ; les résultats multi-sièges sont pour l’instant un tableau numérique sans superposition de courbes sommées par siège ; les superpositions de réponse n’entrent pas encore dans le PDF.
  8. Outils pro non encore implémentés — pas d’enregistreur SPL longue durée, d’intelligibilité STI ni de mesure de distorsion (THD) ; impédance / Thiele-Small et API REST également absentes.
  9. Validation sur appareil en attente — la chaîne API réelle de l’assistant IA (streaming avec une vraie clé / mesure confirmée / archivage des enregistrements) et la chaîne complète des micros UMIK sur matériel réel (y compris l’UMIK-2 à 96 kHz) restent à valider ; un succès en simulateur ne prouve pas la boucle audio sur appareil.
§ 14

Références

  1. Sabine, W. C. (1922). Collected Papers on Acoustics. Harvard University Press.
  2. Allen, J. B., & Berkley, D. A. (1979). Image method for efficiently simulating small-room acoustics. JASA, 65(4), 943–950.
  3. Schroeder, M. R. (1965). New method of measuring reverberation time. JASA, 37(3), 409–412.
  4. Farina, A. (2000). Simultaneous measurement of impulse response and distortion with a swept-sine technique. Audio Engineering Society Convention 108.
  5. Scheibler, R., Bezzam, E., & Dokmanić, I. (2018). Pyroomacoustics: A Python package for audio room simulation and array processing algorithms. ICASSP 2018.
  6. EBU Tech 3276. Listening conditions for the assessment of sound programme material.
  7. ITU-R BS.1116. Methods for the subjective assessment of small impairments in audio systems.
  8. BB93 — Acoustic design of schools (UK).
  9. THX Pro Cinema Certification requirements.
Vous préférez la version simple ?

« Pourquoi votre pièce réécrit la musique »

Lire la version détaillée