OSDN Git Service

サンプルレート変換処理を組み込んだ。しかしモノラルのWAVファイルを読み込むと落ちる。
authorSFPGMR <sfpg@git.sourceforge.jp>
Tue, 13 Sep 2011 10:01:05 +0000 (19:01 +0900)
committerSFPGMR <sfpg@git.sourceforge.jp>
Tue, 13 Sep 2011 10:01:05 +0000 (19:01 +0900)
async/application.cpp
async/async.rc
async/message_loop.h
async/sf_com.h
async/sf_windows.h
async/toplevel_window.cpp
async/wasapi.cpp
async/wasapi.h

index 1eff4de..77a185d 100644 (file)
@@ -128,7 +128,7 @@ namespace sf {
     // wasapi出力スレッドの起動
     output_thread_ = boost::thread(boost::bind(&application::output_thread_main,this));
 
-    bool a = ringbuffer_.is_lock_free();
//   bool a = ringbuffer_.is_lock_free();
 //    wdout << ( ? L"**** true ****":L"---- false ----") << std::endl;
     //sf::dialogbox(L"asyncテスト",L"asyncテスト");
     // メッセージループの実行
@@ -177,7 +177,8 @@ namespace sf {
                 {
                   memset(read_buffer_[read_index_].get() + size,0,wasapi_->get_buffer_byte_size() - size);
                 }
-             }
+              }
+
               not_enqueue_ = false;
               while(!ringbuffer_.enqueue(read_buffer_[read_index_].get()))
               {
@@ -192,6 +193,7 @@ namespace sf {
                   Sleep(0);
                 }
               }
+
               ;
               sf::wdout << boost::wformat(L"index:%d address:%x 差分:%x") 
                 % read_index_ % read_buffer_[read_index_].get()
@@ -271,9 +273,10 @@ namespace sf {
 
         break;
       case player_pause:
-        //wasapi_->reset();
+        wasapi_->stop();
         break;
       case player_stop:
+        wasapi_->stop();
         break;
       }
       Sleep(0);
@@ -287,6 +290,10 @@ namespace sf {
     source_file_path_ = file_path;
     reader_.reset(new WaveFileReader(file_path.c_str(),FALSE));
     THROW_IF_ERR(reader_->GetStreamStatus());
+    if(wasapi_)
+    {
+      wasapi_.reset();
+    }
     wasapi_.reset(new sf::wasapi_shared_timer(reader_->GetWaveFormat()));
     if(!wasapi_->is_enabled())
     {
index 34728aa..db07680 100644 (file)
 //\r
 LANGUAGE LANG_JAPANESE, SUBLANG_JAPANESE_JAPAN\r
 IDD_MAINDIALOG DIALOG 0, 0, 320, 252\r
-STYLE DS_3DLOOK | DS_CENTER | DS_MODALFRAME | DS_SHELLFONT | WS_CAPTION | WS_VISIBLE | WS_GROUP | WS_TABSTOP | WS_SYSMENU\r
-EXSTYLE WS_EX_ACCEPTFILES | WS_EX_APPWINDOW\r
+STYLE DS_3DLOOK | DS_CENTER | DS_MODALFRAME | DS_SHELLFONT | WS_CAPTION | WS_VISIBLE | WS_SYSMENU\r
+EXSTYLE WS_EX_APPWINDOW\r
 CAPTION "\94ñ\93¯\8aú\82Å\83t\83@\83C\83\8b\82ð\93Ç\82Ý\8d\9e\82Ý\81A\8dÄ\90\82·\82é\83e\83X\83g"\r
 FONT 9, "\83\81\83C\83\8a\83I"\r
 {\r
     PUSHBUTTON      "\83t\83@\83C\83\8b", IDC_FILE, 11, 5, 40, 14,WS_TABSTOP \r
     PUSHBUTTON      "\8dÄ\90¶", IDC_PLAY, 53, 5, 40, 14, WS_DISABLED | WS_TABSTOP \r
-    CONTROL         "", IDC_SLIDER, TRACKBAR_CLASS, WS_TABSTOP | WS_DISABLED | TBS_BOTH | TBS_NOTICKS, 6, 29, 309, 15\r
     PUSHBUTTON      "\88ê\8e\9e\92â\8e~", IDC_PAUSE, 95, 5, 40, 14, WS_DISABLED | WS_TABSTOP \r
     PUSHBUTTON      "\92â\8e~", IDC_STOP, 137, 5, 40, 14, WS_DISABLED | WS_TABSTOP \r
+    CONTROL         "", IDC_SLIDER, TRACKBAR_CLASS, WS_TABSTOP | WS_DISABLED | TBS_BOTH | TBS_NOTICKS, 6, 29, 309, 15\r
     CONTROL         "", IDC_WAVEFORM, WC_STATIC, SS_BLACKFRAME, 10, 155, 301, 88\r
-    LTEXT           "Static", IDC_INFO, 10, 49, 301, 99, SS_LEFT | WS_TABSTOP, WS_EX_STATICEDGE \r
+    LTEXT           "Static", IDC_INFO, 10, 49, 301, 99, SS_LEFT, WS_EX_STATICEDGE \r
 }\r
 \r
 \r
index ed07fb4..37c3b90 100644 (file)
@@ -70,7 +70,7 @@ namespace sf {
 
   struct dialog_message_loop
        {
-               dialog_message_loop(HWND dialog) : dialog_(dialog_) {};
+               dialog_message_loop(HWND dialog) : dialog_(dialog) {};
                inline WPARAM operator()()
                {
                        MSG msg;
index 94f0de3..ce07aa6 100644 (file)
  *  @author S.F. (Satoshi Fujiwara)
  */
 #include "objbase.h"
+
+
+
 namespace sf 
 {
+  template <class COM_SMART_PTR > inline void safe_release(COM_SMART_PTR& ptr)
+  {
+    if(ptr)
+    {
+      ptr.Release();
+    }
+  };
     enum com_init 
     {
         multi_threaded  = 0x0,
index 1d79e6f..1c80373 100644 (file)
@@ -83,13 +83,7 @@ _COM_SMARTPTR_TYPEDEF(ID3DBlob,__uuidof(ID3DBlob));
 _COM_SMARTPTR_TYPEDEF(ID3D11ShaderResourceView,__uuidof(ID3D11ShaderResourceView));
 _COM_SMARTPTR_TYPEDEF(ID3D11SamplerState,__uuidof(ID3D11SamplerState));
 
-template <class COM_SMART_PTR > inline void safe_release(COM_SMART_PTR& ptr)
-{
-  if(ptr)
-  {
-    ptr.Release();
-  }
-};
+
 
 namespace sf{
 
@@ -351,7 +345,7 @@ namespace sf{
 
     virtual void send_message(uint32_t message,uint32_t wparam,uint32_t lparam )
     {
-      ::SendMessage(hwnd_,message,wparam,lparam);
+      ::SendNotifyMessage(hwnd_,message,wparam,lparam);
     }
 
     virtual void post_message(uint32_t message,uint32_t wparam,uint32_t lparam )
index 21f4969..992853f 100644 (file)
@@ -226,7 +226,7 @@ struct toplevel_window::impl : public base_win32_dialog_t
   };
 
 
-
+  
   // -------------------------------------------------------------------
   // ウィンドウプロシージャ
   // -------------------------------------------------------------------
@@ -357,7 +357,7 @@ struct toplevel_window::impl : public base_win32_dialog_t
       break;
     case WM_PLAY_PLAY:
       play_();
-      break;
+      return TRUE;
     case WM_PLAY_STOP:
       stop_();
       return TRUE;
@@ -396,15 +396,29 @@ struct toplevel_window::impl : public base_win32_dialog_t
      SendMessage(GetDlgItem(hwnd_,IDC_SLIDER), TBM_SETRANGE, (WPARAM)TRUE, (LPARAM)MAKELONG(0, 30000));
   }
 
+  void ready()
+  {
+    // プレイボタンは有効化
+    enable_control(IDC_PLAY,true);
+    focus(IDC_PLAY);
+    highlight(IDC_PLAY);
+    // その他のボタンは無効化
+    enable_control(IDC_PAUSE,false);
+    enable_control(IDC_SLIDER,true);
+    enable_control(IDC_STOP,false);
+  }
+
   void play()
   {
-    send_message(WM_PLAY_PLAY,0,0);
+    post_message(WM_PLAY_PLAY,0,0);
   }
   
   void play_()
   {
     enable_control(IDC_PLAY,false);
     enable_control(IDC_STOP,true);
+    focus(IDC_STOP);
+    highlight(IDC_STOP);
     enable_control(IDC_PAUSE,true);
     ::SetWindowText(GetDlgItem(hwnd_,IDC_PAUSE),L"一時停止");
     enable_control(IDC_SLIDER,true);
@@ -412,15 +426,17 @@ struct toplevel_window::impl : public base_win32_dialog_t
 
   void stop()
   {
-    send_message(WM_PLAY_STOP,0,0);
+    post_message(WM_PLAY_STOP,0,0);
   }
 
   void stop_()
   {
     enable_control(IDC_PLAY,true);
+    focus(IDC_PLAY);
+    highlight(IDC_PLAY);
     enable_control(IDC_STOP,false);
     enable_control(IDC_PAUSE,false);
-    enable_control(IDC_SLIDER,false);
+    enable_control(IDC_SLIDER,true);
   }
   
   void pause()
@@ -433,8 +449,10 @@ struct toplevel_window::impl : public base_win32_dialog_t
     enable_control(IDC_PLAY,false);
     enable_control(IDC_STOP,false);
     enable_control(IDC_PAUSE,true);
+    focus(IDC_PAUSE);
+    highlight(IDC_PAUSE);
     ::SetWindowText(GetDlgItem(hwnd_,IDC_PAUSE),L"再開");
-    enable_control(IDC_SLIDER,false);
+    enable_control(IDC_SLIDER,true);
   }
   virtual void create(){
     create_device_independent_resources();
@@ -451,7 +469,7 @@ struct toplevel_window::impl : public base_win32_dialog_t
 
   void create_dialog()
   {
-    hwnd_ = ::CreateDialog(HINST_THISCOMPONENT,MAKEINTRESOURCE(IDD_MAINDIALOG),0,thunk_proc_);
+    hwnd_ = ::CreateDialog(HINST_THISCOMPONENT,MAKEINTRESOURCE(IDD_MAINDIALOG),::GetDesktopWindow(),thunk_proc_);
     // ::DialogBox(HINST_THISCOMPONENT,MAKEINTRESOURCE(IDD_MAINDIALOG),0,thunk_proc_);
   }
 
@@ -609,16 +627,7 @@ struct toplevel_window::impl : public base_win32_dialog_t
       }
     }
   }
-  void ready()
-  {
-    // プレイボタンは有効化
-    enable_control(IDC_PLAY,true);
-
-    // その他のボタンは無効化
-    enable_control(IDC_PAUSE,false);
-    enable_control(IDC_SLIDER,false);
-    enable_control(IDC_STOP,false);
-  }
 
   void create_window()
   {
@@ -704,6 +713,19 @@ struct toplevel_window::impl : public base_win32_dialog_t
   {
     ::EnableWindow(GetDlgItem(hwnd_,id),enable?TRUE:FALSE);
   }
+
+  void focus(uint32_t id)
+  {
+    //::PostMessage(GetDlgItem(hwnd_,id),WM_SETFOCUS,NULL,NULL);
+    ::SetFocus(GetDlgItem(hwnd_,id));
+    //::PostMessage(hwnd_,WM_COMMAND,MAKEWPARAM(id,BN_SETFOCUS),(LPARAM)GetDlgItem(hwnd_,id));
+  }
+
+  void highlight(uint32_t id)
+  {
+    //Button_SetState(GetDlgItem(hwnd_,id),TRUE);
+  }
+
 private:
 
   void read_start() {};
index 5bfe2f1..9939738 100644 (file)
@@ -73,9 +73,26 @@ namespace sf{
       //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;
-      THROW_IF_ERR(
-        audio_client_->IsFormatSupported(
-        AUDCLNT_SHAREMODE_SHARED,reinterpret_cast<::WAVEFORMATEX*>(&wfx),&alt_format));
+      
+      HRESULT hr = audio_client_->IsFormatSupported(
+      AUDCLNT_SHAREMODE_SHARED ,reinterpret_cast<::WAVEFORMATEX*>(&wfx.Format),&alt_format);
+      bool sample_rate_convert = false;
+      float sample_rate_backup = 0.0f;
+      if(hr != S_OK)
+      {
+        // サンプルレートのコンバート
+        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));
+          sample_rate_convert = true;
+        } else {
+          throw win32_error_exception(hr);
+        }
+      }
 
       // 再生クライアントの初期化
 
@@ -83,21 +100,27 @@ namespace sf{
 
       REFERENCE_TIME buffer_duration = buffer_period * periods_per_buffer_;
 
-      THROW_IF_ERR(audio_client_->Initialize(AUDCLNT_SHAREMODE_SHARED, 
-                                            AUDCLNT_STREAMFLAGS_NOPERSIST, 
+      THROW_IF_ERR(audio_client_->Initialize(AUDCLNT_SHAREMODE_SHARED  
+                                            AUDCLNT_STREAMFLAGS_NOPERSIST | AUDCLNT_STREAMFLAGS_RATEADJUST
                                             buffer_duration, 
                                             buffer_period,
                                             &(wfx.Format), 
                                             NULL));
 
-
+      audio_client_->Reset();
       // バッファサイズの取得
       THROW_IF_ERR(audio_client_->GetBufferSize(&buffer_size_));
 
       // 再生クライアントの取得
       THROW_IF_ERR(audio_client_->GetService(IID_PPV_ARGS(&audio_render_client_)));
 
-      // 
+      // サンプルレートコンバータ
+      if(sample_rate_convert)
+      {
+        THROW_IF_ERR(audio_client_->GetService(IID_PPV_ARGS(&audio_clock_adjustment_)));
+        audio_clock_adjustment_->SetSampleRate(sample_rate_backup);
+      }
+
       num_of_frames_ = wfx.Format.nBlockAlign;
       mix_format_ = wfx;
       is_enabled_ = true;
@@ -112,13 +135,18 @@ namespace sf{
 
   wasapi_shared_timer::~wasapi_shared_timer()
   {
+    safe_release(audio_clock_adjustment_);
+    safe_release(audio_render_client_);
 
-      // WASAPIの終了処理
+    // WASAPIの終了処理
     if(audio_client_)
     {
       audio_client_->Stop();
       audio_client_.Release();
     }
+
+    safe_release(current_device_);
+    safe_release(device_enumerator_);
   }
 
   void wasapi_shared_timer::create_wave_data(){
@@ -205,6 +233,7 @@ namespace sf{
   void wasapi_shared_timer::stop() {
     //再生停止
     THROW_IF_ERR(audio_client_->Stop());
+    reset();
     is_start_ = false;
   }
 }
index a4ce77b..4801cf5 100644 (file)
@@ -39,6 +39,7 @@ _COM_SMARTPTR_TYPEDEF(IMMDeviceEnumerator,__uuidof(IMMDeviceEnumerator));
 _COM_SMARTPTR_TYPEDEF(IMMDevice,__uuidof(IMMDevice));
 _COM_SMARTPTR_TYPEDEF(IAudioClient,__uuidof(IAudioClient));
 _COM_SMARTPTR_TYPEDEF(IAudioRenderClient,__uuidof(IAudioRenderClient));
+_COM_SMARTPTR_TYPEDEF(IAudioClockAdjustment,__uuidof(IAudioClockAdjustment));
 
 namespace sf {
 
@@ -72,6 +73,7 @@ private:
   IMMDevicePtr current_device_;
   IAudioClientPtr audio_client_;
   IAudioRenderClientPtr audio_render_client_;
+  IAudioClockAdjustmentPtr audio_clock_adjustment_;
   //handle_holder buffer_control_event_;
   WAVEFORMATEXTENSIBLE mix_format_;
   bool is_enabled_;