OSDN Git Service

AUTOヒット時にレーンフラッシュするようにした。
[strokestylet/CsWin10Desktop3.git] / StrokeStyleT / ステージ / 演奏 / 演奏ステージ.cs
index cd8be52..2ec8baa 100644 (file)
@@ -47,27 +47,26 @@ namespace SST.ステージ.演奏
 
                public 演奏ステージ()
                {
-                       this.子リスト.Add( this._ステージ台 = new 画像( @"$(System)\images\ステージ台.png" ) );
+                       this.子リスト.Add( this._ステージ台 = new 画像( @"$(System)images\ステージ台.png" ) );
                        this.子リスト.Add( this._レーンフレーム = new レーンフレーム() );
                        this.子リスト.Add( this._ドラムセット = new ドラムセット() );
-                       this.子リスト.Add( this._ヒット判定バー = new 画像( @"$(System)\images\判定バー.png" ) );
-                       this.子リスト.Add( this._チップ画像 = new 画像( @"$(System)\images\Chips.png" ) );
+                       this.子リスト.Add( this._ヒット判定バー = new 画像( @"$(System)images\判定バー.png" ) );
+                       this.子リスト.Add( this._チップ画像 = new 画像( @"$(System)images\Chips.png" ) );
                        this.子リスト.Add( this._回転羽 = new 回転羽( 最大同時発火数: 32 ) );
                        this.子リスト.Add( this._コンソールフォント = new コンソールフォント() );
                        this.子リスト.Add( this._ドラムサウンド = new ドラムサウンド() );
                        this.子リスト.Add( this._コンボ = new コンボ() );
                        this.子リスト.Add( this._ヒットランク = new ヒットランク() );
-                       this.子リスト.Add( this._FPSパラメータ = new 文字列画像() );
                        this.子リスト.Add( this._クリア時フェードアウト = new フェードアウト( 1.0f ) );
-                       this.子リスト.Add( this._白パネル = new 画像( @"$(System)\images\パネル白64x64.png" ) );
+                       this.子リスト.Add( this._白パネル = new 画像( @"$(System)images\パネル白64x64.png" ) );
+                       this.子リスト.Add( this._FPS = new FPS() );
                }
 
-               protected override void Onæ´»æ\80§å\8c\96( ã\83\87ã\83\90ã\82¤ã\82¹ã\83ªã\82½ã\83¼ã\82¹ dr )
+               protected override void Onæ´»æ\80§å\8c\96( ã\82°ã\83©ã\83\95ã\82£ã\83\83ã\82¯ã\83\87ã\83\90ã\82¤ã\82¹ gd )
                {
                        using( Log.Block( FDKUtilities.現在のメソッド名 ) )
                        {
                                this._活性化した直後である = true;
-                               this._演奏開始時刻sec = 0.0;
                                this._背景動画開始済み = false;
                                this._現在進行描画中の譜面スクロール速度の倍率 = App.ユーザ管理.選択されているユーザ.オプション設定.譜面スクロール速度の倍率;
                                this._描画開始チップ番号 = -1;
@@ -76,7 +75,7 @@ namespace SST.ステージ.演奏
                                //this._デコード済みWaveSource = null;    --> キャッシュなので消さない。
                                this._背景動画開始済み = false;
                                this._BGM再生開始済み = false;
-                               this._チップ画像の矩形リスト = new 矩形リスト( @"$(System)\images\Chips Rectangle List.xml" );      // デバイスリソースは持たないので、子Activityではない。
+                               this._チップ画像の矩形リスト = new 矩形リスト( @"$(System)images\Chips Rectangle List.xml" );      // デバイスリソースは持たないので、子Activityではない。
 
                                this.ヒットランク別ヒット回数.Clear();
                                foreach( ヒットランク種別 hitRankType in Enum.GetValues( typeof( ヒットランク種別 ) ) )
@@ -131,7 +130,7 @@ namespace SST.ステージ.演奏
                        }
                }
 
-               protected override void Oné\9d\9eæ´»æ\80§å\8c\96( ã\83\87ã\83\90ã\82¤ã\82¹ã\83ªã\82½ã\83¼ã\82¹ dr )
+               protected override void Oné\9d\9eæ´»æ\80§å\8c\96( ã\82°ã\83©ã\83\95ã\82£ã\83\83ã\82¯ã\83\87ã\83\90ã\82¤ã\82¹ gd )
                {
                        using( Log.Block( FDKUtilities.現在のメソッド名 ) )
                        {
@@ -145,7 +144,7 @@ namespace SST.ステージ.演奏
                        }
                }
 
-               public override void 進行する()
+               public override void é«\98é\80\9fé\80²è¡\8cã\81\99ã\82\8b()
                {
                        Debug.Assert( this.活性化している );
 
@@ -170,8 +169,8 @@ namespace SST.ステージ.演奏
                                                        double 演奏開始位置の先頭からの時間sec = 0.0;
 
                                                        // 演奏開始時刻の設定(1)
-                                                       this._演奏開始時刻sec = App.サウンドデバイス.GetDevicePosition() - 演奏開始位置の先頭からの時間sec;
-                                                       Log.Info( $"演奏開始時刻(背景動画再生チェック前): {this._演奏開始時刻sec} sec" );
+                                                       App.サウンドタイマ.リセットする( 演奏開始位置の先頭からの時間sec );
+                                                       Log.Info( $"演奏開始時刻(背景動画再生チェック前): {App.サウンドタイマ.現在時刻sec} sec" );
 
                                                        // 演奏開始時刻の設定(2) ビュアーメッセージがある場合、開始時刻を修正する。
                                                        var msg = App.最後に取得したビュアーメッセージ;
@@ -189,70 +188,16 @@ namespace SST.ステージ.演奏
                                                        this._再生中の時刻なら動画とBGMを再生開始する( 演奏開始位置の先頭からの時間sec );
 
                                                        // 演奏開始時刻の設定(3) 動画とBGMが再生された場合、ここに到達するまでに多少の遅延が生じているので、ここで演奏開始時刻を再取得しておく。
-                                                       this._演奏開始時刻sec = App.サウンドデバイス.GetDevicePosition() - 演奏開始位置の先頭からの時間sec;
-                                                       Log.Info( $"演奏開始時刻(背景動画再生チェック後): {this._演奏開始時刻sec} sec" );
+                                                       App.サウンドタイマ.リセットする( 演奏開始位置の先頭からの時間sec );
+                                                       Log.Info( $"演奏開始時刻(背景動画再生チェック後): {App.サウンドタイマ.現在時刻sec} sec" );
                                                        //----------------
                                                        #endregion
-
-                                                       this._FPS = new FPS();
                                                }
                                                //----------------
                                                #endregion
 
                                                this._FPS.FPSをカウントしプロパティを更新する();
 
-                                               #region " 譜面スクロール速度が変化している → 追い付き進行 "
-                                               //----------------
-                                               {
-                                                       double 倍率 = this._現在進行描画中の譜面スクロール速度の倍率;
-
-                                                       if( 倍率 < App.ユーザ管理.選択されているユーザ.オプション設定.譜面スクロール速度の倍率 )
-                                                       {
-                                                               if( 0 > this._スクロール倍率追い付き用_最後の値 )
-                                                               {
-                                                                       this._スクロール倍率追い付き用カウンタ = new LoopCounter( 0, 1000, 10 );    // 0→100; 全部で10×1000 = 10000ms = 10sec あれば十分だろう
-                                                                       this._スクロール倍率追い付き用_最後の値 = 0;
-                                                               }
-                                                               else
-                                                               {
-                                                                       while( this._スクロール倍率追い付き用_最後の値 < this._スクロール倍率追い付き用カウンタ.現在値 )
-                                                                       {
-                                                                               倍率 += 0.025;
-                                                                               this._スクロール倍率追い付き用_最後の値++;
-                                                                       }
-
-                                                                       this._現在進行描画中の譜面スクロール速度の倍率 =
-                                                                               Math.Min( 倍率, App.ユーザ管理.選択されているユーザ.オプション設定.譜面スクロール速度の倍率 );
-                                                               }
-                                                       }
-                                                       else if( 倍率 > App.ユーザ管理.選択されているユーザ.オプション設定.譜面スクロール速度の倍率 )
-                                                       {
-                                                               if( 0 > this._スクロール倍率追い付き用_最後の値 )
-                                                               {
-                                                                       this._スクロール倍率追い付き用カウンタ = new LoopCounter( 0, 1000, 10 );    // 0→100; 全部で10×1000 = 10000ms = 10sec あれば十分だろう
-                                                                       this._スクロール倍率追い付き用_最後の値 = 0;
-                                                               }
-                                                               else
-                                                               {
-                                                                       while( this._スクロール倍率追い付き用_最後の値 < this._スクロール倍率追い付き用カウンタ.現在値 )
-                                                                       {
-                                                                               倍率 -= 0.025;
-                                                                               this._スクロール倍率追い付き用_最後の値++;
-                                                                       }
-
-                                                                       this._現在進行描画中の譜面スクロール速度の倍率 =
-                                                                               Math.Max( 倍率, App.ユーザ管理.選択されているユーザ.オプション設定.譜面スクロール速度の倍率 );
-                                                               }
-                                                       }
-                                                       else
-                                                       {
-                                                               this._スクロール倍率追い付き用_最後の値 = -1;
-                                                               this._スクロール倍率追い付き用カウンタ = null;
-                                                       }
-                                               }
-                                               //----------------
-                                               #endregion
-
                                                #region " 背景動画が再生されているのにBGMがまだ再生されていないなら、すぐに再生を開始する。"
                                                //----------------
                                                if( this._背景動画開始済み && !( this._BGM再生開始済み ) )
@@ -263,25 +208,22 @@ namespace SST.ステージ.演奏
                                                //----------------
                                                #endregion
 
-                                               this._レーンフレーム.進行する();
-                                               this._コンボ.進行する();
-                                               this._ヒットランク.進行する();
-                                               this._ドラムセット.進行する();
-                                               this._回転羽.進行する();
-
                                                double 現在の演奏時刻sec = this._演奏開始からの経過時間secを返す();
 
+                                               // 自動演奏
+
                                                #region " 自動ヒット処理。"
                                                //----------------
-                                               this._描画範囲のチップに処理を適用する( 現在の演奏時刻sec, ( chip, index, ヒット判定バーとの時間sec, ヒット判定バーとの距離 ) => {
+                                               this._描画範囲のチップに処理を適用する( 現在の演奏時刻sec, ( chip, index, ヒット判定バーと描画との時間sec, ヒット判定バーと発声との時間sec, ヒット判定バーとの距離 ) => {
 
                                                        var オプション設定 = App.ユーザ管理.選択されているユーザ.オプション設定;
                                                        var 対応表 = オプション設定.ドラムとチップと入力の対応表[ chip.チップ種別 ];
                                                        var AutoPlay = オプション設定.AutoPlay[ 対応表.AutoPlay種別 ];
 
                                                        bool チップはヒット済みである = chip.ヒット済みである;
-                                                       bool チップはMISSエリアに達している = ( ヒット判定バーとの時間sec > オプション設定.最大ヒット距離sec[ ヒットランク種別.POOR ] );
-                                                       bool チップはヒット判定バーを通過した = ( 0 <= ヒット判定バーとの距離 );
+                                                       bool チップはMISSエリアに達している = ( ヒット判定バーと描画との時間sec > オプション設定.最大ヒット距離sec[ ヒットランク種別.POOR ] );
+                                                       bool チップは描画についてヒット判定バーを通過した = ( 0 <= ヒット判定バーと描画との時間sec );
+                                                       bool チップは発声についてヒット判定バーを通過した = ( 0 <= ヒット判定バーと発声との時間sec );
 
                                                        if( チップはヒット済みである )
                                                        {
@@ -294,12 +236,12 @@ namespace SST.ステージ.演奏
                                                                // MISS判定。
                                                                if( AutoPlay && 対応表.AutoPlayON.MISS判定 )
                                                                {
-                                                                       this._チップのヒット処理を行う( chip, ヒットランク種別.MISS, 対応表.AutoPlayON.自動ヒット時処理 );
+                                                                       this._チップのヒット処理を行う( chip, ヒットランク種別.MISS, 対応表.AutoPlayON.自動ヒット時処理, ヒット判定バーと発声との時間sec );
                                                                        return;
                                                                }
                                                                else if( !AutoPlay && 対応表.AutoPlayOFF.MISS判定 )
                                                                {
-                                                                       this._チップのヒット処理を行う( chip, ヒットランク種別.MISS, 対応表.AutoPlayOFF.ユーザヒット時処理 );
+                                                                       this._チップのヒット処理を行う( chip, ヒットランク種別.MISS, 対応表.AutoPlayOFF.ユーザヒット時処理, ヒット判定バーと発声との時間sec );
                                                                        return;
                                                                }
                                                                else
@@ -308,17 +250,27 @@ namespace SST.ステージ.演奏
                                                                }
                                                        }
 
-                                                       if( チップはヒット判定バーを通過した )
+                                                       if( チップは発声についてヒット判定バーを通過した )
+                                                       {
+                                                               // 自動ヒット判定。
+                                                               if( ( AutoPlay && 対応表.AutoPlayON.自動ヒット && 対応表.AutoPlayON.自動ヒット時処理.再生 ) ||
+                                                                       ( !AutoPlay && 対応表.AutoPlayOFF.自動ヒット && 対応表.AutoPlayOFF.自動ヒット時処理.再生 ) )
+                                                               {
+                                                                       this._チップの発声を行う( chip, ヒット判定バーと発声との時間sec );
+                                                               }
+                                                       }
+
+                                                       if( チップは描画についてヒット判定バーを通過した )
                                                        {
                                                                // 自動ヒット判定。
                                                                if( AutoPlay && 対応表.AutoPlayON.自動ヒット )
                                                                {
-                                                                       this._チップのヒット処理を行う( chip, ヒットランク種別.AUTO, 対応表.AutoPlayON.自動ヒット時処理 );
+                                                                       this._チップのヒット処理を行う( chip, ヒットランク種別.AUTO, 対応表.AutoPlayON.自動ヒット時処理, ヒット判定バーと発声との時間sec );
                                                                        return;
                                                                }
                                                                else if( !AutoPlay && 対応表.AutoPlayOFF.自動ヒット )
                                                                {
-                                                                       this._チップのヒット処理を行う( chip, ヒットランク種別.AUTO, 対応表.AutoPlayOFF.自動ヒット時処理 );
+                                                                       this._チップのヒット処理を行う( chip, ヒットランク種別.AUTO, 対応表.AutoPlayOFF.自動ヒット時処理, ヒット判定バーと発声との時間sec );
                                                                        return;
                                                                }
                                                                else
@@ -331,10 +283,119 @@ namespace SST.ステージ.演奏
                                                //----------------
                                                #endregion
 
-                                               // 入力
+                                               // 入力(1) 手動演奏
 
                                                App.入力管理.すべての入力デバイスをポーリングする( 入力履歴を記録する: false );
 
+                                               #region " ユーザヒット処理。"
+                                               //----------------
+                                               {
+                                                       var オプション設定 = App.ユーザ管理.選択されているユーザ.オプション設定;
+
+                                                       #region " ヒットしてようがしてまいが起こすアクション(空打ち処理)。 "
+                                                       //----------------
+                                                       foreach( var 入力 in App.入力管理.ポーリング結果 )
+                                                       {
+                                                               if( 入力.InputEvent.離された )
+                                                                       continue;   // 押下イベントじゃないなら無視。
+
+                                                               this._ドラムセット.ヒットアニメ開始( 入力.Type, オプション設定.表示レーンの左右 );
+
+                                                               var カラム = オプション設定.ドラムとチップと入力の対応表.対応表.Where( ( kvp ) => ( kvp.Value.ドラム入力種別 == 入力.Type ) );  // カラムは struct なので FirstOrDefault() は使わない。
+                                                               if( 0 < カラム.Count() )
+                                                                       this._レーンフレーム.フラッシュ開始( カラム.First().Value.表示レーン種別 );
+                                                       }
+                                                       //----------------
+                                                       #endregion
+
+                                                       var 処理済み入力 = new List<ドラム入力イベント>(); // ヒット処理が終わった入力は、二重処理しないよう、この中に追加しておく。
+
+                                                       this._描画範囲のチップに処理を適用する( 現在の演奏時刻sec, ( chip, index, ヒット判定バーと描画との時間sec, ヒット判定バーと発声との時間sec, ヒット判定バーとの距離 ) => {
+
+                                                               #region " ヒット判定 "
+                                                               //----------------
+                                                               if( chip.ヒット済みである )
+                                                                       return;
+
+                                                               var チップの対応表 = オプション設定.ドラムとチップと入力の対応表[ chip.チップ種別 ];
+
+                                                               if( オプション設定.AutoPlay[ チップの対応表.AutoPlay種別 ] )
+                                                                       return; // チップが AutoPlay ON である。
+
+                                                               if( !( チップの対応表.AutoPlayOFF.ユーザヒット ) )
+                                                                       return; // このチップは、AutoPlay OFF 時でもユーザヒットの対象ではない。
+
+                                                               double ヒット判定バーとの時間の絶対値sec = Math.Abs( ヒット判定バーと描画との時間sec );
+
+                                                               bool チップはMISSエリアに達している = ( ヒット判定バーと描画との時間sec > オプション設定.最大ヒット距離sec[ ヒットランク種別.POOR ] );
+                                                               if( !( ヒット判定バーと描画との時間sec >= -( オプション設定.最大ヒット距離sec[ ヒットランク種別.POOR ] ) && !チップはMISSエリアに達している ) )
+                                                                       return; // チップはヒット可能エリアにある。
+
+                                                               var ヒット入力 = App.入力管理.ポーリング結果.FirstOrDefault( ( 入力 ) => {
+                                                                       #region " chip にヒットする入力があれば true を返す。"
+                                                                       //----------------
+                                                                       if( !( 入力.InputEvent.押された ) )
+                                                                               return false;   // 押下入力じゃない。
+
+                                                                       if( 処理済み入力.Contains( 入力 ) )
+                                                                               return false;   // すでに今回のターンで処理済み(=処理済み入力リストに追加済み)。
+
+                                                                       // chip がシンバルフリーの対象なら、chip に直接対応する入力の他にも、ヒット判定すべき入力がある。
+                                                                       if( チップの対応表.シンバルフリーの対象 && オプション設定.シンバルフリー )
+                                                                       {
+                                                                               // この入力に対応するカラムのうち、
+                                                                               var カラムs = オプション設定.ドラムとチップと入力の対応表.対応表.Where( ( kvp ) => ( kvp.Value.ドラム入力種別 == 入力.Type ) );
+                                                                               foreach( var カラム in カラムs )
+                                                                               {
+                                                                                       // シンバルフリーなチップがあるなら true。
+                                                                                       if( カラム.Value.シンバルフリーの対象 )
+                                                                                               return true;
+                                                                               }
+                                                                               // まったくなかったら false。
+                                                                               return false;
+                                                                       }
+
+                                                                       // chip に対応する入力なら true。
+                                                                       return ( チップの対応表.ドラム入力種別 == 入力.Type );
+                                                                       //----------------
+                                                                       #endregion
+                                                               } );
+
+                                                               if( null == ヒット入力 )
+                                                                       return;
+                                                               //----------------
+                                                               #endregion
+
+                                                               処理済み入力.Add( ヒット入力 );
+
+                                                               #region " ヒットランクを判定する。"
+                                                               //----------------
+                                                               var ヒットランク = ヒットランク種別.POOR;
+
+                                                               if( ヒット判定バーとの時間の絶対値sec <= オプション設定.最大ヒット距離sec[ ヒットランク種別.PERFECT ] )
+                                                               {
+                                                                       ヒットランク = ヒットランク種別.PERFECT;
+                                                               }
+                                                               else if( ヒット判定バーとの時間の絶対値sec <= オプション設定.最大ヒット距離sec[ ヒットランク種別.GREAT ] )
+                                                               {
+                                                                       ヒットランク = ヒットランク種別.GREAT;
+                                                               }
+                                                               else if( ヒット判定バーとの時間の絶対値sec <= オプション設定.最大ヒット距離sec[ ヒットランク種別.GOOD ] )
+                                                               {
+                                                                       ヒットランク = ヒットランク種別.GOOD;
+                                                               }
+                                                               //----------------
+                                                               #endregion
+
+                                                               this._チップのヒット処理を行う( chip, ヒットランク, チップの対応表.AutoPlayOFF.ユーザヒット時処理, ヒット判定バーと発声との時間sec );
+
+                                                       } );
+                                               }
+                                               //----------------
+                                               #endregion
+
+                                               // 入力(2) アプリ操作
+
                                                if( App.入力管理.キーボードデバイス.キーが押された( 0, Key.Escape ) )
                                                {
                                                        #region " ESC → ステージキャンセル "
@@ -380,130 +441,78 @@ namespace SST.ステージ.演奏
                                                        //----------------
                                                        #endregion
                                                }
+                                       }
+                                       //----------------
+                                       #endregion
+                                       break;
+                       }
+               }
 
-                                               #region " ユーザヒット処理。"
-                                               //----------------
-                                               foreach( var 入力 in App.入力管理.ポーリング結果 )
-                                               {
-                                                       if( 入力.InputEvent.離された )
-                                                               continue;   // 押下イベントじゃないなら無視。
-
-                                                       this._ドラムセット.ヒットアニメ開始( 入力.Type, App.ユーザ管理.選択されているユーザ.オプション設定.表示レーンの左右 );
-                                               }
-
-                                               var 処理済み入力 = new List<ドラム入力イベント>(); // ヒット処理が終わった入力は、二重処理しないよう、この中に追加しておく。
-
-                                               this._描画範囲のチップに処理を適用する( 現在の演奏時刻sec, ( chip, index, ヒット判定バーとの時間sec, ヒット判定バーとの距離 ) => {
-
-                                                       var オプション設定 = App.ユーザ管理.選択されているユーザ.オプション設定;
-                                                       var 対応表 = オプション設定.ドラムとチップと入力の対応表[ chip.チップ種別 ];
-                                                       bool AutoPlay = オプション設定.AutoPlay[ 対応表.AutoPlay種別 ];
-                                                       double ヒット判定バーとの時間の絶対値sec = Math.Abs( ヒット判定バーとの時間sec );
-                                                       bool チップはヒット済みである = chip.ヒット済みである;
-                                                       bool チップはMISSエリアに達している = ( ヒット判定バーとの時間sec > オプション設定.最大ヒット距離sec[ ヒットランク種別.POOR ] );
-                                                       bool チップはヒット可能エリアにある = ( ヒット判定バーとの時間sec >= -( オプション設定.最大ヒット距離sec[ ヒットランク種別.POOR ] ) && !チップはMISSエリアに達している );
-
-                                                       if( AutoPlay || チップはヒット済みである || !( 対応表.AutoPlayOFF.ユーザヒット ) || !( チップはヒット可能エリアにある ) )
-                                                               return;
-
-                                                       // チップにヒットする入力を探す。
-                                                       var ヒット入力 = App.入力管理.ポーリング結果.FirstOrDefault( ( 入力 ) => {
+               public override void 進行描画する( グラフィックデバイス gd )
+               {
+                       Debug.Assert( this.活性化している );
+                       Debug.Assert( null != gd );
 
-                                                               if( !( 入力.InputEvent.押された ) )
-                                                                       return false;   // 押下入力じゃない。
+                       switch( this.現在のフェーズ )
+                       {
+                               case フェーズ.演奏中:
+                                       if( this._活性化した直後である )
+                                               break;  // 進行処理がまだ行われていない。
 
-                                                               if( 処理済み入力.Contains( 入力 ) )
-                                                                       return false;   // すでに今回のターンで処理済み(=処理済み入力リストに追加済み)。
+                                       #region " 譜面スクロール速度が変化している → 追い付き進行 "
+                                       //----------------
+                                       {
+                                               double 倍率 = this._現在進行描画中の譜面スクロール速度の倍率;
 
-                                                               if( 対応表.シンバルフリーの対象 && オプション設定.シンバルフリー )
-                                                               {
-                                                                       // (A) シンバルフリーの対象チップであり、かつシンバルフリーが ON である場合
-                                                                       var 入力の対応表 = オプション設定.ドラムとチップと入力の対応表.対応表.FirstOrDefault( ( kvp ) => ( kvp.Value.ドラム入力種別 == 入力.Type ) ).Value;        // 見つからなきゃバグだ
-                                                                       if( !( 入力の対応表.シンバルフリーの対象 ) )
-                                                                               return false;   // この入力はシンバルフリーの対象ではない。
-                                                               }
-                                                               else
+                                               if( 倍率 < App.ユーザ管理.選択されているユーザ.オプション設定.譜面スクロール速度の倍率 )
+                                               {
+                                                       if( 0 > this._スクロール倍率追い付き用_最後の値 )
+                                                       {
+                                                               this._スクロール倍率追い付き用カウンタ = new LoopCounter( 0, 1000, 10 );    // 0→100; 全部で10×1000 = 10000ms = 10sec あれば十分だろう
+                                                               this._スクロール倍率追い付き用_最後の値 = 0;
+                                                       }
+                                                       else
+                                                       {
+                                                               while( this._スクロール倍率追い付き用_最後の値 < this._スクロール倍率追い付き用カウンタ.現在値 )
                                                                {
-                                                                       // (B) シンバルフリーの対象ではないチップ、またはシンバルフリーが OFF である場合
-                                                                       if( 対応表.ドラム入力種別 != 入力.Type )
-                                                                               return false;   // チップに対応している入力じゃない。
+                                                                       倍率 += 0.025;
+                                                                       this._スクロール倍率追い付き用_最後の値++;
                                                                }
 
-                                                               return true;    // この 入力 はこの chip にヒットしている。
-                                                       } );
-
-                                                       if( null == ヒット入力 )
-                                                               return;
-
-                                                       処理済み入力.Add( ヒット入力 );
-
-                                                       // ヒットランクを判定する。
-
-                                                       var ヒットランク = ヒットランク種別.POOR;
-
-                                                       if( ヒット判定バーとの時間の絶対値sec <= オプション設定.最大ヒット距離sec[ ヒットランク種別.PERFECT ] )
-                                                       {
-                                                               ヒットランク = ヒットランク種別.PERFECT;
+                                                               this._現在進行描画中の譜面スクロール速度の倍率 =
+                                                                       Math.Min( 倍率, App.ユーザ管理.選択されているユーザ.オプション設定.譜面スクロール速度の倍率 );
                                                        }
-                                                       else if( ヒット判定バーとの時間の絶対値sec <= オプション設定.最大ヒット距離sec[ ヒットランク種別.GREAT ] )
+                                               }
+                                               else if( 倍率 > App.ユーザ管理.選択されているユーザ.オプション設定.譜面スクロール速度の倍率 )
+                                               {
+                                                       if( 0 > this._スクロール倍率追い付き用_最後の値 )
                                                        {
-                                                               ヒットランク = ヒットランク種別.GREAT;
+                                                               this._スクロール倍率追い付き用カウンタ = new LoopCounter( 0, 1000, 10 );    // 0→100; 全部で10×1000 = 10000ms = 10sec あれば十分だろう
+                                                               this._スクロール倍率追い付き用_最後の値 = 0;
                                                        }
-                                                       else if( ヒット判定バーとの時間の絶対値sec <= オプション設定.最大ヒット距離sec[ ヒットランク種別.GOOD ] )
+                                                       else
                                                        {
-                                                               ヒットランク = ヒットランク種別.GOOD;
-                                                       }
-
-                                                       // ヒット処理。
-
-                                                       this._チップのヒット処理を行う( chip, ヒットランク, 対応表.AutoPlayOFF.ユーザヒット時処理 );
-
-                                               } );
-                                               //----------------
-                                               #endregion
-                                       }
-                                       //----------------
-                                       #endregion
-                                       break;
-
-                               case フェーズ.クリア時フェードアウト:
-                                       #region " *** "
-                                       //----------------
-                                       if( this._クリア時フェードアウト.開始されていない )
-                                       {
-                                               this._クリア時フェードアウト.開始する();
-                                       }
-                                       else
-                                       {
-                                               this._クリア時フェードアウト.進行する();
+                                                               while( this._スクロール倍率追い付き用_最後の値 < this._スクロール倍率追い付き用カウンタ.現在値 )
+                                                               {
+                                                                       倍率 -= 0.025;
+                                                                       this._スクロール倍率追い付き用_最後の値++;
+                                                               }
 
-                                               if( this._クリア時フェードアウト.完了した )
+                                                               this._現在進行描画中の譜面スクロール速度の倍率 =
+                                                                       Math.Max( 倍率, App.ユーザ管理.選択されているユーザ.オプション設定.譜面スクロール速度の倍率 );
+                                                       }
+                                               }
+                                               else
                                                {
-                                                       this.現在のフェーズ = フェーズ.クリア;
+                                                       this._スクロール倍率追い付き用_最後の値 = -1;
+                                                       this._スクロール倍率追い付き用カウンタ = null;
                                                }
                                        }
                                        //----------------
                                        #endregion
-                                       break;
-
-                               case フェーズ.Failed:
-                               case フェーズ.クリア:
-                               case フェーズ.キャンセル:
-                               case フェーズ.ビュアーメッセージ待機:
-                                       break;
-                       }
-               }
 
-               public override void 描画する( デバイスリソース dr )
-               {
-                       Debug.Assert( this.活性化している );
-                       Debug.Assert( null != dr );
-
-                       switch( this.現在のフェーズ )
-                       {
-                               case フェーズ.演奏中:
-                                       if( this._活性化した直後である )
-                                               break;  // 進行処理がまだ行われていない。
+                                       this._コンボ.進行描画する( gd );
+                                       this._回転羽.進行描画する( gd );
 
                                        double 演奏時刻sec = this._演奏開始からの経過時間secを返す();
 
@@ -518,16 +527,16 @@ namespace SST.ステージ.演奏
                                                                #region " *** "
                                                                //----------------
                                                                {
-                                                                       float w = dr.設計画面サイズ.Width;
-                                                                       float h = dr.設計画面サイズ.Height;
+                                                                       float w = gd.設計画面サイズ.Width;
+                                                                       float h = gd.設計画面サイズ.Height;
 
-                                                                       this._背景動画?.進行描画する( dr, new RectangleF( 0f, 0f, w, h ), 0.2f );  // 全体
+                                                                       this._背景動画?.描画する( gd, new RectangleF( 0f, 0f, w, h ), 0.2f );  // 全体
 
                                                                        float 拡大縮小率 = 0.75f;
                                                                        float 上移動 = 100.0f;
 
                                                                        // 進行描画せず、直前に取得したフレームをそのまま描画する。
-                                                                       this._背景動画?.前のフレームを描画する( dr, new RectangleF(
+                                                                       this._背景動画?.前のフレームを描画する( gd, new RectangleF(
                                                                                w * ( 1f - 拡大縮小率 ) / 2f,
                                                                                h * ( 1f - 拡大縮小率 ) / 2f - 上移動,
                                                                                w * 拡大縮小率,
@@ -540,7 +549,7 @@ namespace SST.ステージ.演奏
                                                        case 動画表示パターン種別.最大表示:
                                                                #region " *** "
                                                                //----------------
-                                                               this._背景動画?.進行描画する( dr, new RectangleF( 0f, 0f, dr.設計画面サイズ.Width, dr.設計画面サイズ.Height ), 1.0f );
+                                                               this._背景動画?.描画する( gd, new RectangleF( 0f, 0f, gd.設計画面サイズ.Width, gd.設計画面サイズ.Height ), 1.0f );
                                                                //----------------
                                                                #endregion
                                                                break;
@@ -552,30 +561,39 @@ namespace SST.ステージ.演奏
                                        //----------------
                                        #endregion
 
-                                       this._ステージ台.描画する( dr, 0f, 0f );
-                                       this._レーンフレーム.描画する( dr, レーンフレームの左端位置 );
-                                       this._コンボ.描画する( dr );
-                                       this._ヒットランク.描画する( dr, レーンフレームの左端位置 );
-                                       this._小節線拍線を描画する( dr, 演奏時刻sec );
-                                       this._ヒット判定バー.描画する( dr, 597f, ヒット判定バーの中央Y座標 - 43f );
-                                       this._ドラムセット.描画する( dr );
-                                       this._チップを描画する( dr, 演奏時刻sec );
-                                       this._回転羽.描画する( dr );
+                                       this._ステージ台.描画する( gd, 0f, 0f );
+                                       this._レーンフレーム.進行描画する( gd, レーンフレームの左端位置 );
+                                       this._コンボ.進行描画する( gd );
+                                       this._ヒットランク.進行描画する( gd, レーンフレームの左端位置 );
+                                       this._小節線拍線を描画する( gd, 演奏時刻sec );
+                                       this._ヒット判定バー.描画する( gd, 597f, ヒット判定バーの中央Y座標 - 43f );
+                                       this._ドラムセット.進行描画する( gd );
+                                       this._チップを描画する( gd, 演奏時刻sec );
+                                       this._回転羽.進行描画する( gd );
                                        this._FPS.VPSをカウントする();
-                                       this._FPSパラメータ.表示文字列 = $"VPS: {this._FPS.現在のVPS.ToString()} / FPS: {this._FPS.現在のFPS.ToString()}";
-                                       this._FPSパラメータ.描画する( dr, 0f, 0f );
+                                       this._FPS.描画する( gd, 0f, 0f );
                                        break;
 
                                case フェーズ.クリア時フェードアウト:
-                                       this._ステージ台.描画する( dr, 0f, 0f );
-                                       this._レーンフレーム.描画する( dr, レーンフレームの左端位置 );
-                                       this._ヒット判定バー.描画する( dr, 597f, ヒット判定バーの中央Y座標 - 43f );
-                                       this._ドラムセット.描画する( dr );
-                                       this._回転羽.描画する( dr );
-                                       this._クリア時フェードアウト.描画する( dr, this._白パネル );
+                                       if( this._クリア時フェードアウト.開始されていない )
+                                       {
+                                               this._クリア時フェードアウト.開始する();
+                                       }
+                                       else
+                                       {
+                                               if( this._クリア時フェードアウト.完了した )
+                                               {
+                                                       this.現在のフェーズ = フェーズ.クリア;
+                                               }
+                                       }
+                                       this._ステージ台.描画する( gd, 0f, 0f );
+                                       this._レーンフレーム.進行描画する( gd, レーンフレームの左端位置 );
+                                       this._ヒット判定バー.描画する( gd, 597f, ヒット判定バーの中央Y座標 - 43f );
+                                       this._ドラムセット.進行描画する( gd );
+                                       this._回転羽.進行描画する( gd );
+                                       this._クリア時フェードアウト.進行描画する( gd, this._白パネル );
                                        this._FPS.VPSをカウントする();
-                                       this._FPSパラメータ.表示文字列 = $"VPS: {this._FPS.現在のVPS.ToString()} / FPS: {this._FPS.現在のFPS.ToString()}";
-                                       this._FPSパラメータ.描画する( dr, 0f, 0f );
+                                       this._FPS.描画する( gd, 0f, 0f );
                                        break;
 
                                case フェーズ.Failed:
@@ -626,8 +644,6 @@ namespace SST.ステージ.演奏
                }
 
 
-               private double _演奏開始時刻sec = 0.0;
-
                private double _現在進行描画中の譜面スクロール速度の倍率 = 1.0;
 
                /// <summary>
@@ -688,8 +704,6 @@ namespace SST.ステージ.演奏
 
                private FPS _FPS = null;
 
-               private 文字列画像 _FPSパラメータ = null;
-
                private LoopCounter _スクロール倍率追い付き用カウンタ = null;
 
                private int _スクロール倍率追い付き用_最後の値 = -1;
@@ -700,6 +714,7 @@ namespace SST.ステージ.演奏
 
                private bool _活性化した直後である;
 
+
                // 譜面描画。
 
                /// <summary>
@@ -771,7 +786,7 @@ namespace SST.ステージ.演奏
                                        double 再生開始時刻sec = ( 時刻sec - 背景動画チップ.発声時刻sec );
                                        this._背景動画?.再生を開始する( 再生開始時刻sec );
                                        this._背景動画開始済み = true;
-                                       this._BGM?.Play( 再生開始時刻sec );
+                                       this._BGM?.Play( 再生開始時刻sec - App.サウンドデバイス.遅延sec );
                                        this._BGM再生開始済み = true;
                                        Log.Info( $"背景動画の再生を開始しました。(再生開始時刻: {再生開始時刻sec} sec)" );
                                }
@@ -784,19 +799,19 @@ namespace SST.ステージ.演奏
 
                private double _演奏開始からの経過時間secを返す()
                {
-                       return App.ã\82µã\82¦ã\83³ã\83\89ã\83\87ã\83\90ã\82¤ã\82¹.GetDevicePosition() - this._æ¼\94å¥\8fé\96\8bå§\8b時刻sec;
+                       return App.ã\82µã\82¦ã\83³ã\83\89ã\82¿ã\82¤ã\83\9e\8f¾å\9c¨時刻sec;
                }
 
                // 小節線・拍線 と チップ は描画階層(奥行き)が異なるので、別々のメソッドに分ける。
 
-               private void _å°\8fç¯\80ç·\9aæ\8b\8dç·\9aã\82\92æ\8f\8fç\94»ã\81\99ã\82\8b( ã\83\87ã\83\90ã\82¤ã\82¹ã\83ªã\82½ã\83¼ã\82¹ dr, double 現在の演奏時刻sec )
+               private void _å°\8fç¯\80ç·\9aæ\8b\8dç·\9aã\82\92æ\8f\8fç\94»ã\81\99ã\82\8b( ã\82°ã\83©ã\83\95ã\82£ã\83\83ã\82¯ã\83\87ã\83\90ã\82¤ã\82¹ gd, double 現在の演奏時刻sec )
                {
                        if( null == this._チップ画像 )
                                return;
 
                        this._チップ画像.加算合成 = false;
 
-                       this._描画範囲のチップに処理を適用する( 現在の演奏時刻sec, ( chip, index, ヒット判定バーとの時間sec, ヒット判定バーとの距離 ) => {
+                       this._描画範囲のチップに処理を適用する( 現在の演奏時刻sec, ( chip, index, ヒット判定バーと描画との時間sec, ヒット判定バーと発声との時間sec, ヒット判定バーとの距離 ) => {
 
                                if( chip.チップ種別 == チップ種別.小節線 )
                                {
@@ -806,8 +821,8 @@ namespace SST.ステージ.演奏
                                        float 上位置 = (float)( ヒット判定バーの中央Y座標 + ヒット判定バーとの距離 - 1f );   // -1f は小節線の厚みの半分。
                                        if( this._チップ画像の矩形リスト[ nameof( チップ種別.小節線 ) ] is RectangleF 画像範囲 )
                                        {
-                                               this._チップ画像.描画する( dr, 左位置, 上位置, 転送元矩形: 画像範囲, 描画先矩形を整数境界に合わせる: true );     // false にすると、
-                                               this._チップ画像.描画する( dr, 左位置 + 画像範囲.Width, 上位置, 転送元矩形: 画像範囲, 描画先矩形を整数境界に合わせる: true );        // チカチカする。
+                                               this._チップ画像.描画する( gd, 左位置, 上位置, 転送元矩形: 画像範囲, 描画先矩形を整数境界に合わせる: true );     // false にすると、
+                                               this._チップ画像.描画する( gd, 左位置 + 画像範囲.Width, 上位置, 転送元矩形: 画像範囲, 描画先矩形を整数境界に合わせる: true );        // チカチカする。
                                        }
                                        //----------------
                                        #endregion
@@ -820,8 +835,8 @@ namespace SST.ステージ.演奏
                                        float 上位置 = (float)( ヒット判定バーの中央Y座標 + ヒット判定バーとの距離 - 1f );   // -1f は拍線の厚みの半分。
                                        if( this._チップ画像の矩形リスト[ nameof( チップ種別.拍線 ) ] is RectangleF 画像範囲 )
                                        {
-                                               this._チップ画像.描画する( dr, 左位置: 左位置, 上位置: 上位置, 転送元矩形: 画像範囲, 描画先矩形を整数境界に合わせる: true );       // false にすると、
-                                               this._チップ画像.描画する( dr, 左位置: 左位置 + 画像範囲.Width, 上位置: 上位置, 転送元矩形: 画像範囲, 描画先矩形を整数境界に合わせる: true );  // チカチカする。
+                                               this._チップ画像.描画する( gd, 左位置: 左位置, 上位置: 上位置, 転送元矩形: 画像範囲, 描画先矩形を整数境界に合わせる: true );       // false にすると、
+                                               this._チップ画像.描画する( gd, 左位置: 左位置 + 画像範囲.Width, 上位置: 上位置, 転送元矩形: 画像範囲, 描画先矩形を整数境界に合わせる: true );  // チカチカする。
                                        }
                                        //----------------
                                        #endregion
@@ -830,21 +845,21 @@ namespace SST.ステージ.演奏
                        } );
                }
 
-               private void _ã\83\81ã\83\83ã\83\97ã\82\92æ\8f\8fç\94»ã\81\99ã\82\8b( ã\83\87ã\83\90ã\82¤ã\82¹ã\83ªã\82½ã\83¼ã\82¹ dr, double 現在の演奏時刻sec )
+               private void _ã\83\81ã\83\83ã\83\97ã\82\92æ\8f\8fç\94»ã\81\99ã\82\8b( ã\82°ã\83©ã\83\95ã\82£ã\83\83ã\82¯ã\83\87ã\83\90ã\82¤ã\82¹ gd, double 現在の演奏時刻sec )
                {
                        if( null == this._チップ画像 )
                                return;
 
                        this._チップ画像.加算合成 = false;
 
-                       this._描画範囲のチップに処理を適用する( 現在の演奏時刻sec, ( chip, index, ヒット判定バーとの時間sec, ヒット判定バーとの距離 ) => {
+                       this._描画範囲のチップに処理を適用する( 現在の演奏時刻sec, ( chip, index, ヒット判定バーと描画との時間sec, ヒット判定バーと発声との時間sec, ヒット判定バーとの距離 ) => {
 
                                float 縦中央位置 = (float)( ヒット判定バーの中央Y座標 + ヒット判定バーとの距離 );
 
                                #region " チップが描画開始チップであり、かつ、そのY座標が画面下端を超えたなら、描画開始チップ番号を更新する。"
                                //----------------
                                if( ( index == this._描画開始チップ番号 ) &&
-                                       ( dr.設計画面サイズ.Height + 40.0 < 縦中央位置 ) )   // +40 はチップが隠れるであろう適当なマージン。
+                                       ( gd.設計画面サイズ.Height + 40.0 < 縦中央位置 ) )   // +40 はチップが隠れるであろう適当なマージン。
                                {
                                        this._描画開始チップ番号++;
 
@@ -1006,7 +1021,7 @@ namespace SST.ステージ.演奏
                                var 画像範囲 = (RectangleF) 元矩形;
 
                                this._チップ画像?.描画する(
-                                       dr,
+                                       gd,
                                        左位置: レーンフレームの左端位置 + レーンフレーム.レーンto横中央相対位置[ lane ] - ( 画像範囲.Width / 2f ),
                                        上位置: 上位置 - ( ( 画像範囲.Height / 2f ) * 音量0to1 ),
                                        転送元矩形: 元矩形,
@@ -1025,7 +1040,7 @@ namespace SST.ステージ.演奏
                                float 左位置 = レーンフレームの左端位置 + レーンフレーム.レーンto横中央相対位置[ lane ] - ( 画像範囲.Width / 2f );
                                float 上位置 = Y - ( チップ1枚の高さ / 2f ) * 音量0to1;
 
-                               this._チップ画像?.描画する( dr, 左位置, 上位置, 転送元矩形: 画像範囲, Y方向拡大率: 音量0to1 );
+                               this._チップ画像?.描画する( gd, 左位置, 上位置, 転送元矩形: 画像範囲, Y方向拡大率: 音量0to1 );
                        }
                        //----------------
                        #endregion
@@ -1035,7 +1050,7 @@ namespace SST.ステージ.演奏
                ///             <see cref="_描画開始チップ番号"/> から画面上端にはみ出すまでの間の各チップに対して、指定された処理を適用する。
                /// </summary>
                /// <param name="適用する処理">引数は、順に、対象のチップ、チップ番号、ヒット判定バーとの時間sec、ヒット判定バーとの距離</param>
-               private void _描画範囲のチップに処理を適用する( double 現在の演奏時刻sec, Action<チップ, int, double, double> 適用する処理 )
+               private void _描画範囲のチップに処理を適用する( double 現在の演奏時刻sec, Action<チップ, int, double, double, double> 適用する処理 )
                {
                        var スコア = App.演奏スコア;
                        if( null == スコア )
@@ -1046,8 +1061,9 @@ namespace SST.ステージ.演奏
                                var チップ = スコア.チップリスト[ i ];
 
                                // ヒット判定バーとチップの間の、時間 と 距離 を算出。→ いずれも、負数ならバー未達、0でバー直上、正数でバー通過。
-                               double ヒット判定バーとの時間sec = 現在の演奏時刻sec - チップ.描画時刻sec;
-                               double ヒット判定バーとの距離 = スコア.指定された時間secに対応する符号付きピクセル数を返す( this._現在進行描画中の譜面スクロール速度の倍率, ヒット判定バーとの時間sec );
+                               double ヒット判定バーと描画との時間sec = 現在の演奏時刻sec - チップ.描画時刻sec;
+                               double ヒット判定バーと発声との時間sec = 現在の演奏時刻sec - チップ.発声時刻sec;
+                               double ヒット判定バーとの距離 = スコア.指定された時間secに対応する符号付きピクセル数を返す( this._現在進行描画中の譜面スクロール速度の倍率, ヒット判定バーと描画との時間sec );
 
                                // 終了判定。
                                bool チップは画面上端より上に出ている = ( ( ヒット判定バーの中央Y座標 + ヒット判定バーとの距離 ) < -40.0 );   // -40 はチップが隠れるであろう適当なマージン。
@@ -1055,33 +1071,20 @@ namespace SST.ステージ.演奏
                                        break;
 
                                // 処理実行。開始判定(描画開始チップ番号の更新)もこの中で。
-                               適用する処理( チップ, i, ヒット判定バーとの時間sec, ヒット判定バーとの距離 );
+                               適用する処理( チップ, i, ヒット判定バーと描画との時間sec, ヒット判定バーと発声との時間sec, ヒット判定バーとの距離 );
                        }
                }
 
-               private void _チップのヒット処理を行う( チップ chip, ヒットランク種別 hitRankType, ドラムとチップと入力の対応表.Column.Columnヒット処理 ヒット処理表 )
+               private void _チップのヒット処理を行う( チップ chip, ヒットランク種別 hitRankType, ドラムとチップと入力の対応表.Column.Columnヒット処理 ヒット処理表, double ヒット判定バーと発声との時間sec )
                {
                        chip.ヒット済みである = true;
 
                        if( ヒット処理表.再生 )
                        {
-                               #region " ã\83\81ã\83\83ã\83\97ã\82\92å\86\8dç\94\9fã\81\99ã\82\8b。"
+                               #region " ã\83\81ã\83\83ã\83\97ã\81®ç\99ºå£°ã\82\92è¡\8cã\81\86。"
                                //----------------
-                               if( chip.チップ種別 == チップ種別.背景動画 )
-                               {
-                                       // 背景動画の再生を開始する。
-                                       this._背景動画?.再生を開始する();
-                                       this._背景動画開始済み = true;
-
-                                       // BGMの再生を開始する。
-                                       this._BGM?.Play();
-                                       this._BGM再生開始済み = true;
-                               }
-                               else
-                               {
-                                       if( App.システム設定.Autoチップのドラム音を再生する )
-                                               this._ドラムサウンド.発声する( chip.チップ種別, ( chip.音量 / (float) チップ.最大音量 ) );
-                               }
+                               if( chip.発声されていない )
+                                       this._チップの発声を行う( chip, ヒット判定バーと発声との時間sec );
                                //----------------
                                #endregion
                        }
@@ -1103,7 +1106,9 @@ namespace SST.ステージ.演奏
                                                        ヒット判定バーの中央Y座標 ) );
 
                                        this._ドラムセット.ヒットアニメ開始( 対応表.ドラム入力種別, App.ユーザ管理.選択されているユーザ.オプション設定.表示レーンの左右 );
-                                       this._レーンフレーム.フラッシュ開始( 対応表.表示レーン種別 );
+
+                                       if( hitRankType == ヒットランク種別.AUTO )
+                                               this._レーンフレーム.フラッシュ開始( 対応表.表示レーン種別 );   // レーンフラッシュは Auto 時のみ。
 
                                        this._ヒットランク.表示開始( chip.チップ種別, hitRankType );
                                        this.ヒットランク別ヒット回数[ hitRankType ]++;
@@ -1137,5 +1142,34 @@ namespace SST.ステージ.演奏
                                #endregion
                        }
                }
+
+               private void _チップの発声を行う( チップ chip, double 再生開始位置sec )
+               {
+                       if( chip.発声済みである )
+                               return;
+
+                       chip.発声済みである = true;
+
+                       if( chip.チップ種別 == チップ種別.背景動画 )
+                       {
+                               App.サウンドタイマ.一時停止する();
+
+                               // 背景動画の再生を開始する。
+                               this._背景動画?.再生を開始する();
+                               this._背景動画開始済み = true;
+
+                               // BGMの再生を開始する。
+                               this._BGM?.Play( 再生開始位置sec );
+                               this._BGM再生開始済み = true;
+
+                               App.サウンドタイマ.再開する();
+                       }
+                       else
+                       {
+                               // BGM以外のサウンドについては、再生開始位置sec は反映せず、常に最初から再生する。
+                               if( App.システム設定.Autoチップのドラム音を再生する )
+                                       this._ドラムサウンド.発声する( chip.チップ種別, ( chip.音量 / (float) チップ.最大音量 ) );
+                       }
+               }
        }
 }