OSDN Git Service

キャプチャ部分のバグ修正。
[winaudioj/wasapi2.git] / wasapi2 / input_agent.cpp
1 /*
2 ==============================================================================
3
4 This file is part of the async
5 Copyright 2005-10 by Satoshi Fujiwara.
6
7 async can be redistributed and/or modified under the terms of the
8 GNU General Public License, as published by the Free Software Foundation;
9 either version 2 of the License, or (at your option) any later version.
10
11 async is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with async; if not, visit www.gnu.org/licenses or write to the
18 Free Software Foundation, Inc., 59 Temple Place, Suite 330, 
19 Boston, MA 02111-1307 USA
20
21 ==============================================================================
22 */
23 #include "StdAfx.h"
24 #include <commctrl.h>
25
26 #if _DEBUG
27 #define _CRTDBG_MAP_ALLOC
28 #include <crtdbg.h>
29 #define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
30 #endif
31
32 #include "message_loop.h"
33 #include "sf_com.h"
34 #include "application.h"
35 #include "input_agent.h"
36 #include "dout.h"
37 #include "async_reader.h"
38
39 using namespace std;
40
41 namespace sf {
42
43   void input_agent_t::run()
44   {
45     // COMの初期化
46     sf::com_initialize init(0,multi_threaded);
47
48     // MMCSSの初期化
49     sf::av_mm_thread_characteristics avmm(wstring(L"Pro Audio"));
50     avmm.set_priority(AVRT_PRIORITY_HIGH);
51
52     //// input デバイスの初期化
53     //wasapi_device_manager::ptr m(wasapi_device_manager::instance());
54     //apply_config_(
55     // m->current_input_device_index(),
56     // m->current_input_device().params
57     //);
58     change_status(status_pause);
59     application& app(*application::instance());
60     int status = STATUS_ERROR;
61     BYTE *buffer = 0;
62     index_ = 0;
63     int source_counter ,dest_counter;
64     source_counter  = dest_counter = 0;
65     //// 出力デバイスが稼働するまで待つ
66     //app.output_thread().wait_status(output_agent_t::status_processing,10);
67     //apply_config_(
68     //wasapi_device_manager::instance()->current_input_device_index(),
69     //wasapi_device_manager::instance()->current_input_device().params);
70     change_status(status_device_config);
71     while(status = status_.load(),status != status_exit)
72     {
73       // イベントを待つ
74       switch(status)
75       {
76       case status_device_config:
77         if(wasapi_input_)
78         {
79           wasapi_input_->stop();
80           dest_counter = 0;
81           change_status(status_device_config_ok);
82         } else {
83           change_status(status_nodevice);
84         }
85         break;
86       case status_process:
87         if(wasapi_input_){
88         if(!wasapi_input_->is_start()){
89           wasapi_input_->start();
90         }
91         change_status(status_processing);
92         }
93         break;
94       case status_processing:
95
96         {
97           assert(wasapi_input_ != nullptr);
98           wasapi_input_->wait();// 入力待ち
99           try{
100             get_buffer g(*wasapi_input_);// キャプチャバッファの取得
101             if(g.size() && g != 0)
102             {
103               source_counter = 0;
104               while(source_counter != g.size())
105               {
106                 BYTE * src = g + source_counter * wasapi_input_->get_frame_size();
107                 int size_byte_src = g.size_byte() - source_counter * wasapi_input_->get_frame_size();
108                 int size_src = g.size() - source_counter;
109
110                 BYTE * dest = buffer_[index_].get() + dest_counter * app.output_device().get_frame_size();
111                 int size_byte_dest = app.output_device().get_buffer_byte_size() - dest_counter * app.output_device().get_frame_size();
112                 int size_dest = app.output_device().get_buffer_size() - dest_counter;
113
114                 if(size_src <= size_dest)
115                 {
116                   ::CopyMemory(dest,src,size_byte_src);
117                   source_counter += size_src;
118                   dest_counter += size_src;
119                 } else if(size_src > size_dest)
120                 {
121                   ::CopyMemory(dest,src,size_byte_dest);
122                   source_counter += size_dest;
123                   dest_counter += size_dest;
124                 }
125                 if(dest_counter == app.output_device().get_buffer_size())
126                 {
127                   if(ringbuffer_.enqueue(buffer_[index_].get()))
128                   {
129                     index_ = (index_ + 1) & (buffer_.size() - 1);
130                   }
131                   dest_counter = 0;
132                 }
133               }
134             }
135           } catch (...) {
136             ;
137           }
138         }
139
140         break;
141       case status_pause:
142         if(wasapi_input_)
143         {
144           wasapi_input_->stop();
145         }
146         change_status(status_pause_ok);
147         break;
148       default:
149         wait_event();
150 //        WaitForSingleObject(event_.get(),WAIT_TIMEOUT_DEFAULT);
151         break;
152       }
153     }
154 loop_end:
155     ;
156     DOUT(L"##### input_threadは終了!" << endl);
157     if(wasapi_input_ && wasapi_input_->is_start())
158     {
159       wasapi_input_->stop();
160       wasapi_input_.reset();
161     }
162
163     agent::done();
164   };
165
166   void input_agent_t::apply_config(int device_index,wasapi_device_manager::device_info::params_t& params)
167   {
168     if(status() != status_device_config_ok && status() != status_nodevice)
169     {
170       change_and_wait(status_device_config,status_device_config_ok);
171     }
172
173     apply_config_(device_index,params);
174     if(wasapi_input_)
175     {
176       change_and_wait(status_device_config,status_device_config_ok);
177     }
178     if(status() != status_nodevice)
179     {
180       init_buffer();
181       change_and_wait(status_process,status_processing);
182     }
183   }
184
185   void input_agent_t::apply_config_(int device_index,wasapi_device_manager::device_info::params_t& params)
186   {
187
188     WAVEFORMATEXTENSIBLE form;
189     if(wasapi_input_)
190     {
191       if(wasapi_input_->is_start())
192       {
193         wasapi_input_->stop();
194       }
195       wasapi_input_.reset();
196     };
197
198     //bits_pair bits = {params.bits,params.valid_bits};
199     //make_wave_format(form,params.sample_rate,params.channel,bits);
200
201     try {
202       if(params.exclusive_mode)
203       {
204         if(params.event_mode){
205           wasapi_input_.reset(new sf::wasapi_capture_exclusive_event(device_index,params));
206         } else {
207           wasapi_input_.reset(new sf::wasapi_capture_exclusive_timer(device_index,params));
208         };
209       } else {
210         if(params.event_mode)
211         {
212           wasapi_input_.reset(new sf::wasapi_capture_shared_event(device_index,params));
213         } else {
214           wasapi_input_.reset(new sf::wasapi_capture_shared_timer(device_index,params));
215         }
216       }
217     } catch (win32_error_exception& e)
218     {
219
220       //window_->message_box((boost::wformat(L"WASAPI初期化エラーが発生しました。設定パラメータを見なおしてください。%s") % e.error()).str(),wstring(L"WASAPI初期化エラー"));
221       throw;
222     }
223
224     wasapi_device_manager::instance()->select_input_device(device_index);
225     wasapi_device_manager::instance()->current_input_device().params = params;
226
227   }
228
229   //void input_agent_t::init_buffer()
230   //{
231   //  audio_base& in(application::instance()->input_device());
232   //  for(int i = 0,size = buffer_.size();i < size;++i)
233   //  {
234   //    buffer_[i].reset(reinterpret_cast<uint8_t*>(_aligned_malloc(sizeof(uint8_t) * in.get_buffer_byte_size(),16)));
235   //  }
236   //}
237
238
239 }
240