diff options
author | Luo Jinghua <sunmoon1997@gmail.com> | 2012-11-27 12:38:48 +0800 |
---|---|---|
committer | Luo Jinghua <sunmoon1997@gmail.com> | 2012-11-27 14:20:28 +0800 |
commit | 2102c82899d1a64108f0d00ef4840edc14a5e388 (patch) | |
tree | e0af18c1b7b7b87db1d1489fdbd5fc51e4dfade5 /src | |
parent | 6b5ecdfb9e0acdc2c22b1814b2b2718275434837 (diff) |
Add an audio queue implementation
Diffstat (limited to 'src')
-rw-r--r-- | src/device_mixer.cpp | 83 | ||||
-rw-r--r-- | src/device_mixer.h | 50 |
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 |