kwave  18.07.70
SampleFIFO.cpp
Go to the documentation of this file.
1 /*************************************************************************
2  SampleFIFO.cpp - simple FIFO, tuned for sample_t
3  -------------------
4  begin : Sun Apr 11 2004
5  copyright : (C) 2004 by Thomas Eschenbacher
6  email : Thomas.Eschenbacher@gmx.de
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #include "config.h"
19 #include "libkwave/Sample.h"
20 #include "libkwave/SampleFIFO.h"
21 #include "libkwave/memcpy.h"
22 
23 //***************************************************************************
25  :m_buffer(), m_size(0), m_read_offset(0), m_lock(QMutex::Recursive)
26 {
27 }
28 
29 //***************************************************************************
31  :m_buffer(other.m_buffer), m_size(other.m_size),
33  m_lock(QMutex::Recursive)
34 {
35 }
36 
37 //***************************************************************************
39 {
40  QMutexLocker _lock(&m_lock);
41  flush();
42 }
43 
44 //***************************************************************************
46 {
47  QMutexLocker _lock(&m_lock);
48 
49  m_buffer.clear();
50  m_read_offset = 0;
51 }
52 
53 //***************************************************************************
55 {
56  if (buffer.isEmpty()) return;
57  QMutexLocker _lock(&m_lock);
58 
59  // always enqueue the new buffer
60  m_buffer.enqueue(buffer);
61 
62  if (!m_size) return; // no limit set
63 
64  // crop away whole unneeded buffers
65  while ((unlockedLength() - m_buffer.head().size()) > m_size)
66  m_buffer.dequeue();
67 }
68 
69 //***************************************************************************
71 {
72  QMutexLocker _lock(&m_lock);
73 
74  if (m_buffer.isEmpty()) return 0;
75 
76  unsigned int rest = buffer.size();
77  const unsigned int available = length();
78  if (rest > available) rest = available;
79 
80  sample_t *dst = buffer.data();
81  unsigned int read = 0;
82  while (rest && !m_buffer.isEmpty()) {
83  const Kwave::SampleArray head = m_buffer.head();
84  const sample_t *src = head.constData();
85  unsigned int src_len = head.size();
86  Q_ASSERT(src_len > m_read_offset);
87 
88  if (m_read_offset + rest >= src_len) {
89  // use the whole buffer up to it's end
90  size_t len = static_cast<size_t>(src_len - m_read_offset);
91  MEMCPY(dst, src + m_read_offset, len * sizeof(sample_t));
92  rest -= len;
93  read += len;
94  dst += len;
95  m_read_offset = 0;
96 
97  // remove the buffer from the queue
98  m_buffer.dequeue();
99  } else {
100  // use only a portion of the buffer
101  MEMCPY(dst, src + m_read_offset, rest * sizeof(sample_t));
102  read += rest;
103  m_read_offset += rest;
104  Q_ASSERT(m_read_offset < src_len);
105  rest = 0;
106  }
107  }
108 
109  return read;
110 }
111 
112 //***************************************************************************
114 {
115  unsigned int len = 0;
116  foreach (const Kwave::SampleArray &buf, m_buffer)
117  len += buf.size();
118  return len;
119 }
120 
121 //***************************************************************************
123 {
124  QMutexLocker _lock(&m_lock);
125  return unlockedLength();
126 }
127 
128 //***************************************************************************
129 void Kwave::SampleFIFO::setSize(unsigned int size)
130 {
131  QMutexLocker _lock(&m_lock);
132  m_size = size;
133 }
134 
135 //***************************************************************************
137 {
138  QMutexLocker _lock(&m_lock);
139 
140  if (!m_size) return; // no limit set
141  if (unlockedLength() <= m_size) return; // nothing to do
142 
143  // we have to throw away some samples
144  while ((unlockedLength() - m_buffer.head().size()) > m_size)
145  m_buffer.dequeue();
146  m_read_offset = 0;
147  if (unlockedLength() <= m_size) return; // nothing more to do
148 
149  // put the read offset into the next buffer
150  Q_ASSERT(unlockedLength() > m_size);
152  Q_ASSERT(unlockedLength() - m_read_offset == m_size);
153 }
154 
155 //***************************************************************************
156 //***************************************************************************
QQueue< Kwave::SampleArray > m_buffer
Definition: SampleFIFO.h:90
virtual void put(const Kwave::SampleArray &source)
Definition: SampleFIFO.cpp:54
virtual void setSize(unsigned int size)
Definition: SampleFIFO.cpp:129
sample_index_t m_read_offset
Definition: SampleFIFO.h:99
virtual unsigned int get(Kwave::SampleArray &buffer)
Definition: SampleFIFO.cpp:70
bool isEmpty() const
Definition: SampleArray.h:118
#define MEMCPY
Definition: memcpy.h:37
sample_index_t m_size
Definition: SampleFIFO.h:93
virtual void crop()
Definition: SampleFIFO.cpp:136
virtual unsigned int length()
Definition: SampleFIFO.cpp:122
virtual void flush()
Definition: SampleFIFO.cpp:45
const sample_t * constData() const
Definition: SampleArray.h:54
virtual ~SampleFIFO()
Definition: SampleFIFO.cpp:38
unsigned int size() const
sample_t * data()
Definition: SampleArray.h:62
unsigned int unlockedLength()
Definition: SampleFIFO.cpp:113
qint32 sample_t
Definition: Sample.h:37