wasapiを実験するプロジェクトです。
Revision | 9125ee20105f02a711ab7a52563d88379e1b454f (tree) |
---|---|
Time | 2012-11-12 19:52:10 |
Author | sfpg <sfpg@user...> |
Commiter | sfpg |
非同期エージェントライブラリでスレッド部分を書き換えてみた。
@@ -0,0 +1,56 @@ | ||
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 "dout.h" | |
35 | +#include "async_reader.h" | |
36 | +#include "application.h" | |
37 | +#include "agent_base.h" | |
38 | + | |
39 | +using namespace std; | |
40 | + | |
41 | +namespace sf { | |
42 | + | |
43 | + void agent_base::init_buffer() | |
44 | + { | |
45 | + audio_base& out(application::instance()->output_device()); | |
46 | + ringbuffer_.reset(); | |
47 | + for(int i = 0,size = buffer_.size();i < size;++i) | |
48 | + { | |
49 | + buffer_[i].reset(reinterpret_cast<uint8_t*>(_aligned_malloc(sizeof(uint8_t) * out.get_buffer_byte_size(),16))); | |
50 | + } | |
51 | + index_ = 0; | |
52 | + } | |
53 | + | |
54 | +} | |
55 | + | |
56 | + |
@@ -0,0 +1,120 @@ | ||
1 | +#pragma once | |
2 | +/* | |
3 | + ============================================================================== | |
4 | + | |
5 | + This file is part of the async | |
6 | + Copyright 2005-10 by Satoshi Fujiwara. | |
7 | + | |
8 | + async can be redistributed and/or modified under the terms of the | |
9 | + GNU General Public License, as published by the Free Software Foundation; | |
10 | + either version 2 of the License, or (at your option) any later version. | |
11 | + | |
12 | + async is distributed in the hope that it will be useful, | |
13 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | + GNU General Public License for more details. | |
16 | + | |
17 | + You should have received a copy of the GNU General Public License | |
18 | + along with async; if not, visit www.gnu.org/licenses or write to the | |
19 | + Free Software Foundation, Inc., 59 Temple Place, Suite 330, | |
20 | + Boston, MA 02111-1307 USA | |
21 | + | |
22 | + ============================================================================== | |
23 | +*/ | |
24 | +#include "singleton.h" | |
25 | +#include "exception.h" | |
26 | +#include "ring_buffer.h" | |
27 | +#include "sf_memory.h" | |
28 | +namespace sf | |
29 | +{ | |
30 | + struct agent_base : public Concurrency::agent | |
31 | + { | |
32 | + struct wait_exception | |
33 | + : public sf::exception | |
34 | + { | |
35 | + wait_exception() : exception(L"wait_error") {} | |
36 | + }; | |
37 | + | |
38 | + agent_base() // : event_((::CreateEventEx(NULL, NULL, 0,EVENT_MODIFY_STATE | SYNCHRONIZE)) | |
39 | + { | |
40 | + status_.store(0, std::memory_order_seq_cst); | |
41 | + } | |
42 | + | |
43 | + virtual ~agent_base(){}; | |
44 | + | |
45 | + //void execute() | |
46 | + //{ | |
47 | + // //g.run(std::bind(&agent_base::thread_main,this)); | |
48 | + // thread_ = std::thread(boost::bind(&agent_base::thread_main,this)); | |
49 | + //} | |
50 | + | |
51 | + | |
52 | + //void join () | |
53 | + //{ | |
54 | + // if(thread_.joinable()) | |
55 | + // { | |
56 | + // thread_.join(); | |
57 | + // } | |
58 | + //} | |
59 | + | |
60 | + // 状態の変更 | |
61 | + void change_status(int value,std::memory_order o = std::memory_order_seq_cst) | |
62 | + { | |
63 | + event_.reset(); | |
64 | + status_.store(value,o); | |
65 | + event_.set(); | |
66 | + DOUT(L"change_status()" << std::endl); | |
67 | + } | |
68 | + | |
69 | + void wait_event() | |
70 | + { | |
71 | + event_.wait(); | |
72 | + } | |
73 | + | |
74 | + void change_and_wait(int value,int wait_value,std::memory_order o = std::memory_order_seq_cst) | |
75 | + { | |
76 | + change_status(value,o); | |
77 | + //PulseEvent(event_.get()); | |
78 | + wait_status(wait_value); | |
79 | + } | |
80 | + | |
81 | + int status(std::memory_order o = std::memory_order_seq_cst) | |
82 | + { | |
83 | + return status_.load(o); | |
84 | + }; | |
85 | + | |
86 | + virtual void init_buffer(); | |
87 | + | |
88 | + void wait_status(int value,int ms = 1,std::memory_order o = std::memory_order_seq_cst) | |
89 | + { | |
90 | + DOUT(L"wait_status()" << std::endl); | |
91 | + int s; | |
92 | + while(s = status_.load(o),s != value) | |
93 | + { | |
94 | + if(s < STATUS_ERROR) | |
95 | + { | |
96 | + throw wait_exception(); | |
97 | + }; | |
98 | + Sleep(ms); | |
99 | + } | |
100 | + }; | |
101 | + | |
102 | + ringbuffer_t& ringbuffer() {return ringbuffer_;} | |
103 | + | |
104 | + static const int STATUS_ERROR = -1; | |
105 | + static const size_t Q_SIZE = 8; | |
106 | + static const int WAIT_TIMEOUT_DEFAULT = 100; | |
107 | + | |
108 | + protected: | |
109 | + virtual void run() = 0; | |
110 | + | |
111 | + //std::thread thread_; | |
112 | + std::atomic<int> status_; | |
113 | + buffer_t buffer_; | |
114 | + Concurrency::event event_; | |
115 | + //handle_holder event_; | |
116 | + uint32_t index_; | |
117 | + ringbuffer_t ringbuffer_; | |
118 | + std::wstring error_; | |
119 | + }; | |
120 | +} |
@@ -0,0 +1,224 @@ | ||
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 | + } | |
82 | + change_status(status_device_config_ok); | |
83 | + break; | |
84 | + case status_process: | |
85 | + if(!wasapi_input_->is_start()){ | |
86 | + wasapi_input_->start(); | |
87 | + } | |
88 | + change_status(status_processing); | |
89 | + case status_processing: | |
90 | + { | |
91 | + wasapi_input_->wait();// 入力待ち | |
92 | + //try{ | |
93 | + // get_buffer g(*wasapi_input_);// キャプチャバッファの取得 | |
94 | + // if(g.size() && g != 0) | |
95 | + // { | |
96 | + // source_counter = 0; | |
97 | + // while(source_counter != g.size()) | |
98 | + // { | |
99 | + // BYTE * src = g + source_counter * wasapi_input_->get_frame_size(); | |
100 | + // int size_byte_src = g.size_byte() - source_counter * wasapi_input_->get_frame_size(); | |
101 | + // int size_src = g.size() - source_counter; | |
102 | + | |
103 | + // BYTE * dest = buffer_[index_].get() + dest_counter * app.output_device().get_frame_size(); | |
104 | + // int size_byte_dest = app.output_device().get_buffer_byte_size() - dest_counter * app.output_device().get_frame_size(); | |
105 | + // int size_dest = app.output_device().get_buffer_size() - dest_counter; | |
106 | + | |
107 | + // if(size_src <= size_dest) | |
108 | + // { | |
109 | + // ::CopyMemory(dest,src,size_byte_src); | |
110 | + // source_counter += size_src; | |
111 | + // dest_counter += size_src; | |
112 | + // } else if(size_src > size_dest) | |
113 | + // { | |
114 | + // ::CopyMemory(dest,src,size_byte_dest); | |
115 | + // source_counter += size_dest; | |
116 | + // dest_counter += size_dest; | |
117 | + // } | |
118 | + // if(dest_counter == app.output_device().get_buffer_size()) | |
119 | + // { | |
120 | + // if(ringbuffer_.enqueue(buffer_[index_].get())) | |
121 | + // { | |
122 | + // index_ = (index_ + 1) & (buffer_.size() - 1); | |
123 | + // } | |
124 | + // dest_counter = 0; | |
125 | + // } | |
126 | + // } | |
127 | + // } | |
128 | + //} catch (...) { | |
129 | + // ; | |
130 | + //} | |
131 | + } | |
132 | + | |
133 | + break; | |
134 | + case status_pause: | |
135 | + if(wasapi_input_) | |
136 | + { | |
137 | + wasapi_input_->stop(); | |
138 | + } | |
139 | + change_status(status_pause_ok); | |
140 | + break; | |
141 | + default: | |
142 | + wait_event(); | |
143 | +// WaitForSingleObject(event_.get(),WAIT_TIMEOUT_DEFAULT); | |
144 | + break; | |
145 | + } | |
146 | + } | |
147 | +loop_end: | |
148 | + ; | |
149 | + DOUT(L"##### input_threadは終了!" << endl); | |
150 | + if(wasapi_input_ && wasapi_input_->is_start()) | |
151 | + { | |
152 | + wasapi_input_->stop(); | |
153 | + } | |
154 | + wasapi_input_.reset(); | |
155 | + | |
156 | + agent::done(); | |
157 | + }; | |
158 | + | |
159 | + void input_agent_t::apply_config(int device_index,wasapi_device_manager::device_info::params_t& params) | |
160 | + { | |
161 | + if(status() != status_device_config_ok){ | |
162 | + change_and_wait(status_device_config,status_device_config_ok); | |
163 | + } | |
164 | + apply_config_(device_index,params); | |
165 | + init_buffer(); | |
166 | + change_and_wait(status_process,status_processing); | |
167 | + } | |
168 | + | |
169 | + void input_agent_t::apply_config_(int device_index,wasapi_device_manager::device_info::params_t& params) | |
170 | + { | |
171 | + | |
172 | + WAVEFORMATEXTENSIBLE form; | |
173 | + if(wasapi_input_) | |
174 | + { | |
175 | + if(wasapi_input_->is_start()) | |
176 | + { | |
177 | + wasapi_input_->stop(); | |
178 | + } | |
179 | + wasapi_input_.reset(); | |
180 | + }; | |
181 | + | |
182 | + //bits_pair bits = {params.bits,params.valid_bits}; | |
183 | + //make_wave_format(form,params.sample_rate,params.channel,bits); | |
184 | + | |
185 | + try { | |
186 | + if(params.exclusive_mode) | |
187 | + { | |
188 | + if(params.event_mode){ | |
189 | + wasapi_input_.reset(new sf::wasapi_capture_exclusive_event(device_index,params)); | |
190 | + } else { | |
191 | + wasapi_input_.reset(new sf::wasapi_capture_exclusive_timer(device_index,params)); | |
192 | + }; | |
193 | + } else { | |
194 | + if(params.event_mode) | |
195 | + { | |
196 | + wasapi_input_.reset(new sf::wasapi_capture_shared_event(device_index,params)); | |
197 | + } else { | |
198 | + wasapi_input_.reset(new sf::wasapi_capture_shared_timer(device_index,params)); | |
199 | + } | |
200 | + } | |
201 | + } catch (win32_error_exception& e) | |
202 | + { | |
203 | + | |
204 | + //window_->message_box((boost::wformat(L"WASAPI初期化エラーが発生しました。設定パラメータを見なおしてください。%s") % e.error()).str(),wstring(L"WASAPI初期化エラー")); | |
205 | + throw; | |
206 | + } | |
207 | + | |
208 | + wasapi_device_manager::instance()->select_input_device(device_index); | |
209 | + wasapi_device_manager::instance()->current_input_device().params = params; | |
210 | + | |
211 | + } | |
212 | + | |
213 | + //void input_agent_t::init_buffer() | |
214 | + //{ | |
215 | + // audio_base& in(application::instance()->input_device()); | |
216 | + // for(int i = 0,size = buffer_.size();i < size;++i) | |
217 | + // { | |
218 | + // buffer_[i].reset(reinterpret_cast<uint8_t*>(_aligned_malloc(sizeof(uint8_t) * in.get_buffer_byte_size(),16))); | |
219 | + // } | |
220 | + //} | |
221 | + | |
222 | + | |
223 | +} | |
224 | + |
@@ -0,0 +1,60 @@ | ||
1 | +#pragma once | |
2 | +/* | |
3 | + ============================================================================== | |
4 | + | |
5 | + This file is part of the async | |
6 | + Copyright 2005-10 by Satoshi Fujiwara. | |
7 | + | |
8 | + async can be redistributed and/or modified under the terms of the | |
9 | + GNU General Public License, as published by the Free Software Foundation; | |
10 | + either version 2 of the License, or (at your option) any later version. | |
11 | + | |
12 | + async is distributed in the hope that it will be useful, | |
13 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | + GNU General Public License for more details. | |
16 | + | |
17 | + You should have received a copy of the GNU General Public License | |
18 | + along with async; if not, visit www.gnu.org/licenses or write to the | |
19 | + Free Software Foundation, Inc., 59 Temple Place, Suite 330, | |
20 | + Boston, MA 02111-1307 USA | |
21 | + | |
22 | + ============================================================================== | |
23 | +*/ | |
24 | +#include "agent_base.h" | |
25 | + | |
26 | +namespace sf { | |
27 | +struct input_agent_t : public agent_base | |
28 | +{ | |
29 | + input_agent_t(){}; | |
30 | + ~input_agent_t(){}; | |
31 | +// ----------------------------- | |
32 | +// WASAPI入力関係 | |
33 | +// ----------------------------- | |
34 | + enum input_status | |
35 | + { | |
36 | + status_device_config, | |
37 | + status_device_config_ok, | |
38 | + status_wait_output_active, | |
39 | + status_wait_output_active_ok, | |
40 | + status_process, | |
41 | + status_processing, | |
42 | + status_pause, | |
43 | + status_pause_ok, | |
44 | + status_exit, | |
45 | + status_error = STATUS_ERROR | |
46 | + }; | |
47 | + | |
48 | + void apply_config(int device_index,wasapi_device_manager::device_info::params_t& params); | |
49 | + //void init_buffer(); | |
50 | + | |
51 | + audio_base& device() {return *wasapi_input_.get();} | |
52 | +protected: | |
53 | + void run(); | |
54 | +private: | |
55 | + // 入力デバイスの設定・変更 | |
56 | + void apply_config_(int device_index,wasapi_device_manager::device_info::params_t& params); | |
57 | + std::unique_ptr<audio_base> wasapi_input_; | |
58 | +}; | |
59 | +} | |
60 | + |
@@ -0,0 +1,124 @@ | ||
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 "mixer_agent.h" | |
36 | +#include "dout.h" | |
37 | +#include "async_reader.h" | |
38 | + | |
39 | +using namespace std; | |
40 | + | |
41 | +namespace sf { | |
42 | + | |
43 | + | |
44 | +void mixer_agent_t::run() | |
45 | +{ | |
46 | + // TODO:ミキサーの実装 | |
47 | + // COMの初期化 | |
48 | + sf::com_initialize init(0,multi_threaded); | |
49 | + | |
50 | + // MMCSSの初期化 | |
51 | + //av_mm_thread_characteristics avmm(wstring(L"Pro Audio")); | |
52 | + //avmm.set_priority(AVRT_PRIORITY::AVRT_PRIORITY_HIGH); | |
53 | + int status; | |
54 | + application& app(*application::instance()); | |
55 | + | |
56 | + // 出力デバイスが稼働するまで待つ | |
57 | + //app.output_thread().wait_status(output_agent_t::status_processing,10); | |
58 | + // バッファ初期化 | |
59 | + //init_buffer(); | |
60 | + change_status(status_config); | |
61 | + while(status = status_.load(),status !=status_exit) | |
62 | + { | |
63 | + switch(status) | |
64 | + { | |
65 | + case status_config: | |
66 | + { | |
67 | + change_status(status_config_ok); | |
68 | + } | |
69 | + break; | |
70 | + case status_process: | |
71 | + { | |
72 | + init_buffer(); | |
73 | + change_status(status_processing); | |
74 | + } | |
75 | + case status_processing: | |
76 | + { | |
77 | + Sleep(app.output_device().get_buffer_duration() / 20000); | |
78 | + BYTE *in(0),*reader(0); | |
79 | + app.input_ringbuffer().dequeue(in); | |
80 | + app.reader_ringbuffer().dequeue(reader); | |
81 | + int size(app.output_device().get_buffer_byte_size()); | |
82 | + BYTE *dest(buffer_[index_].get()); | |
83 | + if(in != 0 && reader != 0) | |
84 | + { | |
85 | + ::CopyMemory(dest,in,size); | |
86 | + size = size / app.output_device().get_frame_size(); | |
87 | + WORD *destw((WORD*)dest),*srcw((WORD*)reader); | |
88 | + for(int i = 0;i < size;++i) | |
89 | + { | |
90 | + *destw++ += *srcw++; | |
91 | + *destw++ += *srcw++; | |
92 | + } | |
93 | + } else if(in != 0) | |
94 | + { | |
95 | + ::CopyMemory(dest,in,size); | |
96 | + } else if(reader != 0) | |
97 | + { | |
98 | + ::CopyMemory(dest,reader,size); | |
99 | + } else { | |
100 | + ::ZeroMemory(dest,size); | |
101 | + } | |
102 | + | |
103 | + while(!ringbuffer_.enqueue(buffer_[index_].get())) | |
104 | + { | |
105 | + Sleep(app.output_device().get_buffer_duration() / 20000); | |
106 | + } | |
107 | + | |
108 | + index_ = (index_ + 1) & (buffer_.size() -1 ); | |
109 | + | |
110 | + } | |
111 | + break; | |
112 | + case status_pause: | |
113 | + change_status(status_pause_ok); | |
114 | + break; | |
115 | + default: | |
116 | + wait_event(); | |
117 | +// WaitForSingleObject(event_.get(),WAIT_TIMEOUT_DEFAULT); | |
118 | + } | |
119 | + } | |
120 | + DOUT(L"***** mixerは終了!" << std::endl); | |
121 | + agent::done(); | |
122 | +} | |
123 | +} | |
124 | + |
@@ -0,0 +1,47 @@ | ||
1 | +#pragma once | |
2 | +/* | |
3 | + ============================================================================== | |
4 | + | |
5 | + This file is part of the async | |
6 | + Copyright 2005-10 by Satoshi Fujiwara. | |
7 | + | |
8 | + async can be redistributed and/or modified under the terms of the | |
9 | + GNU General Public License, as published by the Free Software Foundation; | |
10 | + either version 2 of the License, or (at your option) any later version. | |
11 | + | |
12 | + async is distributed in the hope that it will be useful, | |
13 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | + GNU General Public License for more details. | |
16 | + | |
17 | + You should have received a copy of the GNU General Public License | |
18 | + along with async; if not, visit www.gnu.org/licenses or write to the | |
19 | + Free Software Foundation, Inc., 59 Temple Place, Suite 330, | |
20 | + Boston, MA 02111-1307 USA | |
21 | + | |
22 | + ============================================================================== | |
23 | +*/ | |
24 | +#include "agent_base.h" | |
25 | + | |
26 | +namespace sf { | |
27 | +struct mixer_agent_t : public agent_base | |
28 | +{ | |
29 | + mixer_agent_t(){}; | |
30 | + ~mixer_agent_t(){}; | |
31 | + enum mixer_status | |
32 | + { | |
33 | + status_config, | |
34 | + status_config_ok, | |
35 | + status_process, | |
36 | + status_processing, | |
37 | + status_pause, | |
38 | + status_pause_ok, | |
39 | + status_exit, | |
40 | + status_error = STATUS_ERROR | |
41 | + }; | |
42 | +protected: | |
43 | + void run(); | |
44 | +private: | |
45 | +}; | |
46 | +} | |
47 | + |
@@ -0,0 +1,301 @@ | ||
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 "dout.h" | |
36 | +#include "async_reader.h" | |
37 | +#include "output_agent.h" | |
38 | + | |
39 | + | |
40 | +using namespace std; | |
41 | +using namespace boost; | |
42 | + | |
43 | +namespace sf { | |
44 | + | |
45 | + /// WASAPI出力スレッド | |
46 | + void output_agent_t::run() | |
47 | + { | |
48 | + // COMの初期化 | |
49 | + sf::com_initialize init(0,multi_threaded); | |
50 | + | |
51 | + // MMCSSの初期化 | |
52 | + sf::av_mm_thread_characteristics avmm(wstring(L"Pro Audio")); | |
53 | + avmm.set_priority(AVRT_PRIORITY_HIGH); | |
54 | + //apply_config_( | |
55 | + // wasapi_device_manager::instance()->current_output_device_index(), | |
56 | + // wasapi_device_manager::instance()->current_output_device().params); | |
57 | + BYTE* reader_buffer,*input_buffer,*mix_buffer; | |
58 | + uint32_t status; | |
59 | + size_t size_of_buffer = 0; | |
60 | + size_t remaining_of_buffer = 0; | |
61 | + BYTE* wasapi_buffer = 0; | |
62 | + size_t remaining_of_wasapi_buffer = 0; | |
63 | + memory_block_t mix_work; | |
64 | + | |
65 | + bool wasapi_ready = false; | |
66 | + | |
67 | + //if(wasapi_output_->is_enabled()) | |
68 | + //{ | |
69 | + // change_status(status_processing); | |
70 | + //} else { | |
71 | + change_status(status_device_config); | |
72 | + //} | |
73 | + | |
74 | + application& app(*application::instance()); | |
75 | + | |
76 | + | |
77 | + while(status = status_.load(std::memory_order_acquire), (status != status_exit )) | |
78 | + { | |
79 | + try { | |
80 | + switch (status) | |
81 | + { | |
82 | + case status_device_config: | |
83 | + // 出力デバイスの変更 | |
84 | + if(wasapi_output_ && wasapi_output_->is_start()) | |
85 | + { | |
86 | + wasapi_output_->stop(); | |
87 | + } | |
88 | + remaining_of_buffer = 0; | |
89 | + change_status(status_device_config_ok); | |
90 | + break; | |
91 | + case status_process: | |
92 | + mix_work.reset(reinterpret_cast<BYTE*>(_aligned_malloc(sizeof(uint8_t) * wasapi_output_->get_buffer_byte_size(),16))); | |
93 | + change_status(status_processing); | |
94 | + // fall through | |
95 | + case status_processing: | |
96 | + { | |
97 | + size_of_buffer = wasapi_output_->get_buffer_size(); | |
98 | + assert(wasapi_output_->is_enabled()); | |
99 | + // 処理されたバイト数 | |
100 | + if(remaining_of_buffer == 0) // データ残り0なら | |
101 | + { | |
102 | + //リングバッファから新たにデータを読み込む | |
103 | + //if(!app.mixer_ringbuffer().dequeue(reader_buffer)) // 読み込めない場合 | |
104 | + int size = wasapi_output_->get_buffer_byte_size(); | |
105 | + if(!app.reader_ringbuffer().dequeue(reader_buffer)) reader_buffer = 0; | |
106 | + if(!app.input_ringbuffer().dequeue(input_buffer)) input_buffer = 0; | |
107 | + if(input_buffer != 0 && reader_buffer != 0) | |
108 | + { | |
109 | + ::CopyMemory(mix_work.get(),input_buffer,size); | |
110 | + size = size / app.output_device().get_frame_size(); | |
111 | + WORD *destw((WORD*)mix_work.get()),*srcw((WORD*)reader_buffer); | |
112 | + for(int i = 0;i < size;++i) | |
113 | + { | |
114 | + *destw++ += *srcw++; | |
115 | + *destw++ += *srcw++; | |
116 | + } | |
117 | + } else if(input_buffer != 0) | |
118 | + { | |
119 | + ::CopyMemory(mix_work.get(),input_buffer,size); | |
120 | + } else if(reader_buffer != 0) | |
121 | + { | |
122 | + ::CopyMemory(mix_work.get(),reader_buffer,size); | |
123 | + } else { | |
124 | + get_buffer g(*wasapi_output_.get(),size_of_buffer); | |
125 | + if(g.size() != 0){ | |
126 | + ::ZeroMemory(g.get(),g.size_byte()); | |
127 | + } | |
128 | + goto copy_end; | |
129 | + } | |
130 | + mix_buffer = mix_work.get(); | |
131 | + remaining_of_buffer = size_of_buffer; | |
132 | + } | |
133 | + | |
134 | + // WASAPIからバッファアドレスを取得する | |
135 | + { get_buffer g(*wasapi_output_.get(),size_of_buffer); | |
136 | + wasapi_buffer = g; | |
137 | + remaining_of_wasapi_buffer = g.size();// バッファのサイズ必ずしも | |
138 | + // 要求したバイトが取得できるとはかぎらない | |
139 | + | |
140 | + if(remaining_of_buffer == remaining_of_wasapi_buffer) | |
141 | + { | |
142 | + // バッファの残りとWASAPIバッファの残りが同じとき | |
143 | + const uint32_t size_copy(remaining_of_wasapi_buffer * wasapi_output_->get_frame_size()); | |
144 | + ::CopyMemory(wasapi_buffer,mix_buffer,size_copy); | |
145 | + remaining_of_buffer = 0; | |
146 | + remaining_of_wasapi_buffer = 0; | |
147 | + } else if(remaining_of_buffer > remaining_of_wasapi_buffer) | |
148 | + { | |
149 | + // バッファの残り>WASAPIバッファの残り | |
150 | + const uint32_t size_copy(remaining_of_wasapi_buffer * wasapi_output_->get_frame_size()); | |
151 | + ::CopyMemory(wasapi_buffer,mix_buffer,size_copy); | |
152 | + mix_buffer += size_copy; | |
153 | + remaining_of_buffer -= remaining_of_wasapi_buffer; | |
154 | + remaining_of_wasapi_buffer = 0; | |
155 | + } else if(remaining_of_buffer < remaining_of_wasapi_buffer) | |
156 | + { | |
157 | + // バッファの残り<WASAPIバッファの残り | |
158 | + const uint32_t size_copy(remaining_of_buffer * wasapi_output_->get_frame_size()); | |
159 | + ::CopyMemory(wasapi_buffer,mix_buffer,size_copy); | |
160 | + wasapi_buffer += size_copy; | |
161 | + remaining_of_wasapi_buffer -= remaining_of_buffer; | |
162 | + | |
163 | + int size = wasapi_output_->get_buffer_byte_size(); | |
164 | + if(!app.reader_ringbuffer().dequeue(reader_buffer)) reader_buffer = 0; | |
165 | + if(!app.output_ringbuffer().dequeue(input_buffer)) input_buffer = 0; | |
166 | + | |
167 | + if(input_buffer != 0 && reader_buffer != 0) | |
168 | + { | |
169 | + ::CopyMemory(mix_work.get(),input_buffer,size_of_buffer); | |
170 | + size = size_of_buffer / app.output_device().get_frame_size(); | |
171 | + WORD *destw((WORD*)mix_work.get()),*srcw((WORD*)reader_buffer); | |
172 | + for(int i = 0;i < size;++i) | |
173 | + { | |
174 | + *destw++ += *srcw++; | |
175 | + *destw++ += *srcw++; | |
176 | + } | |
177 | + } else if(input_buffer != 0) | |
178 | + { | |
179 | + ::CopyMemory(mix_work.get(),input_buffer,size); | |
180 | + } else if(reader_buffer != 0) | |
181 | + { | |
182 | + ::CopyMemory(mix_work.get(),reader_buffer,size); | |
183 | + } else { | |
184 | + memset(wasapi_buffer,0,remaining_of_wasapi_buffer * wasapi_output_->get_frame_size()); | |
185 | + continue; | |
186 | + } | |
187 | + mix_buffer = mix_work.get(); | |
188 | + { | |
189 | + const uint32_t size_copy(remaining_of_wasapi_buffer * wasapi_output_->get_frame_size()); | |
190 | + ::CopyMemory(wasapi_buffer,mix_buffer,size_copy); | |
191 | + mix_buffer += size_copy; | |
192 | + remaining_of_buffer = size_of_buffer - remaining_of_wasapi_buffer; | |
193 | + } | |
194 | + } | |
195 | + } | |
196 | +copy_end: | |
197 | + if(!wasapi_output_->is_start()) | |
198 | + { | |
199 | + wasapi_output_->start(); | |
200 | + } | |
201 | + | |
202 | + if(wasapi_output_->get_current_padding() == size_of_buffer) | |
203 | + { | |
204 | + wasapi_output_->wait(); | |
205 | + } else { | |
206 | + DOUT(L"XXXX No Wait !!!! XXXX" << std::endl); | |
207 | + } | |
208 | + } | |
209 | + break; | |
210 | + default: | |
211 | + wait_event(); | |
212 | +// WaitForSingleObject(event_.get(),WAIT_TIMEOUT_DEFAULT); | |
213 | + break; | |
214 | + } | |
215 | + } catch (win32_error_exception& e) { | |
216 | + error_ = (wformat(L"出力スレッドでエラーが発生しました。:%s %x") % e.error() % e.hresult()).str(); | |
217 | + change_status(status_error); | |
218 | + } catch (...) { | |
219 | + error_ = L"出力スレッドで不明なエラーが発生しました。"; | |
220 | + change_status(status_error); | |
221 | + } | |
222 | + } | |
223 | +loop_end: | |
224 | + if(wasapi_output_){ | |
225 | + if(wasapi_output_->is_start()) | |
226 | + { | |
227 | + wasapi_output_->stop(); | |
228 | + } | |
229 | + wasapi_output_.reset(); | |
230 | + } | |
231 | + DOUT(L"***** output_threadは終了!" << std::endl); | |
232 | + agent::done(); | |
233 | + }; | |
234 | + | |
235 | + void output_agent_t::apply_config(int device_index,wasapi_device_manager::device_info::params_t& params) | |
236 | + { | |
237 | + if(status() != status_device_config_ok){ | |
238 | + change_and_wait(status_device_config,status_device_config_ok); | |
239 | + } | |
240 | + | |
241 | + apply_config_(device_index,params); | |
242 | + | |
243 | + change_and_wait(status_process,status_processing); | |
244 | + | |
245 | + //if(reader_ && status_.load() == reader_ready){ | |
246 | + // reader_->reset_data_position(); | |
247 | + // reader_index_ = 0; | |
248 | + //} | |
249 | + } | |
250 | + | |
251 | + void output_agent_t::apply_config_(int device_index,wasapi_device_manager::device_info::params_t& params) | |
252 | + { | |
253 | + | |
254 | + // assert(status_.load() == reader_stop); | |
255 | + | |
256 | + // 出力スレッドを設定変更状態にする | |
257 | + | |
258 | + WAVEFORMATEXTENSIBLE form; | |
259 | + | |
260 | + if(wasapi_output_) | |
261 | + { | |
262 | + if(wasapi_output_->is_start()) | |
263 | + { | |
264 | + wasapi_output_->stop(); | |
265 | + } | |
266 | + wasapi_output_.reset(); | |
267 | + }; | |
268 | + | |
269 | + try { | |
270 | + if(params.exclusive_mode) | |
271 | + { | |
272 | + if(params.event_mode){ | |
273 | + wasapi_output_.reset(new sf::wasapi_exclusive_event(device_index,params)); | |
274 | + } else { | |
275 | + wasapi_output_.reset(new sf::wasapi_exclusive_timer(device_index,params)); | |
276 | + }; | |
277 | + } else { | |
278 | + if(params.event_mode) | |
279 | + { | |
280 | + wasapi_output_.reset(new sf::wasapi_shared_event(device_index,params)); | |
281 | + } else { | |
282 | + wasapi_output_.reset(new sf::wasapi_shared_timer(device_index,params)); | |
283 | + } | |
284 | + } | |
285 | + } catch (win32_error_exception& e) | |
286 | + { | |
287 | + | |
288 | + //window_->message_box((boost::wformat(L"WASAPI初期化エラーが発生しました。設定パラメータを見なおしてください。%s") % e.error()).str(),wstring(L"WASAPI初期化エラー")); | |
289 | + throw; | |
290 | + } | |
291 | + | |
292 | + wasapi_device_manager::instance()->select_output_device(device_index); | |
293 | + wasapi_device_manager::instance()->current_output_device().params = params; | |
294 | + | |
295 | + // バッファのアロケート | |
296 | + init_buffer(); | |
297 | + | |
298 | + | |
299 | + } | |
300 | +} | |
301 | + |
@@ -0,0 +1,69 @@ | ||
1 | +#pragma once | |
2 | +/* | |
3 | + ============================================================================== | |
4 | + | |
5 | + This file is part of the async | |
6 | + Copyright 2005-10 by Satoshi Fujiwara. | |
7 | + | |
8 | + async can be redistributed and/or modified under the terms of the | |
9 | + GNU General Public License, as published by the Free Software Foundation; | |
10 | + either version 2 of the License, or (at your option) any later version. | |
11 | + | |
12 | + async is distributed in the hope that it will be useful, | |
13 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | + GNU General Public License for more details. | |
16 | + | |
17 | + You should have received a copy of the GNU General Public License | |
18 | + along with async; if not, visit www.gnu.org/licenses or write to the | |
19 | + Free Software Foundation, Inc., 59 Temple Place, Suite 330, | |
20 | + Boston, MA 02111-1307 USA | |
21 | + | |
22 | + ============================================================================== | |
23 | +*/ | |
24 | +#include "singleton.h" | |
25 | +#include "exception.h" | |
26 | +#include "ring_buffer.h" | |
27 | +#include "wasapi.h" | |
28 | +#include "agent_base.h" | |
29 | + | |
30 | +namespace sf { | |
31 | +struct output_agent_t : public agent_base | |
32 | +{ | |
33 | +public: | |
34 | + struct exception | |
35 | + : public sf::win32_error_exception | |
36 | + { | |
37 | + exception(uint32_t hr) : win32_error_exception(hr) {}; | |
38 | + exception() : win32_error_exception() {} ; | |
39 | + }; | |
40 | + | |
41 | + output_agent_t() {}; | |
42 | + ~output_agent_t(){}; | |
43 | + | |
44 | + | |
45 | +// ---------------------------- | |
46 | +// WASAPI出力関係 | |
47 | +// ---------------------------- | |
48 | +// 出力デバイスの設定・変更 | |
49 | + enum output_status | |
50 | + { | |
51 | + status_device_config, | |
52 | + status_device_config_ok, | |
53 | + status_process, | |
54 | + status_processing, | |
55 | + status_pause, | |
56 | + status_exit, | |
57 | + status_error = STATUS_ERROR | |
58 | + }; | |
59 | + void apply_config(int device_index,wasapi_device_manager::device_info::params_t& params); | |
60 | + audio_base& device() {return *wasapi_output_.get();} | |
61 | +protected: | |
62 | + void run(); | |
63 | +private: | |
64 | + void apply_config_(int device_index,wasapi_device_manager::device_info::params_t& params); | |
65 | + | |
66 | + std::unique_ptr<audio_base> wasapi_output_; | |
67 | +}; | |
68 | +} | |
69 | + |
@@ -0,0 +1,216 @@ | ||
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 "dout.h" | |
35 | +#include "async_reader.h" | |
36 | +#include "application.h" | |
37 | +#include "reader_agent.h" | |
38 | + | |
39 | +using namespace std; | |
40 | + | |
41 | +namespace sf { | |
42 | + | |
43 | + void reader_agent_t::run() | |
44 | + { | |
45 | + // COMの初期化 | |
46 | + sf::com_initialize init(0,multi_threaded); | |
47 | + application& app(*application::instance().get()); | |
48 | + while(true) | |
49 | + { | |
50 | + switch(status_.load(std::memory_order_acquire)) | |
51 | + { | |
52 | + case status_config: | |
53 | + change_status(status_config_ok); | |
54 | + break; | |
55 | + case status_ready: | |
56 | + DOUT(L"@@@@ reader_agent_t:ready @@@@ " << std::endl); | |
57 | + change_status(status_ready_ok); | |
58 | + break; | |
59 | + case status_exit: | |
60 | + DOUT(L"@@@@ reader_agent_t:exit @@@@ " << std::endl); | |
61 | + goto loop_end; | |
62 | + break; | |
63 | + case status_play: | |
64 | + { | |
65 | +// init_buffer(); | |
66 | + change_status(status_play_ok); | |
67 | + } | |
68 | + case status_play_ok: | |
69 | + { | |
70 | + DOUT(L"@@@@ reader_agent_t:read_file @@@@ " << std::endl); | |
71 | + audio_base& out(app.output_device()); | |
72 | + while(status_.load(std::memory_order_acquire) == status_play_ok) | |
73 | + { | |
74 | + if(reader_->more_data_available() || not_enqueue_) | |
75 | + { | |
76 | + if(!not_enqueue_){ | |
77 | + uint32_t size = reader_->data_bytes_remaining() > out.get_buffer_byte_size() | |
78 | + ? out.get_buffer_byte_size() : reader_->data_bytes_remaining(); | |
79 | + if(size == 0 && repeat_mode_) | |
80 | + { | |
81 | + reader_->reset_data_position(); | |
82 | + size = (reader_->data_bytes_remaining() > out.get_buffer_byte_size()) | |
83 | + ? out.get_buffer_byte_size() : reader_->data_bytes_remaining(); | |
84 | + } | |
85 | + | |
86 | + reader_->read_data(buffer_[index_].get(),sizeof(uint8_t) * size); | |
87 | + //reader_-> | |
88 | + | |
89 | + // ここに変換処理を入れる | |
90 | + position_ += size; | |
91 | + if(position_ > reader_->total_data_bytes() && repeat_mode_) | |
92 | + { | |
93 | + position_ -= reader_->total_data_bytes(); | |
94 | + }; | |
95 | + | |
96 | + reader_->wait(); | |
97 | + if(size < out.get_buffer_byte_size()) | |
98 | + { | |
99 | + memset(buffer_[index_].get() + size,0,out.get_buffer_byte_size() - size); | |
100 | + } | |
101 | + } | |
102 | + | |
103 | + not_enqueue_ = false; | |
104 | + | |
105 | + while(!ringbuffer_.enqueue(buffer_[index_].get())) | |
106 | + { | |
107 | + //wdout << L"++++ queue max ++++ : " << index_ << std::endl; | |
108 | + if(status_.load() != status_play_ok) | |
109 | + { | |
110 | + if(status_.load(std::memory_order_relaxed) == status_pause_ok) | |
111 | + { | |
112 | + not_enqueue_ = true; | |
113 | + } | |
114 | + break; | |
115 | + } else { | |
116 | + Sleep(1); | |
117 | + } | |
118 | + } | |
119 | + | |
120 | + ; | |
121 | + //#ifdef _DEBUG | |
122 | + // wdout << boost::wformat(L"index:%d address:%x 差分:%x") | |
123 | + // % index_ % buffer_[index_].get() | |
124 | + // % (buffer_[(index_ + 1) & (buffer_.size() - 1)].get() - buffer_[index_].get()) | |
125 | + // << std::endl; | |
126 | + //#endif | |
127 | + if(!not_enqueue_){ | |
128 | + index_ = (++index_) & (buffer_.size() - 1); | |
129 | + } | |
130 | + | |
131 | + } else { | |
132 | + status_.store(status_end); | |
133 | + break; | |
134 | + } | |
135 | + } | |
136 | + } | |
137 | + break; | |
138 | + case status_pause: | |
139 | + DOUT(boost::wformat(L"**pause** index:%d address:%x") % index_ % buffer_[index_].get() << std::endl); | |
140 | + change_status(status_pause_ok); | |
141 | + break; | |
142 | + case status_end: | |
143 | + app.reader_end(); | |
144 | + reader_->reset_data_position(); | |
145 | + ringbuffer_.reset(); | |
146 | + position_ = 0; | |
147 | + change_status(status_end_ok); | |
148 | + break; | |
149 | + case status_seek: | |
150 | + reader_->seek(position_); | |
151 | + ringbuffer_.reset(); | |
152 | + index_ = 0; | |
153 | + change_status(status_seek_ok); | |
154 | + break; | |
155 | + case status_stop: | |
156 | + DOUT(L"reader_agent_t **stop**" << std::endl); | |
157 | + reader_->reset_data_position(); | |
158 | + ringbuffer_.reset(); | |
159 | + position_ = 0; | |
160 | + change_status(status_stop_ok); | |
161 | + break; | |
162 | + default: | |
163 | + wait_event(); | |
164 | +// WaitForSingleObject(event_.get(),WAIT_TIMEOUT_DEFAULT); | |
165 | + break; | |
166 | + } | |
167 | + } | |
168 | +loop_end: | |
169 | + ; | |
170 | + DOUT(L"##### reader_agent_tは終了!" << std::endl); | |
171 | + agent::done(); | |
172 | + } | |
173 | + | |
174 | + void reader_agent_t::setup(const std::wstring& file_path) | |
175 | + { | |
176 | + change_and_wait(status_config,status_config_ok); | |
177 | + source_file_path_ = file_path; | |
178 | + reader_.reset(new async_reader(file_path,repeat_mode_)); | |
179 | + init_buffer(); | |
180 | + position_ = 0; | |
181 | + change_and_wait(status_ready,status_ready_ok); | |
182 | + }; | |
183 | + | |
184 | + void reader_agent_t::position(uint64_t pos) | |
185 | + { | |
186 | + uint64_t div = reader_->get_wave_format().Format.nChannels * reader_->get_wave_format().Format.wBitsPerSample / 8; | |
187 | + position_ = (pos / div) * div; | |
188 | + status_backup_ = status_.load(); | |
189 | + | |
190 | + change_and_wait(status_seek,status_seek_ok); | |
191 | + change_and_wait(status_backup_ - 1,status_backup_); | |
192 | + } | |
193 | + | |
194 | + void reader_agent_t::pause() | |
195 | + { | |
196 | + if(status_.load() == status_pause_ok) | |
197 | + { | |
198 | + read_file(); | |
199 | + } else { | |
200 | + change_and_wait(status_pause,status_pause_ok); | |
201 | + } | |
202 | + } | |
203 | + | |
204 | + void reader_agent_t::read_file() | |
205 | + { | |
206 | + change_and_wait(status_play,status_play_ok); | |
207 | + } | |
208 | + | |
209 | + void reader_agent_t::stop() | |
210 | + { | |
211 | + change_and_wait(status_stop,status_stop_ok); | |
212 | + } | |
213 | + | |
214 | +} | |
215 | + | |
216 | + |
@@ -0,0 +1,91 @@ | ||
1 | +#pragma once | |
2 | +/* | |
3 | + ============================================================================== | |
4 | + | |
5 | + This file is part of the async | |
6 | + Copyright 2005-10 by Satoshi Fujiwara. | |
7 | + | |
8 | + async can be redistributed and/or modified under the terms of the | |
9 | + GNU General Public License, as published by the Free Software Foundation; | |
10 | + either version 2 of the License, or (at your option) any later version. | |
11 | + | |
12 | + async is distributed in the hope that it will be useful, | |
13 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | + GNU General Public License for more details. | |
16 | + | |
17 | + You should have received a copy of the GNU General Public License | |
18 | + along with async; if not, visit www.gnu.org/licenses or write to the | |
19 | + Free Software Foundation, Inc., 59 Temple Place, Suite 330, | |
20 | + Boston, MA 02111-1307 USA | |
21 | + | |
22 | + ============================================================================== | |
23 | +*/ | |
24 | +#include "agent_base.h" | |
25 | + | |
26 | +namespace sf { | |
27 | +struct reader_agent_t : public agent_base | |
28 | +{ | |
29 | +public: | |
30 | + struct exception | |
31 | + : public sf::win32_error_exception | |
32 | + { | |
33 | + exception(uint32_t hr) : win32_error_exception(hr) {}; | |
34 | + exception() : win32_error_exception() {} ; | |
35 | + }; | |
36 | + | |
37 | + reader_agent_t() : repeat_mode_(false) {}; | |
38 | + ~reader_agent_t(){}; | |
39 | + | |
40 | + | |
41 | +// void init_buffer(buffer_t& buffer); | |
42 | + | |
43 | +//--------------------------------------- | |
44 | +// ファイル読取り関係 | |
45 | +//--------------------------------------- | |
46 | +public: | |
47 | + enum reader_status | |
48 | + { | |
49 | + status_config, | |
50 | + status_config_ok, | |
51 | + status_ready, | |
52 | + status_ready_ok, | |
53 | + status_stop, | |
54 | + status_stop_ok, | |
55 | + status_play, | |
56 | + status_play_ok, | |
57 | + status_end, | |
58 | + status_end_ok, | |
59 | + status_pause, | |
60 | + status_pause_ok, | |
61 | + status_seek, | |
62 | + status_seek_ok, | |
63 | + status_rew, | |
64 | + status_rew_ok, | |
65 | + status_ff, | |
66 | + status_ff_ok, | |
67 | + status_exit, | |
68 | + status_fail = STATUS_ERROR | |
69 | + }; | |
70 | + | |
71 | + void setup(const std::wstring& file_path); | |
72 | + void read_file(); | |
73 | + void pause(); | |
74 | + void stop(); | |
75 | + uint64_t position() { return position_;}; | |
76 | + void position(uint64_t pos); | |
77 | + uint64_t size() { return reader_->total_data_bytes(); } | |
78 | + void repeat_mode(bool v) { repeat_mode_ = v ;reader_->repeat_mode(v);} | |
79 | + const bool repeat_mode() const {return repeat_mode_;} | |
80 | +protected: | |
81 | + void run(); | |
82 | +private: | |
83 | + std::wstring source_file_path_; | |
84 | + std::unique_ptr<async_reader> reader_; | |
85 | + uint64_t position_;//,output_counter_; | |
86 | + uint32_t status_backup_; | |
87 | + bool repeat_mode_;// リピートモード | |
88 | + bool not_enqueue_; | |
89 | +}; | |
90 | +} | |
91 | + |