AudioPlayer.swift — startRadioSimulation() replaces startLevelSimulation() for radio streams. It generates two overlapping sine waves with a slow breathing amplitude envelope. The key property: it’s driven by an internal radioPhase counter that increments at a fixed rate, completely independent of currentTime. Buffer seeks, HLS restarts, and stream reconnects have zero visual effect. MitsuhaVisualizerView.swift — Two fixes: 1. TimelineView(.periodic(from: .distantPast, by: tickInterval)) — using .distantPast as the stable schedule origin instead of .now. Previously, any recalculation of tickInterval (triggered by isRenderingActive flipping during a radio buffer hiccup) would reset the origin to the current moment, deferring the next tick by a full interval — the visible stall. 2. songId parameter with .onChange(of: songId) that resets peakFollower, levelHistoryBuf, and lastTickTime on song change. This prevents the outgoing song’s simulation spike from “raising” the wave at the start of the next song. NowPlayingView.swift and MainTabView.swift — Pass songId: audioPlayer.currentSong?.id through to MitsuhaVisualizerView and CompactVisualizerView at all call sites. |
||
|---|---|---|
| .. | ||
| API | ||
| Audio | ||
| Models | ||
| Storage | ||