• R/O
  • HTTP
  • SSH
  • HTTPS

wasapi2: Commit

wasapiを実験するプロジェクトです。


Commit MetaInfo

Revision9125ee20105f02a711ab7a52563d88379e1b454f (tree)
Time2012-11-12 19:52:10
Authorsfpg <sfpg@user...>
Commitersfpg

Log Message

非同期エージェントライブラリでスレッド部分を書き換えてみた。

Change Summary

Incremental Difference

--- /dev/null
+++ b/wasapi2/agent_base.cpp
@@ -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+
--- /dev/null
+++ b/wasapi2/agent_base.h
@@ -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+}
--- /dev/null
+++ b/wasapi2/input_agent.cpp
@@ -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+
--- /dev/null
+++ b/wasapi2/input_agent.h
@@ -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+
--- /dev/null
+++ b/wasapi2/mixer_agent.cpp
@@ -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+
--- /dev/null
+++ b/wasapi2/mixer_agent.h
@@ -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+
--- /dev/null
+++ b/wasapi2/output_agent.cpp
@@ -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+
--- /dev/null
+++ b/wasapi2/output_agent.h
@@ -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+
--- /dev/null
+++ b/wasapi2/reader_agent.cpp
@@ -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+
--- /dev/null
+++ b/wasapi2/reader_agent.h
@@ -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+
Show on old repository browser