OSDN Git Service

CSCore の高レベルAPIを使って WASAPI 名前空間を再実装。ただし音量が大きいと音割れする。
[strokestylet/CsWin10Desktop3.git] / StrokeStyleT / ステージ / 曲読込 / 曲読込ステージ.cs
1 using System;
2 using System.Collections.Generic;
3 using System.Diagnostics;
4 using System.Linq;
5 using FDK;      // for string 拡張
6 using FDK.メディア;
7
8 namespace SST.ステージ.曲読込
9 {
10         /// <remarks>
11         /// 入力:
12         ///   Func<string> 読込曲のファイルパスを取得する(null 可)
13         ///   StrokeStyleT.ユーザ管理.現在選択されているユーザ(コンフィグ情報)
14         ///   
15         /// 出力:
16         ///   StrokeStyleT.演奏スコア(ファイルパスが null だったならこちらも null になる)
17         /// </remarks>
18         class 曲読込ステージ : SST.ステージ.ステージ
19         {
20                 // 外部依存アクション。
21                 public Func<string> 読込曲のファイルパスを取得する = null;
22
23                 public enum フェーズ { 初期状態, 読込中, 終了 }
24                 public フェーズ 現在のフェーズ { get; protected set; } = フェーズ.初期状態;
25
26                 protected override void On活性化( デバイスリソース dr )
27                 {
28                         FDK.Log.Info( "曲読込ステージを開始します。" + ( StrokeStyleT.ビュアーモードである ? "(ViewerMode)" : "" ) );
29                         Trace.Assert( null != this.読込曲のファイルパスを取得する, "[バグあり] 活性化の前に外部依存アクションを接続してください。" );
30
31                         // 未解放なら解放する。念のため。
32                         StrokeStyleT.演奏スコア?.Dispose();
33
34                         this.現在のフェーズ = フェーズ.読込中;
35                 }
36                 protected override void On非活性化( デバイスリソース dr )
37                 {
38                         FDK.Log.Info( "曲読込ステージを終了します。" );
39                 }
40                 public override void 進行描画する( デバイスリソース dr )
41                 {
42                         switch( this.現在のフェーズ )
43                         {
44                                 case フェーズ.読込中:
45                                         {
46                                                 // SSTFファイルを読み込んでスコアを構築。
47                                                 string 選択曲ファイルパス = this.読込曲のファイルパスを取得する();
48
49                                                 if( 選択曲ファイルパス.Nullでも空でもない() )
50                                                 {
51                                                         var user = StrokeStyleT.ユーザ管理.現在選択されているユーザ;
52
53                                                         StrokeStyleT.演奏スコア = new SSTFormat.スコア(
54                                                                 SST.フォルダ.絶対パスに含まれるフォルダ変数を展開して返す( 選択曲ファイルパス ),
55                                                                 user.Rideは左,
56                                                                 user.Chinaは左,
57                                                                 user.Splashは左 );
58
59                                                         // サウンドデバイス遅延を全チップの発声時刻へ反映する。
60                                                         float 作成時遅延ms = StrokeStyleT.演奏スコア.Header.サウンドデバイス遅延ms;
61                                                         if( 0f < 作成時遅延ms )
62                                                         {
63                                                                 float 再生時遅延ms = (float) ( StrokeStyleT.サウンドデバイス.遅延sec * 1000.0 );
64                                                                 long 加算分ms = (long) ( 作成時遅延ms - 再生時遅延ms );  // 例: 作成時遅延 7ms, 再生時遅延 10ms の場合、発声時刻に 7-10 = -3ms 加算する(3ms 早く発声させる)。
65
66                                                                 FDK.Log.Info( $"作成時遅延={作成時遅延ms}ms, 再生時遅延={再生時遅延ms}ms => 加算分 = {加算分ms}ms" );
67
68                                                                 foreach( var chip in StrokeStyleT.演奏スコア.チップリスト )
69                                                                         chip.発声時刻ms += 加算分ms;
70                                                         }
71                                                         else
72                                                         {
73                                                                 FDK.Log.WARNING( $"この曲ファイルには 作成時遅延(SoundDevice.Delay) の指定がありません。演奏時に音ズレを起こす可能性があります。" );
74                                                         }
75                                                 }
76                                                 else
77                                                 {
78                                                         // ビュアーモードの起動直後ならこちら。
79                                                         StrokeStyleT.演奏スコア = null;
80                                                 }
81
82                                                 // フェーズ終了。
83                                                 this.現在のフェーズ = フェーズ.終了;
84                                         }
85                                         break;
86                         }
87                 }
88         }
89 }