2 ==============================================================================
\r
4 Copyright 2005-11 by Satoshi Fujiwara.
\r
6 async can be redistributed and/or modified under the terms of the
\r
7 GNU General Public License, as published by the Free Software Foundation;
\r
8 either version 2 of the License, or (at your option) any later version.
\r
10 async is distributed in the hope that it will be useful,
\r
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
13 GNU General Public License for more details.
\r
15 You should have received a copy of the GNU General Public License
\r
16 along with async; if not, visit www.gnu.org/licenses or write to the
\r
17 Free Software Foundation, Inc., 59 Temple Place, Suite 330,
\r
18 Boston, MA 02111-1307 USA
\r
20 ==============================================================================
\r
25 #define _CRTDBG_MAP_ALLOC
\r
27 #define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
\r
29 #include "audio_base.h"
\r
31 #pragma comment(lib, "winmm.lib")
\r
32 #pragma comment(lib, "Avrt.lib")
\r
33 #pragma comment(lib, "Mmdevapi.lib")
\r
35 using namespace std;
\r
36 using namespace Microsoft::WRL;
\r
40 // ==================================
\r
42 // ==================================
\r
45 template<typename ShareModePolicy,typename DrivenPolicy,typename IOClientPolicy>
\r
46 wasapi_base<ShareModePolicy,DrivenPolicy,IOClientPolicy>::wasapi_base(int device_index,wasapi_device_manager::device_info::params_t& params)
\r
47 : is_enabled_(false),position_(0),is_start_(false),driven_policy_(latency_)
\r
49 init(wasapi_device_manager::instance()->output_device_infos().at(device_index),params);
\r
54 wasapi_base<wasapi_shared_policy,wasapi_event_policy,render_client_policy>::wasapi_base(int device_index,wasapi_device_manager::device_info::params_t& params)
\r
55 : is_enabled_(false),position_(0),is_start_(false),driven_policy_()
\r
57 init(wasapi_device_manager::instance()->output_device_infos().at(device_index),params);
\r
58 audio_client_->SetEventHandle(driven_policy_.event_handle());
\r
63 wasapi_base<wasapi_exclusive_policy,wasapi_event_policy,render_client_policy>::wasapi_base(int device_index,wasapi_device_manager::device_info::params_t& params)
\r
64 : is_enabled_(false),position_(0),is_start_(false),driven_policy_()
\r
66 init(wasapi_device_manager::instance()->output_device_infos().at(device_index),params);
\r
67 audio_client_->SetEventHandle(driven_policy_.event_handle());
\r
72 wasapi_base<wasapi_shared_policy,wasapi_timer_policy,capture_client_policy>::wasapi_base(int device_index,wasapi_device_manager::device_info::params_t& params)
\r
73 : is_enabled_(false),position_(0),is_start_(false),driven_policy_(latency_)
\r
75 init(wasapi_device_manager::instance()->input_device_infos().at(device_index),params);
\r
80 wasapi_base<wasapi_exclusive_policy,wasapi_timer_policy,capture_client_policy>::wasapi_base(int device_index,wasapi_device_manager::device_info::params_t& params)
\r
81 : is_enabled_(false),position_(0),is_start_(false),driven_policy_(latency_)
\r
83 init(wasapi_device_manager::instance()->input_device_infos().at(device_index),params);
\r
88 wasapi_base<wasapi_shared_policy,wasapi_event_policy,capture_client_policy>::wasapi_base(int device_index,wasapi_device_manager::device_info::params_t& params)
\r
89 : is_enabled_(false),position_(0),is_start_(false),driven_policy_()
\r
91 init(wasapi_device_manager::instance()->input_device_infos().at(device_index),params);
\r
92 audio_client_->SetEventHandle(driven_policy_.event_handle());
\r
97 wasapi_base<wasapi_exclusive_policy,wasapi_event_policy,capture_client_policy>::wasapi_base(int device_index,wasapi_device_manager::device_info::params_t& params)
\r
98 : is_enabled_(false),position_(0),is_start_(false),driven_policy_()
\r
100 init(wasapi_device_manager::instance()->input_device_infos().at(device_index),params);
\r
101 audio_client_->SetEventHandle(driven_policy_.event_handle());
\r
104 // ========================================
\r
105 // デフォルトのオーディオクライアントの取得
\r
106 // ========================================
\r
108 template<typename ShareModePolicy,typename DrivenPolicy,typename IOClientPolicy>
\r
109 void wasapi_base<ShareModePolicy,DrivenPolicy,IOClientPolicy>::get_default_audio_client()
\r
112 current_device_ = &(wasapi_device_manager::instance()->current_output_device());
\r
114 ComPtr<IActivateAudioInterfaceAsyncOperation> asyncOpPtr;
\r
115 IActivateAudioInterfaceAsyncOperation* asyncOp;
\r
116 ComPtr<ActivateAudioInterfaceCompletionHandler> handler(Make<ActivateAudioInterfaceCompletionHandler>());
\r
117 HRESULT hr = ActivateAudioInterfaceAsync(current_device_->id_.c_str(),__uuidof(IAudioClient2),nullptr,handler.Get(),&asyncOp);
\r
118 asyncOpPtr.Attach(asyncOp);
\r
121 if(handler->ResultCode() == S_OK)
\r
123 audio_client_ = handler->AudioClient();
\r
125 throw win32_error_exception(handler->ResultCode());
\r
128 throw win32_error_exception(handler->ResultCode());
\r
132 // ActivateAudioInterface(current_device_->id_.c_str(),__uuidof(IAudioClient2),&audio_client_);
\r
136 void wasapi_base<wasapi_exclusive_policy,wasapi_event_policy,capture_client_policy>
\r
137 ::get_default_audio_client()
\r
139 current_device_ = &(wasapi_device_manager::instance()->current_output_device());
\r
140 // ActivateAudioInterface(current_device_->id_.c_str(),__uuidof(IAudioClient2),&audio_client_);
\r
143 // ==================================
\r
145 // ==================================
\r
147 template<typename ShareModePolicy,typename DrivenPolicy,typename IOClientPolicy>
\r
148 void wasapi_base<ShareModePolicy,DrivenPolicy,IOClientPolicy>::init(wasapi_device_manager::device_info& device,wasapi_device_manager::device_info::params_t& params)
\r
150 WAVEFORMATEXTENSIBLE wfx;
\r
151 bits_pair bits = {params.bits,params.valid_bits};
\r
152 make_wave_format(wfx,params.sample_rate,params.channel,bits);
\r
153 latency_ = params.latency;//wasapi_device_manager::instance()->current_output_device().latency_default_;
\r
156 sf::co_task_memory<WAVEFORMATEX> alt_format;
\r
158 ComPtr<IActivateAudioInterfaceAsyncOperation> asyncOpPtr;
\r
159 IActivateAudioInterfaceAsyncOperation* asyncOp;
\r
160 ComPtr<ActivateAudioInterfaceCompletionHandler> handler(Make<ActivateAudioInterfaceCompletionHandler>());
\r
161 HRESULT hr = ActivateAudioInterfaceAsync(device.id_.c_str(),__uuidof(IAudioClient2),nullptr,handler.Get(),&asyncOp);
\r
162 asyncOpPtr.Attach(asyncOp);
\r
165 if(handler->ResultCode() == S_OK)
\r
167 audio_client_ = handler->AudioClient();
\r
169 throw win32_error_exception(handler->ResultCode());
\r
172 throw win32_error_exception(handler->ResultCode());
\r
175 current_device_ = &device;
\r
177 // 読みこもうとしているWAVファイルのフォーマットをサポートしているか?
\r
178 THROW_IF_ERR(audio_client_->IsFormatSupported(
\r
179 ShareModePolicy::SHARE_MODE ,&wfx.Format,&alt_format));
\r
180 //if(hr != S_OK) // S_FALSEならそのフォーマットをサポートしていないらしい..
\r
182 // // サンプルレートのコンバート
\r
183 // if(alt_format->nSamplesPerSec != wfx.Format.nSamplesPerSec)
\r
185 // // 本来のサンプルレートをバックアップする
\r
186 // sample_rate_backup = wfx.Format.nSamplesPerSec;
\r
187 // // 代替フォーマットのサンプルレートをセットする
\r
188 // wfx.Format.nSamplesPerSec = alt_format->nSamplesPerSec;
\r
190 // wfx.Format.nAvgBytesPerSec = alt_format->nSamplesPerSec * wfx.Format.nBlockAlign;
\r
192 // // サンプルレート以外でサポートしていない点があれば例外が発生する。
\r
193 // THROW_IF_ERR(audio_client_->IsFormatSupported(
\r
194 // ShareModePolicy::SHARE_MODE ,&wfx.Format,&alt_format));
\r
196 // // sample_rate_convert = true;
\r
198 // // サンプルレート以外であれば例外を出す。
\r
199 // throw win32_error_exception(hr);
\r
206 init_audio_client(wfx);
\r
207 } catch (win32_error_exception& e)
\r
209 if(e.hresult() == AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED)
\r
211 THROW_IF_ERR(audio_client_->GetBufferSize(&buffer_size_));
\r
212 latency_ = actual_latency_ =
\r
213 (double)10000000 * (buffer_size_) / wfx.Format.nSamplesPerSec;
\r
214 audio_client_.Reset();
\r
216 ComPtr<IActivateAudioInterfaceAsyncOperation> asyncOpPtr;
\r
217 IActivateAudioInterfaceAsyncOperation* asyncOp;
\r
218 ComPtr<ActivateAudioInterfaceCompletionHandler> handler(Make<ActivateAudioInterfaceCompletionHandler>());
\r
219 HRESULT hr = ActivateAudioInterfaceAsync(device.id_.c_str(),__uuidof(IAudioClient2),nullptr,handler.Get(),&asyncOp);
\r
220 asyncOpPtr.Attach(asyncOp);
\r
223 if(handler->ResultCode() == S_OK)
\r
225 audio_client_ = handler->AudioClient();
\r
227 throw win32_error_exception(handler->ResultCode());
\r
230 throw win32_error_exception(handler->ResultCode());
\r
233 init_audio_client(wfx);
\r
239 actual_latency_ = latency_;
\r
242 THROW_IF_ERR(audio_client_->GetBufferSize(&buffer_size_));
\r
244 init_io_client(boost::type<IOClientPolicy>());
\r
247 THROW_IF_ERR(audio_client_->GetService(IID_PPV_ARGS(&audio_clock2_)));
\r
248 REFERENCE_TIME psl;
\r
249 THROW_IF_ERR(audio_client_->GetStreamLatency(&psl));
\r
251 wdout << L"StreamLatency:" << psl << endl;
\r
256 //if(sample_rate_convert)
\r
258 // THROW_IF_ERR(audio_client_->GetService(IID_PPV_ARGS(&audio_clock_adjustment_)));
\r
259 // // 本来のサンプルレートをセットする
\r
260 // audio_clock_adjustment_->SetSampleRate(sample_rate_backup);
\r
263 num_of_frames_ = wfx.Format.nBlockAlign;
\r
265 //inc_ = (buffer_size_ * num_of_frames_) / (sizeof(short) * periods_per_buffer_);
\r
266 buffer_in_periods_ = buffer_size_ / periods_per_buffer_;
\r
268 is_enabled_ = true;
\r
271 // =========================
\r
273 // =========================
\r
275 template<typename ShareModePolicy,typename DrivenPolicy,typename IOClientPolicy>
\r
276 void wasapi_base<ShareModePolicy,DrivenPolicy,IOClientPolicy>::init_audio_client(WAVEFORMATEXTENSIBLE& wfx)
\r
278 REFERENCE_TIME buffer_duration = latency_;
\r
280 THROW_IF_ERR(audio_client_->Initialize(ShareModePolicy::SHARE_MODE ,
\r
281 AUDCLNT_STREAMFLAGS_NOPERSIST | DrivenPolicy::STREAM_FLAG /*| AUDCLNT_STREAMFLAGS_RATEADJUST*/,
\r
290 void wasapi_base<wasapi_exclusive_policy,wasapi_event_policy,render_client_policy>::init_audio_client(WAVEFORMATEXTENSIBLE& wfx)
\r
292 REFERENCE_TIME buffer_duration = latency_;
\r
294 THROW_IF_ERR(audio_client_->Initialize(AUDCLNT_SHAREMODE_EXCLUSIVE ,
\r
295 AUDCLNT_STREAMFLAGS_NOPERSIST | wasapi_event_policy::STREAM_FLAG /*| AUDCLNT_STREAMFLAGS_RATEADJUST*/,
\r
304 void wasapi_base<wasapi_exclusive_policy,wasapi_timer_policy,render_client_policy>::init_audio_client(WAVEFORMATEXTENSIBLE& wfx)
\r
306 REFERENCE_TIME buffer_period = latency_;
\r
307 REFERENCE_TIME buffer_duration = buffer_period * periods_per_buffer_;
\r
309 THROW_IF_ERR(audio_client_->Initialize(AUDCLNT_SHAREMODE_EXCLUSIVE ,
\r
310 AUDCLNT_STREAMFLAGS_NOPERSIST /*| AUDCLNT_STREAMFLAGS_RATEADJUST*/,
\r
319 void wasapi_base<wasapi_exclusive_policy,wasapi_event_policy,capture_client_policy>::init_audio_client(WAVEFORMATEXTENSIBLE& wfx)
\r
321 REFERENCE_TIME buffer_duration = latency_;
\r
323 THROW_IF_ERR(audio_client_->Initialize(AUDCLNT_SHAREMODE_EXCLUSIVE ,
\r
324 AUDCLNT_STREAMFLAGS_NOPERSIST | wasapi_event_policy::STREAM_FLAG /*| AUDCLNT_STREAMFLAGS_RATEADJUST*/,
\r
333 void wasapi_base<wasapi_exclusive_policy,wasapi_timer_policy,capture_client_policy>::init_audio_client(WAVEFORMATEXTENSIBLE& wfx)
\r
335 REFERENCE_TIME buffer_period = latency_;
\r
336 REFERENCE_TIME buffer_duration = buffer_period * periods_per_buffer_;
\r
338 THROW_IF_ERR(audio_client_->Initialize(AUDCLNT_SHAREMODE_EXCLUSIVE ,
\r
339 AUDCLNT_STREAMFLAGS_NOPERSIST /*| AUDCLNT_STREAMFLAGS_RATEADJUST*/,
\r
345 // ================================
\r
347 // ================================
\r
349 template<typename ShareModePolicy,typename DrivenPolicy,typename IOClientPolicy>
\r
350 wasapi_base<ShareModePolicy,DrivenPolicy,IOClientPolicy>::~wasapi_base()
\r
352 // safe_release(audio_clock_adjustment_);
\r
357 audio_client_->Stop();
\r
358 audio_client_->Reset();
\r
359 audio_client_.Reset();
\r
361 safe_release(render_client_);
\r
362 safe_release(capture_client_);
\r
363 //safe_release(current_device_);
\r
364 // safe_release(device_collection_);
\r
367 // ================================
\r
368 // テスト用サイン波形テーブルの作成
\r
369 // ================================
\r
370 template<typename ShareModePolicy,typename DrivenPolicy,typename IOClientPolicy>
\r
371 void wasapi_base<ShareModePolicy,DrivenPolicy,IOClientPolicy>::create_wave_data(){
\r
373 boost::uint32_t buffer_size_in_bytes = buffer_size_ * mix_format_.Format.nBlockAlign;
\r
374 size_t render_data_length = mix_format_.Format.nSamplesPerSec * 10 /* 秒 */ * mix_format_.Format.nBlockAlign / sizeof(short);
\r
375 tone_buffer_.reserve(render_data_length);
\r
377 double sampleIncrement = (440 /* Hz */ * (M_PI * 2.0)) / (double)mix_format_.Format.nSamplesPerSec;
\r
378 double theta = 0.0;
\r
380 for (size_t i = 0 ; i < render_data_length ; i += mix_format_.Format.nChannels)
\r
382 double sinValue = sin( theta );
\r
383 for(size_t j = 0 ;j < mix_format_.Format.nChannels; j++)
\r
385 tone_buffer_.push_back((short)(sinValue * _I16_MAX));
\r
387 theta += sampleIncrement;
\r
391 // ===========================
\r
393 // ===========================
\r
394 template<typename ShareModePolicy,typename DrivenPolicy,typename IOClientPolicy>
\r
395 uint32_t wasapi_base<ShareModePolicy,DrivenPolicy,IOClientPolicy>::get_buffer(BYTE** buffer,uint32_t size)
\r
399 uint32_t frames_available;
\r
401 THROW_IF_ERR(audio_client_->GetCurrentPadding(&padding));
\r
402 frames_available = size - padding;
\r
403 THROW_IF_ERR(render_client_->GetBuffer(frames_available,buffer));
\r
404 return frames_available;
\r
409 uint32_t wasapi_base<wasapi_exclusive_policy,wasapi_event_policy,render_client_policy>::get_buffer(BYTE** buffer,uint32_t size)
\r
411 THROW_IF_ERR(render_client_->GetBuffer(size,buffer));
\r
415 // キャプチャ ---------------------------------
\r
416 template<typename ShareModePolicy,typename DrivenPolicy,typename IOClientPolicy>
\r
417 uint32_t wasapi_base<ShareModePolicy,DrivenPolicy,IOClientPolicy>::get_buffer(BYTE** buffer)
\r
421 HRESULT hr = capture_client_->GetBuffer(buffer,&size,&flags,0,0);
\r
422 if(hr == AUDCLNT_S_BUFFER_EMPTY)
\r
430 if(flags == AUDCLNT_BUFFERFLAGS_SILENT)
\r
438 // ===========================
\r
440 // ===========================
\r
441 template<typename ShareModePolicy,typename DrivenPolicy,typename IOClientPolicy>
\r
442 void wasapi_base<ShareModePolicy,DrivenPolicy,IOClientPolicy>::release_buffer(uint32_t num_byte_written)
\r
444 THROW_IF_ERR(render_client_->ReleaseBuffer(num_byte_written,0));
\r
448 void wasapi_base<wasapi_shared_policy,wasapi_event_policy,capture_client_policy>::release_buffer(uint32_t num_byte_written)
\r
450 THROW_IF_ERR(capture_client_->ReleaseBuffer(num_byte_written));
\r
454 void wasapi_base<wasapi_shared_policy,wasapi_timer_policy,capture_client_policy>::release_buffer(uint32_t num_byte_written)
\r
456 THROW_IF_ERR(capture_client_->ReleaseBuffer(num_byte_written));
\r
460 void wasapi_base<wasapi_exclusive_policy,wasapi_event_policy,capture_client_policy>::release_buffer(uint32_t num_byte_written)
\r
462 THROW_IF_ERR(capture_client_->ReleaseBuffer(num_byte_written));
\r
466 void wasapi_base<wasapi_exclusive_policy,wasapi_timer_policy,capture_client_policy>::release_buffer(uint32_t num_byte_written)
\r
468 THROW_IF_ERR(capture_client_->ReleaseBuffer(num_byte_written));
\r
471 // ===========================
\r
473 // ===========================
\r
475 template<typename ShareModePolicy,typename DrivenPolicy,typename IOClientPolicy>
\r
476 void wasapi_base<ShareModePolicy,DrivenPolicy,IOClientPolicy>::start()
\r
478 THROW_IF_ERR(audio_client_->Start());
\r
482 // ===========================
\r
484 // ===========================
\r
486 template<typename ShareModePolicy,typename DrivenPolicy,typename IOClientPolicy>
\r
487 void wasapi_base<ShareModePolicy,DrivenPolicy,IOClientPolicy>::reset()
\r
489 THROW_IF_ERR(audio_client_->Reset());
\r
492 // ===========================
\r
494 // ===========================
\r
496 template<typename ShareModePolicy,typename DrivenPolicy,typename IOClientPolicy>
\r
497 void wasapi_base<ShareModePolicy,DrivenPolicy,IOClientPolicy>::stop() {
\r
501 THROW_IF_ERR(audio_client_->Stop());
\r
508 // ===========================
\r
510 // ===========================
\r
512 template<typename ShareModePolicy,typename DrivenPolicy,typename IOClientPolicy>
\r
513 uint32_t wasapi_base<ShareModePolicy,DrivenPolicy,IOClientPolicy>::get_current_padding()
\r
516 THROW_IF_ERR(audio_client_->GetCurrentPadding(&padding));
\r
521 uint32_t wasapi_base<wasapi_exclusive_policy,wasapi_event_policy,render_client_policy>::get_current_padding()
\r
523 return buffer_size_;
\r
526 template struct wasapi_base<>;
\r
527 template struct wasapi_base<wasapi_shared_policy,wasapi_event_policy>;
\r
528 template struct wasapi_base<wasapi_exclusive_policy,wasapi_timer_policy>;
\r
529 template struct wasapi_base<wasapi_exclusive_policy,wasapi_event_policy>;
\r
530 template struct wasapi_base<wasapi_shared_policy,wasapi_timer_policy,capture_client_policy>;
\r
531 template struct wasapi_base<wasapi_shared_policy,wasapi_event_policy,capture_client_policy>;
\r
532 template struct wasapi_base<wasapi_exclusive_policy,wasapi_timer_policy,capture_client_policy>;
\r
533 template struct wasapi_base<wasapi_exclusive_policy,wasapi_event_policy,capture_client_policy>;
\r