3 #include "SoundDriver.h"
5 using namespace Windows::Foundation;
6 using namespace Windows::Foundation::Collections;
7 using namespace Windows::Devices::Enumeration;
8 using namespace Windows::Media::Devices;
9 using namespace Concurrency;
10 using namespace Platform;
11 #pragma comment(lib, "mmdevapi.lib")
13 using namespace std::placeholders;
14 using namespace Microsoft::WRL;
17 void makeWaveFormat(WAVEFORMATEXTENSIBLE& format,
18 int sample_rate = 44100,int channels = 2,int bits_per_sample = 32,int valid_bits_per_sample = 32,
19 uint32_t type = WAVE_FORMAT_EXTENSIBLE,
20 const GUID& sub_type = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)
22 ZeroMemory(&format,sizeof(WAVEFORMATEXTENSIBLE));
23 format.Format.wFormatTag = type;
24 format.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
25 format.SubFormat = sub_type;
26 format.Format.nSamplesPerSec = sample_rate;
27 format.Format.nChannels = channels;
28 format.Format.wBitsPerSample = bits_per_sample;
29 format.Format.nBlockAlign = (format.Format.wBitsPerSample / 8) * format.Format.nChannels;
30 format.Format.nAvgBytesPerSec = format.Format.nSamplesPerSec * format.Format.nBlockAlign;
31 format.Samples.wValidBitsPerSample = valid_bits_per_sample;
32 format.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
35 void makeWaveFormat(WAVEFORMATEX& format,int sample_rate = 44100,int channels = 2,int bits = 16,uint32_t type = WAVE_FORMAT_PCM)
37 ZeroMemory(&format,sizeof(WAVEFORMATEX));
38 format.wFormatTag = type;
39 format.nSamplesPerSec = sample_rate;
40 format.nChannels = channels;
41 format.wBitsPerSample = bits;
42 format.nBlockAlign = (format.wBitsPerSample / 8) * format.nChannels;
43 format.nAvgBytesPerSec = format.nSamplesPerSec * format.nBlockAlign;
49 struct ActivateAudioInterfaceCompletionHandler
50 : public RuntimeClass< RuntimeClassFlags< ClassicCom >, FtmBase, IActivateAudioInterfaceCompletionHandler >
52 ActivateAudioInterfaceCompletionHandler() :
55 eventHolder_(::CreateEventEx(NULL, NULL, 0, EVENT_MODIFY_STATE | SYNCHRONIZE)) {};
57 ~ActivateAudioInterfaceCompletionHandler(){};
59 // IActivateAudioInterfaceCompletionHandler
60 STDMETHOD(ActivateCompleted)( IActivateAudioInterfaceAsyncOperation *operation )
63 HRESULT hrActivateResult = S_OK;
64 IUnknown *punkAudioInterface = nullptr;
65 // Check for a successful activation result
66 hr = operation->GetActivateResult( &hrActivateResult, &punkAudioInterface );
68 if (SUCCEEDED( hrActivateResult ))
71 // Get the pointer for the Audio Client
72 punkAudioInterface->QueryInterface( IID_PPV_ARGS(&ptr_) );
76 ::SetEvent(eventHolder_.get());
79 ::SetEvent(eventHolder_.get());
81 hr_ = hr = hrActivateResult;
82 ::SetEvent(eventHolder_.get());
86 ::SetEvent(eventHolder_.get());
90 // concurrency::wait(0);
95 ::WaitForSingleObjectEx(eventHolder_.get(),INFINITE,FALSE);
98 HRESULT ResultCode() {return hr_;}
99 IAudioClient2Ptr AudioClient(){return ptr_;}
102 sf::handle_holder eventHolder_;
103 IAudioClient2Ptr ptr_;
106 struct SoundDriver::impl
107 // : public RuntimeClass< RuntimeClassFlags< ClassicCom >, FtmBase, IActivateAudioInterfaceCompletionHandler >
110 impl() : bufferIndex_(0),eventHolder_(nullptr),processBuffer_(std::bind(&SoundDriver::impl::DefaultProcessBuffer,this,_1,_2)),isStart_(false)
112 //::AvMMAvSetMmThreadCharacteristics
113 String^ deviceID = MediaDevice::GetDefaultAudioRenderId(AudioDeviceRole::Default);
116 ComPtr<IActivateAudioInterfaceAsyncOperation> asyncOpPtr;
117 IActivateAudioInterfaceAsyncOperation* asyncOp;
118 ComPtr<ActivateAudioInterfaceCompletionHandler> handler(Make<ActivateAudioInterfaceCompletionHandler>());
119 HRESULT hr = ActivateAudioInterfaceAsync(deviceID->Data(),__uuidof(IAudioClient2),nullptr,handler.Get(),&asyncOp);
120 asyncOpPtr.Attach(asyncOp);
123 if(handler->ResultCode() == S_OK)
125 audioClient_ = handler->AudioClient();
127 throw AudioClientNullException(L"
\8aù
\92è
\82ÌAudioClient
\82ð
\83A
\83N
\83e
\83B
\83x
\81[
\83g
\82Å
\82«
\82Ü
\82¹
\82ñ
\82Å
\82µ
\82½
\81B");
130 throw AudioClientNullException(L"
\8aù
\92è
\82ÌAudioClient
\82ð
\83A
\83N
\83e
\83B
\83x
\81[
\83g
\82Å
\82«
\82Ü
\82¹
\82ñ
\82Å
\82µ
\82½
\81B");
133 //
\83I
\81[
\83f
\83B
\83I
\83t
\83H
\81[
\83}
\83b
\83g
\82Ì
\83`
\83F
\83b
\83N
134 makeWaveFormat(format_);
135 //sf::co_task_memory<WAVEFORMATEXTENSIBLE> mix_format;
136 //audioClient_->GetMixFormat(reinterpret_cast<WAVEFORMATEX**>(&mix_format));
137 // format_ = *mix_format.get();
139 sf::co_task_memory<WAVEFORMATEXTENSIBLE> alt_format;
140 HRESULT hr = audioClient_->IsFormatSupported(
141 AUDCLNT_SHAREMODE_SHARED,
142 reinterpret_cast<WAVEFORMATEX*>(&format_),
143 reinterpret_cast<WAVEFORMATEX**>(&alt_format));
144 int sample_rate_backup = 0;
145 if(hr == S_FALSE) // FALSE
\82Ì
\8e\9e\82Í
\82¨
\82»
\82ç
\82
\83T
\83\93\83v
\83\8a\83\93\83O
\83\8c\81[
\83g
\82ª
\88á
\82¤
147 //
\83T
\83\93\83v
\83\8a\83\93\83O
\83\8c\81[
\83g
\82Ì
\82Ý
\82ª
\88Ù
\82È
\82é
\82©
\83`
\83F
\83b
\83N
\82·
\82é
148 if( alt_format->Format.wFormatTag == format_.Format.wFormatTag &&
149 alt_format->Format.nChannels == format_.Format.nChannels &&
150 alt_format->Format.wBitsPerSample == format_.Format.wBitsPerSample &&
151 alt_format->Samples.wValidBitsPerSample == format_.Samples.wValidBitsPerSample &&
152 alt_format->Format.nSamplesPerSec != format_.Format.nSamplesPerSec
155 sample_rate_backup = format_.Format.nSamplesPerSec;
156 //
\91ã
\91Ö
\83t
\83H
\81[
\83}
\83b
\83g
\82Ì
\83T
\83\93\83v
\83\8b\83\8c\81[
\83g
\82ð
\83Z
\83b
\83g
\82·
\82é
157 format_.Format.nSamplesPerSec = alt_format->Format.nSamplesPerSec;
158 //
\8dÄ
\8cv
\8eZ
\82·
\82é
159 format_.Format.nAvgBytesPerSec = alt_format->Format.nSamplesPerSec * format_.Format.nBlockAlign;
160 //
\82à
\82¤
\88ê
\89ñ
\83`
\83F
\83b
\83N
\82·
\82é
\81B
161 //
\83T
\83\93\83v
\83\8b\83\8c\81[
\83g
\88È
\8aO
\82Å
\83T
\83|
\81[
\83g
\82µ
\82Ä
\82¢
\82È
\82¢
\90Ý
\92è
\82ª
\82 \82ê
\82Î
\97á
\8aO
\82ª
\94
\90¶
\82·
\82é
\81B
163 ThrowIfErr(audioClient_->IsFormatSupported(
164 AUDCLNT_SHAREMODE_SHARED,
165 reinterpret_cast<WAVEFORMATEX*>(&format_),
166 reinterpret_cast<WAVEFORMATEX**>(&alt_format)));
168 throw AudioFormatNotSupportedException(L"
\82±
\82Ì
\83I
\81[
\83f
\83B
\83I
\83f
\83o
\83C
\83X
\82Å
\90Ý
\92è
\82µ
\82Ä
\82¢
\82é
\83t
\83H
\81[
\83}
\83b
\83g
\82Í
\91Î
\89\9e\82µ
\82Ä
\82¢
\82Ü
\82¹
\82ñ
\81B");
172 // Audio Client
\82Ì
\8f\89\8aú
\89»
174 REFERENCE_TIME defaultDevicePeriod,minDevicePriod;
175 audioClient_->GetDevicePeriod(&defaultDevicePeriod,&minDevicePriod);
176 hr = audioClient_->Initialize(
177 AUDCLNT_SHAREMODE_SHARED,
178 AUDCLNT_STREAMFLAGS_NOPERSIST |
179 AUDCLNT_STREAMFLAGS_EVENTCALLBACK ,
181 reinterpret_cast<WAVEFORMATEX*>(&format_),NULL);
182 if(hr == AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED)
184 ThrowIfErr(audioClient_->GetBufferSize(&bufferSize_));
185 latency_ = (double)10000000 * (bufferSize_) / format_.Format.nSamplesPerSec;
186 audioClient_.Reset();
188 ComPtr<IActivateAudioInterfaceAsyncOperation> asyncOp;
189 ActivateAudioInterfaceCompletionHandler handler;
190 HRESULT hr = ActivateAudioInterfaceAsync(deviceID->Data(),__uuidof(IAudioClient2),nullptr,&handler,&asyncOp);
193 if(handler.ResultCode() == S_OK)
195 audioClient_ = handler.AudioClient();
197 throw AudioClientNullException(L"
\8aù
\92è
\82ÌAudioClient
\82ð
\83A
\83N
\83e
\83B
\83x
\81[
\83g
\82Å
\82«
\82Ü
\82¹
\82ñ
\82Å
\82µ
\82½
\81B");
200 throw AudioClientNullException(L"
\8aù
\92è
\82ÌAudioClient
\82ð
\83A
\83N
\83e
\83B
\83x
\81[
\83g
\82Å
\82«
\82Ü
\82¹
\82ñ
\82Å
\82µ
\82½
\81B");
203 ThrowIfErr(audioClient_->Initialize(
204 AUDCLNT_SHAREMODE_SHARED,
205 AUDCLNT_STREAMFLAGS_NOPERSIST |
206 AUDCLNT_STREAMFLAGS_EVENTCALLBACK ,
208 reinterpret_cast<WAVEFORMATEX*>(&format_),NULL));
213 ThrowIfErr(audioClient_->GetBufferSize(&bufferSize_));
215 buffer_[0].reset((float*)_aligned_malloc( bufferSize_ * format_.Format.nBlockAlign,16));
216 buffer_[1].reset((float*)_aligned_malloc( bufferSize_ * format_.Format.nBlockAlign,16));
217 bufferByteCount_ = bufferSize_ * format_.Format.nBlockAlign;
219 audioClient_->GetStreamLatency(&latency_);
220 ThrowIfErr(audioClient_->GetService(__uuidof(IAudioRenderClient),&audioRenderClient_));
221 eventHolder_.reset(::CreateEventEx(NULL, NULL, 0, EVENT_MODIFY_STATE | SYNCHRONIZE));
222 audioClient_->SetEventHandle(eventHolder_.get());
224 processBuffer_(buffer_[bufferIndex_],bufferSize_);
226 ThrowIfErr(audioRenderClient_->GetBuffer(bufferSize_,&rawBuffer));
227 audioRenderClient_->ReleaseBuffer(bufferSize_,0);
228 bufferIndex_ = (bufferIndex_ + 1) & 0x1;
229 processBuffer_(buffer_[bufferIndex_],bufferSize_);
233 // ThrowIfErr(ActivateAudioInterfaceAsync(deviceID->Data(),__uuidof(IAudioClient2),nullptr,this,&asyncOp));
238 audioClient_->Stop();
239 audioRenderClient_.Reset();
240 audioClient_->Reset();
245 ::WaitForSingleObjectEx(eventHolder_.get(),INFINITE,FALSE);
247 ThrowIfErr(audioClient_->GetCurrentPadding(&padding));
251 ThrowIfErr(audioRenderClient_->GetBuffer(bufferSize_,&rawBuffer));
252 ::memcpy(rawBuffer,buffer_[bufferIndex_].get(),bufferByteCount_);
253 audioRenderClient_->ReleaseBuffer(bufferSize_,0);
254 bufferIndex_ = (bufferIndex_ + 1) & 0x1;
255 processBuffer_(buffer_[bufferIndex_],bufferSize_);
259 void SetProcessBufferFunc(ProcessBufferType&& v)
262 processBuffer_ = std::move(v);
265 void ResetProcessBufferFunc()
268 processBuffer_ = std::move(std::bind(&SoundDriver::impl::DefaultProcessBuffer,this,_1,_2));
276 ThrowIfErr(audioClient_->Start());
283 if(!isStart_) return;
285 ThrowIfErr(audioClient_->Stop());
290 WAVEFORMATEXTENSIBLE& Format()
295 void DefaultProcessBuffer(boost::shared_array<float> arr,int bufferSize)
297 //
\8d¡
\82Ì
\82Æ
\82±
\82ë
\8fo
\97Í
\82Í
\83X
\83e
\83\8c\83I
\91O
\92ñ
298 //for(int j = 0;j < voices_.size();++j)
300 // voices_[j].Process(buffer);
301 // *ptr += buffer[0];
302 // *(ptr + 1) += buffer[1];
304 float *ptr = arr.get();
306 ZeroMemory(ptr,bufferByteCount_);
308 //for(int i = 0;i < bufferSize;++i)
310 // sequencer_->Process();
311 // synth_->Process(ptr);
316 // IActivateAudioInterfaceCompletionHandler
317 STDMETHOD(ActivateCompleted)( IActivateAudioInterfaceAsyncOperation *operation )
322 throw AudioClientNullException(L"
\8aù
\92è
\82ÌAudioClient
\82ð
\83A
\83N
\83e
\83B
\83x
\81[
\83g
\82Å
\82«
\82Ü
\82¹
\82ñ
\82Å
\82µ
\82½
\81B");
334 ProcessBufferType processBuffer_;
335 IAudioClient2Ptr audioClient_;
336 uint32_t bufferSize_;
337 REFERENCE_TIME latency_;
338 // IAudioClockAdjustmentPtr audioClockAdjustment_;
339 IAudioRenderClientPtr audioRenderClient_;
340 WAVEFORMATEXTENSIBLE format_;
341 sf::handle_holder eventHolder_;
342 boost::shared_array<float> buffer_[2];
344 int bufferByteCount_;
349 SoundDriver::SoundDriver() : impl_(new impl()) {}
351 SoundDriver::~SoundDriver()
356 void SoundDriver::Render()
361 void SoundDriver::SetProcessBufferFunc(ProcessBufferType&& v)
363 impl_->SetProcessBufferFunc(std::move(v));
366 void SoundDriver::ResetProcessBufferFunc()
368 impl_->ResetProcessBufferFunc();
371 void SoundDriver::Start()
376 void SoundDriver::Stop()
381 WAVEFORMATEXTENSIBLE& SoundDriver::Format()
383 return impl_->Format();