summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuo Jinghua <sunmoon1997@gmail.com>2012-11-27 12:38:48 +0800
committerLuo Jinghua <sunmoon1997@gmail.com>2012-11-27 14:20:28 +0800
commit2102c82899d1a64108f0d00ef4840edc14a5e388 (patch)
treee0af18c1b7b7b87db1d1489fdbd5fc51e4dfade5
parent6b5ecdfb9e0acdc2c22b1814b2b2718275434837 (diff)
Add an audio queue implementation
-rw-r--r--src/device_mixer.cpp83
-rw-r--r--src/device_mixer.h50
2 files changed, 133 insertions, 0 deletions
diff --git a/src/device_mixer.cpp b/src/device_mixer.cpp
index 09a640a..1529c78 100644
--- a/src/device_mixer.cpp
+++ b/src/device_mixer.cpp
@@ -311,4 +311,87 @@ namespace audiere {
m_last_r = new_r;
}
+ AudioQueue::AudioQueue(int blockSize, int queueLen)
+ {
+ m_block_size = blockSize;
+ m_max_queue_len = queueLen;
+ m_shutdown = false;
+
+ for (int i = 0; i < queueLen + 1; i++) {
+ char* buf = new char[blockSize];
+
+ m_buffer_list.push_back(AudioBuffer(buf, blockSize));
+ m_free_list.push_back(&m_buffer_list.back());
+ }
+ }
+
+ AudioQueue::~AudioQueue()
+ {
+ shutdown();
+ m_mutex.lock();
+ m_mutex.unlock();
+
+ while (!m_buffer_list.empty()) {
+ delete [] m_buffer_list.front().m_buf;
+ m_buffer_list.pop_front();
+ }
+ }
+
+ AudioBuffer* AudioQueue::get_buffer()
+ {
+ SYNCHRONIZED(m_buffer_mutex);
+ if (m_free_list.empty())
+ return 0;
+
+ AudioBuffer* buf = m_free_list.front();
+ m_free_list.pop_front();
+ return buf;
+ }
+
+ void AudioQueue::put_buffer(AudioBuffer* buffer)
+ {
+ SYNCHRONIZED(m_buffer_mutex);
+ m_free_list.push_back(buffer);
+ }
+
+ bool AudioQueue::push(AudioBuffer* buffer)
+ {
+ SYNCHRONIZED(m_mutex);
+
+ if (m_shutdown)
+ return false;
+
+ while (m_queue.size() >= size_t(m_max_queue_len)) {
+ m_cond.wait(m_mutex, 10);
+ if (m_shutdown)
+ return false;
+ }
+
+ m_queue.push_back(buffer);
+ return true;
+ }
+
+ AudioBuffer* AudioQueue::pop()
+ {
+ SYNCHRONIZED(m_mutex);
+
+ if (m_shutdown || m_queue.empty())
+ return 0;
+
+ bool donotify = m_queue.size() >= size_t(m_max_queue_len);
+
+ AudioBuffer* buf = m_queue.front();
+ m_queue.pop_front();
+ if (donotify)
+ m_cond.notify();
+ return buf;
+ }
+
+ void AudioQueue::shutdown()
+ {
+ SYNCHRONIZED(m_mutex);
+
+ m_shutdown = true;
+ m_cond.notify();
+ }
}
diff --git a/src/device_mixer.h b/src/device_mixer.h
index 8ddd674..eb2ece0 100644
--- a/src/device_mixer.h
+++ b/src/device_mixer.h
@@ -89,6 +89,56 @@ namespace audiere {
friend class MixerDevice;
};
+ class AudioBuffer {
+ public:
+ AudioBuffer()
+ : m_buf(0), m_size(0) {
+ }
+
+ AudioBuffer(char* buf, int size)
+ : m_buf(buf), m_size(size) {
+ }
+
+ AudioBuffer(const AudioBuffer& o)
+ : m_buf(o.m_buf), m_size(o.m_size) {
+ }
+
+ char* m_buf;
+ int m_size;
+ };
+
+ class AudioQueue {
+ private:
+ AudioQueue();
+ AudioQueue(const AudioQueue&);
+
+ public:
+ AudioQueue(int blockSize, int queueLen);
+ ~AudioQueue();
+
+ AudioBuffer* get_buffer();
+ void put_buffer(AudioBuffer* buffer);
+
+ bool push(AudioBuffer* buffer);
+ AudioBuffer* pop();
+
+ void shutdown();
+
+ private:
+ CondVar m_cond;
+ Mutex m_mutex;
+ std::list<AudioBuffer*> m_queue;
+
+ Mutex m_buffer_mutex;
+ std::list<AudioBuffer> m_buffer_list;
+ std::list<AudioBuffer*> m_free_list;
+
+ int m_block_size;
+ int m_max_queue_len;
+
+ bool m_shutdown;
+ };
+
}
#endif