SDRAngel  4.11.5
Developer docs for <a href="https://github.com/f4exb/sdrangel">SDRangel<\a>, an Open Source Qt5 / OpenGL 3.0+ SDR and signal analyzer frontend to various hardware.
samplesinkfifo.cpp
Go to the documentation of this file.
1  // Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany //
3 // written by Christian Daniel //
4 // //
5 // This program is free software; you can redistribute it and/or modify //
6 // it under the terms of the GNU General Public License as published by //
7 // the Free Software Foundation as version 3 of the License, or //
8 // (at your option) any later version. //
9 // //
10 // This program is distributed in the hope that it will be useful, //
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of //
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
13 // GNU General Public License V3 for more details. //
14 // //
15 // You should have received a copy of the GNU General Public License //
16 // along with this program. If not, see <http://www.gnu.org/licenses/>. //
18 
19 #include "samplesinkfifo.h"
20 
21 #define MIN(x, y) (((x) < (y)) ? (x) : (y))
22 
24 {
25  m_size = 0;
26  m_fill = 0;
27  m_head = 0;
28  m_tail = 0;
29 
30  m_data.resize(s);
31  m_size = m_data.size();
32 
33  if(m_size != s)
34  qCritical("SampleSinkFifo: out of memory");
35 }
36 
38  QObject(parent),
39  m_data()
40 {
41  m_suppressed = -1;
42  m_size = 0;
43  m_fill = 0;
44  m_head = 0;
45  m_tail = 0;
46 }
47 
48 SampleSinkFifo::SampleSinkFifo(int size, QObject* parent) :
49  QObject(parent),
50  m_data()
51 {
52  m_suppressed = -1;
53 
54  create(size);
55 }
56 
58  QObject(other.parent()),
59  m_data(other.m_data)
60 {
61  m_suppressed = -1;
62  m_size = m_data.size();
63  m_fill = 0;
64  m_head = 0;
65  m_tail = 0;
66 }
67 
69 {
70  QMutexLocker mutexLocker(&m_mutex);
71 
72  m_size = 0;
73 }
74 
76 {
77  create(size);
78 
79  return m_data.size() == (uint)size;
80 }
81 
82 uint SampleSinkFifo::write(const quint8* data, uint count)
83 {
84  QMutexLocker mutexLocker(&m_mutex);
85  uint total;
86  uint remaining;
87  uint len;
88  const Sample* begin = (const Sample*)data;
89  count /= sizeof(Sample);
90 
91  total = MIN(count, m_size - m_fill);
92  if(total < count) {
93  if(m_suppressed < 0) {
94  m_suppressed = 0;
95  m_msgRateTimer.start();
96  qCritical("SampleSinkFifo: overflow - dropping %u samples", count - total);
97  } else {
98  if(m_msgRateTimer.elapsed() > 2500) {
99  qCritical("SampleSinkFifo: %u messages dropped", m_suppressed);
100  qCritical("SampleSinkFifo: overflow - dropping %u samples", count - total);
101  m_suppressed = -1;
102  } else {
103  m_suppressed++;
104  }
105  }
106  }
107 
108  remaining = total;
109  while(remaining > 0) {
110  len = MIN(remaining, m_size - m_tail);
111  std::copy(begin, begin + len, m_data.begin() + m_tail);
112  m_tail += len;
113  m_tail %= m_size;
114  m_fill += len;
115  begin += len;
116  remaining -= len;
117  }
118 
119  if(m_fill > 0)
120  emit dataReady();
121 
122  return total;
123 }
124 
125 uint SampleSinkFifo::write(SampleVector::const_iterator begin, SampleVector::const_iterator end)
126 {
127  QMutexLocker mutexLocker(&m_mutex);
128  uint count = end - begin;
129  uint total;
130  uint remaining;
131  uint len;
132 
133  total = MIN(count, m_size - m_fill);
134  if(total < count) {
135  if(m_suppressed < 0) {
136  m_suppressed = 0;
137  m_msgRateTimer.start();
138  qCritical("SampleSinkFifo: overflow - dropping %u samples", count - total);
139  } else {
140  if(m_msgRateTimer.elapsed() > 2500) {
141  qCritical("SampleSinkFifo: %u messages dropped", m_suppressed);
142  qCritical("SampleSinkFifo: overflow - dropping %u samples", count - total);
143  m_suppressed = -1;
144  } else {
145  m_suppressed++;
146  }
147  }
148  }
149 
150  remaining = total;
151  while(remaining > 0) {
152  len = MIN(remaining, m_size - m_tail);
153  std::copy(begin, begin + len, m_data.begin() + m_tail);
154  m_tail += len;
155  m_tail %= m_size;
156  m_fill += len;
157  begin += len;
158  remaining -= len;
159  }
160 
161  if(m_fill > 0)
162  emit dataReady();
163 
164  return total;
165 }
166 
167 uint SampleSinkFifo::read(SampleVector::iterator begin, SampleVector::iterator end)
168 {
169  QMutexLocker mutexLocker(&m_mutex);
170  uint count = end - begin;
171  uint total;
172  uint remaining;
173  uint len;
174 
175  total = MIN(count, m_fill);
176  if(total < count)
177  qCritical("SampleSinkFifo: underflow - missing %u samples", count - total);
178 
179  remaining = total;
180  while(remaining > 0) {
181  len = MIN(remaining, m_size - m_head);
182  std::copy(m_data.begin() + m_head, m_data.begin() + m_head + len, begin);
183  m_head += len;
184  m_head %= m_size;
185  m_fill -= len;
186  begin += len;
187  remaining -= len;
188  }
189 
190  return total;
191 }
192 
194  SampleVector::iterator* part1Begin, SampleVector::iterator* part1End,
195  SampleVector::iterator* part2Begin, SampleVector::iterator* part2End)
196 {
197  QMutexLocker mutexLocker(&m_mutex);
198  uint total;
199  uint remaining;
200  uint len;
201  uint head = m_head;
202 
203  total = MIN(count, m_fill);
204  if(total < count)
205  qCritical("SampleSinkFifo: underflow - missing %u samples", count - total);
206 
207  remaining = total;
208  if(remaining > 0) {
209  len = MIN(remaining, m_size - head);
210  *part1Begin = m_data.begin() + head;
211  *part1End = m_data.begin() + head + len;
212  head += len;
213  head %= m_size;
214  remaining -= len;
215  } else {
216  *part1Begin = m_data.end();
217  *part1End = m_data.end();
218  }
219  if(remaining > 0) {
220  len = MIN(remaining, m_size - head);
221  *part2Begin = m_data.begin() + head;
222  *part2End = m_data.begin() + head + len;
223  } else {
224  *part2Begin = m_data.end();
225  *part2End = m_data.end();
226  }
227 
228  return total;
229 }
230 
232 {
233  QMutexLocker mutexLocker(&m_mutex);
234 
235  if(count > m_fill) {
236  qCritical("SampleSinkFifo: cannot commit more than available samples");
237  count = m_fill;
238  }
239  m_head = (m_head + count) % m_size;
240  m_fill -= count;
241 
242  return count;
243 }
SampleSinkFifo(QObject *parent=nullptr)
uint write(const quint8 *data, uint count)
SampleVector m_data
uint readCommit(uint count)
bool setSize(int size)
#define MIN(x, y)
uint read(SampleVector::iterator begin, SampleVector::iterator end)
uint size() const
void create(uint s)
uint readBegin(uint count, SampleVector::iterator *part1Begin, SampleVector::iterator *part1End, SampleVector::iterator *part2Begin, SampleVector::iterator *part2End)