diff options
author | Matthias P. Braendli <matthias.braendli@mpb.li> | 2014-03-09 15:48:56 +0100 |
---|---|---|
committer | Matthias P. Braendli <matthias.braendli@mpb.li> | 2014-03-09 15:48:56 +0100 |
commit | 8e34d9a78752f3a7d8d49adbb219f51da4b2702e (patch) | |
tree | 26b77f0ca7a3177a9096bb116d7ead50eaa4dc9f /src/SampleQueue.h | |
parent | 6971dbeba89788773caeffc863ebe3bc5fd652f6 (diff) | |
download | ODR-AudioEnc-8e34d9a78752f3a7d8d49adbb219f51da4b2702e.tar.gz ODR-AudioEnc-8e34d9a78752f3a7d8d49adbb219f51da4b2702e.tar.bz2 ODR-AudioEnc-8e34d9a78752f3a7d8d49adbb219f51da4b2702e.zip |
Get drift-canceling encoder to work
Diffstat (limited to 'src/SampleQueue.h')
-rw-r--r-- | src/SampleQueue.h | 102 |
1 files changed, 75 insertions, 27 deletions
diff --git a/src/SampleQueue.h b/src/SampleQueue.h index eabc301..778526e 100644 --- a/src/SampleQueue.h +++ b/src/SampleQueue.h @@ -9,6 +9,8 @@ #ifndef _SAMPLE_QUEUE_H_ #define _SAMPLE_QUEUE_H_ +#define DEBUG_SAMPLE_QUEUE 0 + #include <boost/thread.hpp> #include <queue> @@ -18,10 +20,23 @@ * that pushes elements into the queue, and one consumer that * retrieves the elements. * - * The queue can make the consumer block until enough elements - * are available. + * This queue should contain audio sample data, interleaved L/R + * form, 2bytes per sample. Therefore, the push and pop functions + * should always place or retrieve data in multiples of + * bytes_per_sample * number_of_channels + * + * The queue has a maximum size. If this size is reached, push() + * ignores new data. + * + * If pop() is called but there is not enough data in the queue, + * the missing samples are replaced by zeros. pop() will always + * write the requested length. */ + +/* The template is actually not really tested for anything else + * than uint8_t + */ template<typename T> class SampleQueue { @@ -30,7 +45,9 @@ public: unsigned int channels, size_t max_size) : m_bytes_per_sample(bytes_per_sample), - m_channels(channels), m_max_size(max_size) {} + m_channels(channels), + m_max_size(max_size), + m_overruns(0) {} /* Push a bunch of samples into the buffer */ @@ -38,10 +55,18 @@ public: { boost::mutex::scoped_lock lock(m_mutex); + assert(len % (m_channels * m_bytes_per_sample) == 0); + +#if DEBUG_SAMPLE_QUEUE + fprintf(stdout, "######## push %s %zu, %zu >= %zu\n", + (m_queue.size() >= m_max_size) ? "overrun" : "ok", + len / 4, + m_queue.size() / 4, + m_max_size / 4); +#endif + if (m_queue.size() >= m_max_size) { - /*fprintf(stderr, "######## push overrun %zu, %zu\n", - len, - m_queue.size()); // */ + m_overruns++; return 0; } @@ -50,9 +75,6 @@ public: } size_t new_size = m_queue.size(); - lock.unlock(); - - //m_condition_variable.notify_one(); return new_size; } @@ -69,14 +91,36 @@ public: */ size_t pop(T* buf, size_t len) { + size_t ovr; + return pop(buf, len, ovr); + } + + /* Get len elements, place them into the buf array. + * Also update the overrun variable with the information + * of how many overruns we saw since the last pop. + * Returns the number of elements it was able to take + * from the queue + */ + size_t pop(T* buf, size_t len, size_t* overruns) + { boost::mutex::scoped_lock lock(m_mutex); - fprintf(stderr, "######## pop %zu (%zu)\n", - len, - m_queue.size()); + + assert(len % (m_channels * m_bytes_per_sample) == 0); + +#if DEBUG_SAMPLE_QUEUE + fprintf(stdout, "######## pop %zu (%zu), %zu overruns: ", + len / 4, + m_queue.size() / 4, + m_overruns); +#endif + *overruns = m_overruns; + m_overruns = 0; size_t ret = 0; if (m_queue.size() < len) { + /* Not enough data in queue, fill with zeros */ + size_t i; for (i = 0; i < m_queue.size(); i++) { buf[i] = m_queue[i]; @@ -89,8 +133,16 @@ public: } m_queue.resize(0); + +#if DEBUG_SAMPLE_QUEUE + fprintf(stdout, "after short pop %zu (%zu)\n", + len / 4, + m_queue.size() / 4); +#endif } else { + /* Queue contains enough data */ + for (size_t i = 0; i < len; i++) { buf[i] = m_queue[i]; } @@ -98,33 +150,29 @@ public: ret = len; m_queue.erase(m_queue.begin(), m_queue.begin() + len); - } - - return ret; - } - /* - void wait_and_pop(T& popped_value) - { - boost::mutex::scoped_lock lock(m_mutex); - while(m_queue.size() < m_required_size) - { - m_condition_variable.wait(lock); +#if DEBUG_SAMPLE_QUEUE + fprintf(stdout, "after ok pop %zu (%zu)\n", + len / 4, + m_queue.size() / 4); +#endif } - popped_value = m_queue.front(); - m_queue.pop_front(); + return ret; } - */ private: std::deque<T> m_queue; mutable boost::mutex m_mutex; - //boost::condition_variable m_condition_variable; unsigned int m_channels; unsigned int m_bytes_per_sample; size_t m_max_size; + + /* Counter to keep track of number of overruns between calls + * to pop() + */ + size_t m_overruns; }; #endif |