2 using System.Collections.Generic;
4 namespace FDK.メディア.サウンド.WASAPI
7 /// Sound のリストを持ち、そのサウンドデータを合成してWASAPIデバイスへ出力するミキサー。
9 public unsafe class Mixer : IDisposable
14 public Mixer( int エンドポイントバッファサイズsample ) : this()
16 this.初期化する( エンドポイントバッファサイズsample );
18 public void 初期化する( int エンドポイントバッファサイズsample )
22 if( エンドポイントバッファサイズsample == this.エンドポイントバッファサイズsample )
23 return; // サイズに変更があったときのみ初期化する。
25 this.エンドポイントバッファサイズsample = エンドポイントバッファサイズsample;
28 if( null != this.合成用バッファ )
29 FDK.Memory.Free( this.合成用バッファ );
30 this.合成用バッファ = FDK.Memory.Alloc( this.エンドポイントバッファサイズsample * ( 4 * 2 ) ); // 1sample = 32bit×2ch
38 if( null != this.合成用バッファ )
40 FDK.Memory.Free( this.合成用バッファ );
43 this.エンドポイントバッファサイズsample = -1;
46 public void サウンドリストをクリアする()
53 public void サウンドを追加する( Sound sound )
57 this.サウンドリスト.Add( sound );
60 public void サウンドを削除する( Sound sound )
64 this.サウンドリスト.Remove( sound );
67 public CSCore.CoreAudioAPI.AudioClientBufferFlags エンドポイントへ出力する( void* エンドポイントの出力先, int 出力数sample )
71 if( null == this.合成用バッファ )
72 return CSCore.CoreAudioAPI.AudioClientBufferFlags.Silent;
74 #region " すべてのサウンドについて、合成バッファへ出力する。"
78 foreach( var sound in this.サウンドリスト )
80 var flag = sound.次のサウンドデータを出力する( this.合成用バッファ, 出力数sample, 最初の出力である );
82 if( false == flag.HasFlag( CSCore.CoreAudioAPI.AudioClientBufferFlags.Silent ) )
83 最初の出力である = false; // sound が何らかのデータを出力した(戻り値がSILENTじゃなかった)
86 // 全サウンドが SILENT だったなら、エンドポイントには何も書き込まずに SILENT フラグを返す。
88 return CSCore.CoreAudioAPI.AudioClientBufferFlags.Silent;
91 #region " 合成バッファのデータ値(32bit;オーバーサンプル)を16bitに丸めてエンドポイントに出力する。"
93 Int32* 出力元 = (Int32*) ( this.合成用バッファ );
94 Int16* 出力先 = (Int16*) エンドポイントの出力先;
95 for( int i = 0; i < 出力数sample; i++ )
99 // 音量やミュートの処理は不要。(WASAPI が自動でマスタ音量・ミュート状態に合わせてくれる)
105 else if( 32767 < src )
107 *出力先++ = (Int16) src;
113 else if( 32767 < src )
115 *出力先++ = (Int16) src;
120 return CSCore.CoreAudioAPI.AudioClientBufferFlags.None;
123 private int エンドポイントバッファサイズsample = -1;
124 private readonly List<Sound> サウンドリスト = new List<Sound>();
125 private void* 合成用バッファ = null;
126 private readonly object スレッド間同期 = new object();