Async 1.8.0
AsyncAudioThreadSource.h
Go to the documentation of this file.
1
27#ifndef ASYNC_AUDIO_THREAD_SOURCE_INCLUDED
28#define ASYNC_AUDIO_THREAD_SOURCE_INCLUDED
29
30
31/****************************************************************************
32 *
33 * System Includes
34 *
35 ****************************************************************************/
36
37#include <vector>
38#include <mutex>
39#include <condition_variable>
40//#include <iostream>
41
42
43/****************************************************************************
44 *
45 * Project Includes
46 *
47 ****************************************************************************/
48
49#include <AsyncApplication.h>
50#include <AsyncAudioSink.h>
51#include <AsyncAudioSource.h>
52#include <AsyncTaskRunner.h>
53
54
55/****************************************************************************
56 *
57 * Local Includes
58 *
59 ****************************************************************************/
60
61
62
63/****************************************************************************
64 *
65 * Forward declarations
66 *
67 ****************************************************************************/
68
69
70
71/****************************************************************************
72 *
73 * Namespace
74 *
75 ****************************************************************************/
76
77namespace Async
78{
79
80
81/****************************************************************************
82 *
83 * Forward declarations of classes inside of the declared namespace
84 *
85 ****************************************************************************/
86
87
88
89/****************************************************************************
90 *
91 * Defines & typedefs
92 *
93 ****************************************************************************/
94
95
96
97/****************************************************************************
98 *
99 * Exported Global Variables
100 *
101 ****************************************************************************/
102
103
104
105/****************************************************************************
106 *
107 * Class definitions
108 *
109 ****************************************************************************/
110
126{
127 public:
132
137
141 virtual ~AudioThreadSource(void)
142 {
143 assert(std::this_thread::get_id() == Async::Application::app().threadId());
144 }
145
146 /*
147 * @brief No assignment operator
148 */
150
151 protected:
161 virtual int sinkWriteSamples(const float *samples, int count)
162 {
163 {
164 std::lock_guard<std::mutex> lk(m_in_buf_mu);
165 m_flush = false;
166 m_in_buf.insert(m_in_buf.end(), samples, samples+count);
167 if (!m_pending_processing)
168 {
169 m_pending_processing = true;
170 m_runner(&AudioThreadSource::resumeOutput, this);
171 }
172 }
173 return count;
174 }
175
183 virtual void sinkFlushSamples(void)
184 {
185 {
186 std::lock_guard<std::mutex> lk(m_in_buf_mu);
187 m_flush = true;
188 if (!m_pending_processing)
189 {
190 m_pending_processing = true;
191 m_runner(&AudioThreadSource::resumeOutput, this);
192 }
193 }
194 }
195
204 {
205 std::unique_lock<std::mutex> lk(m_all_flushed_mu);
206 m_all_flushed_cond.wait(lk, [this]{ return m_all_flushed; });
207 }
208
209 private:
210 std::mutex m_in_buf_mu;
211 std::vector<float> m_in_buf;
212 std::vector<float> m_out_buf;
213 std::vector<float>::iterator m_out_buf_it = m_out_buf.begin();
214 bool m_flush = false;
215 bool m_all_flushed = true;
216 std::mutex m_all_flushed_mu;
217 std::condition_variable_any m_all_flushed_cond;
218 bool m_pending_processing = false;
219 Async::TaskRunner m_runner;
220
228 void resumeOutput(void)
229 {
230 for (;;)
231 {
232 {
233 std::lock_guard<std::mutex> lk(m_in_buf_mu);
234 m_pending_processing = false;
235 if (m_out_buf.empty() && !m_in_buf.empty())
236 {
237 m_out_buf.swap(m_in_buf);
238 m_out_buf_it = m_out_buf.begin();
239 }
240 }
241 if (!m_out_buf.empty())
242 {
243 int write_cnt = m_out_buf.end()-m_out_buf_it;
244 int cnt = AudioSource::sinkWriteSamples(&(*m_out_buf_it), write_cnt);
245 if (cnt > 0)
246 {
247 m_out_buf_it += std::min(cnt, write_cnt);
248 if (m_out_buf_it == m_out_buf.end())
249 {
250 m_out_buf.clear();
251 m_out_buf_it = m_out_buf.begin();
252 }
253 }
254 else
255 {
256 break;
257 }
258 }
259 else
260 {
261 if (m_flush)
262 {
263 {
264 std::lock_guard<std::mutex> lk(m_in_buf_mu);
265 m_flush = false;
266 }
267 {
268 std::lock_guard<std::mutex> lk(m_all_flushed_mu);
269 m_all_flushed = false;
270 }
272 }
273 break;
274 }
275 }
276 }
277
285 void allSamplesFlushed(void)
286 {
287 {
288 std::lock_guard<std::mutex> lk(m_all_flushed_mu);
289 m_all_flushed = true;
290 }
291 m_all_flushed_cond.notify_all();
292 }
293}; /* class AudioThreadSource */
294
295
296} /* namespace */
297
298#endif /* ASYNC_AUDIO_THREAD_SOURCE_INCLUDED */
299
300/*
301 * This file has not been truncated
302 */
The core class for writing asyncronous applications.
This file contains the base class for an audio sink.
This file contains the base class for an audio source.
Run tasks from the Async main thread.
static Application & app(void)
Get the one and only application instance.
The base class for an audio source.
void sinkFlushSamples(void)
int sinkWriteSamples(const float *samples, int len)
A threadsafe audio source base class.
virtual ~AudioThreadSource(void)
Destructor.
AudioThreadSource & operator=(const AudioThreadSource &)=delete
AudioThreadSource(const AudioThreadSource &)=delete
No copy constructor.
AudioThreadSource(void)
Default constructor.
virtual int sinkWriteSamples(const float *samples, int count)
Queue samples for delivery to the connected sink.
virtual void sinkFlushSamples(void)
Flush samples in the connected sink when the queue is empty.
void waitForAllSamplesFlushed(void)
Block execution until all samples have been flushed.
Run tasks from the Async main thread with automatic cleanup.
Namespace for the asynchronous programming classes.