public 演奏ステージ()
{
- this.子リスト.Add( this.コンボ = new コンボ() );
- this.子リスト.Add( this.レーンフレーム = new レーンフレーム() );
- this.子リスト.Add( this.スクロール譜面 = new スクロール譜面() );
- this.子リスト.Add( this.ヒット判定文字列 = new ヒット判定文字列() );
- this.子リスト.Add( this.回転羽 = new 回転羽( 最大同時発火数: 32 ) );
- this.子リスト.Add( this.ドラムサウンド = new ドラムサウンド() );
- this.子リスト.Add( this.ドラムセット = new ドラムセット() );
- this.子リスト.Add( this.判定バー = new 画像( @"$(Static)\images\判定バー.png" ) );
- this.子リスト.Add( this.ステージ台 = new 画像( @"$(Static)\images\ステージ台.png" ) );
- this.子リスト.Add( this.FPS画像 = new 文字列画像() );
+ this.子リスト.Add( this._コンボ = new コンボ() );
+ this.子リスト.Add( this._レーンフレーム = new レーンフレーム() );
+ this.子リスト.Add( this._スクロール譜面 = new スクロール譜面() );
+ this.子リスト.Add( this._ヒット判定文字列 = new ヒット判定文字列() );
+ this.子リスト.Add( this._回転羽 = new 回転羽( 最大同時発火数: 32 ) );
+ this.子リスト.Add( this._ドラムサウンド = new ドラムサウンド() );
+ this.子リスト.Add( this._ドラムセット = new ドラムセット() );
+ this.子リスト.Add( this._判定バー = new 画像( @"$(Static)\images\判定バー.png" ) );
+ this.子リスト.Add( this._ステージ台 = new 画像( @"$(Static)\images\ステージ台.png" ) );
+ this.子リスト.Add( this._FPS画像 = new 文字列画像() );
// 子Activity の外部依存 Action の実体を定義する。
- this.スクロール譜面.ヒット判定文字列開始 = ( chipType, hitType ) => {
- this.ヒット判定文字列.表示開始( chipType, hitType );
+ this._スクロール譜面.ヒット判定文字列開始 = ( chipType, hitType ) => {
+ this._ヒット判定文字列.表示開始( chipType, hitType );
};
- this.スクロール譜面.コンボリセット = () => {
- this.コンボ.COMBO値.Value = 0;
+ this._スクロール譜面.コンボリセット = () => {
+ this._コンボ.COMBO値.Value = 0;
};
- this.スクロール譜面.コンボ加算 = () => {
- this.コンボ.COMBO値.Value++;
+ this._スクロール譜面.コンボ加算 = () => {
+ this._コンボ.COMBO値.Value++;
};
- this.スクロール譜面.ヒット判定数加算 = ( hitType ) => {
+ this._スクロール譜面.ヒット判定数加算 = ( hitType ) => {
this.ヒットした回数[ hitType ]++;
};
- this.スクロール譜面.背景動画の長さsec = () => {
+ this._スクロール譜面.背景動画の長さsec = () => {
return ( null != this._BGM ) ? this._BGM.長さsec : 0.0;
};
- this.スクロール譜面.背景動画再生開始 = ( 開始位置sec ) => {
+ this._スクロール譜面.背景動画再生開始 = ( 開始位置sec ) => {
this._背景動画?.再生を開始する( 開始位置sec );
this._背景動画開始済み.Value = true;
if( null != this._BGM )
this._BGM?.Play( 開始位置sec );
this._BGM再生開始済み = true;
};
- this.スクロール譜面.チップヒット = ( chip ) => {
- this.回転羽.発火する( chip.チップ種別 );
- if( this.Autoチップのドラム音を再生する )
- this.ドラムサウンド.発声する( chip.チップ種別, chip.音量 * 0.25f );
+ this._スクロール譜面.チップヒット = ( chip ) => {
+ this._回転羽.発火する( chip.チップ種別 );
+ if( this._Autoチップのドラム音を再生する )
+ this._ドラムサウンド.発声する( chip.チップ種別, chip.音量 * 0.25f );
};
- this.スクロール譜面.ステージクリア = () => {
+ this._スクロール譜面.ステージクリア = () => {
this.現在のフェーズ.Value = フェーズ.クリアor失敗;
};
- this.スクロール譜面.リアルタイム演奏時刻sec = () => {
+ this._スクロール譜面.リアルタイム演奏時刻sec = () => {
return this._現在の演奏時刻secを返す();
};
- this.スクロール譜面.譜面スクロール速度の倍率 = () => {
+ this._スクロール譜面.譜面スクロール速度の倍率 = () => {
return this._現在進行描画中の譜面スクロール速度の倍率.Value;
};
- this.スクロール譜面.FPSをカウント = () => {
+ this._スクロール譜面.FPSをカウント = () => {
this._FPS.FPSをカウントしプロパティを更新する();
};
}
// 動画を子リストに追加。
this.子リスト.Add( this._背景動画 = new 動画( StrokeStyleT.演奏スコア.背景動画ファイル名, StrokeStyleT.Config.動画デコーダのキューサイズ ) );
- // 動画から BGM を作成。
- this._BGM = StrokeStyleT.サウンドデバイス.CreateSound( StrokeStyleT.演奏スコア.背景動画ファイル名 );
+ // 動画から音声パートを抽出して BGM を作成。
+ if( ( null != this._デコード済みWaveSource ) && this._デコード済みWaveSource.Path.Equals( StrokeStyleT.演奏スコア.背景動画ファイル名 ) )
+ {
+ // (A) 前回生成したBGMとパスが同じなので、前回のデコード済み WaveSource をキャッシュとして再利用する。
+ FDK.Log.Info( "前回生成したサウンドデータを再利用します。" );
+ }
+ else
+ {
+ // (B) 初めての生成か、または前回生成したBGMとパスが違うので、新しくデコード済み WaveSource を生成する。
+ this._デコード済みWaveSource?.Dispose();
+ this._デコード済みWaveSource = new FDK.メディア.サウンド.WASAPI.DecodedWaveSource(
+ StrokeStyleT.演奏スコア.背景動画ファイル名,
+ StrokeStyleT.サウンドデバイス.WaveFormat );
+ }
+ this._BGM?.Dispose();
+ this._BGM = StrokeStyleT.サウンドデバイス.CreateSound( this._デコード済みWaveSource );
}
else
{
this._背景動画 = null;
this._BGM = null;
+ //this._デコード済みWaveSource = null; キャッシュは消さない。
}
//----------------
#endregion
- this.演奏開始時刻sec = 0.0;
+ this._演奏開始時刻sec = 0.0;
this._現在進行描画中の譜面スクロール速度の倍率.Value = StrokeStyleT.ユーザ管理.現在選択されているユーザ.譜面スクロール速度の倍率;
this._BGM再生開始済み = false;
this._背景動画開始済み.Value = false;
- this.レーンフレーム.左端位置dpx = 400f;
- this.レーンフレーム.高さdpx = dr.設計画面サイズdpx.Height;
+ this._レーンフレーム.左端位置dpx = 400f;
+ this._レーンフレーム.高さdpx = dr.設計画面サイズdpx.Height;
+
this.ヒットした回数.Clear();
foreach( var 判定 in typeof( ヒット判定種別 ).GetEnumValues() )
this.ヒットした回数[ (ヒット判定種別) 判定 ] = 0;
- // 最初のフェーズを設定する。
+ #region " 最初のフェーズを設定する。"
+ //----------------
if( StrokeStyleT.ビュアーモードである )
{
// 演奏スコアが設定済みなら演奏開始。それ以外ならメッセージ待機へ。
// 演奏開始。
this.現在のフェーズ.Value = フェーズ.演奏中;
}
+ //----------------
+ #endregion
- this.活性化した直後である = true;
+ this._活性化した直後である = true;
}
protected override void On非活性化( デバイスリソース dr )
{
FDK.Log.Info( "演奏ステージを終了します。" );
- //this.BGMを解放する(); → ここではまだ解放しない。結果ステージが終わるときに、外部から解放する。
+ //this.BGMを解放する(); → ここではまだ解放しない。結果ステージに非活性化時に、外部から解放する。
+ //FDK.Utilities.解放する( ref this._DecodedWaveSource ); → 演奏ステージインスタンスの破棄時に、外部から解放する。
if( null != this._背景動画 )
this.子リスト.Remove( this._背景動画 ); // 子リストから削除
#region " 初めての進行描画。"
//----------------
- if( this.活性化した直後である )
+ if( this._活性化した直後である )
{
- this.活性化した直後である = false;
+ this._活性化した直後である = false;
this._FPS = new FDK.カウンタ.FPS();
double 演奏開始位置の先頭からの時間sec = 0.0;
{
FDK.Log.Info( msg.ToString() );
- 演奏開始位置の先頭からの時間sec = this.スクロール譜面.演奏開始小節番号を設定しその時刻secを返す( msg.演奏開始小節番号 );
+ 演奏開始位置の先頭からの時間sec = this._スクロール譜面.演奏開始小節番号を設定しその時刻secを返す( msg.演奏開始小節番号 );
FDK.Log.Info( $"演奏開始の先頭からの時間sec: {演奏開始位置の先頭からの時間sec}" );
- this.Autoチップのドラム音を再生する = msg.ドラムチップ発声;
+ this._Autoチップのドラム音を再生する = msg.ドラムチップ発声;
}
// 演奏開始時刻sec の設定(1)
- this.演奏開始時刻sec = StrokeStyleT.サウンドデバイス.GetDevicePosition() - 演奏開始位置の先頭からの時間sec;
- FDK.Log.Info( $"演奏開始時刻sec(背景動画再生チェック前): {this.演奏開始時刻sec}" );
+ this._演奏開始時刻sec = StrokeStyleT.サウンドデバイス.GetDevicePosition() - 演奏開始位置の先頭からの時間sec;
+ FDK.Log.Info( $"演奏開始時刻sec(背景動画再生チェック前): {this._演奏開始時刻sec}" );
- this.スクロール譜面.再生中の時刻なら動画とBGMを再生開始する( 演奏開始位置の先頭からの時間sec );
+ this._スクロール譜面.再生中の時刻なら動画とBGMを再生開始する( 演奏開始位置の先頭からの時間sec );
// 演奏開始時刻sec の設定(2) 動画とBGMが再生された場合の誤差を修正する。
- this.演奏開始時刻sec = StrokeStyleT.サウンドデバイス.GetDevicePosition() - 演奏開始位置の先頭からの時間sec;
- FDK.Log.Info( $"演奏開始時刻sec(背景動画再生チェック後): {this.演奏開始時刻sec}" );
+ this._演奏開始時刻sec = StrokeStyleT.サウンドデバイス.GetDevicePosition() - 演奏開始位置の先頭からの時間sec;
+ FDK.Log.Info( $"演奏開始時刻sec(背景動画再生チェック後): {this._演奏開始時刻sec}" );
}
//----------------
#endregion
//----------------
#endregion
- this.ステージ台.描画する( dr, 0.0f, 0.0f );
- this.レーンフレーム.進行描画する( dr );
- this.コンボ.進行描画する( dr );
- this.ヒット判定文字列.進行描画する( dr );
- this.スクロール譜面.小節線拍線を進行描画する( dr, 演奏時刻sec );
- this.判定バー.描画する( dr, 597f, 座標.判定バーの中央Y座標dpx - 43f );
- this.ドラムセット.進行描画する( dr );
- this.スクロール譜面.チップを進行描画する( dr, 演奏時刻sec );
- this.回転羽.進行描画する( dr );
+ this._ステージ台.描画する( dr, 0.0f, 0.0f );
+ this._レーンフレーム.進行描画する( dr );
+ this._コンボ.進行描画する( dr );
+ this._ヒット判定文字列.進行描画する( dr );
+ this._スクロール譜面.小節線拍線を進行描画する( dr, 演奏時刻sec );
+ this._判定バー.描画する( dr, 597f, 座標.判定バーの中央Y座標dpx - 43f );
+ this._ドラムセット.進行描画する( dr );
+ this._スクロール譜面.チップを進行描画する( dr, 演奏時刻sec );
+ this._回転羽.進行描画する( dr );
this._FPS.VPSをカウントする();
- this.FPS画像.表示文字列 = $"VPS: {this._FPS.現在のVPS.ToString()} / FPS: {this._FPS.現在のFPS.ToString()}";
- this.FPS画像.進行描画する( dr, 0f, 0f );
+ this._FPS画像.表示文字列 = $"VPS: {this._FPS.現在のVPS.ToString()} / FPS: {this._FPS.現在のFPS.ToString()}";
+ this._FPS画像.進行描画する( dr, 0f, 0f );
// 入力。
if( StrokeStyleT.キーボード入力.キーが押された( SharpDX.DirectInput.Key.Escape ) &&
StrokeStyleT.ビュアーモードではない ) // ビュアーモードでは無効。
{
- this.BGMを解放する();
+ this.BGMを停止する();
this.現在のフェーズ.Value = フェーズ.キャンセル;
}
// 上矢印押下 → 譜面スクロール速度の倍率を +0.5
public void 演奏を停止する()
{
- this.スクロール譜面?.演奏を停止する();
+ this._スクロール譜面?.演奏を停止する();
+
this._背景動画開始済み.Value = false;
- this.BGMを解放する();
- this.コンボ.COMBO値.Value = 0;
+
+ this.BGMを停止する();
+
+ this._コンボ.COMBO値.Value = 0;
}
- public void BGMを解放する()
+ public void BGMを停止する()
{
- if( null != this._BGM ) // è\83\8cæ\99¯å\8b\95ç\94»ã\81\8cã\81ªã\81\91ã\82\8cã\81° BGM ã\82\82 null ã\81§ã\81\82ã\82\8b
+ if( null != this._BGM ) // è\83\8cæ\99¯å\8b\95ç\94»ã\81\8cã\81ªã\81\91ã\82\8cã\81° BGM ã\82\82 null ã\81§ã\81\82ã\82\8aã\80\81ã\81\9dã\82\8cã\81¯ã\82¨ã\83©ã\83¼ã\81§ã\81¯ã\81ªã\81\84ã\80\82
{
this._BGM.Stop();
FDK.Utilities.解放する( ref this._BGM );
+ //FDK.Utilities.解放する( ref this._デコード済みWaveSource ); → ここでは解放しない。
}
}
- protected bool 活性化した直後である = false;
- protected double 演奏開始時刻sec = 0.0;
- protected bool Autoチップのドラム音を再生する = true;
- protected readonly SST.ステージ.演奏.コンボ コンボ;
- protected readonly SST.ステージ.演奏.レーンフレーム レーンフレーム;
- protected readonly SST.ステージ.演奏.スクロール譜面 スクロール譜面;
- protected readonly SST.ステージ.演奏.ヒット判定文字列 ヒット判定文字列;
- protected readonly SST.ステージ.演奏.回転羽 回転羽 = new 回転羽( 32 );
- protected readonly SST.ステージ.演奏.ドラムサウンド ドラムサウンド;
- protected readonly SST.ステージ.ドラムセット ドラムセット;
- protected readonly FDK.メディア.画像 判定バー;
- protected readonly FDK.メディア.画像 ステージ台;
- protected readonly FDK.メディア.文字列画像 FPS画像;
+ public void BGMのキャッシュを解放する()
+ {
+ this.BGMを停止する();
+
+ FDK.Utilities.解放する( ref this._デコード済みWaveSource );
+ }
+ private bool _活性化した直後である = false;
+ private double _演奏開始時刻sec = 0.0;
+ private bool _Autoチップのドラム音を再生する = true;
+ private readonly SST.ステージ.演奏.コンボ _コンボ;
+ private readonly SST.ステージ.演奏.レーンフレーム _レーンフレーム;
+ private readonly SST.ステージ.演奏.スクロール譜面 _スクロール譜面;
+ private readonly SST.ステージ.演奏.ヒット判定文字列 _ヒット判定文字列;
+ private readonly SST.ステージ.演奏.回転羽 _回転羽 = new 回転羽( 32 );
+ private readonly SST.ステージ.演奏.ドラムサウンド _ドラムサウンド;
+ private readonly SST.ステージ.ドラムセット _ドラムセット;
+ private readonly FDK.メディア.画像 _判定バー;
+ private readonly FDK.メディア.画像 _ステージ台;
+ private readonly FDK.メディア.文字列画像 _FPS画像;
private FDK.同期.RWLock<bool> _背景動画開始済み = new FDK.同期.RWLock<bool>( false );
private bool _BGM再生開始済み = false;
private FDK.同期.RWLock<double> _現在進行描画中の譜面スクロール速度の倍率 = new FDK.同期.RWLock<double>( 0.0 );
-
/// <remarks>
- /// 解放は、演奏ステージクラスの非活性化後に、外部から行われる。
- /// <see cref="SST.ステージ.演奏.演奏ステージ.BGMを解放する"/>
+ /// 停止と解放は、演奏ステージクラスの非活性化後に、外部から行われる。
+ /// <see cref="SST.ステージ.演奏.演奏ステージ.BGMを停止する"/>
+ /// <see cref="SST.ステージ.演奏.演奏ステージ.BGMのキャッシュを解放する"/>
/// </remarks>
private FDK.メディア.サウンド.WASAPI.Sound _BGM = null;
+ /// <summary>
+ /// BGM の生成もとになるデコード済みサウンドデータ。
+ /// </summary>
+ /// <remarks>
+ /// 活性化と非活性化に関係なく、常に最後にデコードしたデータを持つ。(キャッシュ)
+ /// 演奏ステージインスタンスを破棄する際に、このインスタンスもDisposeすること。
+ /// </remarks>
+ private FDK.メディア.サウンド.WASAPI.DecodedWaveSource _デコード済みWaveSource = null;
private FDK.メディア.動画 _背景動画 = null;
private FDK.カウンタ.FPS _FPS = null;
private double _現在の演奏時刻secを返す()
{
- return StrokeStyleT.サウンドデバイス.GetDevicePosition() - this.演奏開始時刻sec;
+ return StrokeStyleT.サウンドデバイス.GetDevicePosition() - this._演奏開始時刻sec;
}
}
}