feat: add music sync viz modes and auto_gain audio filter
Lint & Test / test (push) Has been cancelled

Add 4 new audio visualization modes powered by MusicAnalyzer:
- pulse_on_beat: BPM-synced pulsing with smooth beat phase
- energy_gradient: bass/mid/treble mapped to scrolling gradient
- spectrum_bands: three VU zones for frequency bands
- strobe_on_drop: state-driven strobe on detected musical drops

MusicAnalyzer provides BPM estimation (median IBI), beat phase tracking,
asymmetric energy envelope, 3-band frequency splitting, and drop
detection state machine (idle/buildup/drop/recovery).

Add auto_gain audio filter for automatic level normalization via rolling
peak tracking with configurable target level and response time.

Deprecate auto_gain on Audio Value Source (use the filter instead).
This commit is contained in:
2026-04-05 01:40:34 +03:00
parent 6e8b159126
commit b04978af58
14 changed files with 598 additions and 37 deletions
@@ -191,6 +191,7 @@ _RESPONSE_MAP: dict = {
color=s.color.to_dict(),
color_peak=s.color_peak.to_dict(),
mirror=s.mirror,
beat_decay=s.beat_decay.to_dict(),
),
ApiInputColorStripSource: lambda s, kw: ApiInputCSSResponse(
**kw,
@@ -164,6 +164,7 @@ class AudioCSSResponse(_CSSResponseBase):
color: Any = Field(description="Primary color")
color_peak: Any = Field(description="Peak color")
mirror: bool = Field(description="Mirror mode")
beat_decay: Any = Field(default=0.15, description="Beat pulse decay rate (music modes)")
class ApiInputCSSResponse(_CSSResponseBase):
@@ -340,6 +341,9 @@ class AudioCSSCreate(_CSSCreateBase):
color: Any = Field(default=None, description="Primary color")
color_peak: Any = Field(default=None, description="Peak color [R,G,B]")
mirror: Optional[bool] = Field(None, description="Mirror mode")
beat_decay: Any = Field(
default=None, description="Beat pulse decay rate (music modes, 0.01-0.5)"
)
class ApiInputCSSCreate(_CSSCreateBase):
@@ -527,6 +531,7 @@ class AudioCSSUpdate(_CSSUpdateBase):
color: Any = Field(default=None, description="Primary color")
color_peak: Any = Field(default=None, description="Peak color [R,G,B]")
mirror: Optional[bool] = Field(None, description="Mirror mode")
beat_decay: Any = Field(default=None, description="Beat pulse decay rate (music modes)")
class ApiInputCSSUpdate(_CSSUpdateBase):