OSDN Git Service

Device クラスのメンバを若干修正。
[strokestylet/CsWin10Desktop3.git] / FDK24 / メディア / サウンド / WASAPI / Device.cs
index 1066023..8fdd9e8 100644 (file)
@@ -19,7 +19,7 @@ namespace FDK.メディア.サウンド.WASAPI
                        protected set;
                } = true;
 
-               public void 初期化する( float 希望更新間隔ms )
+               public void 初期化する( double 希望更新間隔sec = 0.015 )
                {
                        int hr = 0;
 
@@ -28,8 +28,6 @@ namespace FDK.メディア.サウンド.WASAPI
                                Trace.Assert( this.Dispose済み );
                                this.Dispose済み = false;
 
-                               this.希望更新間隔ms = 希望更新間隔ms;
-
                                #region " AudioClientをアクティベートする。"
                                //-----------------
                                using( var devices = new CSCore.CoreAudioAPI.MMDeviceEnumerator() )
@@ -41,25 +39,27 @@ namespace FDK.メディア.サウンド.WASAPI
                                #endregion
                                #region " 指定された希望更新間隔とデバイス能力をもとに、更新間隔を決定する。"
                                //-----------------
-                               long 共有モードでの間隔in100ns = 0;
-                               long 排他モードでの最小間隔in100ns = 0;
+                               long 共有モードでの間隔100ns = 0;
+                               long 排他モードでの最小間隔100ns = 0;
 
-                               // 最小間隔を取得する。
-                               hr = this.AudioClient.GetDevicePeriodNative( out 共有モードでの間隔in100ns, out 排他モードでの最小間隔in100ns );
+                               // デバイスから間隔値を取得する。
+                               hr = this.AudioClient.GetDevicePeriodNative( out 共有モードでの間隔100ns, out 排他モードでの最小間隔100ns );
                                if( 0 > hr )
                                        System.Runtime.InteropServices.Marshal.ThrowExceptionForHR( hr );
 
-                               // 取得できたらms単位に変換。
-                               this.最小間隔ms = (float) 排他モードでの最小間隔in100ns / 10000.0f;
+                               var 最小間隔ms = (float) 排他モードでの最小間隔100ns / 10000.0f;
 
-                               // 更新間隔ms を「希望更新間隔とデバイスの最小間隔の大きい方以上 かつ 1秒以下で丸められた値」にする。
-                               this.更新間隔ms = System.Math.Min( 1000.0f, System.Math.Max( this.希望更新間隔ms, this.最小間隔ms ) );
+                               // 更新間隔ms を「希望更新間隔とデバイスの最小間隔の大きい方 かつ 最大1秒までの値」にする。
+                               this.更新間隔ms = System.Math.Min( 1000.0f, System.Math.Max( (float) ( 希望更新間隔sec * 1000.0 ), 最小間隔ms ) );
                                //-----------------
                                #endregion
+                               #region " デバイスフォーマットを決定する。"
+                               //----------------
+                               this.WaveFormat = new CSCore.WaveFormat( 44100, 16, 2, CSCore.AudioEncoding.Pcm );
+                               //----------------
+                               #endregion
                                #region " AudioClient を初期化する。"
                                //-----------------
-                               var waveFormat = new CSCore.WaveFormat( 44100, 16, 2, CSCore.AudioEncoding.Pcm );
-
                                try
                                {
                                        this.AudioClient.Initialize(
@@ -67,7 +67,7 @@ namespace FDK.メディア.サウンド.WASAPI
                                                CSCore.CoreAudioAPI.AudioClientStreamFlags.StreamFlagsEventCallback,    // イベント駆動モード。
                                                (long) ( this.更新間隔ms * 10000.0f + 0.5f ),   // バッファサイズ。イベント駆動モードでは、更新間隔と同じ値でなければならない。
                                                (long) ( this.更新間隔ms * 10000.0f + 0.5f ),   // 更新間隔。
-                                               waveFormat, // バッファのフォーマット。
+                                               this.WaveFormat, // バッファのフォーマット。
                                                Guid.Empty );   // この AudioClient = AudioStrem が所属する AudioSession。null ならデフォルトのAudioSessionに登録される。
                                }
                                catch( CSCore.CoreAudioAPI.CoreAudioAPIException e )
@@ -76,7 +76,7 @@ namespace FDK.メディア.サウンド.WASAPI
                                        if( AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED == e.ErrorCode )
                                        {
                                                int 更新間隔に一番近くてアライメントされているサイズsample = this.AudioClient.GetBufferSize();
-                                               this.更新間隔ms = ( 更新間隔に一番近くてアライメントされているサイズsample * 1000.0f / (float) waveFormat.SampleRate );
+                                               this.更新間隔ms = ( 更新間隔に一番近くてアライメントされているサイズsample * 1000.0f / (float) this.WaveFormat.SampleRate );
 
                                                // AudioClient を一度解放し、もう一度アクティベートし直す。
                                                this.AudioClient.Dispose();
@@ -92,25 +92,24 @@ namespace FDK.メディア.サウンド.WASAPI
                                                        CSCore.CoreAudioAPI.AudioClientStreamFlags.StreamFlagsEventCallback,    // イベント駆動モード。
                                                        (long) ( this.更新間隔ms * 10000.0f + 0.5f ),   // バッファサイズ。イベント駆動モードでは、更新間隔と同じ値でなければならない。
                                                        (long) ( this.更新間隔ms * 10000.0f + 0.5f ),   // 更新間隔。
-                                                       waveFormat, // バッファのフォーマット。
+                                                       this.WaveFormat, // バッファのフォーマット。
                                                        Guid.Empty );   // この AudioClient = AudioStrem が所属する AudioSession。NULLならデフォルトのAudioSessionに登録される。
 
                                                // それでもエラーなら例外発生。
                                        }
                                }
 
-
                                // 更新間隔を sample, byte 単位で保存する。
                                this.更新間隔sample = this.AudioClient.GetBufferSize(); // バッファの長さはサンプル単位で返される。
-                               this.更新間隔byte = this.更新間隔sample * ( waveFormat.Channels * waveFormat.BitsPerSample / 8 );
+                               this.更新間隔byte = this.更新間隔sample * ( this.WaveFormat.Channels * this.WaveFormat.BytesPerSample );
                                //-----------------
                                #endregion
-                               #region " AudioClient から AudioRenderClient を取得する。"
+                               #region " AudioRenderClient を取得する。"
                                //-----------------
                                this.AudioRenderClient = CSCore.CoreAudioAPI.AudioRenderClient.FromAudioClient( this.AudioClient );
                                //-----------------
                                #endregion
-                               #region " AudioClient から AudioClock を取得する。"
+                               #region " AudioClock を取得する。"
                                //-----------------
                                this.bs_AudioClock = CSCore.CoreAudioAPI.AudioClock.FromAudioClient( this.AudioClient );
                                //-----------------
@@ -135,31 +134,29 @@ namespace FDK.メディア.サウンド.WASAPI
                                //-----------------
                                FDK.Log.Info( $"WASAPIクライアントを初期化しました。" );
                                FDK.Log.Info( $" モード: 排他&イベント駆動" );
-                               FDK.Log.Info( $" フォーマット: {waveFormat.BitsPerSample} bits, {waveFormat.SampleRate} Hz" );
-                               FDK.Log.Info( $" エンドポイントバッファ: {( (float) this.更新間隔sample / (double) waveFormat.SampleRate ) * 1000.0f} ミリ秒 ({this.更新間隔sample} samples) × 2枚" );
-                               FDK.Log.Info( $" 希望更新間隔: {this.希望更新間隔ms} ミリ秒" );
+                               FDK.Log.Info( $" フォーマット: {this.WaveFormat.BitsPerSample} bits, {this.WaveFormat.SampleRate} Hz" );
+                               FDK.Log.Info( $" エンドポイントバッファ: {( (float) this.更新間隔sample / (double) this.WaveFormat.SampleRate ) * 1000.0f} ミリ秒 ({this.更新間隔sample} samples) × 2枚" );
+                               FDK.Log.Info( $" 希望更新間隔: {希望更新間隔sec * 1000.0} ミリ秒" );
                                FDK.Log.Info( $" 更新間隔: {this.更新間隔ms} ミリ秒 ({this.更新間隔sample} samples)" );
-                               FDK.Log.Info( $" 最小間隔: {this.最小間隔ms} ミリ秒" );
+                               FDK.Log.Info( $" 最小間隔: {最小間隔ms} ミリ秒" );
                                //-----------------
                                #endregion
 
                                #region " ワークキューとイベントを作成し、作業項目を登録する。"
                                //-----------------
-                               {
-                                       // MediaFoundation が管理する、プロセス&MMCSSタスクごとに1つずつ作ることができる特別な共有ワークキューを取得、または生成して取得する。
-                                       int dwTaskId = 0;
-                                       SharpDX.MediaFoundation.MediaFactory.LockSharedWorkQueue(
-                                               ( 11.0 > this.更新間隔ms ) ? "Pro Audio" : "Games", 0, ref dwTaskId, out this.QueueID );
-
-                                       // エンドポイントバッファからの出力要請イベントを作成し、AudioClient に登録する。
-                                       this.出力要請イベント = CreateEvent( IntPtr.Zero, false, false, "WASAPI出力要請イベント" );
-                                       this.AudioClient.SetEventHandle( this.出力要請イベント );
-
-                                       // コールバックを作成し、ワークキューに最初の作業項目を登録する。
-                                       this.出力要請イベントのコールバック = new MFAsyncCallback( this.QueueID, ( ar ) => {
-                                               this.出力要請イベントへ対応する( ar );
-                                       } );
-                               }
+                               // MediaFoundation が管理する、プロセス&MMCSSタスクごとに1つずつ作ることができる特別な共有ワークキューを取得、または生成して取得する。
+                               int dwTaskId = 0;
+                               SharpDX.MediaFoundation.MediaFactory.LockSharedWorkQueue(
+                                       ( 11.0 > this.更新間隔ms ) ? "Pro Audio" : "Games", 0, ref dwTaskId, out this.QueueID );
+
+                               // エンドポイントバッファからの出力要請イベントを作成し、AudioClient に登録する。
+                               this.出力要請イベント = CreateEvent( IntPtr.Zero, false, false, "WASAPI出力要請イベント" );
+                               this.AudioClient.SetEventHandle( this.出力要請イベント );
+
+                               // コールバックを作成し、ワークキューに最初の作業項目を登録する。
+                               this.出力要請イベントのコールバック = new MFAsyncCallback( this.QueueID, ( ar ) => {
+                                       this.出力要請イベントへ対応する( ar );
+                               } );
                                //-----------------
                                #endregion
                                #region " 最初の作業項目を追加する。"
@@ -247,11 +244,10 @@ namespace FDK.メディア.サウンド.WASAPI
                protected CSCore.CoreAudioAPI.AudioRenderClient AudioRenderClient = null;
 
                // エンドポイントバッファ情報
-               protected float 希望更新間隔ms;
-               protected float 最小間隔ms;
+               protected int 更新間隔sample = 0;   // デバイスから取得する。
                protected float 更新間隔ms;
-               protected int 更新間隔sample;
                protected int 更新間隔byte;
+               protected CSCore.WaveFormat WaveFormat = null;
 
                // ミキサー。サウンドリストもここ。
                protected Mixer Mixer = null;