summaryrefslogtreecommitdiffstats
path: root/src/SampleQueue.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/SampleQueue.h')
-rw-r--r--src/SampleQueue.h102
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