namespace FDK.メディア.サウンド.WASAPI
{
- public unsafe class ExclusiveDevice : IDisposable
+ public unsafe class Device : IDisposable
{
- private static int AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED = unchecked((int) 0x88890019);
-
- public float 遅延ms => ( this.更新間隔ms );
-
- // for SoundTimer
- public CSCore.CoreAudioAPI.AudioClock AudioClock => this.bs_AudioClock;
-
- public ExclusiveDevice()
+ public float 遅延ms
{
+ get { return this.更新間隔ms; }
}
+ public CSCore.CoreAudioAPI.AudioClock AudioClock
+ {
+ get { return this.bs_AudioClock; }
+ }
+ public bool Dispose済み
+ {
+ get;
+ protected set;
+ } = true;
+
public void 初期化する( float 希望更新間隔ms )
{
int hr = 0;
- lock( this.排他利用 )
+ lock( this.スレッド間同期 )
{
- #region " 初期化済みなら何もしない。"
- //-----------------
- if( this.初期化済み )
- return;
-
- this.初期化済み = true;
- //-----------------
- #endregion
+ Trace.Assert( this.Dispose済み );
+ this.Dispose済み = false;
this.希望更新間隔ms = 希望更新間隔ms;
}
public void Dispose()
{
- #region " 未初期化なら何もしない。"
- //-----------------
- if( false == this.初期化済み )
- return;
+ Trace.Assert( false == this.Dispose済み );
- this.初期化済み = false;
- //-----------------
- #endregion
#region " WASAPI作業項目を終了させる。オーディオのレンダリングを止める前に行うこと。"
//-----------------
{
//-----------------
#endregion
- lock( this.排他利用 )
+ lock( this.スレッド間同期 )
{
#region " オーディオのレンダリングを停止する。"
//-----------------
CloseHandle( this.出力要請イベント );
//-----------------
#endregion
+
+ this.Dispose済み = true;
}
FDK.Log.Info( "WASAPIクライアントを終了しました。" );
this.Mixer.サウンドを削除する( sound );
}
- private bool 初期化済み = false;
-
// WASAPI オブジェクト
- private CSCore.CoreAudioAPI.AudioClient AudioClient = null;
- private CSCore.CoreAudioAPI.AudioRenderClient AudioRenderClient = null;
- private CSCore.CoreAudioAPI.AudioClock bs_AudioClock = null;
+ protected CSCore.CoreAudioAPI.AudioClient AudioClient = null;
+ protected CSCore.CoreAudioAPI.AudioRenderClient AudioRenderClient = null;
// エンドポイントバッファ情報
- private float 希望更新間隔ms;
- private float 最小間隔ms;
- private float 更新間隔ms;
- private int 更新間隔sample;
- private int 更新間隔byte;
-
- // WASAPIバッファへの出力。
- private Mixer Mixer = null; // ミキサー。サウンドリストもここ。
+ protected float 希望更新間隔ms;
+ protected float 最小間隔ms;
+ protected float 更新間隔ms;
+ protected int 更新間隔sample;
+ protected int 更新間隔byte;
+
+ // ミキサー。サウンドリストもここ。
+ protected Mixer Mixer = null;
+
+ // WASAPIバッファ出力用
private int QueueID = int.MaxValue;
private IntPtr 出力要請イベント = IntPtr.Zero;
private MFAsyncCallback 出力要請イベントのコールバック = null;
private long 出力要請イベントキャンセル用キー = 0;
private FDK.同期.TriStateEvent 出力終了通知 = new 同期.TriStateEvent();
- private readonly object 排他利用 = new object();
+
+ private readonly object スレッド間同期 = new object();
private void 作業項目をキューに格納する()
{
- // IAsyncCallback を内包した AsyncResult を作成する。
var asyncResult = (SharpDX.MediaFoundation.AsyncResult) null;
-
- SharpDX.MediaFoundation.MediaFactory.CreateAsyncResult(
- null,
- SharpDX.ComObject.ToCallbackPtr<SharpDX.MediaFoundation.IAsyncCallback>( this.出力要請イベントのコールバック ),
- null,
- out asyncResult );
-
- // 作成した AsyncResult を、ワークキュー投入イベントの待機状態にする。
- SharpDX.MediaFoundation.MediaFactory.PutWaitingWorkItem(
- hEvent: this.出力要請イベント,
- priority: 0,
- resultRef: asyncResult,
- keyRef: out this.出力要請イベントキャンセル用キー );
-
- asyncResult?.Dispose();
+ try
+ {
+ // IAsyncCallback を内包した AsyncResult を作成する。
+ SharpDX.MediaFoundation.MediaFactory.CreateAsyncResult(
+ null,
+ SharpDX.ComObject.ToCallbackPtr<SharpDX.MediaFoundation.IAsyncCallback>( this.出力要請イベントのコールバック ),
+ null,
+ out asyncResult );
+
+ // 作成した AsyncResult を、ワークキュー投入イベントの待機状態にする。
+ SharpDX.MediaFoundation.MediaFactory.PutWaitingWorkItem(
+ hEvent: this.出力要請イベント,
+ priority: 0,
+ resultRef: asyncResult,
+ keyRef: out this.出力要請イベントキャンセル用キー );
+ }
+ finally
+ {
+ // out 引数に使う変数は using 変数にはできないので、代わりに try-finally を使う。
+ asyncResult?.Dispose();
+ }
}
/// <summary>
return;
}
- lock( this.排他利用 )
+ lock( this.スレッド間同期 )
{
// エンドポインタの空きバッファへのポインタを取得する。
// このポインタが差すのはネイティブで確保されたメモリなので、GCの対象外である。はず。
}
}
+ #region " バックストア。"
+ //----------------
+ private CSCore.CoreAudioAPI.AudioClock bs_AudioClock = null;
+ //----------------
+ #endregion
+
#region " Win32 API "
//-----------------
+ private static int AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED = unchecked((int) 0x88890019);
+
[System.Runtime.InteropServices.DllImport( "kernel32.dll" )]
private static extern IntPtr CreateEvent( IntPtr lpEventAttributes, bool bManualReset, bool bInitialState, string lpName );
{
get { return StrokeStyleT.bs_フォルダ; }
}
- public static FDK.メディア.サウンド.WASAPI.ExclusiveDevice Wasapiデバイス
+ public static FDK.メディア.サウンド.WASAPI.Device Wasapiデバイス
{
get { return StrokeStyleT.bs_Wasapiデバイス; }
}
#endregion
#region " WASAPI デバイスを初期化する。"
//----------------
- StrokeStyleT.bs_Wasapiデバイス = new FDK.メディア.サウンド.WASAPI.ExclusiveDevice();
+ StrokeStyleT.bs_Wasapiデバイス = new FDK.メディア.サウンド.WASAPI.Device();
StrokeStyleT.bs_Wasapiデバイス.初期化する( 15.0f );
//----------------
#endregion
private static SST.フォルダ bs_フォルダ = null;
private static FDK.入力.Keyboard bs_キーボード入力 = null;
private static FDK.入力.MidiIn bs_MIDI入力 = null;
- private static FDK.メディア.サウンド.WASAPI.ExclusiveDevice bs_Wasapiデバイス = null;
+ private static FDK.メディア.サウンド.WASAPI.Device bs_Wasapiデバイス = null;
private static readonly System.Random bs_乱数 = new Random( DateTime.Now.Millisecond );
private static SST.ユーザ.ユーザ管理 bs_ユーザ管理 = null;
private static SST.曲.曲ツリー管理 bs_曲ツリー管理 = null;