OSDN Git Service

WAVEファイル読み込みを整理・改良。エラー処理を例外ベースにてHRESULTをなくす。
[winaudioj/async.git] / async / wasapi.cpp
index 9939738..b2262fa 100644 (file)
@@ -30,66 +30,58 @@ namespace sf{
   wasapi_shared_timer::wasapi_shared_timer(::WAVEFORMATEXTENSIBLE& wfx) 
     : is_enabled_(false),position_(0),is_start_(false)/*,buffer_control_event_(::CreateEventEx(NULL, NULL, 0, EVENT_MODIFY_STATE | SYNCHRONIZE))*/
   {
-    //if(buffer_control_event_ == NULL)
-    //{
-    //  return;
-    //}
 
     try {
-//      thread_priority_.set_priority(AVRT_PRIORITY_NORMAL);
+      //      thread_priority_.set_priority(AVRT_PRIORITY_NORMAL);
 
       // WASAPIの初期化処理
 
       // IMMDeviceEnumeratorの取得
       THROW_IF_ERR(
         CoCreateInstance(
-          __uuidof(MMDeviceEnumerator), NULL, CLSCTX_INPROC_SERVER,
-          IID_PPV_ARGS(&device_enumerator_)));
-      
+        __uuidof(MMDeviceEnumerator), NULL, CLSCTX_INPROC_SERVER,
+        IID_PPV_ARGS(&device_enumerator_)));
+
       // デフォルトのオーディオデバイスを取得する
       THROW_IF_ERR(
         device_enumerator_
-          ->GetDefaultAudioEndpoint(eRender,eMultimedia,&current_device_)
-       );
+        ->GetDefaultAudioEndpoint(eRender,eMultimedia,&current_device_)
+        );
 
       // オーディオクライアントを取得
       THROW_IF_ERR(
         current_device_
-          ->Activate(__uuidof(IAudioClient), CLSCTX_INPROC_SERVER,
-          NULL, reinterpret_cast<void **>(&audio_client_))
+        ->Activate(__uuidof(IAudioClient), CLSCTX_INPROC_SERVER,
+        NULL, reinterpret_cast<void **>(&audio_client_))
         );
 
-      // フォーマット定義
-      //audio_client_->GetMixFormat(&mix_format_);
-      //WAVEFORMATEXTENSIBLE *waveFormatExtensible = reinterpret_cast<WAVEFORMATEXTENSIBLE *>((WAVEFORMATEX*)mix_format_.get());
-      //waveFormatExtensible->SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
-      //waveFormatExtensible->Format.wBitsPerSample = 16;
-      //waveFormatExtensible->Format.nBlockAlign = (mix_format_->wBitsPerSample / 8) * mix_format_->nChannels;
-      //waveFormatExtensible->Format.nAvgBytesPerSec = waveFormatExtensible->Format.nSamplesPerSec*waveFormatExtensible->Format.nBlockAlign;
-      //waveFormatExtensible->Samples.wValidBitsPerSample = 16;
-
-      //mix_format_->wFormatTag = WAVE_FORMAT_PCM;
-      //mix_format_->wBitsPerSample = 16;
-      //mix_format_->nBlockAlign = (mix_format_->wBitsPerSample / 8) * mix_format_->nChannels;
-      //mix_format_->nAvgBytesPerSec = mix_format_->nSamplesPerSec*mix_format_->nBlockAlign;
+      // 代替フォーマット定義
       sf::co_task_memory<WAVEFORMATEX>  alt_format;
-      
+
+      // 読みこもうとしているWAVファイルのフォーマットをサポートしているか?
       HRESULT hr = audio_client_->IsFormatSupported(
-      AUDCLNT_SHAREMODE_SHARED ,reinterpret_cast<::WAVEFORMATEX*>(&wfx.Format),&alt_format);
+        AUDCLNT_SHAREMODE_SHARED ,&wfx.Format,&alt_format);
       bool sample_rate_convert = false;
       float sample_rate_backup = 0.0f;
-      if(hr != S_OK)
+      if(hr != S_OK) //  S_FALSEならそのフォーマットをサポートしていないらしい..
       {
         // サンプルレートのコンバート
         if(alt_format->nSamplesPerSec != wfx.Format.nSamplesPerSec)
         {
+          // 本来のサンプルレートをバックアップする
           sample_rate_backup = wfx.Format.nSamplesPerSec;
+          // 代替フォーマットのサンプルレートをセットする
           wfx.Format.nSamplesPerSec = alt_format->nSamplesPerSec;
+          // 再計算する
           wfx.Format.nAvgBytesPerSec = alt_format->nSamplesPerSec * wfx.Format.nBlockAlign;
+          // もう一回チェックする。
+          // サンプルレート以外でサポートしていない点があれば例外が発生する。
           THROW_IF_ERR(audio_client_->IsFormatSupported(
-            AUDCLNT_SHAREMODE_SHARED ,reinterpret_cast<::WAVEFORMATEX*>(&wfx.Format),&alt_format));
+            AUDCLNT_SHAREMODE_SHARED ,&wfx.Format,&alt_format));
+          // フラグをセットする
           sample_rate_convert = true;
         } else {
+          // サンプルレート以外であれば例外を出す。
           throw win32_error_exception(hr);
         }
       }
@@ -101,13 +93,12 @@ namespace sf{
       REFERENCE_TIME buffer_duration = buffer_period * periods_per_buffer_;
 
       THROW_IF_ERR(audio_client_->Initialize(AUDCLNT_SHAREMODE_SHARED  , 
-                                            AUDCLNT_STREAMFLAGS_NOPERSIST | AUDCLNT_STREAMFLAGS_RATEADJUST, 
-                                            buffer_duration, 
-                                            buffer_period,
-                                            &(wfx.Format), 
-                                            NULL));
+        AUDCLNT_STREAMFLAGS_NOPERSIST | AUDCLNT_STREAMFLAGS_RATEADJUST, 
+        buffer_duration, 
+        buffer_period,
+        &(wfx.Format), 
+        NULL));
 
-      audio_client_->Reset();
       // バッファサイズの取得
       THROW_IF_ERR(audio_client_->GetBufferSize(&buffer_size_));
 
@@ -118,6 +109,7 @@ namespace sf{
       if(sample_rate_convert)
       {
         THROW_IF_ERR(audio_client_->GetService(IID_PPV_ARGS(&audio_clock_adjustment_)));
+        // 本来のサンプルレートをセットする
         audio_clock_adjustment_->SetSampleRate(sample_rate_backup);
       }
 
@@ -160,12 +152,12 @@ namespace sf{
 
     for (size_t i = 0 ; i < render_data_length ; i += mix_format_.Format.nChannels)
     {
-        double sinValue = sin( theta );
-        for(size_t j = 0 ;j < mix_format_.Format.nChannels; j++)
-        {
-            tone_buffer_.push_back((short)(sinValue * _I16_MAX));
-        }
-        theta += sampleIncrement;
+      double sinValue = sin( theta );
+      for(size_t j = 0 ;j < mix_format_.Format.nChannels; j++)
+      {
+        tone_buffer_.push_back((short)(sinValue * _I16_MAX));
+      }
+      theta += sampleIncrement;
     }
   };
 
@@ -177,7 +169,7 @@ namespace sf{
 
     if(!is_start_)
     {
-    
+
       // 最初にバッファを埋める
       THROW_IF_ERR(audio_render_client_->GetBuffer(buffer_size_,&buffer));
       ::CopyMemory(buffer,source_buffer,get_buffer_byte_size());
@@ -224,7 +216,7 @@ namespace sf{
       {
         Sleep(latency_ms_);
       }
-   }
+    }
   }
   void wasapi_shared_timer::reset()
   {