OSDN Git Service

Boost.MSMでメニュー部分を実装
[shooting3/shootinggame.git] / ShootingGame / SoundDriver.cpp
1 #include "pch.h"
2 #include "sf_memory.h"
3 #include "SoundDriver.h"
4 using namespace std;
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")
12
13 namespace stps = std::placeholders;
14 using namespace Microsoft::WRL;
15
16 namespace {
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)
21   {
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;
33   }
34
35   void makeWaveFormat(WAVEFORMATEX& format,int sample_rate = 44100,int channels = 2,int bits = 16,uint32_t type = WAVE_FORMAT_PCM)
36   {
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;
44   };
45 }
46
47 namespace sf {
48
49   struct ActivateAudioInterfaceCompletionHandler 
50     : public  RuntimeClass< RuntimeClassFlags< ClassicCom >, FtmBase, IActivateAudioInterfaceCompletionHandler >
51   {
52     ActivateAudioInterfaceCompletionHandler() :
53       hr_(S_OK),
54       ptr_(nullptr),
55       eventHolder_(::CreateEventEx(NULL, NULL, 0, EVENT_MODIFY_STATE | SYNCHRONIZE)) {};
56
57     ~ActivateAudioInterfaceCompletionHandler(){};
58
59     // IActivateAudioInterfaceCompletionHandler
60     STDMETHOD(ActivateCompleted)( IActivateAudioInterfaceAsyncOperation *operation )
61     {
62       HRESULT hr = S_OK;
63       HRESULT hrActivateResult = S_OK;
64       IUnknown *punkAudioInterface = nullptr;
65       // Check for a successful activation result
66       hr = operation->GetActivateResult( &hrActivateResult, &punkAudioInterface );
67       if(SUCCEEDED(hr)){
68         if (SUCCEEDED( hrActivateResult ))
69         {
70           hr_ = S_OK;
71           // Get the pointer for the Audio Client
72           punkAudioInterface->QueryInterface( IID_PPV_ARGS(&ptr_) );
73           if( nullptr == ptr_ )
74           {
75             hr_ = E_FAIL;
76             ::SetEvent(eventHolder_.get());
77             return hr_;
78           }
79           ::SetEvent(eventHolder_.get());
80         } else {
81           hr_ = hr = hrActivateResult;
82           ::SetEvent(eventHolder_.get());
83         }
84       } else {
85         hr_ = hr;
86         ::SetEvent(eventHolder_.get());
87       }
88       return hr;
89       //operation
90       //    concurrency::wait(0);
91     }
92
93     void wait()
94     {
95       ::WaitForSingleObjectEx(eventHolder_.get(),INFINITE,FALSE);
96     }
97
98     HRESULT ResultCode() {return hr_;}
99     IAudioClient2Ptr AudioClient(){return ptr_;}
100   private:
101     HRESULT hr_;
102     sf::handle_holder eventHolder_;
103     IAudioClient2Ptr ptr_;
104   };
105
106   struct SoundDriver::impl 
107     //    : public RuntimeClass< RuntimeClassFlags< ClassicCom >, FtmBase, IActivateAudioInterfaceCompletionHandler > 
108   {
109
110     impl() : bufferIndex_(0),eventHolder_(nullptr),processBuffer_(std::bind(&SoundDriver::impl::DefaultProcessBuffer,this,stps::_1,stps::_2)),isStart_(false)
111     {
112       //::AvMMAvSetMmThreadCharacteristics
113       String^ deviceID = MediaDevice::GetDefaultAudioRenderId(AudioDeviceRole::Default);
114
115       {
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);
121         if(SUCCEEDED(hr)){
122           handler->wait();
123           if(handler->ResultCode() == S_OK)
124           {
125             audioClient_ = handler->AudioClient();
126           } else {
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");
128           }
129         } else {
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");
131         }
132       }
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();
138
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¤
146       {
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
153           )
154         {
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
162           alt_format.reset();
163           ThrowIfErr(audioClient_->IsFormatSupported(
164             AUDCLNT_SHAREMODE_SHARED,
165             reinterpret_cast<WAVEFORMATEX*>(&format_),
166             reinterpret_cast<WAVEFORMATEX**>(&alt_format)));
167         } else {
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");
169         }
170       }
171
172       // Audio Client\82Ì\8f\89\8aú\89»
173
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 ,
180         minDevicePriod,0,
181         reinterpret_cast<WAVEFORMATEX*>(&format_),NULL);
182       if(hr == AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED)
183       {
184         ThrowIfErr(audioClient_->GetBufferSize(&bufferSize_));
185         latency_ = (double)10000000 * (bufferSize_) / format_.Format.nSamplesPerSec;
186         audioClient_.Reset();
187
188         ComPtr<IActivateAudioInterfaceAsyncOperation> asyncOp;
189         ActivateAudioInterfaceCompletionHandler handler;
190         HRESULT hr = ActivateAudioInterfaceAsync(deviceID->Data(),__uuidof(IAudioClient2),nullptr,&handler,&asyncOp);
191         if(SUCCEEDED(hr)){
192           handler.wait();
193           if(handler.ResultCode() == S_OK)
194           {
195             audioClient_ = handler.AudioClient();
196           } else {
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");
198           }
199         } else {
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");
201         }
202
203         ThrowIfErr(audioClient_->Initialize(
204           AUDCLNT_SHAREMODE_SHARED,
205           AUDCLNT_STREAMFLAGS_NOPERSIST | 
206           AUDCLNT_STREAMFLAGS_EVENTCALLBACK ,
207           latency_,0,
208           reinterpret_cast<WAVEFORMATEX*>(&format_),NULL));
209       } else {
210         ThrowIfErr(hr);
211       }
212
213       ThrowIfErr(audioClient_->GetBufferSize(&bufferSize_));
214
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;
218
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());
223
224       processBuffer_(buffer_[bufferIndex_],bufferSize_);
225       BYTE* rawBuffer;
226       ThrowIfErr(audioRenderClient_->GetBuffer(bufferSize_,&rawBuffer));
227       audioRenderClient_->ReleaseBuffer(bufferSize_,0);
228       bufferIndex_ = (bufferIndex_ + 1) & 0x1;
229       processBuffer_(buffer_[bufferIndex_],bufferSize_);
230
231       Start();
232
233       //     ThrowIfErr(ActivateAudioInterfaceAsync(deviceID->Data(),__uuidof(IAudioClient2),nullptr,this,&asyncOp));
234
235     }
236
237     ~impl(){
238       audioClient_->Stop();
239       audioRenderClient_.Reset();
240       audioClient_->Reset();
241     };
242
243     void Render()
244     {
245       ::WaitForSingleObjectEx(eventHolder_.get(),INFINITE,FALSE);
246       uint32_t padding;
247       ThrowIfErr(audioClient_->GetCurrentPadding(&padding));
248       if(!padding)
249       {
250         BYTE* rawBuffer;
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_);
256       }
257     }
258
259     void SetProcessBufferFunc(ProcessBufferType&& v)
260     {
261       Stop();
262       processBuffer_ = std::move(v);
263       Start();
264     }
265     void ResetProcessBufferFunc()
266     {
267       Stop();
268       processBuffer_ = std::move(std::bind(&SoundDriver::impl::DefaultProcessBuffer,this,stps::_1,stps::_2));
269       Start();
270     }
271
272     void Start()
273     {
274       if(isStart_) return;
275
276       ThrowIfErr(audioClient_->Start());
277
278       isStart_ = true;
279     }
280
281     void Stop()
282     {
283       if(!isStart_) return;
284
285       ThrowIfErr(audioClient_->Stop());
286
287       isStart_ = false;
288     }
289
290     WAVEFORMATEXTENSIBLE& Format()
291     {
292       return format_;
293     }
294
295     void DefaultProcessBuffer(boost::shared_array<float> arr,int bufferSize)
296     {
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)
299       //{
300       //  voices_[j].Process(buffer);
301       //  *ptr +=  buffer[0]; 
302       //  *(ptr + 1) += buffer[1]; 
303       //}
304       float *ptr = arr.get();
305
306       ZeroMemory(ptr,bufferByteCount_);
307
308       //for(int i = 0;i < bufferSize;++i)
309       //{
310       //  sequencer_->Process();
311       //  synth_->Process(ptr);
312       //  ptr += 2;
313       //}
314     }
315
316     // IActivateAudioInterfaceCompletionHandler
317     STDMETHOD(ActivateCompleted)( IActivateAudioInterfaceAsyncOperation *operation )
318     {
319       try {
320         if(!audioClient_)
321         {
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");
323         }
324
325
326       } catch (...) 
327       {
328         return E_FAIL;
329       }
330       return S_OK;
331     }
332
333   private:
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];
343     int bufferIndex_;
344     int bufferByteCount_;
345     bool isStart_;
346
347   };
348
349   SoundDriver::SoundDriver() : impl_(new impl()) {}
350
351   SoundDriver::~SoundDriver()
352   {
353     impl_.reset();
354   }
355
356   void SoundDriver::Render()
357   {
358     impl_->Render();
359   }
360
361   void SoundDriver::SetProcessBufferFunc(ProcessBufferType&& v)
362   {
363     impl_->SetProcessBufferFunc(std::move(v));
364   }
365
366   void SoundDriver::ResetProcessBufferFunc()
367   {
368     impl_->ResetProcessBufferFunc();
369   }
370
371   void SoundDriver::Start()
372   {
373     impl_->Start();
374   }
375
376   void SoundDriver::Stop()
377   {
378     impl_->Stop();
379   }
380
381   WAVEFORMATEXTENSIBLE& SoundDriver::Format()
382   {
383     return impl_->Format();
384   }
385
386 }