Repository navigation
Visualization Idle Suppression
log5r edited this page Oct 10, 2026
·
1 revision
Issue #31 を PR #55 で修正したときの設計判断と検証方法をまとめます。
-
ホストビューの再評価:
TimelineView(paused:)に渡す値は、変化したときだけ代入するPlayerViewModel.isVisualizerIdleにします。フレームごとに変わるaudioFrame・fps・EQ 状態は Canvas の中でだけ読みます。旧コードのisPlaying == false && audioFrame.isSilentは短絡評価されるので、フレームごとの再評価は再生中ではなく、一時停止・停止後の減衰(最大約 3 秒)の間に起きていました。 -
解析の抑制:
VisualizationConsumerモディファイアは、audioFrameを描画するビューが表示中であることを登録します。登録しているのはスペクトラム、VU 針、DEBUG の Duo 診断です。consumer がいないとき、または App レベルのscenePhase == .backgroundのときは、SpectrumAnalyzer.setAnalysisEnabled(false)を呼びます。- 抑制すると世代が進み、予約済みのチャンク・減衰・未配送のフレームは無効になります。
- 再開時は無音フレームを 1 回発行して表示を初期化します。
- 背面で再生中は、再生クロックを 1Hz にします。
-
マーキー:
MarqueeTimelineScheduleは、スクロール中だけ 1/60 秒間隔のエントリを返し、保持区間では境界の 1 エントリだけを返します。 -
VU 針:
Ballistics.stepは経過時間を 1/60 秒以下の等分ステップで積分します。上限は 0.2 秒です。これで 10/30/60fps の応答が一致します。
App レベルで読む値は全シーンの集約です。いずれかのシーンが .active なら .active になり、.background になるのは全シーンが背面のときだけです。
macOS では、SwiftUI の検証用アプリで次のように確認しました(2026-10-10)。
| 状態 | scenePhase |
|---|---|
| 別アプリの背後で見えているウインドウ | .active |
| ウインドウを最小化 |
.inactive(onDisappear は呼ばれない) |
| Cmd-H でアプリを隠す | .background |
| 起動直後 | 一瞬 .background になり、その後 .active
|
iOS では、ロックやホーム画面への移動で .background になり、コントロールセンターや App スイッチャーの表示中は .inactive になります。iOS 側は文書で確認しただけで、実機では確認していません。.inactive でもアプリは画面に見えていることがあるため、抑制の判定には .background だけを使います。その結果、最小化した macOS ウインドウでは解析が続きます。
- Instruments による Path 生成数と body 評価回数の比較
- iPhone のロック中の Energy Log
- 実機での復帰表示