arduino-audio-tools
Buffers.h
1 
2 #pragma once
3 
4 #include "AudioTools/CoreAudio/AudioBasic/Collections.h"
5 #include "AudioTools/CoreAudio/AudioLogger.h"
6 
7 #ifndef INT_MAX
8 # define INT_MAX 2147483647
9 #endif
10 
17 namespace audio_tools {
18 
19 // forward declaration
20 template <typename T>
21 class NBuffer;
22 
29 template <typename T>
30 class BaseBuffer {
31  public:
32  BaseBuffer() = default;
33  virtual ~BaseBuffer() = default;
34  BaseBuffer(BaseBuffer const &) = delete;
35  //BaseBuffer &operator=(BaseBuffer const &) = delete;
36 
38  virtual T read() = 0;
39 
41  virtual int readArray(T data[], int len) {
42  if (data==nullptr){
43  LOGE("NPE");
44  return 0;
45  }
46  int lenResult = min(len, available());
47  for (int j = 0; j < lenResult; j++) {
48  data[j] = read();
49  }
50  LOGD("readArray %d -> %d", len, lenResult);
51  return lenResult;
52  }
53 
55  virtual int clearArray(int len) {
56  int lenResult = min(len, available());
57  for (int j = 0; j < lenResult; j++) {
58  read();
59  }
60  return lenResult;
61  }
62 
63 
65  virtual int writeArray(const T data[], int len) {
66  // LOGD("%s: %d", LOG_METHOD, len);
67  // CHECK_MEMORY();
68 
69  int result = 0;
70  for (int j = 0; j < len; j++) {
71  if (!write(data[j])) {
72  break;
73  }
74  result = j + 1;
75  }
76  // CHECK_MEMORY();
77  LOGD("writeArray %d -> %d", len, result);
78  return result;
79  }
80 
81 
83  virtual int writeArrayOverwrite(const T data[], int len) {
84  int to_delete = len - availableForWrite();
85  if (to_delete>0){
86  clearArray(to_delete);
87  }
88  return writeArray(data, len);
89  }
90 
91 
93  int readFrames(T data[][2], int len) {
94  LOGD("%s: %d", LOG_METHOD, len);
95  // CHECK_MEMORY();
96  int result = min(len, available());
97  for (int j = 0; j < result; j++) {
98  T sample = read();
99  data[j][0] = sample;
100  data[j][1] = sample;
101  }
102  // CHECK_MEMORY();
103  return result;
104  }
105 
106  template <int rows, int channels>
107  int readFrames(T (&data)[rows][channels]) {
108  int lenResult = min(rows, available());
109  for (int j = 0; j < lenResult; j++) {
110  T sample = read();
111  for (int i = 0; i < channels; i++) {
112  // data[j][i] = htons(sample);
113  data[j][i] = sample;
114  }
115  }
116  return lenResult;
117  }
118 
120  virtual T peek() = 0;
121 
123  virtual bool isFull() = 0;
124 
125  bool isEmpty() { return available() == 0; }
126 
128  virtual bool write(T data) = 0;
129 
131  virtual void reset() = 0;
132 
134  void clear() { reset(); }
135 
137  virtual int available() = 0;
138 
140  virtual int availableForWrite() = 0;
141 
143  virtual T *address() = 0;
144 
145  virtual size_t size() = 0;
146 
148  virtual float levelPercent() {
149  // prevent div by 0.
150  if (size()==0) return 0.0;
151  return 100.0 * static_cast<float>(available()) / static_cast<float>(size());
152  }
153 
154  protected:
155  void setWritePos(int pos){};
156 
157  friend NBuffer<T>;
158 };
159 
168 template <typename T>
169 class SingleBuffer : public BaseBuffer<T> {
170  public:
176  SingleBuffer(int size) {
177  buffer.resize(size);
178  reset();
179  }
180 
185 
187  void onExternalBufferRefilled(void *data, int len) {
188  this->owns_buffer = false;
189  this->buffer = (uint8_t *)data;
190  this->current_read_pos = 0;
191  this->current_write_pos = len;
192  }
193 
194  bool write(T sample) override {
195  bool result = false;
196  if (current_write_pos < buffer.size()) {
197  buffer[current_write_pos++] = sample;
198  result = true;
199  }
200  return result;
201  }
202 
203  T read() override {
204  T result = 0;
205  if (current_read_pos < current_write_pos) {
206  result = buffer[current_read_pos++];
207  }
208  return result;
209  }
210 
211  T peek() override {
212  T result = 0;
213  if (current_read_pos < current_write_pos) {
214  result = buffer[current_read_pos];
215  }
216  return result;
217  }
218 
219  int available() override {
220  int result = current_write_pos - current_read_pos;
221  return max(result, 0);
222  }
223 
224  int availableForWrite() override { return buffer.size() - current_write_pos; }
225 
226  bool isFull() override { return availableForWrite() <= 0; }
227 
229  int clearArray(int len) override{
230  int len_available = available();
231  if (len>available()) {
232  reset();
233  return len_available;
234  }
235  current_read_pos += len;
236  len_available -= len;
237  memmove(buffer.data(), buffer.data()+current_read_pos, len_available);
238  current_read_pos = 0;
239  current_write_pos = len_available;
240 
241  if (is_clear_with_zero){
242  memset(buffer.data()+current_write_pos,0,buffer.size()-current_write_pos);
243  }
244 
245  return len;
246  }
247 
249  T *address() override { return buffer.data(); }
250 
252  T *data() { return buffer.data()+current_read_pos; }
253 
254  void reset() override {
255  current_read_pos = 0;
256  current_write_pos = 0;
257  if (is_clear_with_zero){
258  memset(buffer.data(),0,buffer.size());
259  }
260  }
261 
264  size_t setAvailable(size_t available_size) {
265  size_t result = min(available_size, (size_t) buffer.size());
266  current_read_pos = 0;
267  current_write_pos = result;
268  return result;
269  }
270 
271 
272  size_t size() { return buffer.size(); }
273 
274  void resize(int size) {
275  if (buffer.size() != size) {
276  TRACED();
277  buffer.resize(size);
278  }
279  }
280 
282  void setClearWithZero(bool flag){
283  is_clear_with_zero = flag;
284  }
285 
286  protected:
287  int current_read_pos = 0;
288  int current_write_pos = 0;
289  bool owns_buffer = true;
290  bool is_clear_with_zero = false;
291  Vector<T> buffer{0};
292 
293  void setWritePos(int pos) { current_write_pos = pos; }
294 };
295 
301 template <typename T>
302 class RingBuffer : public BaseBuffer<T> {
303  public:
304  RingBuffer(int size) {
305  resize(size);
306  reset();
307  }
308 
309  virtual T read() {
310  if (isEmpty()) return -1;
311 
312  T value = _aucBuffer[_iTail];
313  _iTail = nextIndex(_iTail);
314  _numElems--;
315 
316  return value;
317  }
318 
319  // peeks the actual entry from the buffer
320  virtual T peek() {
321  if (isEmpty()) return -1;
322 
323  return _aucBuffer[_iTail];
324  }
325 
326  virtual int peekArray(T*data, int n){
327  if (isEmpty()) return -1;
328  int result = 0;
329  int count = _numElems;
330  int tail = _iTail;
331  for (int j=0;j<n;j++){
332  data[j] = _aucBuffer[tail];
333  tail = nextIndex(tail);
334  count--;
335  result++;
336  if (count==0)break;
337  }
338  return result;
339  }
340 
341  // checks if the buffer is full
342  virtual bool isFull() { return available() == max_size; }
343 
344  bool isEmpty() { return available() == 0; }
345 
346  // write add an entry to the buffer
347  virtual bool write(T data) {
348  bool result = false;
349  if (!isFull()) {
350  _aucBuffer[_iHead] = data;
351  _iHead = nextIndex(_iHead);
352  _numElems++;
353  result = true;
354  }
355  return result;
356  }
357 
358  // clears the buffer
359  virtual void reset() {
360  _iHead = 0;
361  _iTail = 0;
362  _numElems = 0;
363  }
364 
365  // provides the number of entries that are available to read
366  virtual int available() { return _numElems; }
367 
368  // provides the number of entries that are available to write
369  virtual int availableForWrite() { return (max_size - _numElems); }
370 
371  // returns the address of the start of the physical read buffer
372  virtual T *address() { return _aucBuffer.data(); }
373 
374  virtual void resize(int len) {
375  if (max_size != len) {
376  LOGI("resize: %d", len);
377  _aucBuffer.resize(len);
378  max_size = len;
379  }
380  }
381 
383  virtual size_t size() { return max_size; }
384 
385  protected:
386  Vector<T> _aucBuffer;
387  int _iHead;
388  int _iTail;
389  int _numElems;
390  int max_size = 0;
391 
392  int nextIndex(int index) { return (uint32_t)(index + 1) % max_size; }
393 };
394 
405 template <class File, typename T>
406 class RingBufferFile : public BaseBuffer<T> {
407  public:
408  RingBufferFile(bool autoRewind = true) { setAutoRewind(autoRewind); }
409  RingBufferFile(File &file, bool autoRewind = true) {
410  setFile(file);
411  setAutoRewind(autoRewind);
412  }
413 
417  void setAutoRewind(bool flag) { auto_rewind = true; }
418 
420  void setFile(File &bufferFile, bool clear = false) {
421  p_file = &bufferFile;
422  if (!*p_file) {
423  LOGE("file is not valid");
424  }
425  // if no clear has been requested we can access the existing data in the
426  // p_file
427  if (!clear) {
428  element_count = p_file->size() / sizeof(T);
429  LOGI("existing elements: %s", element_count);
430  read_pos = element_count;
431  }
432  }
433 
434  T read() override {
435  if (isEmpty()) return -1;
436 
437  T result = peek();
438  read_pos++;
439  element_count--;
440  // the buffer is empty
441  if (auto_rewind && isEmpty()) {
442  LOGI("pos 0");
443  write_pos = 0;
444  read_pos = 0;
445  }
446 
447  return result;
448  }
449 
451  int readArray(T data[], int count) override {
452  if (p_file == nullptr) return 0;
453  int read_count = min(count, element_count);
454  file_seek(read_pos);
455  int elements_processed = file_read(data, read_count);
456  read_pos += elements_processed;
457  element_count -= elements_processed;
458  return elements_processed;
459  }
460 
461  // peeks the actual entry from the buffer
462  T peek() override {
463  if (p_file == nullptr) return 0;
464  if (isEmpty()) return -1;
465 
466  file_seek(read_pos);
467  T result;
468  size_t count = file_read(&result, 1);
469  return result;
470  }
471 
472  // checks if the buffer is full
473  bool isFull() override { return available() == max_size; }
474 
475  bool isEmpty() { return available() == 0; }
476 
477  // write add an entry to the buffer
478  virtual bool write(T data) override { return writeArray(&data, 1); }
479 
481  int writeArray(const T data[], int len) override {
482  if (p_file == nullptr) return 0;
483  file_seek(write_pos);
484  int elements_written = file_write(data, len);
485  write_pos += elements_written;
486  element_count += elements_written;
487  return elements_written;
488  }
489 
490  // clears the buffer
491  void reset() override {
492  write_pos = 0;
493  read_pos = 0;
494  element_count = 0;
495  if (p_file != nullptr) file_seek(0);
496  }
497 
498  // provides the number of entries that are available to read
499  int available() override { return element_count; }
500 
501  // provides the number of entries that are available to write
502  int availableForWrite() override { return (max_size - element_count); }
503 
504  // /// Returns the maximum capacity of the buffer
505  // int size() override { return max_size; }
506 
507  // not supported
508  T *address() override { return nullptr; }
509 
510  size_t size() override {
511  return write_pos - read_pos;
512  }
513 
514  protected:
515  File *p_file = nullptr;
516  int write_pos;
517  int read_pos;
518  int element_count;
519  int max_size = INT_MAX;
520  bool auto_rewind = true;
521 
522  void file_seek(int pos) {
523  if (p_file->position() != pos * sizeof(T)) {
524  LOGD("file_seek: %d", pos);
525  if (!p_file->seek(pos * sizeof(T))) {
526  LOGE("seek %d", pos * sizeof(T))
527  }
528  }
529  }
530 
531  int file_write(const T *data, int count) {
532  LOGD("file_write: %d", count);
533  if (p_file == nullptr) return 0;
534  int to_write = sizeof(T) * count;
535  int bytes_written = p_file->write((const uint8_t *)data, to_write);
536  // p_file->flush();
537  int elements_written = bytes_written / sizeof(T);
538  if (bytes_written != to_write) {
539  LOGE("write: %d -> %d", to_write, bytes_written);
540  }
541  return elements_written;
542  }
543 
544  int file_read(T *result, int count) {
545  LOGD("file_read: %d", count);
546  size_t result_bytes = p_file->read((uint8_t *)result, sizeof(T) * count);
547  if (result_bytes != count * sizeof(T)) {
548  LOGE("readBytes: %d -> %d", (int)sizeof(T) * count, (int)result_bytes);
549  result = 0;
550  }
551  return count;
552  }
553 };
554 
562 template <typename T>
563 class NBuffer : public BaseBuffer<T> {
564  public:
565  NBuffer(int size, int count) {
566  resize(size, count);
567  }
568 
569  virtual ~NBuffer() {
570  freeMemory();
571  }
572 
573  // reads an entry from the buffer
574  T read() {
575  T result = 0;
576  if (available() > 0) {
577  result = actual_read_buffer->read();
578  }
579  return result;
580  }
581 
582  // peeks the actual entry from the buffer
583  T peek() {
584  T result = 0;
585  if (available() > 0) {
586  result = actual_read_buffer->peek();
587  }
588  return result;
589  }
590 
591  // checks if the buffer is full
592  bool isFull() { return availableForWrite() == 0; }
593 
594  // write add an entry to the buffer
595  bool write(T data) {
596  bool result = false;
597  if (actual_write_buffer == nullptr) {
598  actual_write_buffer = getNextAvailableBuffer();
599  }
600  if (actual_write_buffer != nullptr) {
601  result = actual_write_buffer->write(data);
602  // if buffer is full move to next available
603  if (actual_write_buffer->isFull()) {
604  addFilledBuffer(actual_write_buffer);
605  actual_write_buffer = getNextAvailableBuffer();
606  }
607  } else {
608  // Logger.debug("actual_write_buffer is full");
609  }
610 
611  if (start_time == 0l) {
612  start_time = millis();
613  }
614  if (result)
615  sample_count++;
616 
617  return result;
618  }
619 
620  // determines the available entries for the current read buffer
621  int available() {
622  if (actual_read_buffer == nullptr) {
623  actual_read_buffer = getNextFilledBuffer();
624  }
625  if (actual_read_buffer == nullptr) {
626  return 0;
627  }
628  int result = actual_read_buffer->available();
629  if (result == 0) {
630  // make current read buffer available again
631  resetCurrent();
632  result = (actual_read_buffer == nullptr) ? 0 : actual_read_buffer->available();
633  }
634  return result;
635  }
636 
637  // deterMINes the available entries for the write buffer
639  if (actual_write_buffer == nullptr) {
640  actual_write_buffer = getNextAvailableBuffer();
641  }
642  // if we used up all buffers - there is nothing available any more
643  if (actual_write_buffer == nullptr) {
644  return 0;
645  }
646  // check on actual buffer
647  if (actual_write_buffer->isFull()) {
648  // if buffer is full we move it to filled buffers ang get the next
649  // available
650  addFilledBuffer(actual_write_buffer);
651  actual_write_buffer = getNextAvailableBuffer();
652  }
653  return actual_write_buffer->availableForWrite();
654  }
655 
656  // resets all buffers
657  void reset() {
658  TRACED();
659  while (actual_read_buffer != nullptr) {
660  actual_read_buffer->reset();
661  addAvailableBuffer(actual_read_buffer);
662  // get next read buffer
663  actual_read_buffer = getNextFilledBuffer();
664  }
665  }
666 
667  // provides the actual sample rate
668  unsigned long sampleRate() {
669  unsigned long run_time = (millis() - start_time);
670  return run_time == 0 ? 0 : sample_count * 1000 / run_time;
671  }
672 
673  // returns the address of the start of the phsical read buffer
674  T *address() {
675  return actual_read_buffer == nullptr ? nullptr
676  : actual_read_buffer->address();
677  }
678 
679  // Alternative interface using address: the current buffer has been filled
680  BaseBuffer<T> &writeEnd() {
681  if (actual_write_buffer != nullptr) {
682  actual_write_buffer->setWritePos(buffer_size);
683  addFilledBuffer(actual_write_buffer);
684  }
685  actual_write_buffer = getNextAvailableBuffer();
686  return *actual_write_buffer;
687  }
688 
689  // Alternative interface using address: marks actual buffer as processed and
690  // provides access to next read buffer
691  BaseBuffer<T> &readEnd() {
692  // make current read buffer available again
693  resetCurrent();
694  return *actual_read_buffer;
695  }
696 
697  virtual int bufferCountFilled() {
698  return filled_buffers.size();
699  }
700 
701  virtual int bufferCountEmpty() {
702  return available_buffers.size();
703  }
704 
705  virtual void resize(int size, int count) {
706  if (buffer_size==size && buffer_count == count)
707  return;
708  freeMemory();
709  filled_buffers.resize(count);
710  available_buffers.resize(count);
711  //filled_buffers.clear();
712  //available_buffers.clear();
713 
714  buffer_count = count;
715  buffer_size = size;
716  for (int j = 0; j < count; j++) {
717  BaseBuffer<T>* buffer = new SingleBuffer<T>(size);
718  LOGD("new buffer %p", buffer);
719  available_buffers.enqueue(buffer);
720  }
721  }
722 
723  size_t size() { return buffer_size * buffer_count;}
724 
725  protected:
726  int buffer_size = 0;
727  uint16_t buffer_count = 0;
728  BaseBuffer<T> *actual_read_buffer = nullptr;
729  BaseBuffer<T> *actual_write_buffer = nullptr;
730  QueueFromVector<BaseBuffer<T> *> available_buffers{0, nullptr};
731  QueueFromVector<BaseBuffer<T> *> filled_buffers{0, nullptr};
732  //Queue<BaseBuffer<T> *> available_buffers;
733  //Queue<BaseBuffer<T> *> filled_buffers;
734  unsigned long start_time = 0;
735  unsigned long sample_count = 0;
736 
737  // empty constructor only allowed by subclass
738  NBuffer() = default;
739 
740  void freeMemory() {
741  if (actual_write_buffer){
742  LOGD("deleting %p", actual_write_buffer);
743  delete actual_write_buffer;
744  actual_write_buffer = nullptr;
745  }
746  if (actual_read_buffer){
747  LOGD("deleting %p", actual_read_buffer);
748  delete actual_read_buffer;
749  actual_read_buffer = nullptr;
750  }
751 
752  BaseBuffer<T> *ptr = getNextAvailableBuffer();
753  while (ptr != nullptr) {
754  LOGD("deleting %p", ptr);
755  delete ptr;
756  ptr = getNextAvailableBuffer();
757  }
758 
759  ptr = getNextFilledBuffer();
760  while (ptr != nullptr) {
761  LOGD("deleting %p", ptr);
762  delete ptr;
763  ptr = getNextFilledBuffer();
764  }
765  }
766 
767  void resetCurrent() {
768  if (actual_read_buffer != nullptr) {
769  actual_read_buffer->reset();
770  addAvailableBuffer(actual_read_buffer);
771  }
772  // get next read buffer
773  actual_read_buffer = getNextFilledBuffer();
774  }
775 
776  virtual BaseBuffer<T> *getNextAvailableBuffer() {
777  if (available_buffers.empty()) return nullptr;
778  BaseBuffer<T> *result = nullptr;
779  available_buffers.dequeue(result);
780  return result;
781  }
782 
783  virtual bool addAvailableBuffer(BaseBuffer<T> *buffer) {
784  return available_buffers.enqueue(buffer);
785  }
786 
787  virtual BaseBuffer<T> *getNextFilledBuffer() {
788  if (filled_buffers.empty()) return nullptr;
789  BaseBuffer<T> *result = nullptr;
790  filled_buffers.dequeue(result);
791  return result;
792  }
793 
794  virtual bool addFilledBuffer(BaseBuffer<T> *buffer) {
795  return filled_buffers.enqueue(buffer);
796  }
797 };
798 
808 template <typename T>
810  public:
811  BufferedArray(Stream &input, int len) {
812  LOGI("BufferedArray(%d)", len);
813  array.resize(len);
814  p_stream = &input;
815  }
816  // access values, the offset and length are specified in samples of type <T>
817  int16_t *getValues(size_t offset, size_t length) {
818  LOGD("getValues(%d,%d) - max %d", offset, length, array.size());
819  if (offset == 0) {
820  // we restart at the beginning
821  last_end = 0;
822  actual_end = length;
823  } else {
824  // if first position is at end we do not want to read the full buffer
825  last_end = actual_end >= 0 ? actual_end : offset;
826  // increase actual end if bigger then old
827  actual_end = offset + length > actual_end ? offset + length : actual_end;
828  }
829  int size = actual_end - last_end;
830  if (size > 0) {
831  LOGD("readBytes(%d,%d)", last_end, size);
832  assert(last_end + size <= array.size());
833  p_stream->readBytes((uint8_t *)(&array[last_end]), size * 2);
834  }
835  assert(offset < actual_end);
836  return &array[offset];
837  }
838 
839  protected:
840  int actual_end = -1;
841  int last_end = 0;
842  Vector<T> array;
843  Stream *p_stream = nullptr;
844 };
845 
846 } // namespace audio_tools
Shared functionality of all buffers.
Definition: Buffers.h:30
virtual T * address()=0
returns the address of the start of the physical read buffer
virtual int readArray(T data[], int len)
reads multiple values
Definition: Buffers.h:41
virtual void reset()=0
clears the buffer
virtual int writeArray(const T data[], int len)
Fills the buffer data.
Definition: Buffers.h:65
virtual bool isFull()=0
checks if the buffer is full
virtual int writeArrayOverwrite(const T data[], int len)
Fills the buffer data and overwrites the oldest data if the buffer is full.
Definition: Buffers.h:83
virtual int clearArray(int len)
Removes the next len entries.
Definition: Buffers.h:55
virtual T read()=0
reads a single value
virtual int availableForWrite()=0
provides the number of entries that are available to write
int readFrames(T data[][2], int len)
reads multiple values for array of 2 dimensional frames
Definition: Buffers.h:93
virtual T peek()=0
peeks the actual entry from the buffer
virtual float levelPercent()
Returns the level of the buffer in %.
Definition: Buffers.h:148
void clear()
same as reset
Definition: Buffers.h:134
virtual bool write(T data)=0
write add an entry to the buffer
virtual int available()=0
provides the number of entries that are available to read
Class which is usfull ot provide incremental data access e.g. for EdgeImpulse which request data with...
Definition: Buffers.h:809
Arduino File support using std::fstream.
Definition: File.h:25
A lock free N buffer. If count=2 we create a DoubleBuffer, if count=3 a TripleBuffer etc.
Definition: Buffers.h:563
T * address()
returns the address of the start of the physical read buffer
Definition: Buffers.h:674
bool isFull()
checks if the buffer is full
Definition: Buffers.h:592
int available()
provides the number of entries that are available to read
Definition: Buffers.h:621
bool write(T data)
write add an entry to the buffer
Definition: Buffers.h:595
T peek()
peeks the actual entry from the buffer
Definition: Buffers.h:583
int availableForWrite()
provides the number of entries that are available to write
Definition: Buffers.h:638
T read()
reads a single value
Definition: Buffers.h:574
void reset()
clears the buffer
Definition: Buffers.h:657
An File backed Ring Buffer that we can use to receive streaming audio. We expect an open p_file as pa...
Definition: Buffers.h:406
T * address() override
returns the address of the start of the physical read buffer
Definition: Buffers.h:508
int readArray(T data[], int count) override
reads multiple values
Definition: Buffers.h:451
void setFile(File &bufferFile, bool clear=false)
Assigns the p_file to be used.
Definition: Buffers.h:420
T peek() override
peeks the actual entry from the buffer
Definition: Buffers.h:462
void setAutoRewind(bool flag)
Definition: Buffers.h:417
int available() override
provides the number of entries that are available to read
Definition: Buffers.h:499
virtual bool write(T data) override
write add an entry to the buffer
Definition: Buffers.h:478
int availableForWrite() override
provides the number of entries that are available to write
Definition: Buffers.h:502
bool isFull() override
checks if the buffer is full
Definition: Buffers.h:473
int writeArray(const T data[], int len) override
Fills the data from the buffer.
Definition: Buffers.h:481
void reset() override
clears the buffer
Definition: Buffers.h:491
T read() override
reads a single value
Definition: Buffers.h:434
Implements a typed Ringbuffer.
Definition: Buffers.h:302
virtual T read()
reads a single value
Definition: Buffers.h:309
virtual int availableForWrite()
provides the number of entries that are available to write
Definition: Buffers.h:369
virtual int available()
provides the number of entries that are available to read
Definition: Buffers.h:366
virtual bool write(T data)
write add an entry to the buffer
Definition: Buffers.h:347
virtual void reset()
clears the buffer
Definition: Buffers.h:359
virtual T * address()
returns the address of the start of the physical read buffer
Definition: Buffers.h:372
virtual size_t size()
Returns the maximum capacity of the buffer.
Definition: Buffers.h:383
virtual bool isFull()
checks if the buffer is full
Definition: Buffers.h:342
virtual T peek()
peeks the actual entry from the buffer
Definition: Buffers.h:320
A simple Buffer implementation which just uses a (dynamically sized) array.
Definition: Buffers.h:169
T * address() override
Provides address to beginning of the buffer.
Definition: Buffers.h:249
T * data()
Provides address of actual data.
Definition: Buffers.h:252
T peek() override
peeks the actual entry from the buffer
Definition: Buffers.h:211
size_t setAvailable(size_t available_size)
Definition: Buffers.h:264
bool write(T sample) override
write add an entry to the buffer
Definition: Buffers.h:194
SingleBuffer(int size)
Construct a new Single Buffer object.
Definition: Buffers.h:176
void setClearWithZero(bool flag)
Sets the buffer to 0 on clear.
Definition: Buffers.h:282
int available() override
provides the number of entries that are available to read
Definition: Buffers.h:219
int availableForWrite() override
provides the number of entries that are available to write
Definition: Buffers.h:224
bool isFull() override
checks if the buffer is full
Definition: Buffers.h:226
void onExternalBufferRefilled(void *data, int len)
notifies that the external buffer has been refilled
Definition: Buffers.h:187
SingleBuffer()
Construct a new Single Buffer w/o allocating any memory.
Definition: Buffers.h:184
void reset() override
clears the buffer
Definition: Buffers.h:254
T read() override
reads a single value
Definition: Buffers.h:203
int clearArray(int len) override
consumes len bytes and moves current data to the beginning
Definition: Buffers.h:229
Definition: NoArduino.h:125
Vector implementation which provides the most important methods as defined by std::vector....
Definition: Vector.h:21
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition: AudioConfig.h:823
uint32_t millis()
Returns the milliseconds since the start.
Definition: Time.h:12