annotate base/RingBuffer.h @ 5:31c4ed2d5da6

* Hook up SV file i/o. You can now save and load sessions. Some problems -- gain is not reloaded correctly for waveforms, reloaded panes are not properly reconnected to the panner, and no doubt plenty of others.
author Chris Cannam
date Tue, 17 Jan 2006 17:45:55 +0000
parents d86891498eef
children 2fb933f88604
rev   line source
Chris@0 1 /* -*- c-basic-offset: 4 -*- vi:set ts=8 sts=4 sw=4: */
Chris@0 2
Chris@0 3 /*
Chris@0 4 A waveform viewer and audio annotation editor.
Chris@2 5 Chris Cannam, Queen Mary University of London, 2005-2006
Chris@0 6
Chris@0 7 This is experimental software. Not for distribution.
Chris@0 8 */
Chris@0 9
Chris@0 10 /*
Chris@0 11 This is a modified version of a source file from the
Chris@0 12 Rosegarden MIDI and audio sequencer and notation editor.
Chris@0 13 This file copyright 2000-2005 Chris Cannam.
Chris@0 14 */
Chris@0 15
Chris@0 16 #ifndef _RINGBUFFER_H_
Chris@0 17 #define _RINGBUFFER_H_
Chris@0 18
Chris@0 19 #include <sys/types.h>
Chris@0 20
Chris@0 21 #include "System.h"
Chris@0 22 #include "Scavenger.h"
Chris@0 23
Chris@0 24 //#define DEBUG_RINGBUFFER 1
Chris@0 25
Chris@0 26 #ifdef DEBUG_RINGBUFFER
Chris@0 27 #include <iostream>
Chris@0 28 #endif
Chris@0 29
Chris@0 30 /**
Chris@0 31 * RingBuffer implements a lock-free ring buffer for one writer and N
Chris@0 32 * readers, that is to be used to store a sample type T.
Chris@0 33 *
Chris@0 34 * For efficiency, RingBuffer frequently initialises samples by
Chris@0 35 * writing zeroes into their memory space, so T should normally be a
Chris@0 36 * simple type that can safely be set to zero using memset.
Chris@0 37 */
Chris@0 38
Chris@0 39 template <typename T, int N = 1>
Chris@0 40 class RingBuffer
Chris@0 41 {
Chris@0 42 public:
Chris@0 43 /**
Chris@0 44 * Create a ring buffer with room to write n samples.
Chris@0 45 *
Chris@0 46 * Note that the internal storage size will actually be n+1
Chris@0 47 * samples, as one element is unavailable for administrative
Chris@0 48 * reasons. Since the ring buffer performs best if its size is a
Chris@0 49 * power of two, this means n should ideally be some power of two
Chris@0 50 * minus one.
Chris@0 51 */
Chris@0 52 RingBuffer(size_t n);
Chris@0 53
Chris@0 54 virtual ~RingBuffer();
Chris@0 55
Chris@0 56 /**
Chris@0 57 * Return the total capacity of the ring buffer in samples.
Chris@0 58 * (This is the argument n passed to the constructor.)
Chris@0 59 */
Chris@0 60 size_t getSize() const;
Chris@0 61
Chris@0 62 /**
Chris@0 63 * Resize the ring buffer. This also empties it. Actually swaps
Chris@0 64 * in a new, larger buffer; the old buffer is scavenged after a
Chris@0 65 * seemly delay. Should be called from the write thread.
Chris@0 66 */
Chris@0 67 void resize(size_t newSize);
Chris@0 68
Chris@0 69 /**
Chris@0 70 * Lock the ring buffer into physical memory. Returns true
Chris@0 71 * for success.
Chris@0 72 */
Chris@0 73 bool mlock();
Chris@0 74
Chris@0 75 /**
Chris@0 76 * Reset read and write pointers, thus emptying the buffer.
Chris@0 77 * Should be called from the write thread.
Chris@0 78 */
Chris@0 79 void reset();
Chris@0 80
Chris@0 81 /**
Chris@0 82 * Return the amount of data available for reading by reader R, in
Chris@0 83 * samples.
Chris@0 84 */
Chris@0 85 size_t getReadSpace(int R = 0) const;
Chris@0 86
Chris@0 87 /**
Chris@0 88 * Return the amount of space available for writing, in samples.
Chris@0 89 */
Chris@0 90 size_t getWriteSpace() const;
Chris@0 91
Chris@0 92 /**
Chris@0 93 * Read n samples from the buffer, for reader R. If fewer than n
Chris@0 94 * are available, the remainder will be zeroed out. Returns the
Chris@0 95 * number of samples actually read.
Chris@0 96 */
Chris@0 97 size_t read(T *destination, size_t n, int R = 0);
Chris@0 98
Chris@0 99 /**
Chris@0 100 * Read n samples from the buffer, for reader R, adding them to
Chris@0 101 * the destination. If fewer than n are available, the remainder
Chris@0 102 * will be left alone. Returns the number of samples actually
Chris@0 103 * read.
Chris@0 104 */
Chris@0 105 size_t readAdding(T *destination, size_t n, int R = 0);
Chris@0 106
Chris@0 107 /**
Chris@0 108 * Read one sample from the buffer, for reader R. If no sample is
Chris@0 109 * available, this will silently return zero. Calling this
Chris@0 110 * repeatedly is obviously slower than calling read once, but it
Chris@0 111 * may be good enough if you don't want to allocate a buffer to
Chris@0 112 * read into.
Chris@0 113 */
Chris@0 114 T readOne(int R = 0);
Chris@0 115
Chris@0 116 /**
Chris@0 117 * Read n samples from the buffer, if available, for reader R,
Chris@0 118 * without advancing the read pointer -- i.e. a subsequent read()
Chris@0 119 * or skip() will be necessary to empty the buffer. If fewer than
Chris@0 120 * n are available, the remainder will be zeroed out. Returns the
Chris@0 121 * number of samples actually read.
Chris@0 122 */
Chris@0 123 size_t peek(T *destination, size_t n, int R = 0) const;
Chris@0 124
Chris@0 125 /**
Chris@0 126 * Read one sample from the buffer, if available, without
Chris@0 127 * advancing the read pointer -- i.e. a subsequent read() or
Chris@0 128 * skip() will be necessary to empty the buffer. Returns zero if
Chris@0 129 * no sample was available.
Chris@0 130 */
Chris@0 131 T peekOne(int R = 0) const;
Chris@0 132
Chris@0 133 /**
Chris@0 134 * Pretend to read n samples from the buffer, for reader R,
Chris@0 135 * without actually returning them (i.e. discard the next n
Chris@0 136 * samples). Returns the number of samples actually available for
Chris@0 137 * discarding.
Chris@0 138 */
Chris@0 139 size_t skip(size_t n, int R = 0);
Chris@0 140
Chris@0 141 /**
Chris@0 142 * Write n samples to the buffer. If insufficient space is
Chris@0 143 * available, not all samples may actually be written. Returns
Chris@0 144 * the number of samples actually written.
Chris@0 145 */
Chris@0 146 size_t write(const T *source, size_t n);
Chris@0 147
Chris@0 148 /**
Chris@0 149 * Write n zero-value samples to the buffer. If insufficient
Chris@0 150 * space is available, not all zeros may actually be written.
Chris@0 151 * Returns the number of zeroes actually written.
Chris@0 152 */
Chris@0 153 size_t zero(size_t n);
Chris@0 154
Chris@0 155 protected:
Chris@0 156 T *m_buffer;
Chris@0 157 volatile size_t m_writer;
Chris@0 158 volatile size_t m_readers[N];
Chris@0 159 size_t m_size;
Chris@0 160 bool m_mlocked;
Chris@0 161
Chris@0 162 static Scavenger<ScavengerArrayWrapper<T> > m_scavenger;
Chris@0 163
Chris@0 164 private:
Chris@0 165 RingBuffer(const RingBuffer &); // not provided
Chris@0 166 RingBuffer &operator=(const RingBuffer &); // not provided
Chris@0 167 };
Chris@0 168
Chris@0 169 template <typename T, int N>
Chris@0 170 Scavenger<ScavengerArrayWrapper<T> > RingBuffer<T, N>::m_scavenger;
Chris@0 171
Chris@0 172 template <typename T, int N>
Chris@0 173 RingBuffer<T, N>::RingBuffer(size_t n) :
Chris@0 174 m_buffer(new T[n + 1]),
Chris@0 175 m_writer(0),
Chris@0 176 m_size(n + 1),
Chris@0 177 m_mlocked(false)
Chris@0 178 {
Chris@0 179 #ifdef DEBUG_RINGBUFFER
Chris@0 180 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::RingBuffer(" << n << ")" << std::endl;
Chris@0 181 #endif
Chris@0 182
Chris@0 183 for (int i = 0; i < N; ++i) m_readers[i] = 0;
Chris@0 184
Chris@0 185 m_scavenger.scavenge();
Chris@0 186 }
Chris@0 187
Chris@0 188 template <typename T, int N>
Chris@0 189 RingBuffer<T, N>::~RingBuffer()
Chris@0 190 {
Chris@0 191 #ifdef DEBUG_RINGBUFFER
Chris@0 192 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::~RingBuffer" << std::endl;
Chris@0 193 #endif
Chris@0 194
Chris@0 195 if (m_mlocked) {
Chris@0 196 MUNLOCK((void *)m_buffer, m_size * sizeof(T));
Chris@0 197 }
Chris@0 198 delete[] m_buffer;
Chris@0 199
Chris@0 200 m_scavenger.scavenge();
Chris@0 201 }
Chris@0 202
Chris@0 203 template <typename T, int N>
Chris@0 204 size_t
Chris@0 205 RingBuffer<T, N>::getSize() const
Chris@0 206 {
Chris@0 207 #ifdef DEBUG_RINGBUFFER
Chris@0 208 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::getSize(): " << m_size-1 << std::endl;
Chris@0 209 #endif
Chris@0 210
Chris@0 211 return m_size - 1;
Chris@0 212 }
Chris@0 213
Chris@0 214 template <typename T, int N>
Chris@0 215 void
Chris@0 216 RingBuffer<T, N>::resize(size_t newSize)
Chris@0 217 {
Chris@0 218 #ifdef DEBUG_RINGBUFFER
Chris@0 219 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::resize(" << newSize << ")" << std::endl;
Chris@0 220 #endif
Chris@0 221
Chris@0 222 m_scavenger.scavenge();
Chris@0 223
Chris@0 224 if (m_mlocked) {
Chris@0 225 MUNLOCK((void *)m_buffer, m_size * sizeof(T));
Chris@0 226 }
Chris@0 227
Chris@0 228 m_scavenger.claim(new ScavengerArrayWrapper<T>(m_buffer));
Chris@0 229
Chris@0 230 reset();
Chris@0 231 m_buffer = new T[newSize + 1];
Chris@0 232 m_size = newSize + 1;
Chris@0 233
Chris@0 234 if (m_mlocked) {
Chris@0 235 if (MLOCK((void *)m_buffer, m_size * sizeof(T))) {
Chris@0 236 m_mlocked = false;
Chris@0 237 }
Chris@0 238 }
Chris@0 239 }
Chris@0 240
Chris@0 241 template <typename T, int N>
Chris@0 242 bool
Chris@0 243 RingBuffer<T, N>::mlock()
Chris@0 244 {
Chris@0 245 if (MLOCK((void *)m_buffer, m_size * sizeof(T))) return false;
Chris@0 246 m_mlocked = true;
Chris@0 247 return true;
Chris@0 248 }
Chris@0 249
Chris@0 250 template <typename T, int N>
Chris@0 251 void
Chris@0 252 RingBuffer<T, N>::reset()
Chris@0 253 {
Chris@0 254 #ifdef DEBUG_RINGBUFFER
Chris@0 255 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::reset" << std::endl;
Chris@0 256 #endif
Chris@0 257
Chris@0 258 m_writer = 0;
Chris@0 259 for (int i = 0; i < N; ++i) m_readers[i] = 0;
Chris@0 260 }
Chris@0 261
Chris@0 262 template <typename T, int N>
Chris@0 263 size_t
Chris@0 264 RingBuffer<T, N>::getReadSpace(int R) const
Chris@0 265 {
Chris@0 266 size_t writer = m_writer;
Chris@0 267 size_t reader = m_readers[R];
Chris@0 268 size_t space = 0;
Chris@0 269
Chris@0 270 if (writer > reader) space = writer - reader;
Chris@0 271 else space = ((writer + m_size) - reader) % m_size;
Chris@0 272
Chris@0 273 #ifdef DEBUG_RINGBUFFER
Chris@0 274 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::getReadSpace(" << R << "): " << space << std::endl;
Chris@0 275 #endif
Chris@0 276
Chris@0 277 return space;
Chris@0 278 }
Chris@0 279
Chris@0 280 template <typename T, int N>
Chris@0 281 size_t
Chris@0 282 RingBuffer<T, N>::getWriteSpace() const
Chris@0 283 {
Chris@0 284 size_t space = 0;
Chris@0 285 for (int i = 0; i < N; ++i) {
Chris@0 286 size_t here = (m_readers[i] + m_size - m_writer - 1) % m_size;
Chris@0 287 if (i == 0 || here < space) space = here;
Chris@0 288 }
Chris@0 289
Chris@0 290 #ifdef DEBUG_RINGBUFFER
Chris@0 291 size_t rs(getReadSpace()), rp(m_readers[0]);
Chris@0 292
Chris@0 293 std::cerr << "RingBuffer: write space " << space << ", read space "
Chris@0 294 << rs << ", total " << (space + rs) << ", m_size " << m_size << std::endl;
Chris@0 295 std::cerr << "RingBuffer: reader " << rp << ", writer " << m_writer << std::endl;
Chris@0 296 #endif
Chris@0 297
Chris@0 298 #ifdef DEBUG_RINGBUFFER
Chris@0 299 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::getWriteSpace(): " << space << std::endl;
Chris@0 300 #endif
Chris@0 301
Chris@0 302 return space;
Chris@0 303 }
Chris@0 304
Chris@0 305 template <typename T, int N>
Chris@0 306 size_t
Chris@0 307 RingBuffer<T, N>::read(T *destination, size_t n, int R)
Chris@0 308 {
Chris@0 309 #ifdef DEBUG_RINGBUFFER
Chris@0 310 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::read(dest, " << n << ", " << R << ")" << std::endl;
Chris@0 311 #endif
Chris@0 312
Chris@0 313 size_t available = getReadSpace(R);
Chris@0 314 if (n > available) {
Chris@0 315 #ifdef DEBUG_RINGBUFFER
Chris@0 316 std::cerr << "WARNING: Only " << available << " samples available"
Chris@0 317 << std::endl;
Chris@0 318 #endif
Chris@0 319 memset(destination + available, 0, (n - available) * sizeof(T));
Chris@0 320 n = available;
Chris@0 321 }
Chris@0 322 if (n == 0) return n;
Chris@0 323
Chris@0 324 size_t here = m_size - m_readers[R];
Chris@0 325 if (here >= n) {
Chris@0 326 memcpy(destination, m_buffer + m_readers[R], n * sizeof(T));
Chris@0 327 } else {
Chris@0 328 memcpy(destination, m_buffer + m_readers[R], here * sizeof(T));
Chris@0 329 memcpy(destination + here, m_buffer, (n - here) * sizeof(T));
Chris@0 330 }
Chris@0 331
Chris@0 332 m_readers[R] = (m_readers[R] + n) % m_size;
Chris@0 333
Chris@0 334 #ifdef DEBUG_RINGBUFFER
Chris@0 335 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::read: read " << n << ", reader now " << m_readers[R] << std::endl;
Chris@0 336 #endif
Chris@0 337
Chris@0 338 return n;
Chris@0 339 }
Chris@0 340
Chris@0 341 template <typename T, int N>
Chris@0 342 size_t
Chris@0 343 RingBuffer<T, N>::readAdding(T *destination, size_t n, int R)
Chris@0 344 {
Chris@0 345 #ifdef DEBUG_RINGBUFFER
Chris@0 346 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::readAdding(dest, " << n << ", " << R << ")" << std::endl;
Chris@0 347 #endif
Chris@0 348
Chris@0 349 size_t available = getReadSpace(R);
Chris@0 350 if (n > available) {
Chris@0 351 #ifdef DEBUG_RINGBUFFER
Chris@0 352 std::cerr << "WARNING: Only " << available << " samples available"
Chris@0 353 << std::endl;
Chris@0 354 #endif
Chris@0 355 n = available;
Chris@0 356 }
Chris@0 357 if (n == 0) return n;
Chris@0 358
Chris@0 359 size_t here = m_size - m_readers[R];
Chris@0 360
Chris@0 361 if (here >= n) {
Chris@0 362 for (size_t i = 0; i < n; ++i) {
Chris@0 363 destination[i] += (m_buffer + m_readers[R])[i];
Chris@0 364 }
Chris@0 365 } else {
Chris@0 366 for (size_t i = 0; i < here; ++i) {
Chris@0 367 destination[i] += (m_buffer + m_readers[R])[i];
Chris@0 368 }
Chris@0 369 for (size_t i = 0; i < (n - here); ++i) {
Chris@0 370 destination[i + here] += m_buffer[i];
Chris@0 371 }
Chris@0 372 }
Chris@0 373
Chris@0 374 m_readers[R] = (m_readers[R] + n) % m_size;
Chris@0 375 return n;
Chris@0 376 }
Chris@0 377
Chris@0 378 template <typename T, int N>
Chris@0 379 T
Chris@0 380 RingBuffer<T, N>::readOne(int R)
Chris@0 381 {
Chris@0 382 #ifdef DEBUG_RINGBUFFER
Chris@0 383 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::readOne(" << R << ")" << std::endl;
Chris@0 384 #endif
Chris@0 385
Chris@0 386 if (m_writer == m_readers[R]) {
Chris@0 387 #ifdef DEBUG_RINGBUFFER
Chris@0 388 std::cerr << "WARNING: No sample available"
Chris@0 389 << std::endl;
Chris@0 390 #endif
Chris@0 391 T t;
Chris@0 392 memset(&t, 0, sizeof(T));
Chris@0 393 return t;
Chris@0 394 }
Chris@0 395 T value = m_buffer[m_readers[R]];
Chris@0 396 if (++m_readers[R] == m_size) m_readers[R] = 0;
Chris@0 397 return value;
Chris@0 398 }
Chris@0 399
Chris@0 400 template <typename T, int N>
Chris@0 401 size_t
Chris@0 402 RingBuffer<T, N>::peek(T *destination, size_t n, int R) const
Chris@0 403 {
Chris@0 404 #ifdef DEBUG_RINGBUFFER
Chris@0 405 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::peek(dest, " << n << ", " << R << ")" << std::endl;
Chris@0 406 #endif
Chris@0 407
Chris@0 408 size_t available = getReadSpace(R);
Chris@0 409 if (n > available) {
Chris@0 410 #ifdef DEBUG_RINGBUFFER
Chris@0 411 std::cerr << "WARNING: Only " << available << " samples available"
Chris@0 412 << std::endl;
Chris@0 413 #endif
Chris@0 414 memset(destination + available, 0, (n - available) * sizeof(T));
Chris@0 415 n = available;
Chris@0 416 }
Chris@0 417 if (n == 0) return n;
Chris@0 418
Chris@0 419 size_t here = m_size - m_readers[R];
Chris@0 420 if (here >= n) {
Chris@0 421 memcpy(destination, m_buffer + m_readers[R], n * sizeof(T));
Chris@0 422 } else {
Chris@0 423 memcpy(destination, m_buffer + m_readers[R], here * sizeof(T));
Chris@0 424 memcpy(destination + here, m_buffer, (n - here) * sizeof(T));
Chris@0 425 }
Chris@0 426
Chris@0 427 #ifdef DEBUG_RINGBUFFER
Chris@0 428 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::peek: read " << n << std::endl;
Chris@0 429 #endif
Chris@0 430
Chris@0 431 return n;
Chris@0 432 }
Chris@0 433
Chris@0 434 template <typename T, int N>
Chris@0 435 T
Chris@0 436 RingBuffer<T, N>::peekOne(int R) const
Chris@0 437 {
Chris@0 438 #ifdef DEBUG_RINGBUFFER
Chris@0 439 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::peek(" << R << ")" << std::endl;
Chris@0 440 #endif
Chris@0 441
Chris@0 442 if (m_writer == m_readers[R]) {
Chris@0 443 #ifdef DEBUG_RINGBUFFER
Chris@0 444 std::cerr << "WARNING: No sample available"
Chris@0 445 << std::endl;
Chris@0 446 #endif
Chris@0 447 T t;
Chris@0 448 memset(&t, 0, sizeof(T));
Chris@0 449 return t;
Chris@0 450 }
Chris@0 451 T value = m_buffer[m_readers[R]];
Chris@0 452 return value;
Chris@0 453 }
Chris@0 454
Chris@0 455 template <typename T, int N>
Chris@0 456 size_t
Chris@0 457 RingBuffer<T, N>::skip(size_t n, int R)
Chris@0 458 {
Chris@0 459 #ifdef DEBUG_RINGBUFFER
Chris@0 460 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::skip(" << n << ", " << R << ")" << std::endl;
Chris@0 461 #endif
Chris@0 462
Chris@0 463 size_t available = getReadSpace(R);
Chris@0 464 if (n > available) {
Chris@0 465 #ifdef DEBUG_RINGBUFFER
Chris@0 466 std::cerr << "WARNING: Only " << available << " samples available"
Chris@0 467 << std::endl;
Chris@0 468 #endif
Chris@0 469 n = available;
Chris@0 470 }
Chris@0 471 if (n == 0) return n;
Chris@0 472 m_readers[R] = (m_readers[R] + n) % m_size;
Chris@0 473 return n;
Chris@0 474 }
Chris@0 475
Chris@0 476 template <typename T, int N>
Chris@0 477 size_t
Chris@0 478 RingBuffer<T, N>::write(const T *source, size_t n)
Chris@0 479 {
Chris@0 480 #ifdef DEBUG_RINGBUFFER
Chris@0 481 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::write(" << n << ")" << std::endl;
Chris@0 482 #endif
Chris@0 483
Chris@0 484 size_t available = getWriteSpace();
Chris@0 485 if (n > available) {
Chris@0 486 #ifdef DEBUG_RINGBUFFER
Chris@0 487 std::cerr << "WARNING: Only room for " << available << " samples"
Chris@0 488 << std::endl;
Chris@0 489 #endif
Chris@0 490 n = available;
Chris@0 491 }
Chris@0 492 if (n == 0) return n;
Chris@0 493
Chris@0 494 size_t here = m_size - m_writer;
Chris@0 495 if (here >= n) {
Chris@0 496 memcpy(m_buffer + m_writer, source, n * sizeof(T));
Chris@0 497 } else {
Chris@0 498 memcpy(m_buffer + m_writer, source, here * sizeof(T));
Chris@0 499 memcpy(m_buffer, source + here, (n - here) * sizeof(T));
Chris@0 500 }
Chris@0 501
Chris@0 502 m_writer = (m_writer + n) % m_size;
Chris@0 503
Chris@0 504 #ifdef DEBUG_RINGBUFFER
Chris@0 505 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::write: wrote " << n << ", writer now " << m_writer << std::endl;
Chris@0 506 #endif
Chris@0 507
Chris@0 508 return n;
Chris@0 509 }
Chris@0 510
Chris@0 511 template <typename T, int N>
Chris@0 512 size_t
Chris@0 513 RingBuffer<T, N>::zero(size_t n)
Chris@0 514 {
Chris@0 515 #ifdef DEBUG_RINGBUFFER
Chris@0 516 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::zero(" << n << ")" << std::endl;
Chris@0 517 #endif
Chris@0 518
Chris@0 519 size_t available = getWriteSpace();
Chris@0 520 if (n > available) {
Chris@0 521 #ifdef DEBUG_RINGBUFFER
Chris@0 522 std::cerr << "WARNING: Only room for " << available << " samples"
Chris@0 523 << std::endl;
Chris@0 524 #endif
Chris@0 525 n = available;
Chris@0 526 }
Chris@0 527 if (n == 0) return n;
Chris@0 528
Chris@0 529 size_t here = m_size - m_writer;
Chris@0 530 if (here >= n) {
Chris@0 531 memset(m_buffer + m_writer, 0, n * sizeof(T));
Chris@0 532 } else {
Chris@0 533 memset(m_buffer + m_writer, 0, here * sizeof(T));
Chris@0 534 memset(m_buffer, 0, (n - here) * sizeof(T));
Chris@0 535 }
Chris@0 536
Chris@0 537 m_writer = (m_writer + n) % m_size;
Chris@0 538 return n;
Chris@0 539 }
Chris@0 540
Chris@0 541 #endif // _RINGBUFFER_H_