protected set;
} = true;
- public void 初期化する( float 希望更新間隔ms )
+ public void 初期化する( double 希望更新間隔sec = 0.015 )
{
int hr = 0;
Trace.Assert( this.Dispose済み );
this.Dispose済み = false;
- this.希望更新間隔ms = 希望更新間隔ms;
-
#region " AudioClientをアクティベートする。"
//-----------------
using( var devices = new CSCore.CoreAudioAPI.MMDeviceEnumerator() )
#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(
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 )
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();
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 );
//-----------------
//-----------------
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 " 最初の作業項目を追加する。"
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;