arduino-audio-tools
AudioStreams.h
1 #pragma once
2 #include "AudioConfig.h"
3 #include "AudioTimer/AudioTimer.h"
4 #include "AudioTools/AudioTypes.h"
5 #include "AudioTools/Buffers.h"
6 #include "AudioTools/AudioLogger.h"
7 #include "AudioTools/BaseConverter.h"
8 #include "AudioEffects/SoundGenerator.h"
9 
10 #ifndef IRAM_ATTR
11 # define IRAM_ATTR
12 #endif
13 
14 #ifdef USE_STREAM_WRITE_OVERRIDE
15 # define STREAM_WRITE_OVERRIDE override
16 #else
17 # define STREAM_WRITE_OVERRIDE
18 #endif
19 
20 #ifdef USE_STREAM_READ_OVERRIDE
21 # define STREAM_READ_OVERRIDE override
22 #else
23 # define STREAM_READ_OVERRIDE
24 #endif
25 
26 #ifdef USE_STREAM_READCHAR_OVERRIDE
27 # define STREAM_READCHAR_OVERRIDE override
28 #else
29 # define STREAM_READCHAR_OVERRIDE
30 #endif
31 
32 namespace audio_tools {
33 
40 class AudioStream : public Stream, public AudioInfoSupport, public AudioInfoSource {
41  public:
42  AudioStream() = default;
43  virtual ~AudioStream() = default;
44  AudioStream(AudioStream const&) = delete;
45  AudioStream& operator=(AudioStream const&) = delete;
46 
47  virtual bool begin(){return true;}
48  virtual void end(){}
49 
50  // Call from subclass or overwrite to do something useful
51  virtual void setAudioInfo(AudioInfo newInfo) override {
52  TRACED();
53 
54  if (info != newInfo){
55  info = newInfo;
56  info.logInfo("in:");
57  }
58  // replicate information
59  AudioInfo out_new = audioInfoOut();
60  if (out_new) {
61  out_new.logInfo("out:");
62  notifyAudioChange(out_new);
63  }
64 
65  }
66 
67  virtual size_t readBytes(uint8_t *buffer, size_t length) STREAM_READ_OVERRIDE { return not_supported(0, "readBytes"); }
68 
69  virtual size_t write(const uint8_t *buffer, size_t size) override{ return not_supported(0,"write"); }
70 
71  virtual size_t write(uint8_t ch) override {
72  tmp_out.resize(MAX_SINGLE_CHARS);
73  if (tmp_out.isFull()){
74  flush();
75  }
76  return tmp_out.write(ch);
77  }
78 
79  virtual int available() override { return DEFAULT_BUFFER_SIZE; };
80 
81 
82  operator bool() { return available() > 0; }
83 
84  virtual AudioInfo audioInfo() override {
85  return info;
86  }
87 
88  virtual int availableForWrite() override { return DEFAULT_BUFFER_SIZE; }
89 
90  virtual void flush() override {
91  if (tmp_out.available()>0){
92  write((const uint8_t*)tmp_out.address(), tmp_out.available());
93  }
94  }
95 
97  virtual void writeSilence(size_t len){
98  int16_t zero = 0;
99  for (int j=0;j<len/2;j++){
100  write((uint8_t*)&zero,2);
101  }
102  }
103 
105  virtual size_t readSilence(uint8_t *buffer, size_t length) {
106  memset(buffer, 0, length);
107  return length;
108  }
109 
110 
111 // Methods which should be suppressed in the documentation
112 #ifndef DOXYGEN
113 
114  virtual size_t readBytes(char *buffer, size_t length) STREAM_READCHAR_OVERRIDE {
115  return readBytes((uint8_t *)buffer, length);
116  }
117 
118  virtual int read() override {
119  refillReadBuffer();
120  return tmp_in.read();
121  }
122 
123  virtual int peek() override {
124  refillReadBuffer();
125  return tmp_in.peek();
126  }
127 
128 
129 #endif
130 
131  protected:
132  AudioInfo info;
133  RingBuffer<uint8_t> tmp_in{0};
134  RingBuffer<uint8_t> tmp_out{0};
135 
136 
137  virtual int not_supported(int out, const char* msg="") {
138  LOGE("AudioStream: %s unsupported operation!", msg);
139  // trigger stacktrace
140  assert(false);
141  return out;
142  }
143 
144  void refillReadBuffer() {
145  tmp_in.resize(MAX_SINGLE_CHARS);
146  if (tmp_in.isEmpty()){
147  TRACED();
148  const int len = tmp_in.size();
149  uint8_t bytes[len];
150  int len_eff = readBytes(bytes, len);
151  //LOGD("tmp_in available: %d / size: %d / to be written %d", tmp_in.available(), tmp_in.size(), len_eff);
152  tmp_in.writeArray(bytes,len_eff);
153  }
154  }
155 
156 };
157 
164  public:
166  TRACED();
167  p_stream = &s;
168  p_stream->setTimeout(clientTimeout);
169  }
170 
171  virtual bool begin(){return true;}
172  virtual void end(){}
173 
174  virtual size_t readBytes(uint8_t *buffer, size_t length) {
175  //Serial.print("Timeout audiostream: ");
176  //Serial.println(p_stream->getTimeout());
177  return p_stream->readBytes(buffer, length);
178  }
179 
180  int read() { return p_stream->read(); }
181 
182  int peek() { return p_stream->peek(); }
183 
184  int available() { return p_stream->available(); }
185 
186  virtual size_t write(uint8_t c) { return p_stream->write(c); }
187 
188  virtual size_t write(const uint8_t *buffer, size_t size) {
189  return p_stream->write(buffer, size);
190  }
191 
192  virtual int availableForWrite() { return p_stream->availableForWrite(); }
193 
194  virtual void flush() { p_stream->flush(); }
195 
196  protected:
197  Stream *p_stream;
198  int32_t clientTimeout = URL_CLIENT_TIMEOUT; // 60000;
199 };
200 
208 class ModifyingStream : public AudioStream {
209  public:
211  virtual void setStream(Stream& in) = 0;
213  virtual void setOutput(Print& out) = 0;
214 };
215 
223 class MemoryStream : public AudioStream {
224  public:
226  MemoryStream(int buffer_size, MemoryType memoryType) {
227  LOGD("MemoryStream: %d", buffer_size);
228  this->buffer_size = buffer_size;
229  this->memory_type = memoryType;
230  resize(buffer_size);
231  info.clear(); // mark audio info as unknown
232  }
233 
235  MemoryStream(const uint8_t *buffer, int buffer_size, bool isActive=true, MemoryType memoryType = FLASH_RAM) {
236  LOGD("MemoryStream: %d", buffer_size);
237  setValue(buffer, buffer_size, memoryType);
238  is_active = isActive;
239  info.clear(); // mark audio info as unknown
240  }
241 
244  copy(source);
245  }
246 
249  setValue(source.buffer, source.buffer_size, source.memory_type);
250  // clear source data
251  source.setValue(nullptr, 0, source.memory_type);
252  }
253 
254  ~MemoryStream() {
255  TRACED();
256  if (memoryCanChange() && buffer!=nullptr) free(buffer);
257  }
258 
261  copy(other);
262  return *this;
263  }
264 
266  bool begin(AudioInfo info){
267  this->info = info;
268  return begin();
269  }
270 
272  bool begin() override {
273  TRACED();
274  write_pos = memoryCanChange() ? 0 : buffer_size;
275  if (this->buffer==nullptr && memoryCanChange()){
276  resize(buffer_size);
277  }
278  read_pos = 0;
279  is_active = true;
280  return true;
281  }
282 
283  virtual size_t write(uint8_t byte) override {
284  if (!is_active) return 0;
285  if (memory_type == FLASH_RAM) return 0;
286  if (buffer==nullptr) return 0;
287  int result = 0;
288  if (write_pos < buffer_size) {
289  result = 1;
290  buffer[write_pos] = byte;
291  write_pos++;
292  }
293  return result;
294  }
295 
296  virtual size_t write(const uint8_t *buffer, size_t size) override {
297  if (!is_active) return 0;
298  if (memory_type == FLASH_RAM) return 0;
299  size_t result = 0;
300  for (size_t j = 0; j < size; j++) {
301  if (!write(buffer[j])) {
302  break;
303  }
304  result = j + 1;
305  }
306  return result;
307  }
308 
309  virtual int available() override {
310  if (!is_active) return 0;
311  if (buffer==nullptr) return 0;
312  int result = write_pos - read_pos;
313  if (result<=0 && is_loop){
314  // rewind to start
315  read_pos = rewind_pos;
316  result = write_pos - read_pos;
317  // call callback
318  if (rewind!=nullptr) rewind();
319  }
320  return is_loop ? DEFAULT_BUFFER_SIZE : result;
321  }
322 
323  virtual int availableForWrite() override {
324  if (!is_active) return 0;
325  if (memory_type == FLASH_RAM) return 0;
326  return buffer_size - write_pos;
327  }
328 
329  virtual int read() override {
330  int result = peek();
331  if (result >= 0) {
332  read_pos++;
333  }
334  return result;
335  }
336 
337  virtual size_t readBytes(uint8_t *buffer, size_t length) override {
338  if (!is_active) return 0;
339  size_t count = 0;
340  while (count < length) {
341  int c = read();
342  if (c < 0) break;
343  *buffer++ = (char)c;
344  count++;
345  }
346  return count;
347  }
348 
349  virtual int peek() override {
350  if (!is_active) return -1;
351  int result = -1;
352  if (available() > 0) {
353  result = buffer[read_pos];
354  }
355  return result;
356  }
357 
358  virtual void flush() override {}
359 
360  virtual void end() override {
361  read_pos = 0;
362  is_active = false;
363  }
364 
366  virtual void clear(bool reset = false) {
367  if (memoryCanChange()){
368  write_pos = 0;
369  read_pos = 0;
370  if (buffer==nullptr){
371  resize(buffer_size);
372  }
373  if (reset) {
374  // we clear the buffer data
375  memset(buffer, 0, buffer_size);
376  }
377  } else {
378  read_pos = 0;
379  LOGW("data is read only");
380  }
381  }
382 
384  virtual void setLoop(bool loop){
385  is_loop = loop;
386  rewind_pos = 0;
387  if (buffer!=nullptr && buffer_size > 12){
388  if (memcmp("WAVE", buffer+8, 4)==0){
389  rewind_pos = 44;
390  }
391  }
392  }
393 
395  virtual void setLoop(bool loop, int rewindPos){
396  is_loop = loop;
397  rewind_pos = rewindPos;
398  }
399 
401  virtual bool resize(size_t size){
402  if (!memoryCanChange()) return false;
403 
404  buffer_size = size;
405  switch(memory_type){
406 #if defined(ESP32) && defined(ARDUINO)
407  case PS_RAM:
408  buffer = (buffer==nullptr) ? (uint8_t*)ps_calloc(size,1) : (uint8_t*)ps_realloc(buffer, size);
409  break;
410 #endif
411  default:
412  buffer = (buffer==nullptr) ? (uint8_t*)calloc(size,1) : (uint8_t*)realloc(buffer, size);
413  break;
414  }
415  return buffer != nullptr;
416  }
417 
418  virtual uint8_t* data(){
419  return buffer;
420  }
421 
423  void setRewindCallback(void (*cb)()){
424  this->rewind = cb;
425  }
426 
428  void setValue(const uint8_t *buffer, int buffer_size, MemoryType memoryType = FLASH_RAM) {
429  this->buffer_size = buffer_size;
430  this->read_pos = 0;
431  this->write_pos = buffer_size;
432  this->buffer = (uint8_t *)buffer;
433  this->memory_type = memoryType;
434  }
435 
436  protected:
437  int write_pos = 0;
438  int read_pos = 0;
439  int buffer_size = 0;
440  int rewind_pos = 0;
441  uint8_t *buffer = nullptr;
442  MemoryType memory_type = RAM;
443  bool is_loop = false;
444  void (*rewind)() = nullptr;
445  bool is_active = false;
446 
447  bool memoryCanChange() {
448  return memory_type!=FLASH_RAM;
449  }
450 
451  void copy(MemoryStream& source) {
452  if (this == &source) return;
453  if (source.memory_type == FLASH_RAM){
454  setValue(source.buffer, source.buffer_size, source.memory_type);
455  } else {
456  setValue(nullptr, source.buffer_size, source.memory_type);
457  resize(buffer_size);
458  memcpy(buffer, source.buffer, buffer_size);
459  }
460  }
461 };
462 
471 public:
472  struct DataNode {
473  size_t len=0;
474  uint8_t* data=nullptr;
475 
476  DataNode() = default;
478  DataNode(void*inData, int len){
479  this->len = len;
480  this->data = (uint8_t*) malloc(len);
481  assert(this->data!=nullptr);
482  memcpy(this->data, inData, len);
483  }
484 
485  ~DataNode(){
486  if (data!=nullptr) {
487  free(data);
488  data = nullptr;
489  }
490  }
491  };
492 
493  DynamicMemoryStream() = default;
494 
495  DynamicMemoryStream(bool isLoop, int defaultBufferSize=DEFAULT_BUFFER_SIZE ) {
496  this->default_buffer_size = defaultBufferSize;
497  is_loop = isLoop;
498  }
499  // Assign values from ref, clearing the original ref
500  void assign(DynamicMemoryStream &ref){
501  audio_list.swap(ref.audio_list);
502  it = ref.it;
503  total_available=ref.total_available;
504  default_buffer_size = ref.default_buffer_size;
505  alloc_failed = ref.alloc_failed;;
506  is_loop = ref.is_loop;
507  ref.clear();
508  }
509 
511  virtual bool begin() override {
512  clear();
513  temp_audio.resize(default_buffer_size);
514  return true;
515  }
516 
517  virtual void end() override {
518  clear();
519  }
520 
522  virtual void setLoop(bool loop){
523  is_loop = loop;
524  }
525 
526  void clear() {
527  DataNode *p_node;
528  bool ok;
529  do{
530  ok = audio_list.pop_front(p_node);
531  if (ok){
532  delete p_node;
533  }
534  } while (ok);
535 
536  temp_audio.reset();
537  total_available = 0;
538  alloc_failed = false;
539  rewind();
540  }
541 
542  size_t size(){
543  return total_available;
544  }
545 
547  void rewind() {
548  it = audio_list.begin();
549  }
550 
551  virtual size_t write(const uint8_t *buffer, size_t size) override {
552  DataNode *p_node = new DataNode((void*)buffer, size);
553  if (p_node->data!=nullptr){
554  alloc_failed = false;
555  total_available += size;
556  audio_list.push_back(p_node);
557 
558  // setup interator to point to first record
559  if (it == audio_list.end()){
560  it = audio_list.begin();
561  }
562 
563  return size;
564  }
565  alloc_failed = true;
566  return 0;
567  }
568 
569  virtual int availableForWrite() override {
570  return alloc_failed ? 0 : default_buffer_size;
571  }
572 
573  virtual int available() override {
574  if (it == audio_list.end()){
575  if (is_loop) rewind();
576  if (it == audio_list.end()) {
577  return 0;
578  }
579  }
580  return (*it)->len;
581  }
582 
583  virtual size_t readBytes(uint8_t *buffer, size_t length) override {
584  // provide unprocessed data
585  if (temp_audio.available()>0){
586  return temp_audio.readArray(buffer, length);
587  }
588 
589  // We have no more data
590  if (it==audio_list.end()){
591  if (is_loop){
592  rewind();
593  } else {
594  // stop the processing
595  return 0;
596  }
597  }
598 
599  // provide data from next node
600  DataNode *p_node = *it;
601  int result_len = min(length, (size_t) p_node->len);
602  memcpy(buffer, p_node->data, result_len);
603  // save unprocessed data to temp buffer
604  if (p_node->len>length){
605  uint8_t *start = p_node->data+result_len;
606  int uprocessed_len = p_node->len - length;
607  temp_audio.writeArray(start, uprocessed_len);
608  }
609  //move to next pos
610  ++it;
611  return result_len;
612  }
613 
614  List<DataNode*> &list() {
615  return audio_list;
616  }
617 
621  template<typename T>
622  void postProcessSmoothTransition(int channels, float factor = 0.01, int remove=0){
623  if (remove>0){
624  for (int j=0;j<remove;j++){
625  DataNode* node = nullptr;
626  audio_list.pop_front(node);
627  if (node!=nullptr) delete node;
628  node = nullptr;
629  audio_list.pop_back(node);
630  if (node!=nullptr) delete node;
631  }
632  }
633 
634  // Remove popping noise
635  SmoothTransition<T> clean_start(channels, true, false, factor);
636  auto first = *list().begin();
637  if (first!=nullptr){
638  clean_start.convert(first->data,first->len);
639  }
640 
641  SmoothTransition<T> clean_end(channels, false, true, factor);
642  auto last = * (--(list().end()));
643  if (last!=nullptr){
644  clean_end.convert(last->data,last->len);
645  }
646  }
647 
648 
649 protected:
650  List<DataNode*> audio_list;
651  List<DataNode*>::Iterator it = audio_list.end();
652  size_t total_available=0;
653  int default_buffer_size=DEFAULT_BUFFER_SIZE;
654  bool alloc_failed = false;
655  RingBuffer<uint8_t> temp_audio{DEFAULT_BUFFER_SIZE};
656  bool is_loop = false;
657 
658 };
659 
671 template <class T>
673  public:
674  GeneratedSoundStream() = default;
675 
677  TRACED();
678  setInput(generator);
679  }
680 
681  void setInput(SoundGenerator<T> &generator){
682  this->generator_ptr = &generator;
683  }
684 
685  AudioInfo defaultConfig() { return this->generator_ptr->defaultConfig(); }
686 
688  bool begin() override {
689  TRACED();
690  if (generator_ptr==nullptr){
691  LOGE("%s",source_not_defined_error);
692  return false;
693  }
694  generator_ptr->begin();
695  notifyAudioChange(generator_ptr->audioInfo());
696  active = true;
697  return active;
698  }
699 
701  bool begin(AudioInfo cfg) {
702  TRACED();
703  if (generator_ptr==nullptr){
704  LOGE("%s",source_not_defined_error);
705  return false;
706  }
707  generator_ptr->begin(cfg);
708  notifyAudioChange(generator_ptr->audioInfo());
709  active = true;
710  return active;
711  }
712 
714  void end() override {
715  TRACED();
716  generator_ptr->end();
717  active = true; // legacy support - most sketches do not call begin
718  }
719 
720  AudioInfo audioInfo() override {
721  return generator_ptr->audioInfo();
722  }
723 
725  virtual int available() override { return active ? DEFAULT_BUFFER_SIZE*2 : 0; }
726 
728  size_t readBytes(uint8_t *buffer, size_t length) override {
729  if (!active) return 0;
730  LOGD("GeneratedSoundStream::readBytes: %u", (unsigned int)length);
731  return generator_ptr->readBytes(buffer, length);
732  }
733 
734  bool isActive() {return active && generator_ptr->isActive();}
735 
736  operator bool() { return isActive(); }
737 
738  void flush() override {}
739 
740  protected:
741  bool active = true; // support for legacy sketches
742  SoundGenerator<T> *generator_ptr;
743  const char* source_not_defined_error = "Source not defined";
744 
745 };
746 
756  public:
757  BufferedStream(size_t buffer_size) {
758  TRACED();
759  buffer.resize(buffer_size);
760  }
761 
762  BufferedStream(size_t buffer_size, Print &out) {
763  TRACED();
764  setOutput(out);
765  buffer.resize(buffer_size);
766  }
767 
768  BufferedStream(size_t buffer_size, Stream &io) {
769  TRACED();
770  setStream(io);
771  buffer.resize(buffer_size);
772  }
773 
774  void setOutput(Print &out){
775  p_out = &out;
776  }
777  void setStream(Print &out){
778  setOutput(out);
779  }
780  void setStream(Stream &io){
781  p_in = &io;
782  p_out = &io;
783  }
784 
786  size_t write(uint8_t c) override {
787  if (buffer.isFull()) {
788  flush();
789  }
790  return buffer.write(c);
791  }
792 
794  size_t write(const uint8_t *data, size_t len) override {
795  LOGD("%s: %zu", LOG_METHOD, len);
796  int result = 0;
797  for (int j=0;j<len;j++){
798  result += write(data[j]);
799  }
800  return result;
801  }
802 
804  void flush() override {
805  // just dump the memory of the buffer and clear it
806  if (buffer.available() > 0) {
807  writeExt(buffer.address(), buffer.available());
808  buffer.reset();
809  }
810  }
811 
813  int read() override {
814  if (buffer.isEmpty()) {
815  refill();
816  }
817  return buffer.read();
818  }
819 
821  int peek() override{
822  if (buffer.isEmpty()) {
823  refill();
824  }
825  return buffer.peek();
826  };
827 
829  size_t readBytes(uint8_t *data, size_t length) override {
830  if (buffer.isEmpty()) {
831  return readExt(data, length);
832  } else {
833  refill();
834  return buffer.readArray(data, length);
835  }
836  }
837 
839  int available() override {
840  if (buffer.isEmpty()) {
841  refill();
842  }
843  return buffer.available();
844  }
845 
847  void clear() { buffer.reset(); }
848 
849  protected:
850  SingleBuffer<uint8_t> buffer;
851  Print* p_out = nullptr;
852  Stream* p_in = nullptr;
853 
854  // refills the buffer with data from i2s
855  void refill() {
856  size_t result = readExt(buffer.address(), buffer.size());
857  buffer.setAvailable(result);
858  }
859 
860  virtual size_t writeExt(const uint8_t *data, size_t len) {
861  return p_out == nullptr ? 0 : p_out->write(data, len);
862  }
863  virtual size_t readExt(uint8_t *data, size_t len) {
864  return p_in == nullptr ? 0 : p_in->readBytes(data, len);
865  }
866 };
867 
875 class NullStream : public AudioStream {
876  public:
877 
878  bool begin(AudioInfo info) {
879  this->info = info;
880  return true;
881  }
882 
883  AudioInfo defaultConfig() {
884  AudioInfo info;
885  return info;
886  }
887 
888  size_t write(const uint8_t *buffer, size_t len) override{
889  return len;
890  }
891 
892  size_t readBytes(uint8_t *buffer, size_t len) override{
893  memset(buffer,0, len);
894  return len;
895  }
896 
897  void setAudioInfo(AudioInfo info) override {
898  this->info = info;
899  }
900 };
901 
910  public:
911  RingBufferStream(int size = DEFAULT_BUFFER_SIZE) {
912  resize(size);
913  }
914 
915  virtual int available() override {
916  // LOGD("RingBufferStream::available: %zu",buffer->available());
917  return buffer.available();
918  }
919 
920  virtual int availableForWrite() override {
921  return buffer.availableForWrite();
922  }
923 
924  virtual void flush() override {}
925  virtual int peek() override { return buffer.peek(); }
926  virtual int read() override { return buffer.read(); }
927 
928  virtual size_t readBytes(uint8_t *data, size_t length) override {
929  return buffer.readArray(data, length);
930  }
931 
932  virtual size_t write(const uint8_t *data, size_t len) override {
933  // LOGD("RingBufferStream::write: %zu",len);
934  return buffer.writeArray(data, len);
935  }
936 
937  virtual size_t write(uint8_t c) override { return buffer.write(c); }
938 
939  void resize(int size){
940  buffer.resize(size);
941  }
942 
943  size_t size() {
944  return buffer.size();
945  }
946 
947 
948  protected:
949  RingBuffer<uint8_t> buffer{0};
950 };
951 
952 
960 template <class T>
961 class QueueStream : public AudioStream {
962  public:
964  QueueStream(int bufferSize, int bufferCount, bool autoRemoveOldestDataIfFull=false)
965  : AudioStream() {
966  owns_buffer = true;
967  callback_buffer_ptr = new NBuffer<T>(bufferSize, bufferCount);
968  remove_oldest_data = autoRemoveOldestDataIfFull;
969  }
972  owns_buffer = false;
973  callback_buffer_ptr = &buffer;
974  }
975 
976  virtual ~QueueStream() {
977  if(owns_buffer) {
978  delete callback_buffer_ptr;
979  }
980  }
981 
983  virtual bool begin() override {
984  TRACED();
985  active = true;
986  return true;
987  }
988 
990  virtual bool begin(size_t activeWhenPercentFilled){
991  // determine total buffer size in bytes
992  size_t size = callback_buffer_ptr->size() * sizeof(T);
993  // calculate limit
994  active_limit = size * activeWhenPercentFilled / 100;
995  return true;
996  }
997 
999  virtual void end() override {
1000  TRACED();
1001  active = false;
1002  };
1003 
1004  int available() override {
1005  return active ? callback_buffer_ptr->available()*sizeof(T) : 0;
1006  }
1007 
1008  int availableForWrite() override {
1009  return callback_buffer_ptr->availableForWrite()*sizeof(T);
1010  }
1011 
1012  virtual size_t write(const uint8_t *data, size_t len) override {
1013  if (active_limit==0 && !active) return 0;
1014 
1015  // activate automaticaly when limit has been reached
1016  if (active_limit > 0 && !active && available() >= active_limit){
1017  this->active = true;
1018  }
1019 
1020  // make space by deleting oldest entries
1021  if (remove_oldest_data){
1022  int available_bytes = callback_buffer_ptr->availableForWrite()*sizeof(T);
1023  if ((int)len>available_bytes){
1024  int gap = len-available_bytes;
1025  uint8_t tmp[gap];
1026  readBytes(tmp, gap);
1027  }
1028  }
1029 
1030  return callback_buffer_ptr->writeArray(data, len / sizeof(T));
1031  }
1032 
1033  virtual size_t readBytes(uint8_t *data, size_t len) override {
1034  if (!active) return 0;
1035  return callback_buffer_ptr->readArray(data, len / sizeof(T));
1036  }
1037 
1039  void clear() {
1040  if (active){
1041  callback_buffer_ptr->reset();
1042  }
1043  }
1044 
1046  operator bool(){
1047  return active;
1048  }
1049 
1050  protected:
1051  BaseBuffer<T> *callback_buffer_ptr;
1052  size_t active_limit = 0;
1053  bool active;
1054  bool remove_oldest_data;
1055  bool owns_buffer;
1056 
1057 };
1058 
1059 // support legacy name
1060 template <typename T>
1061 using CallbackBufferedStream = QueueStream<T>;
1062 
1071 template<typename T>
1073 
1074  public:
1075  ConverterStream() = default;
1076 
1077  ConverterStream(BaseConverter &converter) {
1078  setConverter(converter);
1079  }
1080 
1081  ConverterStream(Stream &stream, BaseConverter &converter) {
1082  setConverter(converter);
1083  setStream(stream);
1084  }
1085 
1086  ConverterStream(Print &out, BaseConverter &converter) {
1087  setConverter(converter);
1088  setOutput(out);
1089  }
1090 
1091  void setStream(Stream &stream){
1092  TRACEI();
1093  p_stream = &stream;
1094  p_out = &stream;
1095  }
1096 
1097  void setOutput(Print &out){
1098  TRACEI();
1099  p_out = &out;
1100  }
1101 
1102  void setConverter(BaseConverter& cnv){
1103  p_converter = &cnv;
1104  }
1105 
1106  virtual int availableForWrite() { return p_out->availableForWrite(); }
1107 
1108  virtual size_t write(const uint8_t *buffer, size_t size) {
1109  size_t result = p_converter->convert((uint8_t *)buffer, size);
1110  if (result>0) {
1111  size_t result_written = p_out->write(buffer, result);
1112  return size * result_written / result;
1113  }
1114  return 0;
1115  }
1116 
1117  size_t readBytes(uint8_t *data, size_t length) override {
1118  if (p_stream==nullptr) return 0;
1119  size_t result = p_stream->readBytes(data, length);
1120  return p_converter->convert(data, result);
1121  }
1122 
1124  virtual int available() override {
1125  if (p_stream==nullptr) return 0;
1126  return p_stream->available();
1127  }
1128 
1129  protected:
1130  Stream *p_stream = nullptr;
1131  Print *p_out = nullptr;
1132  BaseConverter *p_converter;
1133 
1134 };
1135 
1143  public:
1144  MeasuringStream(int count=10, Print *logOut=nullptr){
1145  this->count = count;
1146  this->max_count = count;
1147  p_stream = &null;
1148  p_print = &null;
1149  start_time = millis();
1150  p_logout = logOut;
1151  }
1152 
1153  MeasuringStream(Print &print, int count=10, Print *logOut=nullptr){
1154  this->count = count;
1155  this->max_count = count;
1156  setOutput(print);
1157  start_time = millis();
1158  p_logout = logOut;
1159  }
1160 
1161  MeasuringStream(Stream &stream, int count=10, Print *logOut=nullptr){
1162  this->count = count;
1163  this->max_count = count;
1164  setStream(stream);
1165  start_time = millis();
1166  p_logout = logOut;
1167  }
1168 
1170  void setStream(Stream& io) override {
1171  p_print = &io;
1172  p_stream = &io;
1173  };
1174 
1176  void setOutput(Print& out) override {
1177  p_print = &out;
1178  }
1179 
1180 
1182  size_t readBytes(uint8_t* data, size_t len) override {
1183  return measure(p_stream->readBytes(data, len));
1184  }
1185 
1186  int available() override {
1187  return p_stream->available();
1188  }
1189 
1191  virtual size_t write(const uint8_t *buffer, size_t size) override {
1192  return measure(p_print->write(buffer, size));
1193  }
1194 
1196  virtual int availableForWrite() override {
1197  return p_print->availableForWrite();
1198  }
1199 
1202  return bytes_per_second;
1203  }
1204 
1206  uint32_t startTime() {
1207  return start_time;
1208  }
1209 
1211  AudioStream::info = info;
1212  setFrameSize(info.bits_per_sample / 8 *info.channels);
1213  }
1214 
1215  bool begin(){
1216  return AudioStream::begin();
1217  }
1218 
1219  bool begin(AudioInfo info){
1220  setAudioInfo(info);
1221  return true;
1222  }
1223 
1224  void setFrameSize(int size){
1225  frame_size = size;
1226  }
1227 
1228  protected:
1229  int max_count=0;
1230  int count=0;
1231  Stream *p_stream=nullptr;
1232  Print *p_print=nullptr;
1233  uint32_t start_time;
1234  int total_bytes = 0;
1235  int bytes_per_second = 0;
1236  int frame_size = 0;
1237  NullStream null;
1238  Print *p_logout=nullptr;
1239 
1240  size_t measure(size_t len) {
1241  count--;
1242  total_bytes+=len;
1243 
1244  if (count<=0){
1245  uint32_t end_time = millis();
1246  int time_diff = end_time - start_time; // in ms
1247  if (time_diff>0){
1248  bytes_per_second = total_bytes / time_diff * 1000;
1249  printResult();
1250  count = max_count;
1251  total_bytes = 0;
1252  start_time = end_time;
1253  }
1254  }
1255  return len;
1256  }
1257 
1258  void printResult() {
1259  char msg[70];
1260  if (frame_size==0){
1261  snprintf(msg, 70, "==> Bytes per second: %d", bytes_per_second);
1262  } else {
1263  snprintf(msg, 70, "==> Samples per second: %d", bytes_per_second/frame_size);
1264  }
1265  if (p_logout!=nullptr){
1266  p_logout->println(msg);
1267  } else {
1268  LOGI("%s",msg);
1269  }
1270  }
1271 };
1272 
1280  public:
1281  size_t total_size = 0;
1282 };
1291  public:
1292  ProgressStream() = default;
1293 
1294  ProgressStream(Print &print){
1295  setPrint(print);
1296  }
1297 
1298  ProgressStream(Stream &stream){
1299  setStream(stream);
1300  }
1301 
1302  ProgressStream(AudioStream &stream){
1303  setStream(stream);
1304  p_info_from = &stream;
1305  }
1306 
1307  ProgressStreamInfo& defaultConfig() {
1308  return progress_info;
1309  }
1310 
1311  void setAudioInfo(AudioInfo info) override {
1313  progress_info.copyFrom(info);
1314  }
1315 
1316  void setStream(Stream &stream){
1317  p_stream =&stream;
1318  p_print = &stream;
1319  }
1320 
1321  void setStream(Print &print){
1322  p_print =&print;
1323  }
1324 
1325  void setPrint(Print &print){
1326  p_print =&print;
1327  }
1328 
1329  bool begin() override {
1330  if (p_info_from!=nullptr){
1331  setAudioInfo(p_info_from->audioInfo());
1332  }
1333  return AudioStream::begin();
1334  }
1335 
1337  bool begin(size_t len){
1338  setSize(len);
1339  return begin();
1340  }
1341 
1342  bool begin(ProgressStreamInfo info){
1343  progress_info = info;
1344  setAudioInfo(info);
1345  return begin();
1346  }
1347 
1349  void setSize(size_t len){
1350  total_processed = 0;
1351  progress_info.total_size = len;
1352  }
1353 
1355  size_t size(){
1356  return progress_info.total_size;
1357  }
1358 
1360  size_t processedBytes() {
1361  return total_processed;
1362  }
1363 
1365  size_t processedSecs() {
1366  return total_processed / byteRate();
1367  }
1368 
1370  size_t totalBytes() {
1371  return progress_info.total_size;
1372  }
1373 
1375  size_t totalSecs() {
1376  return totalBytes() / byteRate();
1377  }
1378 
1380  float percentage() {
1381  if (progress_info.total_size==0) return 0;
1382  return 100.0 * total_processed / progress_info.total_size;
1383  }
1384 
1386  size_t readBytes(uint8_t* data, size_t len) override {
1387  if (p_stream==nullptr) return 0;
1388  return measure(p_stream->readBytes(data, len));
1389  }
1390 
1391  int available() override {
1392  if (p_stream==nullptr) return 0;
1393  return p_stream->available();
1394  }
1395 
1397  virtual size_t write(const uint8_t *buffer, size_t size) override {
1398  if (p_print==nullptr) return 0;
1399  return measure(p_print->write(buffer, size));
1400  }
1401 
1403  virtual int availableForWrite() override {
1404  if (p_print==nullptr) return 0;
1405  return p_print->availableForWrite();
1406  }
1407 
1408  protected:
1409  ProgressStreamInfo progress_info;
1410  Stream *p_stream=nullptr;
1411  Print *p_print=nullptr;
1412  AudioInfoSupport *p_info_from=nullptr;
1413  size_t total_processed = 0;
1414 
1415  size_t measure(size_t len) {
1416  total_processed += len;
1417  return len;
1418  }
1419 
1420  size_t byteRate() {
1421  AudioInfo info = audioInfo();
1422  int byte_rate = info.sample_rate * info.bits_per_sample * info.channels / 8;
1423  if (byte_rate==0){
1424  LOGE("Audio Info not defined");
1425  return 0;
1426  }
1427  return byte_rate;
1428  }
1429 
1430 };
1431 
1437 struct ThrottleConfig : public AudioInfo {
1438  ThrottleConfig() {
1439  sample_rate = 44100;
1440  bits_per_sample = 16;
1441  channels = 2;
1442  }
1443  int correction_us = 0;
1444 };
1445 
1452 class Throttle : public ModifyingStream {
1453  public:
1454  Throttle() = default;
1455  Throttle(Print &out) { setOutput(out); }
1456  Throttle(Stream &io) { setStream(io); }
1457 
1459  void setStream(Stream& io) override {
1460  p_out = &io;
1461  p_in = &io;
1462  };
1463 
1465  void setOutput(Print& out) override {
1466  p_out = &out;
1467  }
1468 
1469  ThrottleConfig defaultConfig() {
1470  ThrottleConfig c;
1471  return c;
1472  }
1473 
1474  bool begin(ThrottleConfig cfg) {
1475  LOGI("begin sample_rate: %d, channels: %d, bits: %d", (int) info.sample_rate,(int) info.channels, (int)info.bits_per_sample);
1476  this->info = cfg;
1477  this->cfg = cfg;
1478  return begin();
1479  }
1480 
1481  bool begin(AudioInfo info) {
1482  LOGI("begin sample_rate: %d, channels: %d, bits: %d", (int)info.sample_rate, (int) info.channels, (int)info.bits_per_sample);
1483  this->info = info;
1484  this->cfg.copyFrom(info);
1485  return begin();
1486  }
1487 
1488  bool begin(){
1489  frame_size = cfg.bits_per_sample / 8 * cfg.channels;
1490  startDelay();
1491  return true;
1492  }
1493 
1494  // (re)starts the timing
1495  void startDelay() {
1496  start_time = micros();
1497  sum_frames = 0;
1498  }
1499 
1500  int availableForWrite() {
1501  if (p_out){
1502  return p_out->availableForWrite();
1503  }
1504  return DEFAULT_BUFFER_SIZE;
1505  }
1506 
1507  size_t write(const uint8_t* data, size_t len){
1508  size_t result = p_out->write(data, len);
1509  delayBytes(len);
1510  return result;
1511  }
1512 
1513  int available() {
1514  if (p_in==nullptr) return 0;
1515  return p_in->available();
1516  }
1517 
1518  size_t readBytes(uint8_t* data, size_t len){
1519  if (p_in==nullptr) {
1520  delayBytes(len);
1521  return 0;
1522  }
1523  size_t result = p_in->readBytes(data, len);
1524  delayBytes(len);
1525  return result;
1526  }
1527 
1528  // delay
1529  void delayBytes(size_t bytes) { delayFrames(bytes / frame_size); }
1530 
1531  // delay
1532  void delayFrames(size_t frames) {
1533  sum_frames += frames;
1534  uint64_t durationUsEff = micros() - start_time;
1535  uint64_t durationUsToBe = getDelayUs(sum_frames);
1536  int64_t waitUs = durationUsToBe - durationUsEff + cfg.correction_us;
1537  LOGD("wait us: %ld", static_cast<long>(waitUs));
1538  if (waitUs > 0) {
1539  int64_t waitMs = waitUs / 1000;
1540  if (waitMs > 0) delay(waitMs);
1541  delayMicroseconds(waitUs - (waitMs * 1000));
1542  } else {
1543  LOGD("negative delay!")
1544  }
1545  }
1546 
1547  inline int64_t getDelayUs(uint64_t frames){
1548  return (frames * 1000000) / cfg.sample_rate;
1549  }
1550 
1551  inline int64_t getDelayMs(uint64_t frames){
1552  return getDelayUs(frames) / 1000;
1553  }
1554 
1555  inline int64_t getDelaySec(uint64_t frames){
1556  return getDelayUs(frames) / 1000000l;
1557  }
1558 
1559  protected:
1560  uint32_t start_time = 0;
1561  uint32_t sum_frames = 0;
1562  ThrottleConfig cfg;
1563  int frame_size = 0;
1564  Print *p_out = nullptr;
1565  Stream *p_in = nullptr;
1566 };
1567 
1568 
1577 template<typename T>
1578 class InputMixer : public AudioStream {
1579  public:
1580  InputMixer() = default;
1581 
1583  void add(Stream &in, int weight=100){
1584  streams.push_back(&in);
1585  weights.push_back(weight);
1586  total_weights += weight;
1587  }
1588 
1590  void set(int channel, Stream &in){
1591  if (channel<size()){
1592  streams[channel] = &in;
1593  } else {
1594  LOGE("Invalid channel %d - max is %d", channel, size()-1);
1595  }
1596  }
1597 
1598  virtual bool begin(AudioInfo info) {
1599  setAudioInfo(info);
1600  frame_size = info.bits_per_sample/8 * info.channels;
1601  LOGI("frame_size: %d",frame_size);
1602  return frame_size>0;
1603  }
1604 
1606  void setWeight(int channel, int weight){
1607  if (channel<size()){
1608  weights[channel] = weight;
1609  int total = 0;
1610  for (int j=0;j<weights.size();j++){
1611  total += weights[j];
1612  }
1613  total_weights = total;
1614  } else {
1615  LOGE("Invalid channel %d - max is %d", channel, size()-1);
1616  }
1617  }
1618 
1620  void end() override {
1621  streams.clear();
1622  weights.clear();
1623  result_vect.clear();
1624  current_vect.clear();
1625  total_weights = 0.0;
1626  }
1627 
1629  int size() {
1630  return streams.size();
1631  }
1632 
1634  size_t readBytes(uint8_t* data, size_t len) override {
1635  if (total_weights==0 || frame_size==0 || len==0) {
1636  LOGW("readBytes: %d",(int)len);
1637  return 0;
1638  }
1639 
1640  if (limit_available_data){
1641  len = min((int)len, availableBytes());
1642  }
1643 
1644  int result_len = 0;
1645 
1646  if (len > 0) {
1647  // result_len must be full frames
1648  result_len = len * frame_size / frame_size;
1649  // replace sample based with vector based implementation
1650  //readBytesSamples((T*)data, result_len));
1651  result_len = readBytesVector((T*)data, result_len);
1652  }
1653  return result_len;
1654  }
1655 
1657  void setLimitToAvailableData(bool flag){
1658  limit_available_data = flag;
1659  }
1660 
1662  void setRetryCount(int retry){
1663  retry_count = retry;
1664  }
1665 
1666  protected:
1667  Vector<Stream*> streams{0};
1668  Vector<int> weights{0};
1669  int total_weights = 0;
1670  int frame_size = 4;
1671  bool limit_available_data = false;
1672  int retry_count = 5;
1673  Vector<int> result_vect;
1674  Vector<T> current_vect;
1675 
1677  int readBytesVector(T* p_data, int byteCount) {
1678  int samples = byteCount / sizeof(T);
1679  result_vect.resize(samples);
1680  current_vect.resize(samples);
1681  int stream_count = size();
1682  resultClear();
1683  int samples_eff_max = 0;
1684  for (int j=0;j<stream_count;j++){
1685  if (weights[j]>0){
1686  int samples_eff = readSamples(streams[j],current_vect.data(), samples, retry_count);
1687  if (samples_eff > samples_eff_max)
1688  samples_eff_max = samples_eff;
1689  // if all weights are 0.0 we stop to output
1690  float factor = total_weights == 0.0f ? 0.0f : static_cast<float>(weights[j]) / total_weights;
1691  resultAdd(factor);
1692  }
1693  }
1694  // copy result
1695  for (int j=0;j<samples;j++){
1696  p_data[j] = result_vect[j];
1697  }
1698  return samples_eff_max * sizeof(T);
1699  }
1700 
1703  int result = DEFAULT_BUFFER_SIZE;
1704  for (int j=0;j<size();j++){
1705  result = min(result, streams[j]->available());
1706  }
1707  return result;
1708  }
1709 
1710  void resultAdd(float fact){
1711  for (int j=0;j<current_vect.size();j++){
1712  current_vect[j]*=fact;
1713  result_vect[j] += current_vect[j];
1714  }
1715  }
1716 
1717  void resultClear(){
1718  memset(result_vect.data(), 0, sizeof(int)*result_vect.size());
1719  }
1720 
1721 };
1722 
1732 template<typename T>
1733 class InputMerge : public AudioStream {
1734  public:
1736  InputMerge() = default;
1737 
1741  InputMerge(Stream &left, Stream &right) {
1742  add(left);
1743  add(right);
1744  };
1745 
1746  virtual bool begin(AudioInfo info) {
1747  if (size()!=info.channels){
1748  info.channels = size();
1749  LOGW("channels corrected to %d", size());
1750  }
1751  setAudioInfo(info);
1752  return begin();
1753  }
1754 
1755  virtual bool begin() {
1756  // make sure that we use the correct channel count
1757  info.channels = size();
1758  return AudioStream::begin();
1759  }
1760 
1762  size_t readBytes(uint8_t* data, size_t len) override {
1763  LOGD("readBytes: %d",(int)len);
1764  T *p_data = (T*) data;
1765  int result_len = MIN(available(), len/size());
1766  int sample_count = result_len / sizeof(T);
1767  int size_value = size();
1768  int result_idx = 0;
1769  for (int j=0;j<sample_count; j++){
1770  for (int i=0; i<size_value; i++){
1771  p_data[result_idx++] = weights[i] * readSample<T>(streams[i]);
1772  }
1773  }
1774  return result_idx*sizeof(T);
1775  }
1776 
1778  void add(Stream &in, float weight=1.0){
1779  streams.push_back(&in);
1780  weights.push_back(weight);
1781  }
1782 
1784  void setWeight(int channel, float weight){
1785  if (channel<size()){
1786  weights[channel] = weight;
1787  } else {
1788  LOGE("Invalid channel %d - max is %d", channel, size()-1);
1789  }
1790  }
1791 
1793  void end() override {
1794  streams.clear();
1795  weights.clear();
1796  }
1797 
1799  int size() {
1800  return streams.size();
1801  }
1802 
1804  int available() override {
1805  int result = streams[0]->available();
1806  for (int j=1;j<size();j++){
1807  int tmp = streams[j]->available();
1808  if (tmp<result){
1809  result = tmp;
1810  }
1811  }
1812  return result;
1813  }
1814 
1815  protected:
1816  Vector<Stream*> streams{10};
1817  Vector<float> weights{10};
1818 };
1819 
1820 
1829  public:
1830  CallbackStream() = default;
1831 
1833  CallbackStream(Stream &io, size_t (*cb_update)(uint8_t* data, size_t len)) {
1834  p_stream = &io;
1835  p_out = &io;
1836  setUpdateCallback(cb_update);
1837  }
1838 
1840  CallbackStream(Print &out, size_t (*cb_update)(uint8_t* data, size_t len)) {
1841  p_out = &out;
1842  setUpdateCallback(cb_update);
1843  }
1844 
1845  CallbackStream(size_t (*cb_read)(uint8_t* data, size_t len), size_t (*cb_write)(const uint8_t* data, size_t len)) {
1846  setWriteCallback(cb_write);
1847  setReadCallback(cb_read);
1848  }
1849 
1850  void setWriteCallback(size_t (*cb_write)(const uint8_t* data, size_t len)){
1851  this->cb_write = cb_write;
1852  }
1853 
1854  void setReadCallback(size_t (*cb_read)(uint8_t* data, size_t len)){
1855  this->cb_read = cb_read;
1856  }
1857 
1858  void setUpdateCallback(size_t (*cb_update)(uint8_t* data, size_t len)){
1859  this->cb_update = cb_update;
1860  }
1861 
1862  // callback result negative -> no change; callbeack result >=0 provides the result
1863  void setAvailableCallback(int (*cb)()){
1864  this->cb_available = cb;
1865  }
1866 
1867  virtual bool begin(AudioInfo info) {
1868  setAudioInfo(info);
1869  return begin();
1870  }
1871 
1872  virtual bool begin() override {
1873  active = true;
1874  return true;
1875  }
1876  void end() override { active = false;}
1877 
1878  int available() override {
1879  int result = AudioStream::available();
1880  // determine value from opional variable
1881  if (available_bytes>=0)
1882  return available_bytes;
1883  // check if there is a callback
1884  if (cb_available==nullptr)
1885  return result;
1886  // determine value from callback
1887  int tmp_available = cb_available();
1888  if (tmp_available < 0)
1889  return result;
1890 
1891  return tmp_available;
1892  }
1893 
1894  size_t readBytes(uint8_t* data, size_t len) override {
1895  if (!active) return 0;
1896  // provide data from callback
1897  if (cb_read){
1898  return cb_read(data, len);
1899  }
1900  // provide data from source
1901  size_t result = 0;
1902  if (p_stream){
1903  result = p_stream->readBytes(data , len);
1904  }
1905  if (cb_update){
1906  result = cb_update(data, result);
1907  }
1908  return result;
1909  }
1910 
1911  size_t write(const uint8_t* data, size_t len) override {
1912  if (!active) return 0;
1913  // write to callback
1914  if (cb_write){
1915  return cb_write(data, len);
1916  }
1917  // write to output
1918  if(p_out){
1919  size_t result = len;
1920  if (cb_update) {
1921  result = cb_update((uint8_t*)data, len);
1922  }
1923  return p_out->write(data, result);
1924  }
1925  // no processing possible
1926  return 0;
1927  }
1928 
1930  void setStream(Stream &in){
1931  p_stream = &in;
1932  p_out = &in;
1933  }
1934 
1936  void setOutput(Print &out){
1937  p_out = &out;
1938  }
1939 
1941  void setOutput(Stream &in){
1942  p_stream = &in;
1943  p_out = &in;
1944  }
1945 
1947  void setStream(Print &out){
1948  p_out = &out;
1949  }
1950 
1952  void setAvailable(int val){
1953  available_bytes = val;
1954  }
1955 
1956 
1957 
1958  protected:
1959  bool active=true;
1960  size_t (*cb_write)(const uint8_t* data, size_t len) = nullptr;
1961  size_t (*cb_read)(uint8_t* data, size_t len) = nullptr;
1962  size_t (*cb_update)(uint8_t* data, size_t len) = nullptr;
1963  int (*cb_available)() = nullptr;
1964  Stream *p_stream = nullptr;
1965  Print *p_out = nullptr;
1966  int available_bytes = -1;
1967 };
1968 
1978 class CatStream : public AudioStream {
1979  public:
1980  CatStream(){
1981  _timeout = 0;
1982  }
1983  void add(Stream *stream){
1984  input_streams.push_back(stream);
1985  }
1986  void add(Stream &stream){
1987  input_streams.push_back(&stream);
1988  }
1989 
1990  bool begin() override {
1991  is_active = true;
1992  return AudioStream::begin();
1993  }
1994 
1995  void end() override {
1996  is_active = false;
1997  return AudioStream::end();
1998  }
1999 
2000  int available() override {
2001  if (!is_active) return 0;
2002  if (!moveToNextStreamOnEnd()){
2003  return 0;
2004  }
2005  return availableWithTimout();
2006  }
2007 
2008  size_t readBytes(uint8_t* data, size_t len) override {
2009  if (!is_active) return 0;
2010  if (!moveToNextStreamOnEnd()){
2011  return 0;
2012  }
2013  return p_current_stream->readBytes(data, len);
2014  }
2015 
2017  operator bool(){
2018  return is_active && available()>0;
2019  }
2020 
2021  void setOnBeginCallback(void (*callback)(Stream* stream) ){
2022  begin_callback = callback;
2023  }
2024  void setOnEndCallback(void (*callback)(Stream* stream) ){
2025  end_callback = callback;
2026  }
2027 
2028 protected:
2029  Vector<Stream*> input_streams;
2030  Stream *p_current_stream = nullptr;
2031  bool is_active = false;
2032  void (*begin_callback)(Stream* stream) = nullptr;
2033  void (*end_callback)(Stream* stream) = nullptr;
2034 
2037  // keep on running
2038  if (p_current_stream!=nullptr && p_current_stream->available()>0) return true;
2039  // at end?
2040  if ((p_current_stream==nullptr || availableWithTimout()==0)){
2041  if (end_callback && p_current_stream) end_callback(p_current_stream);
2042  if (!input_streams.empty()) {
2043  LOGI("using next stream");
2044  p_current_stream = input_streams[0];
2045  input_streams.pop_front();
2046  if (begin_callback && p_current_stream) begin_callback(p_current_stream);
2047  } else {
2048  p_current_stream = nullptr;
2049  }
2050  }
2051  // returns true if we have a valid stream
2052  return p_current_stream!=nullptr;
2053  }
2054 
2055  int availableWithTimout(){
2056  int result = p_current_stream->available();
2057  if (result==0){
2058  for (int j=0; j <_timeout/10;j++){
2059  delay(10);
2060  result = p_current_stream->available();
2061  if (result!=0) break;
2062  }
2063  }
2064  return result;
2065  }
2066 
2067 };
2068 
2076 template<typename T, class TF>
2078  public:
2079  FilteredStream() = default;
2080  FilteredStream(Stream &stream) : ModifyingStream() {
2081  setStream(stream);
2082  }
2083  FilteredStream(Stream &stream, int channels) : ModifyingStream() {
2084  this->channels = channels;
2085  setStream(stream);
2086  p_converter = new ConverterNChannels<T,TF>(channels);
2087  }
2088  FilteredStream(Print &stream) : ModifyingStream() {
2089  setOutput(stream);
2090  }
2091  FilteredStream(Print &stream, int channels) : ModifyingStream() {
2092  this->channels = channels;
2093  setOutput(stream);
2094  p_converter = new ConverterNChannels<T,TF>(channels);
2095  }
2096 
2097  void setStream(Stream &stream){
2098  p_stream = &stream;
2099  p_print = &stream;
2100  }
2101 
2102  void setOutput(Print &stream){
2103  p_print = &stream;
2104  }
2105 
2106  bool begin(AudioInfo info){
2107  setAudioInfo(info);
2108  this->channels = info.channels;
2109  if (p_converter !=nullptr && info.channels!=channels){
2110  LOGE("Inconsistent number of channels");
2111  return false;
2112  }
2113  return begin();
2114  }
2115 
2116  bool begin() override {
2117  if (channels ==0){
2118  LOGE("channels must not be 0");
2119  return false;
2120  }
2121  if (p_converter==nullptr){
2122  p_converter = new ConverterNChannels<T,TF>(channels);
2123  }
2124  return AudioStream::begin();
2125  }
2126 
2127  virtual size_t write(const uint8_t *buffer, size_t size) override {
2128  if (p_converter==nullptr) return 0;
2129  size_t result = p_converter->convert((uint8_t *)buffer, size);
2130  return p_print->write(buffer, result);
2131  }
2132 
2133  size_t readBytes(uint8_t *data, size_t length) override {
2134  if (p_converter==nullptr) return 0;
2135  if (p_stream==nullptr) return 0;
2136  size_t result = p_stream->readBytes(data, length);
2137  result = p_converter->convert(data, result);
2138  return result;
2139  }
2140 
2141  virtual int available() override {
2142  if (p_stream==nullptr) return 0;
2143  return p_stream->available();
2144  }
2145 
2146  virtual int availableForWrite() override {
2147  return p_print->availableForWrite();
2148  }
2149 
2152  void setFilter(int channel, Filter<TF> *filter) {
2153  if (p_converter!=nullptr){
2154  p_converter->setFilter(channel, filter);
2155  } else {
2156  LOGE("p_converter is null");
2157  }
2158  }
2159 
2162  void setFilter(int channel, Filter<TF> &filter) {
2163  setFilter(channel, &filter);
2164  }
2165 
2166  protected:
2167  int channels=0;
2168  Stream *p_stream = nullptr;
2169  Print *p_print = nullptr;
2170  ConverterNChannels<T,TF> *p_converter;
2171 
2172 };
2173 
2174 #ifdef USE_TIMER
2181  RxTxMode rx_tx_mode = RX_MODE;
2182  uint16_t buffer_size = DEFAULT_BUFFER_SIZE;
2183  bool use_timer = true;
2184  int timer_id = -1;
2185  TimerFunction timer_function = DirectTimerCallback;
2186  bool adapt_sample_rate = false;
2187  uint16_t (*callback)(uint8_t *data, uint16_t len) = nullptr;
2188 };
2189 
2190 // forward declaration: relevant only if use_timer == true
2191 static void timerCallback(void *obj);
2202  friend void timerCallback(void *obj);
2203 
2204  public:
2205  TimerCallbackAudioStream() : BufferedStream(80) { TRACED(); }
2206 
2208  TRACED();
2209  if (timer != nullptr) delete timer;
2210  if (buffer != nullptr) delete buffer;
2211  if (frame != nullptr) delete[] frame;
2212  }
2213 
2217  return def;
2218  }
2219 
2221  virtual void setAudioInfo(AudioInfo info) {
2222  TRACED();
2223  if (cfg.sample_rate != info.sample_rate || cfg.channels != info.channels ||
2224  cfg.bits_per_sample != info.bits_per_sample) {
2225  bool do_restart = active;
2226  if (do_restart) end();
2227  cfg.sample_rate = info.sample_rate;
2228  cfg.channels = info.channels;
2229  cfg.bits_per_sample = info.bits_per_sample;
2230  if (do_restart) begin(cfg);
2231  }
2232  }
2233 
2236  AudioInfo audioInfo() { return cfg; }
2237 
2238  void begin(TimerCallbackAudioStreamInfo config) {
2239  LOGD("%s: %s", LOG_METHOD,
2240  config.rx_tx_mode == RX_MODE ? "RX_MODE" : "TX_MODE");
2241  this->cfg = config;
2242  this->frameCallback = config.callback;
2243  if (cfg.use_timer) {
2244  frameSize = cfg.bits_per_sample * cfg.channels / 8;
2245  frame = new uint8_t[frameSize];
2246  buffer = new RingBuffer<uint8_t>(cfg.buffer_size);
2247  timer = new TimerAlarmRepeating();
2248  timer->setTimerFunction(cfg.timer_function);
2249  if (cfg.timer_id>=0){
2250  timer->setTimer(cfg.timer_id);
2251  }
2252  time = AudioTime::toTimeUs(cfg.sample_rate);
2253  LOGI("sample_rate: %u -> time: %u milliseconds", (unsigned int)cfg.sample_rate, (unsigned int)time);
2254  timer->setCallbackParameter(this);
2255  timer->begin(timerCallback, time, TimeUnit::US);
2256  }
2257 
2258  notifyAudioChange(cfg);
2259  active = true;
2260  }
2261 
2263  bool begin() {
2264  TRACED();
2265  if (this->frameCallback != nullptr) {
2266  if (cfg.use_timer) {
2267  timer->begin(timerCallback, time, TimeUnit::US);
2268  }
2269  active = true;
2270  }
2271  return active;
2272  }
2273 
2275  void end() {
2276  TRACED();
2277  if (cfg.use_timer) {
2278  timer->end();
2279  }
2280  active = false;
2281  }
2282 
2284  uint16_t currentSampleRate() { return currentRateValue; }
2285 
2286  protected:
2288  bool active = false;
2289  uint16_t (*frameCallback)(uint8_t *data, uint16_t len);
2290  // below only relevant with timer
2291  TimerAlarmRepeating *timer = nullptr;
2292  RingBuffer<uint8_t> *buffer = nullptr;
2293  uint8_t *frame = nullptr;
2294  uint16_t frameSize = 0;
2295  uint32_t time = 0;
2296  unsigned long lastTimestamp = 0u;
2297  uint32_t currentRateValue = 0;
2298  uint32_t printCount = 0;
2299 
2300  // used for audio sink
2301  virtual size_t writeExt(const uint8_t *data, size_t len) override {
2302  if (!active) return 0;
2303  TRACED();
2304  size_t result = 0;
2305  if (!cfg.use_timer) {
2306  result = frameCallback((uint8_t *)data, len);
2307  } else {
2308  result = buffer->writeArray((uint8_t *)data, len);
2309  }
2310  if (++printCount % 10000 == 0) printSampleRate();
2311  return result;
2312  }
2313 
2314  // used for audio source
2315  virtual size_t readExt(uint8_t *data, size_t len) override {
2316  if (!active) return 0;
2317  TRACED();
2318 
2319  size_t result = 0;
2320  if (!cfg.use_timer) {
2321  result = frameCallback(data, len);
2322  } else {
2323  result = buffer->readArray(data, len);
2324  }
2325  if (++printCount % 10000 == 0) printSampleRate();
2326  return result;
2327  }
2328 
2330  virtual void measureSampleRate() {
2331  unsigned long ms = millis();
2332  if (lastTimestamp > 0u) {
2333  uint32_t diff = ms - lastTimestamp;
2334  if (diff > 0) {
2335  uint16_t rate = 1 * 1000 / diff;
2336 
2337  if (currentRateValue == 0) {
2338  currentRateValue = rate;
2339  } else {
2340  currentRateValue = (currentRateValue + rate) / 2;
2341  }
2342  }
2343  }
2344  lastTimestamp = ms;
2345  }
2346 
2348  virtual void printSampleRate() {
2349  LOGI("effective sample rate: %u", (unsigned int)currentRateValue);
2350  if (cfg.adapt_sample_rate &&
2351  abs((int)currentRateValue - (int)cfg.sample_rate) > 200) {
2352  cfg.sample_rate = currentRateValue;
2353  notifyAudioChange(cfg);
2354  }
2355  }
2356 };
2357 
2358 // relevant only if use_timer == true
2359 void IRAM_ATTR timerCallback(void *obj) {
2360  TimerCallbackAudioStream *src = (TimerCallbackAudioStream *)obj;
2361  if (src != nullptr) {
2362  // LOGD("%s: %s", LOG_METHOD, src->cfg.rx_tx_mode==RX_MODE ?
2363  // "RX_MODE":"TX_MODE");
2364  if (src->cfg.rx_tx_mode == RX_MODE) {
2365  // input
2366  uint16_t available_bytes = src->frameCallback(src->frame, src->frameSize);
2367  uint16_t buffer_available = src->buffer->availableForWrite();
2368  if (buffer_available < available_bytes) {
2369  // if buffer is full make space
2370  uint16_t to_clear = available_bytes - buffer_available;
2371  uint8_t tmp[to_clear];
2372  src->buffer->readArray(tmp, to_clear);
2373  }
2374  if (src->buffer->writeArray(src->frame, available_bytes) !=
2375  available_bytes) {
2376  assert(false);
2377  }
2378  } else {
2379  // output
2380  if (src->buffer != nullptr && src->frame != nullptr &&
2381  src->frameSize > 0) {
2382  uint16_t available_bytes =
2383  src->buffer->readArray(src->frame, src->frameSize);
2384  if (available_bytes !=
2385  src->frameCallback(src->frame, available_bytes)) {
2386  LOGE("data underflow");
2387  }
2388  }
2389  }
2390  src->measureSampleRate();
2391  }
2392 }
2393 
2394 #endif
2395 
2396 } // namespace audio_tools
Supports the subscription to audio change notifications.
Definition: AudioTypes.h:155
Supports changes to the sampling rate, bits and channels.
Definition: AudioTypes.h:136
virtual AudioInfo audioInfoOut()
provides the actual output AudioInfo: this is usually the same as audioInfo() unless we use a transfo...
Definition: AudioTypes.h:143
virtual AudioInfo audioInfo()=0
provides the actual input AudioInfo
Base class for all Audio Streams. It support the boolean operator to test if the object is ready with...
Definition: AudioStreams.h:40
virtual size_t readSilence(uint8_t *buffer, size_t length)
Source to generate silence: just sets the buffer to 0.
Definition: AudioStreams.h:105
virtual void setAudioInfo(AudioInfo newInfo) override
Defines the input AudioInfo.
Definition: AudioStreams.h:51
virtual void writeSilence(size_t len)
Writes len bytes of silence (=0).
Definition: AudioStreams.h:97
virtual AudioInfo audioInfo() override
provides the actual input AudioInfo
Definition: AudioStreams.h:84
To be used to support implementations where the readBytes is not virtual.
Definition: AudioStreams.h:163
static uint32_t toTimeUs(uint32_t samplingRate, uint8_t limit=10)
converts sampling rate to delay in microseconds (μs)
Definition: AudioTypes.h:259
Shared functionality of all buffers.
Definition: Buffers.h:30
virtual int readArray(T data[], int len)
reads multiple values
Definition: Buffers.h:41
virtual int writeArray(const T data[], int len)
Fills the buffer data.
Definition: Buffers.h:65
Abstract Base class for Converters A converter is processing the data in the indicated array.
Definition: BaseConverter.h:24
The Arduino Stream supports operations on single characters. This is usually not the best way to push...
Definition: AudioStreams.h:755
void flush() override
empties the buffer
Definition: AudioStreams.h:804
size_t write(uint8_t c) override
writes a byte to the buffer
Definition: AudioStreams.h:786
int peek() override
peeks a byte - to be avoided
Definition: AudioStreams.h:821
int available() override
Returns the available bytes in the buffer: to be avoided.
Definition: AudioStreams.h:839
size_t write(const uint8_t *data, size_t len) override
Use this method: write an array.
Definition: AudioStreams.h:794
void clear()
Clears all the data in the buffer.
Definition: AudioStreams.h:847
int read() override
reads a byte - to be avoided
Definition: AudioStreams.h:813
void setStream(Stream &io)
Defines/Changes the input & output.
Definition: AudioStreams.h:780
void setOutput(Print &out)
Defines/Changes the output target.
Definition: AudioStreams.h:774
size_t readBytes(uint8_t *data, size_t length) override
Use this method !!
Definition: AudioStreams.h:829
CallbackStream: A Stream that allows to register callback methods for accessing and providing data....
Definition: AudioStreams.h:1828
void setOutput(Stream &in)
same as setStream
Definition: AudioStreams.h:1941
CallbackStream(Print &out, size_t(*cb_update)(uint8_t *data, size_t len))
Allows to change the audio before sending it to the output.
Definition: AudioStreams.h:1840
void setStream(Print &out)
same as set Output
Definition: AudioStreams.h:1947
void setAvailable(int val)
optioinally define available bytes for next read
Definition: AudioStreams.h:1952
void setOutput(Print &out)
Defines/Changes the output target.
Definition: AudioStreams.h:1936
CallbackStream(Stream &io, size_t(*cb_update)(uint8_t *data, size_t len))
Allows to change the audio before sending it to the output or before getting it from the original inp...
Definition: AudioStreams.h:1833
void setStream(Stream &in)
Defines/Changes the input & output.
Definition: AudioStreams.h:1930
Provides data from a concatenation of Streams. Please note that the provided Streams can be played on...
Definition: AudioStreams.h:1978
bool moveToNextStreamOnEnd()
moves to the next stream if necessary: returns true if we still have a valid stream
Definition: AudioStreams.h:2036
void setFilter(int channel, Filter< FT > *filter)
defines the filter for an individual channel - the first channel is 0
Definition: BaseConverter.h:1059
Both the data of the read or write operations will be converted with the help of the indicated conver...
Definition: AudioStreams.h:1072
void setStream(Stream &stream)
Defines/Changes the input & output.
Definition: AudioStreams.h:1091
void setOutput(Print &out)
Defines/Changes the output target.
Definition: AudioStreams.h:1097
virtual int available() override
Returns the available bytes in the buffer: to be avoided.
Definition: AudioStreams.h:1124
MemoryStream which is written and read using the internal RAM. For each write the data is allocated o...
Definition: AudioStreams.h:470
void postProcessSmoothTransition(int channels, float factor=0.01, int remove=0)
Post processing after the recording. We add a smooth transition at the beginning and at the end.
Definition: AudioStreams.h:622
virtual bool begin() override
Intializes the processing.
Definition: AudioStreams.h:511
virtual void setLoop(bool loop)
Automatically rewinds to the beginning when reaching the end.
Definition: AudioStreams.h:522
void rewind()
Sets the read position to the beginning.
Definition: AudioStreams.h:547
Abstract filter interface definition;.
Definition: Filter.h:28
Stream to which we can apply Filters for each channel. The filter might change the result size!
Definition: AudioStreams.h:2077
void setStream(Stream &stream)
Defines/Changes the input & output.
Definition: AudioStreams.h:2097
void setFilter(int channel, Filter< TF > &filter)
Definition: AudioStreams.h:2162
void setOutput(Print &stream)
Defines/Changes the output target.
Definition: AudioStreams.h:2102
void setFilter(int channel, Filter< TF > *filter)
Definition: AudioStreams.h:2152
Source for reading generated tones. Please note.
Definition: AudioStreams.h:672
size_t readBytes(uint8_t *buffer, size_t length) override
privide the data as byte stream
Definition: AudioStreams.h:728
void end() override
stop the processing
Definition: AudioStreams.h:714
bool begin() override
start the processing
Definition: AudioStreams.h:688
AudioInfo audioInfo() override
provides the actual input AudioInfo
Definition: AudioStreams.h:720
bool begin(AudioInfo cfg)
start the processing
Definition: AudioStreams.h:701
virtual int available() override
This is unbounded so we just return the buffer size.
Definition: AudioStreams.h:725
Merges multiple input channels. The input must be mono! So if you provide 2 mono channels you get a s...
Definition: AudioStreams.h:1733
InputMerge()=default
Default constructor.
size_t readBytes(uint8_t *data, size_t len) override
Provides the data from all streams mixed together.
Definition: AudioStreams.h:1762
void end() override
Remove all input streams.
Definition: AudioStreams.h:1793
int available() override
Provides the min available data from all streams.
Definition: AudioStreams.h:1804
void setWeight(int channel, float weight)
Defines a new weight for the indicated channel: If you set it to 0 it is muted.
Definition: AudioStreams.h:1784
void add(Stream &in, float weight=1.0)
Adds a new input stream.
Definition: AudioStreams.h:1778
InputMerge(Stream &left, Stream &right)
Constructor for stereo signal from to mono input stream.
Definition: AudioStreams.h:1741
int size()
Number of stremams to which are mixed together = number of result channels.
Definition: AudioStreams.h:1799
MixerStream is mixing the input from Multiple Input Streams. All streams must have the same audo form...
Definition: AudioStreams.h:1578
void add(Stream &in, int weight=100)
Adds a new input stream.
Definition: AudioStreams.h:1583
void set(int channel, Stream &in)
Replaces a stream at the indicated channel.
Definition: AudioStreams.h:1590
size_t readBytes(uint8_t *data, size_t len) override
Provides the data from all streams mixed together.
Definition: AudioStreams.h:1634
void end() override
Remove all input streams.
Definition: AudioStreams.h:1620
int availableBytes()
Provides the available bytes from the first stream with data.
Definition: AudioStreams.h:1702
void setLimitToAvailableData(bool flag)
Limit the copy to the available data of all streams: stops to provide data when any stream has ended.
Definition: AudioStreams.h:1657
void setRetryCount(int retry)
Defines the maximum number of retrys to get data from an input before we abort the read and provide e...
Definition: AudioStreams.h:1662
int readBytesVector(T *p_data, int byteCount)
mixing using a vector of samples
Definition: AudioStreams.h:1677
int size()
Number of stremams to which are mixed together.
Definition: AudioStreams.h:1629
void setWeight(int channel, int weight)
Dynamically update the new weight for the indicated channel: If you set it to 0 it is muted (and the ...
Definition: AudioStreams.h:1606
Definition: List.h:26
Double linked list.
Definition: List.h:18
Class which measures the thruput.
Definition: AudioStreams.h:1142
void setOutput(Print &out) override
Defines/Changes the output target.
Definition: AudioStreams.h:1176
size_t readBytes(uint8_t *data, size_t len) override
Provides the data from all streams mixed together.
Definition: AudioStreams.h:1182
void setAudioInfo(AudioInfo info)
Defines the input AudioInfo.
Definition: AudioStreams.h:1210
virtual int availableForWrite() override
Provides the nubmer of bytes we can write.
Definition: AudioStreams.h:1196
uint32_t startTime()
Provides the time when the last measurement was started.
Definition: AudioStreams.h:1206
void setStream(Stream &io) override
Defines/Changes the input & output.
Definition: AudioStreams.h:1170
virtual size_t write(const uint8_t *buffer, size_t size) override
Writes raw PCM audio data, which will be the input for the volume control.
Definition: AudioStreams.h:1191
int bytesPerSecond()
Returns the actual thrughput in bytes per second.
Definition: AudioStreams.h:1201
A simple Stream implementation which is backed by allocated memory.
Definition: AudioStreams.h:223
MemoryStream(const uint8_t *buffer, int buffer_size, bool isActive=true, MemoryType memoryType=FLASH_RAM)
Constructor for data from Progmem, active is set to true automatically by default.
Definition: AudioStreams.h:235
virtual void setLoop(bool loop, int rewindPos)
Automatically rewinds to the indicated position when reaching the end.
Definition: AudioStreams.h:395
virtual void clear(bool reset=false)
clears the audio data: sets all values to 0
Definition: AudioStreams.h:366
void setValue(const uint8_t *buffer, int buffer_size, MemoryType memoryType=FLASH_RAM)
Update the values (buffer and size)
Definition: AudioStreams.h:428
MemoryStream(MemoryStream &&source)
Move Constructor.
Definition: AudioStreams.h:248
MemoryStream & operator=(MemoryStream &other)
copy assignement operator
Definition: AudioStreams.h:260
MemoryStream(MemoryStream &source)
Copy Constructor.
Definition: AudioStreams.h:243
virtual void setLoop(bool loop)
Automatically rewinds to the beginning when reaching the end. For wav files we move to pos 44 to igno...
Definition: AudioStreams.h:384
virtual bool resize(size_t size)
Resizes the available memory. Returns false for PROGMEM or when allocation failed.
Definition: AudioStreams.h:401
MemoryStream(int buffer_size, MemoryType memoryType)
Constructor for alloction in RAM.
Definition: AudioStreams.h:226
bool begin() override
resets the read pointer
Definition: AudioStreams.h:272
bool begin(AudioInfo info)
Define some audio info and start the processing.
Definition: AudioStreams.h:266
void setRewindCallback(void(*cb)())
Callback which is executed when we rewind (in loop mode) to the beginning.
Definition: AudioStreams.h:423
Abstract class: Objects can be put into a pipleline.
Definition: AudioStreams.h:208
virtual void setStream(Stream &in)=0
Defines/Changes the input & output.
virtual void setOutput(Print &out)=0
Defines/Changes the output target.
A lock free N buffer. If count=2 we create a DoubleBuffer, if count=3 a TripleBuffer etc.
Definition: Buffers.h:559
The Arduino Stream which provides silence and simulates a null device when used as audio target or au...
Definition: AudioStreams.h:875
void setAudioInfo(AudioInfo info) override
Defines the input AudioInfo.
Definition: AudioStreams.h:897
Definition: NoArduino.h:58
Generic calss to measure the the total bytes which were processed in order to calculate the progress ...
Definition: AudioStreams.h:1290
bool begin(size_t len)
Updates the total size and restarts the percent calculation: Same as calling setSize()
Definition: AudioStreams.h:1337
size_t size()
Provides the current total size (defined by setSize)
Definition: AudioStreams.h:1355
size_t totalSecs()
Converts the totalBytes() to seconds.
Definition: AudioStreams.h:1375
size_t readBytes(uint8_t *data, size_t len) override
Provides the data from all streams mixed together.
Definition: AudioStreams.h:1386
size_t processedBytes()
Provides the number of processed bytes.
Definition: AudioStreams.h:1360
void setStream(Stream &stream)
Defines/Changes the input & output.
Definition: AudioStreams.h:1316
void setSize(size_t len)
Updates the total size and restarts the percent calculation.
Definition: AudioStreams.h:1349
virtual int availableForWrite() override
Provides the nubmer of bytes we can write.
Definition: AudioStreams.h:1403
float percentage()
Provides the processed percentage: If no size has been defined we return 0.
Definition: AudioStreams.h:1380
size_t processedSecs()
Provides the number of processed seconds.
Definition: AudioStreams.h:1365
void setAudioInfo(AudioInfo info) override
Defines the input AudioInfo.
Definition: AudioStreams.h:1311
size_t totalBytes()
Provides the total_size provided in the configuration.
Definition: AudioStreams.h:1370
virtual size_t write(const uint8_t *buffer, size_t size) override
Writes raw PCM audio data, which will be the input for the volume control.
Definition: AudioStreams.h:1397
Configuration for ProgressStream.
Definition: AudioStreams.h:1279
AudioStream class which stores the data in a temporary queue buffer. The queue can be consumed e....
Definition: AudioStreams.h:961
QueueStream(BaseBuffer< T > &buffer)
Create stream from any BaseBuffer subclass.
Definition: AudioStreams.h:971
virtual bool begin() override
Activates the output.
Definition: AudioStreams.h:983
virtual bool begin(size_t activeWhenPercentFilled)
Activate only when filled buffer reached %.
Definition: AudioStreams.h:990
void clear()
Clears the data in the buffer.
Definition: AudioStreams.h:1039
QueueStream(int bufferSize, int bufferCount, bool autoRemoveOldestDataIfFull=false)
Default constructor.
Definition: AudioStreams.h:964
virtual void end() override
stops the processing
Definition: AudioStreams.h:999
virtual T read()
reads a single value
Definition: Buffers.h:305
virtual int available()
provides the number of entries that are available to read
Definition: Buffers.h:362
virtual bool write(T data)
write add an entry to the buffer
Definition: Buffers.h:343
virtual void reset()
clears the buffer
Definition: Buffers.h:355
virtual T * address()
returns the address of the start of the physical read buffer
Definition: Buffers.h:368
virtual size_t size()
Returns the maximum capacity of the buffer.
Definition: Buffers.h:379
virtual bool isFull()
checks if the buffer is full
Definition: Buffers.h:338
virtual T peek()
peeks the actual entry from the buffer
Definition: Buffers.h:316
A Stream backed by a Ringbuffer. We can write to the end and read from the beginning of the stream.
Definition: AudioStreams.h:909
T * address() override
Provides address to beginning of the buffer.
Definition: Buffers.h:243
T peek() override
peeks the actual entry from the buffer
Definition: Buffers.h:205
size_t setAvailable(size_t available_size)
Definition: Buffers.h:258
bool write(T sample) override
write add an entry to the buffer
Definition: Buffers.h:188
int available() override
provides the number of entries that are available to read
Definition: Buffers.h:213
int availableForWrite() override
provides the number of entries that are available to write
Definition: Buffers.h:218
T read() override
reads a single value
Definition: Buffers.h:197
Changes the samples at the beginning or at the end to slowly ramp up the volume.
Definition: BaseConverter.h:1236
Base class to define the abstract interface for the sound generating classes.
Definition: SoundGenerator.h:25
Definition: NoArduino.h:125
Throttle the sending or receiving of the audio data to limit it to the indicated sample rate.
Definition: AudioStreams.h:1452
void setOutput(Print &out) override
Defines/Changes the output target.
Definition: AudioStreams.h:1465
void setStream(Stream &io) override
Defines/Changes the input & output.
Definition: AudioStreams.h:1459
Common Interface definition for TimerAlarmRepeating.
Definition: AudioTimer.h:25
Callback driven Audio Source (rx_tx_mode==RX_MODE) or Audio Sink (rx_tx_mode==TX_MODE)....
Definition: AudioStreams.h:2201
TimerCallbackAudioStreamInfo audioInfoExt()
Provides the current audio information.
Definition: AudioStreams.h:2235
uint16_t currentSampleRate()
Provides the effective sample rate.
Definition: AudioStreams.h:2284
TimerCallbackAudioStreamInfo defaultConfig()
Provides the default configuration.
Definition: AudioStreams.h:2215
bool begin()
Restart the processing.
Definition: AudioStreams.h:2263
AudioInfo audioInfo()
provides the actual input AudioInfo
Definition: AudioStreams.h:2236
virtual void measureSampleRate()
calculates the effective sample rate
Definition: AudioStreams.h:2330
virtual void setAudioInfo(AudioInfo info)
updates the audio information
Definition: AudioStreams.h:2221
virtual void printSampleRate()
log and update effective sample rate
Definition: AudioStreams.h:2348
void end()
Stops the processing.
Definition: AudioStreams.h:2275
Vector implementation which provides the most important methods as defined by std::vector....
Definition: Vector.h:21
MemoryType
Memory types.
Definition: AudioTypes.h:33
RxTxMode
The Microcontroller is the Audio Source (TX_MODE) or Audio Sink (RX_MODE). RXTX_MODE is Source and Si...
Definition: AudioTypes.h:26
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition: AnalogAudio.h:10
size_t readSamples(Stream *p_stream, T *data, int samples, int retryCount=-1)
guaranteed to return the requested data
Definition: AudioTypes.h:434
void delayMicroseconds(uint32_t ms)
Waits for the indicated milliseconds.
void delay(uint32_t ms)
Waits for the indicated milliseconds.
Definition: Millis.h:11
uint32_t micros()
Returns the milliseconds since the start.
uint32_t millis()
Returns the milliseconds since the start.
Definition: Millis.h:18
Basic Audio information which drives e.g. I2S.
Definition: AudioTypes.h:50
void copyFrom(AudioInfo info)
Same as set.
Definition: AudioTypes.h:105
sample_rate_t sample_rate
Sample Rate: e.g 44100.
Definition: AudioTypes.h:53
uint16_t channels
Number of channels: 2=stereo, 1=mono.
Definition: AudioTypes.h:55
uint8_t bits_per_sample
Number of bits per sample (int16_t = 16 bits)
Definition: AudioTypes.h:57
Definition: AudioStreams.h:472
DataNode(void *inData, int len)
Constructor.
Definition: AudioStreams.h:478
Configure Throttle setting.
Definition: AudioStreams.h:1437
TimerCallbackAudioStream Configuration.
Definition: AudioStreams.h:2180