From 1ff7bd1a2c788a4139b6675d19dbc7f1708f3af5 Mon Sep 17 00:00:00 2001 From: =?utf8?q?=E3=81=8F=E3=81=BE=E3=81=8B=E3=81=BF=E5=B7=A5=E6=88=BF?= Date: Sun, 13 Nov 2016 15:08:06 +0900 Subject: [PATCH] =?utf8?q?Device=20=E3=82=AF=E3=83=A9=E3=82=B9=E3=81=AE?= =?utf8?q?=E3=83=A1=E3=83=B3=E3=83=90=E3=82=92=E8=8B=A5=E5=B9=B2=E4=BF=AE?= =?utf8?q?=E6=AD=A3=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit ms単位からsec単位へ。 --- FDK24/メディア/サウンド/WASAPI/Device.cs | 80 +++++++++++------------- 1 file changed, 38 insertions(+), 42 deletions(-) diff --git a/FDK24/メディア/サウンド/WASAPI/Device.cs b/FDK24/メディア/サウンド/WASAPI/Device.cs index 1066023..8fdd9e8 100644 --- a/FDK24/メディア/サウンド/WASAPI/Device.cs +++ b/FDK24/メディア/サウンド/WASAPI/Device.cs @@ -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; -- 2.11.0