kwave  18.07.70
SampleReader.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  SampleReader.cpp - stream for reading samples from a track
3  -------------------
4  begin : Apr 25 2001
5  copyright : (C) 2001 by Thomas Eschenbacher
6  email : Thomas Eschenbacher <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 
20 #include <QApplication>
21 
22 #include "libkwave/Sample.h"
23 #include "libkwave/SampleReader.h"
24 #include "libkwave/Stripe.h"
25 #include "libkwave/Utils.h"
26 #include "libkwave/memcpy.h"
27 
28 // define this for using only slow Qt array functions
29 // #define STRICTLY_QT
30 
32 #define MIN_PROGRESS_INTERVAL 500
33 
34 //***************************************************************************
36  Kwave::Stripe::List stripes)
37  :m_mode(mode), m_stripes(stripes),
38  m_src_position(stripes.left()), m_first(stripes.left()),
39  m_last(stripes.right()), m_buffer(blockSize()),
40  m_buffer_used(0), m_buffer_position(0),
41  m_progress_time(), m_last_seek_pos(stripes.right())
42 {
43  m_progress_time.start();
44 }
45 
46 //***************************************************************************
48 {
49 }
50 
51 //***************************************************************************
53 {
55  m_buffer_used = 0;
57 
58  emit proceeded();
59 }
60 
61 //***************************************************************************
62 static inline void padBuffer(Kwave::SampleArray &buffer,
63  unsigned int offset, unsigned int len)
64 {
65 #ifdef STRICTLY_QT
66  while (len--)
67  buffer[offset++] = 0;
68 #else
69  memset((&buffer[offset]), 0x00,
70  len * sizeof(const_cast<const Kwave::SampleArray &>(buffer)[0]));
71 #endif
72 }
73 
74 //***************************************************************************
76 {
77  Q_ASSERT(m_buffer_position >= m_buffer_used);
78  m_buffer_used = 0;
80  if (eof()) return;
81  if (m_buffer.isEmpty()) return; // we had a OOM before?
82 
83  unsigned int rest = m_buffer.size();/* - m_buffer_used (is 0) */
84  if (m_src_position + rest > m_last)
85  rest = Kwave::toUint(m_last - m_src_position + 1);
86  Q_ASSERT(rest <= m_buffer.size());
87  if (rest > m_buffer.size()) rest = m_buffer.size();
88  Q_ASSERT(rest);
89 
90  unsigned int len = readSamples(m_src_position, m_buffer, 0, rest);
91  Q_ASSERT(len == rest);
92  m_buffer_used += len;
93 
94  // inform others that we proceeded
95  if (m_progress_time.elapsed() > MIN_PROGRESS_INTERVAL) {
96  m_progress_time.restart();
97  emit proceeded();
98  QApplication::sendPostedEvents();
99  }
100 }
101 
102 //***************************************************************************
104  sample_t &min, sample_t &max)
105 {
106  bool empty = true;
107  min = SAMPLE_MAX;
108  max = SAMPLE_MIN;
109 
110  foreach (Kwave::Stripe s, m_stripes) {
111  if (!s.length()) continue;
112  sample_index_t start = s.start();
113  sample_index_t end = s.end();
114 
115  if (end < first) continue; // not yet in range
116  if (start > last) break; // done
117 
118  // overlap -> not empty
119  empty = false;
120 
121  // get min/max from the stripe
122  unsigned int s1 = Kwave::toUint(
123  (first > start) ? (first - start) : 0);
124  unsigned int s2 = Kwave::toUint(
125  (last < end) ? (last - start) : (end - start));
126  s.minMax(s1, s2, min, max);
127  }
128 
129  // special case: no signal in that range -> set to zero
130  if (empty) {
131  min = 0;
132  max = 0;
133  }
134 }
135 
136 //***************************************************************************
138  unsigned int dstoff,
139  unsigned int length)
140 {
141  if (eof() || !length) return 0; // already done or nothing to do
142 
143  // just a sanity check
144  Q_ASSERT(buffer.size());
145  Q_ASSERT(dstoff < buffer.size());
146  if (dstoff >= buffer.size()) return 0;
147 
148  unsigned int count = 0;
149  unsigned int rest = length;
150  if (dstoff + rest > buffer.size()) rest = buffer.size() - dstoff;
151  Q_ASSERT(rest);
152  if (!rest) return 0;
153 
154  // first try to read from the current buffer
156  unsigned int cnt = rest;
157  unsigned int src = m_buffer_position;
158  unsigned int dst = dstoff;
159 
160  if (m_buffer_position + cnt > m_buffer_used)
162 
163  m_buffer_position += cnt;
164  count += cnt;
165  rest -= cnt;
166  dstoff += cnt;
167  qDebug("filling from buffer dstoff=%u, cnt=%u",dstoff,cnt);
168 #ifdef STRICTLY_QT
169  while (cnt--) {
170  buffer[dst++] = m_buffer[src++];
171  }
172 #else
173  const Kwave::SampleArray &in = m_buffer;
174  MEMCPY(&(buffer[dst]), &(in[src]), cnt * sizeof(sample_t));
175 #endif
176 
177  if (m_buffer_position >= m_buffer_used) {
178  // buffer is empty now
179  m_buffer_position = m_buffer_used = 0;
180  }
181 
182  if (!rest) {
183  // inform others that we proceeded
184  if (m_progress_time.elapsed() > MIN_PROGRESS_INTERVAL) {
185  m_progress_time.restart();
186  emit proceeded();
187  QApplication::sendPostedEvents();
188  }
189  return count; // done
190  }
191  }
192 
193  // take the rest directly out of the stripe(s)
194  if (m_src_position + rest > (m_last + 1)) // clip to end of reader range
195  rest = Kwave::toUint((m_last + 1) - m_src_position);
196  if (dstoff + rest > buffer.size()) // clip to end of buffer
197  rest = buffer.size() - dstoff;
198  Q_ASSERT(dstoff + rest <= buffer.size());
199  unsigned int len = readSamples(m_src_position, buffer, dstoff, rest);
200  Q_ASSERT(len == rest);
201  count += len;
202 
203  // inform others that we proceeded
204  if (m_progress_time.elapsed() > MIN_PROGRESS_INTERVAL) {
205  m_progress_time.restart();
206  emit proceeded();
207  QApplication::sendPostedEvents();
208  }
209  return count;
210 }
211 
212 //***************************************************************************
214 {
215  if (m_buffer_position + count < m_buffer_used) {
216  // skip within the buffer
217  m_buffer_position += count;
218  } else {
219  // skip out of the buffer
220  count -= m_buffer_used;
221  m_src_position += count;
223  }
224 
225  // if this reader is of "single pass forward only" type: remove all
226  // stripes that we have passed -> there is no way back!
228  while (!m_stripes.isEmpty() &&
229  (m_stripes.first().end() < m_src_position))
230  {
231  m_stripes.removeFirst();
232  }
233  }
234 }
235 
236 //***************************************************************************
238 {
239  const sample_index_t current_pos = m_src_position +
241 
242  if (pos == current_pos) return; // nothing to do
243 
244  if (pos < current_pos) {
245  // if we are in SinglePassReverse mode, discard all stripes
246  // that we already have passed, up to the end
248  while (!m_stripes.isEmpty() &&
249  (m_stripes.last().start() > m_last_seek_pos))
250  {
251 // qDebug("SampleReader: removing stripe [%9u ... %9u] (end=%9u)",
252 // m_stripes.last().start(),
253 // m_stripes.last().end(),
254 // m_last_seek_pos);
255  m_stripes.removeLast();
256  }
257  }
258 
259  // seek backwards
260  const sample_index_t count = current_pos - pos;
261  if (count <= m_buffer_position) {
262  // go back within the buffer
263  m_buffer_position -= count;
264  } else {
265  // skip out of the buffer
267  m_buffer_position = m_buffer_used = 0;
268  }
269  } else {
270  // seek forward
271  skip(pos - current_pos);
272  }
273 
275 }
276 
277 //***************************************************************************
279 {
280  // get new buffer if end of last buffer reached
282  const Kwave::SampleArray &buffer = m_buffer;
283  sample = (m_buffer_position < m_buffer_used) ?
284  buffer[m_buffer_position++] : 0;
285  return *this;
286 }
287 
288 //***************************************************************************
290  Kwave::SampleArray &buffer)
291 {
292  unsigned int size = buffer.size();
293  unsigned int count = read(buffer, 0, size);
294  if (count != size) {
295  bool ok = buffer.resize(count);
296  Q_ASSERT(ok); // shrinking should always be possible
297  if (!ok) {
298  qWarning("Kwave::SampleReader::operator >> - OOM?");
299  }
300  }
301  return *this;
302 }
303 
304 //***************************************************************************
306 {
307  Kwave::SampleArray buffer(blockSize());
308  (*this) >> buffer;
309  emit output(buffer);
310 }
311 
312 //***************************************************************************
314  Kwave::SampleArray &buffer,
315  unsigned int buf_offset,
316  unsigned int length)
317 {
318  Q_ASSERT(length);
319  if (!length) return 0; // nothing to do !?
320  Q_ASSERT(buf_offset + length <= buffer.size());
321 
322  unsigned int rest = length;
323  sample_index_t left = offset;
324  sample_index_t right = offset + length - 1;
325 
326  foreach (Kwave::Stripe s, m_stripes) {
327  if (!s.length()) continue;
328  sample_index_t start = s.start();
329  sample_index_t end = s.end();
330 
331  if (left < start) {
332  // gap before the stripe -> pad
333  sample_index_t pad = Kwave::toUint(start - left);
334  if (pad > rest) pad = rest;
335  padBuffer(buffer, buf_offset, Kwave::toUint(pad));
336  buf_offset += pad;
337  rest -= pad;
338  left += pad;
339  if (!rest) break;
340  }
341 
342  if (start > right) break; // done, we are after the range
343 
344  if (left <= end) {
345  // some kind of overlap
346  Q_ASSERT(left >= start);
347  unsigned int ofs = Kwave::toUint(left - start);
348  unsigned int len = Kwave::toUint(end - left + 1);
349  if (len > rest) len = rest;
350  unsigned int count = s.read(buffer, buf_offset, ofs, len);
351  Q_ASSERT(count == len);
352  buf_offset += count;
353  rest -= count;
354  left += count;
355  if (!rest) break;
356  }
357  }
358 
359  // pad at the end
360  if (rest) padBuffer(buffer, buf_offset, rest);
361 
362  m_src_position += length;
363 
364  // if this reader is of "single pass forward only" type: remove all
365  // stripes that we have passed -> there is no way back!
367  while (!m_stripes.isEmpty() &&
368  (m_stripes.first().end() < m_src_position))
369  {
370  m_stripes.removeFirst();
371  }
372  }
373 
374  return length;
375 }
376 
377 //***************************************************************************
378 //***************************************************************************
sample_index_t m_last
Definition: SampleReader.h:187
unsigned int length() const
Definition: Stripe.cpp:276
ReaderMode
Definition: ReaderMode.h:27
void skip(sample_index_t count)
virtual void goOn() Q_DECL_OVERRIDE
unsigned int read(Kwave::SampleArray &buffer, unsigned int dstoff, unsigned int offset, unsigned int length)
Definition: Stripe.cpp:502
sample_index_t m_first
Definition: SampleReader.h:184
#define SAMPLE_MIN
Definition: Sample.h:49
unsigned int m_buffer_position
Definition: SampleReader.h:196
void output(Kwave::SampleArray data)
quint64 sample_index_t
Definition: Sample.h:28
sample_index_t m_src_position
Definition: SampleReader.h:181
bool eof() const
Definition: SampleReader.h:66
void seek(sample_index_t pos)
sample_index_t last() const
Definition: SampleReader.h:121
Kwave::SampleArray m_buffer
Definition: SampleReader.h:190
void minMax(sample_index_t first, sample_index_t last, sample_t &min, sample_t &max)
sample_index_t start() const
Definition: Stripe.cpp:262
sample_index_t first() const
Definition: SampleReader.h:116
sample_index_t pos() const
Definition: SampleReader.h:111
sample_index_t end() const
Definition: Stripe.cpp:282
bool isEmpty() const
Definition: SampleArray.h:118
#define MEMCPY
Definition: memcpy.h:37
QList< Kwave::Stripe > m_stripes
Definition: SampleReader.h:173
virtual unsigned int blockSize() const
#define MIN_PROGRESS_INTERVAL
#define SAMPLE_MAX
Definition: Sample.h:52
virtual ~SampleReader() Q_DECL_OVERRIDE
static void padBuffer(Kwave::SampleArray &buffer, unsigned int offset, unsigned int len)
SampleReader(Kwave::ReaderMode mode, Kwave::Stripe::List stripes)
unsigned int size() const
unsigned int read(Kwave::SampleArray &buffer, unsigned int dstoff, unsigned int length)
unsigned int toUint(T x)
Definition: Utils.h:109
SampleReader & operator>>(sample_t &sample)
unsigned int readSamples(sample_index_t offset, Kwave::SampleArray &buffer, unsigned int buf_offset, unsigned int length)
bool resize(unsigned int size) Q_REQUIRED_RESULT
unsigned int m_buffer_used
Definition: SampleReader.h:193
qint32 sample_t
Definition: Sample.h:37
void minMax(unsigned int first, unsigned int last, sample_t &min, sample_t &max)
Definition: Stripe.cpp:537
Kwave::ReaderMode m_mode
Definition: SampleReader.h:170
sample_index_t m_last_seek_pos
Definition: SampleReader.h:202