Feat/music#297
Merged
Merged
Conversation
Grammaire de base du futur mode Music (cf. specs/music_mode.md), sans audio ni UI — uniquement la production de figures, entièrement testée. - BeatPattern : slots strike/release/hold, le beat = le 'to' (impact), from = ancre - onset_figures : banque curée de 9 figures (niveaux 1-3) - depth_contour : contours générés (alternance/climb/reach), frappes adjacentes != - music_capability_bounds : profil lu comme bornes (réutilise rhythmBpmCeilAxisFor) - music_pattern_generator : escalade par phrase, mapping BPM ½×/1×/2×, soupapes depth+hold 9 tests verts, analyze propre.
- beat_clock : interface BeatClock + BeatTick (1 tick/battement, drapeaux bar/phrase) - beat_grid : BeatGrid (maths pures temps→battement) + BeatScheduler.poll (émission déterministe, rattrapage, anti-doublon) - tap_tempo : TapTempoEstimator (médiane d'intervalles, reset gap, clamp) + TapTempoSource (Stopwatch partagé, Timer/Stream, horloge injectable pour tests) 10 tests verts, analyze propre.
- slot_action : SlotAction (strike/release/hold + profondeur + battement + bpm) - music_session_engine : régénère un BeatPattern par phrase, traduit chaque battement en SlotAction. Alignement PR1 : 1 slot = 1 battement en 1×, ½× = 1 slot tous les 2 battements (frappes profondes espacées, pas de retempo audio). Double-temps reporté PR3. onBeat() pur testable + attach(clock) pour le stream. 6 tests verts (25 au total sur le mode music).
…eur) Bloc 4 de PR1 — câblage app, contrôleur autonome (pas de SessionController). - MusicSessionController : TapTempoSource → MusicSessionEngine → BeepEngine (strike→playPositionOnce, hold→playHoldOnce, release muet). BeepEngine intact. - MusicModeScreen : zone de tap, BPM live, courbe de profondeur (CustomPaint), start/stop ; charge le profil via CapabilityService.snapshotProfile. - mode_selection : 4e carte « MUSIC » ; cartes passées en liste scrollable (4 Expanded débordaient sur petit écran / widget_test). - i18n fr/en/de/es (7 clés). 633 tests verts, analyze complet propre.
…nimée Retours de test live PR1 : - BeepEngine.setMixWithOthers : contexte audio global mixWithOthers (iOS) / AndroidAudioFocus.none — les bips se mélangent à Spotify au lieu d'en prendre le focus. Activé à l'entrée du mode Music, focus exclusif rendu en sortie. - Remplace la courbe (buguée : repaint jamais déclenché) par _MusicDepthGauge : échelle verticale head→full + orbe qui glisse vers la profondeur courante (façon MovementAnimation), strike = pop, hold = anneau, release = atténué. Piloté par les SlotAction (même source que l'audio → synchro, pas de drift). 633 tests verts, analyze propre.
…icipation) Retours de test #2 : - setMixWithOthers pose désormais le contexte mixWithOthers sur CHAQUE player du pool (le contexte global seul ne suffisait pas : chaque player gardait le focus exclusif et coupait Spotify à la 1ʳᵉ lecture). - Remplace la jauge par une timeline : passé court · NOW · slots à venir (droite) pour anticiper. MusicSessionEngine.peek (lecture seule) expose les prochains slots du pattern courant. y = profondeur, nodes par nature, NOW marqué/agrandi. 635 tests verts (2 nouveaux sur peek), analyze propre.
…a timeline Retour : la timeline (points multiples) était illisible et saccadée. On revient au visuel de la session que la joueuse connaît : MovementAnimation en rhythm, auto-animé au tempo (beepEngine: null), un seul curseur qui glisse sur l'axe head→full vers la profondeur cible courante (la plus profonde de la figure, stable par phrase). Timeline + peek-viz retirés du contrôleur. 635 tests verts, analyze propre.
Retour debug : le pattern changeait à chaque phrase (jamais le temps de le sentir → bips perçus aléatoires) et le visuel ne montrait pas la figure. - MusicSessionEngine.repeatPhrases (défaut 4) : la même figure est conservée 4 phrases avant régénération ; le pattern boucle en continu entre-temps. Expose cursor (tête de lecture). - _PatternView (séquenceur) : 1 colonne/slot, y = profondeur réelle jouée (strike=plein, hold=anneau, release=point), tête de lecture sur le slot en cours — synchro à l'audio (même source). Montre la vraie figure + sa boucle. - Remplace MovementAnimation (qui ne montrait que head↔profondeur-max). 635 tests verts, analyze propre.
Pour la mise au point : bouton bug dans l'AppBar du mode Music. Quand actif, ignoreGating se propage bounds→générateur : - profondeur libre jusqu'à full DÈS la phrase 0 (pas d'escalade lente), - aucun plafond BPM, aucune limite de hold, tous les niveaux de figures. Recrée le contrôleur au basculement (retaper le tempo). i18n fr/en/de/es. 636 tests verts, analyze propre.
…liers) Retour : il manquait les points d'ancre (remontée entre frappes) et les holds n'étaient pas des paliers. - Ancre (release) = un cran AU-DESSUS de la plus haute des 2 frappes voisines (head/mid → tip), au lieu d'un head fixe gris. Ligne 'tip' ajoutée à l'échelle. - Hold = palier plat épais à la profondeur tenue (au lieu d'un anneau). - Frappe = creux plein ; ancre = sommet plein plus petit ; le tout relié en zigzag = la courbe du mouvement bouche (plonge sur le temps, remonte entre). Tracé only, 636 tests verts, analyze propre.
…aque plongée) Retour : on ne peut pas enchaîner 2 plongées sans ancre, et un hold doit être encadré par des ancres. Mes figures (oo, o_o) violaient ça. Refonte de la banque : une figure = suite de gestes (up, down) — up battements à l'ancre puis down battements en bas (frappe + holds). Correct PAR CONSTRUCTION : - jamais 2 frappes sans release entre elles, - toute frappe précédée d'une ancre, - holds encadrés par des ancres (plongée = strike+holds, bornée par des ups). Soupape hold retirée (cassait la grammaire). Tests de validité grammaticale (banque + sortie générateur). 637 tests verts, analyze propre.
Re-correction : l'ancre fait toujours 1 battement (« 1 fois sur 2 »), et un hold SAUTE une ancre → la plongée (frappe + holds) doit être de longueur IMPAIRE (1, 3, 5, 7 ; chaque cran impair = un saut d'ancre de plus). Mes plongées de 2 (longueur paire) cassaient l'alternance ancre/frappe. Figure = liste de longueurs de plongée impaires, ancre implicite = 1 battement. Tests durcis : ancre toujours suivie d'une frappe (unique), plongées impaires. 637 tests verts, analyze propre.
…re fluide Retours : - Le pattern changeait au milieu (régén sur frontière de phrase ≠ longueur du pattern). Désormais régén UNIQUEMENT en fin de boucle, après repeatLoops (4) boucles complètes. Test : tout changement tombe sur curseur 0. - Courbe du mouvement arrondie (béziers quadratiques via les milieux de segment). - Tête de lecture animée en continu : AnimationController par slot (durée = slotInterval), glisse du slot courant vers le suivant au lieu de sauter. 637 tests verts, analyze propre.
…urbe Catmull-Rom Retours : - 1er temps n'est plus une ancre : expansion réordonnée frappe→holds→ancre (la dernière ancre précède cycliquement la 1ʳᵉ frappe). - Une frappe qui amorce un hold sonne comme un HOLD (1ᵉʳ temps seulement) ; les temps de hold suivants sont muets (SlotAction.sustained). - Les ancres sonnent (tick léger, position tip). - Courbe Catmull-Rom (cubiques de Bézier) : passe par les nœuds, ne coupe plus les angles sur les changements brusques. 637 tests verts, analyze propre.
Le lookahead de profondeur d'ancre tient compte de la première frappe (cyclique), donc la dernière ancre reste bien au-dessus du premier temps.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.