2 ==============================================================================
4 Copyright 2005-11 by Satoshi Fujiwara.
6 async can be redistributed and/or modified under the terms of the
7 GNU General Public License, as published by the Free Software Foundation;
8 either version 2 of the License, or (at your option) any later version.
10 async is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with async; if not, visit www.gnu.org/licenses or write to the
17 Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18 Boston, MA 02111-1307 USA
20 ==============================================================================
25 #define _CRTDBG_MAP_ALLOC
27 #define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
29 #include "sf_memory.h"
30 #include "audio_base.h"
34 wasapi_exclusive_timer::wasapi_exclusive_timer(::WAVEFORMATEXTENSIBLE& wfx)
35 : is_enabled_(false),position_(0),is_start_(false)/*,buffer_control_event_(::CreateEventEx(NULL, NULL, 0, EVENT_MODIFY_STATE | SYNCHRONIZE))*/
39 // thread_priority_.set_priority(AVRT_PRIORITY_NORMAL);
43 // IMMDeviceEnumeratorの取得
46 __uuidof(MMDeviceEnumerator), NULL, CLSCTX_INPROC_SERVER,
47 IID_PPV_ARGS(&device_enumerator_)));
49 // デフォルトのオーディオデバイスを取得する
52 ->GetDefaultAudioEndpoint(eRender,eMultimedia,¤t_device_)
58 ->Activate(__uuidof(IAudioClient), CLSCTX_INPROC_SERVER,
59 NULL, reinterpret_cast<void **>(&audio_client_))
63 sf::co_task_memory<WAVEFORMATEX> alt_format;
65 // 読みこもうとしているWAVファイルのフォーマットをサポートしているか?
66 THROW_IF_ERR(audio_client_->IsFormatSupported(
67 AUDCLNT_SHAREMODE_EXCLUSIVE ,&wfx.Format,&alt_format));
71 REFERENCE_TIME buffer_period = latency_ms_ /* ms */ * 10000 ;
73 REFERENCE_TIME buffer_duration = buffer_period * periods_per_buffer_;
75 THROW_IF_ERR(audio_client_->Initialize(AUDCLNT_SHAREMODE_EXCLUSIVE ,
76 AUDCLNT_STREAMFLAGS_NOPERSIST,
83 THROW_IF_ERR(audio_client_->GetBufferSize(&buffer_size_));
86 THROW_IF_ERR(audio_client_->GetService(IID_PPV_ARGS(&audio_render_client_)));
88 num_of_frames_ = wfx.Format.nBlockAlign;
91 } catch (win32_error_exception& e)
93 exception_holder_.reset(new win32_error_exception(e.hresult()));
100 wasapi_exclusive_timer::~wasapi_exclusive_timer()
102 safe_release(audio_clock_adjustment_);
103 safe_release(audio_render_client_);
108 audio_client_->Stop();
109 audio_client_->Reset();
110 audio_client_.Release();
113 safe_release(current_device_);
114 safe_release(device_enumerator_);
117 void wasapi_exclusive_timer::play_buffer(BYTE* source_buffer)
119 static const size_t inc = (buffer_size_ * num_of_frames_) / (sizeof(short) * periods_per_buffer_);
120 static const size_t buffer_in_periods = buffer_size_ / periods_per_buffer_;
127 THROW_IF_ERR(audio_render_client_->GetBuffer(buffer_size_,&buffer));
128 ::CopyMemory(buffer,source_buffer,get_buffer_byte_size());
131 THROW_IF_ERR(audio_render_client_->ReleaseBuffer(buffer_size_,0));
134 THROW_IF_ERR(audio_client_->Start());
144 uint32_t frames_available;
145 uint32_t count_period = periods_per_buffer_;
146 while(count_period > 0)
149 THROW_IF_ERR(audio_client_->GetCurrentPadding(&padding));
150 frames_available = buffer_size_ - padding;
152 // パディングを除いた部分のバッファを埋める。
153 // パディングを除いた部分のサイズがbuffer_in_periodsより小さい場合はつぎにまわす。
154 // パディングを除いた部分を一気に埋めようとしたけどできなかった。。
155 while(buffer_in_periods <= frames_available && count_period > 0 )
157 THROW_IF_ERR(audio_render_client_->GetBuffer(buffer_in_periods,&buffer));
158 ::CopyMemory(buffer,source_buffer,buffer_in_periods * num_of_frames_);
159 THROW_IF_ERR(audio_render_client_->ReleaseBuffer(buffer_in_periods,0));
161 source_buffer += buffer_in_periods * num_of_frames_;
164 THROW_IF_ERR(audio_client_->GetCurrentPadding(&padding));
165 frames_available = buffer_size_ - padding;
174 void wasapi_exclusive_timer::reset()
176 THROW_IF_ERR(audio_client_->Reset());
178 void wasapi_exclusive_timer::stop() {
182 THROW_IF_ERR(audio_client_->Stop());