arduino-audio-tools
AudioStreams.h
1 #pragma once
2 #include "AudioConfig.h"
3 #include "AudioTools/CoreAudio/AudioTimer/AudioTimer.h"
4 #include "AudioTools/CoreAudio/AudioTypes.h"
5 #include "AudioTools/CoreAudio/Buffers.h"
6 #include "AudioTools/CoreAudio/AudioLogger.h"
7 #include "AudioTools/CoreAudio/BaseConverter.h"
8 #include "AudioTools/CoreAudio/AudioEffects/SoundGenerator.h"
9 #include "AudioTools/CoreAudio/BaseStream.h"
10 #include "AudioTools/CoreAudio/AudioOutput.h"
11 
12 #ifndef IRAM_ATTR
13 # define IRAM_ATTR
14 #endif
15 
16 
17 namespace audio_tools {
18 
25  public:
27  TRACED();
28  p_stream = &s;
29  p_stream->setTimeout(clientTimeout);
30  }
31 
32  virtual bool begin(){return true;}
33  virtual void end(){}
34 
35  virtual size_t readBytes(uint8_t *data, size_t len) {
36  //Serial.print("Timeout audiostream: ");
37  //Serial.println(p_stream->getTimeout());
38  return p_stream->readBytes(data, len);
39  }
40 
41  int read() { return p_stream->read(); }
42 
43  int peek() { return p_stream->peek(); }
44 
45  int available() { return p_stream->available(); }
46 
47  virtual size_t write(uint8_t c) { return p_stream->write(c); }
48 
49  virtual size_t write(const uint8_t *data, size_t len) {
50  return p_stream->write(data, len);
51  }
52 
53  virtual int availableForWrite() { return p_stream->availableForWrite(); }
54 
55  virtual void flush() { p_stream->flush(); }
56 
57  protected:
58  Stream *p_stream;
59  int32_t clientTimeout = URL_CLIENT_TIMEOUT; // 60000;
60 };
61 
69 class ModifyingStream : public AudioStream {
70  public:
72  virtual void setStream(Stream& in) = 0;
74  virtual void setOutput(Print& out) = 0;
75 };
76 
84 class MemoryStream : public AudioStream {
85  public:
87  MemoryStream(int buffer_size, MemoryType memoryType) {
88  LOGD("MemoryStream: %d", buffer_size);
89  this->buffer_size = buffer_size;
90  this->memory_type = memoryType;
91  resize(buffer_size);
92  info.clear(); // mark audio info as unknown
93  }
94 
96  MemoryStream(const uint8_t *buffer, int buffer_size, bool isActive=true, MemoryType memoryType = FLASH_RAM) {
97  LOGD("MemoryStream: %d", buffer_size);
98  setValue(buffer, buffer_size, memoryType);
99  is_active = isActive;
100  info.clear(); // mark audio info as unknown
101  }
102 
105  copy(source);
106  }
107 
110  setValue(source.buffer, source.buffer_size, source.memory_type);
111  // clear source data
112  source.setValue(nullptr, 0, source.memory_type);
113  }
114 
115  ~MemoryStream() {
116  TRACED();
117  if (memoryCanChange() && buffer!=nullptr) free(buffer);
118  }
119 
122  copy(other);
123  return *this;
124  }
125 
127  operator bool() override { return available() > 0; }
128 
130  bool begin(AudioInfo info){
131  this->info = info;
132  return begin();
133  }
134 
136  bool begin() override {
137  TRACED();
138  write_pos = memoryCanChange() ? 0 : buffer_size;
139  if (this->buffer==nullptr && memoryCanChange()){
140  resize(buffer_size);
141  }
142  read_pos = 0;
143  is_active = true;
144  return true;
145  }
146 
147  virtual size_t write(uint8_t byte) override {
148  if (!is_active) return 0;
149  if (memory_type == FLASH_RAM) return 0;
150  if (buffer==nullptr) return 0;
151  int result = 0;
152  if (write_pos < buffer_size) {
153  result = 1;
154  buffer[write_pos] = byte;
155  write_pos++;
156  }
157  return result;
158  }
159 
160  virtual size_t write(const uint8_t *data, size_t len) override {
161  if (!is_active) return 0;
162  if (memory_type == FLASH_RAM) return 0;
163  size_t result = 0;
164  for (size_t j = 0; j < len; j++) {
165  if (!write(data[j])) {
166  break;
167  }
168  result = j + 1;
169  }
170  return result;
171  }
172 
173  virtual int available() override {
174  if (!is_active) return 0;
175  if (buffer==nullptr) return 0;
176  int result = write_pos - read_pos;
177  if (result<=0 && is_loop){
178  // rewind to start
179  read_pos = rewind_pos;
180  result = write_pos - read_pos;
181  // call callback
182  if (rewind!=nullptr) rewind();
183  }
184  return is_loop ? DEFAULT_BUFFER_SIZE : result;
185  }
186 
187  virtual int availableForWrite() override {
188  if (!is_active) return 0;
189  if (memory_type == FLASH_RAM) return 0;
190  return buffer_size - write_pos;
191  }
192 
193  virtual int read() override {
194  int result = peek();
195  if (result >= 0) {
196  read_pos++;
197  }
198  return result;
199  }
200 
201  virtual size_t readBytes(uint8_t *data, size_t len) override {
202  if (!is_active) return 0;
203  size_t count = 0;
204  while (count < len) {
205  int c = read();
206  if (c < 0) break;
207  *data++ = (char)c;
208  count++;
209  }
210  return count;
211  }
212 
213  virtual int peek() override {
214  if (!is_active) return -1;
215  int result = -1;
216  if (available() > 0) {
217  result = buffer[read_pos];
218  }
219  return result;
220  }
221 
222  virtual void flush() override {}
223 
224  virtual void end() override {
225  read_pos = 0;
226  is_active = false;
227  }
228 
230  virtual void clear(bool reset = false) {
231  if (memoryCanChange()){
232  write_pos = 0;
233  read_pos = 0;
234  if (buffer==nullptr){
235  resize(buffer_size);
236  }
237  if (reset) {
238  // we clear the buffer data
239  memset(buffer, 0, buffer_size);
240  }
241  } else {
242  read_pos = 0;
243  LOGW("data is read only");
244  }
245  }
246 
248  virtual void setLoop(bool loop){
249  is_loop = loop;
250  rewind_pos = 0;
251  if (buffer!=nullptr && buffer_size > 12){
252  if (memcmp("WAVE", buffer+8, 4)==0){
253  rewind_pos = 44;
254  }
255  }
256  }
257 
259  virtual void setLoop(bool loop, int rewindPos){
260  is_loop = loop;
261  rewind_pos = rewindPos;
262  }
263 
265  virtual bool resize(size_t size){
266  if (!memoryCanChange()) return false;
267 
268  buffer_size = size;
269  switch(memory_type){
270 #if defined(ESP32) && defined(ARDUINO)
271  case PS_RAM:
272  buffer = (buffer==nullptr) ? (uint8_t*)ps_calloc(size,1) : (uint8_t*)ps_realloc(buffer, size);
273  break;
274 #endif
275  default:
276  buffer = (buffer==nullptr) ? (uint8_t*)calloc(size,1) : (uint8_t*)realloc(buffer, size);
277  break;
278  }
279  return buffer != nullptr;
280  }
281 
282  virtual uint8_t* data(){
283  return buffer;
284  }
285 
287  void setRewindCallback(void (*cb)()){
288  this->rewind = cb;
289  }
290 
292  void setValue(const uint8_t *buffer, int buffer_size, MemoryType memoryType = FLASH_RAM) {
293  this->buffer_size = buffer_size;
294  this->read_pos = 0;
295  this->write_pos = buffer_size;
296  this->buffer = (uint8_t *)buffer;
297  this->memory_type = memoryType;
298  }
299 
300  protected:
301  int write_pos = 0;
302  int read_pos = 0;
303  int buffer_size = 0;
304  int rewind_pos = 0;
305  uint8_t *buffer = nullptr;
306  MemoryType memory_type = RAM;
307  bool is_loop = false;
308  void (*rewind)() = nullptr;
309  bool is_active = false;
310 
311  bool memoryCanChange() {
312  return memory_type!=FLASH_RAM;
313  }
314 
315  void copy(MemoryStream& source) {
316  if (this == &source) return;
317  if (source.memory_type == FLASH_RAM){
318  setValue(source.buffer, source.buffer_size, source.memory_type);
319  } else {
320  setValue(nullptr, source.buffer_size, source.memory_type);
321  resize(buffer_size);
322  memcpy(buffer, source.buffer, buffer_size);
323  }
324  }
325 };
326 
335  public:
336  RingBufferStream(int size = DEFAULT_BUFFER_SIZE) { resize(size); }
337 
338  virtual int available() override {
339  // LOGD("RingBufferStream::available: %zu",buffer->available());
340  return buffer.available();
341  }
342 
343  virtual int availableForWrite() override {
344  return buffer.availableForWrite();
345  }
346 
347  virtual void flush() override {}
348  virtual int peek() override { return buffer.peek(); }
349  virtual int read() override { return buffer.read(); }
350 
351  virtual size_t readBytes(uint8_t *data, size_t len) override {
352  return buffer.readArray(data, len);
353  }
354 
355  virtual size_t write(const uint8_t *data, size_t len) override {
356  // LOGD("RingBufferStream::write: %zu",len);
357  return buffer.writeArray(data, len);
358  }
359 
360  virtual size_t write(uint8_t c) override { return buffer.write(c); }
361 
362  void resize(int size) { buffer.resize(size); }
363 
364  size_t size() { return buffer.size(); }
365 
366  protected:
367  RingBuffer<uint8_t> buffer{0};
368 };
369 
381 template <class T>
383  public:
384  GeneratedSoundStream() = default;
385 
387  TRACED();
388  setInput(generator);
389  }
390 
391  void setInput(SoundGenerator<T> &generator){
392  this->generator_ptr = &generator;
393  }
394 
395  AudioInfo defaultConfig() { return this->generator_ptr->defaultConfig(); }
396 
397  void setAudioInfo(AudioInfo newInfo) override {
398  if (newInfo.bits_per_sample != sizeof(T)*8){
399  LOGE("Wrong bits_per_sample: %d", newInfo.bits_per_sample);
400  }
401  AudioStream::setAudioInfo(newInfo);
402  }
403 
405  bool begin() override {
406  TRACED();
407  if (generator_ptr==nullptr){
408  LOGE("%s",source_not_defined_error);
409  return false;
410  }
411  generator_ptr->begin();
412  notifyAudioChange(generator_ptr->audioInfo());
413  active = true;
414  return active;
415  }
416 
418  bool begin(AudioInfo cfg) {
419  TRACED();
420  if (generator_ptr==nullptr){
421  LOGE("%s",source_not_defined_error);
422  return false;
423  }
424  generator_ptr->begin(cfg);
425  notifyAudioChange(generator_ptr->audioInfo());
426  active = true;
427  return active;
428  }
429 
431  void end() override {
432  TRACED();
433  generator_ptr->end();
434  active = true; // legacy support - most sketches do not call begin
435  }
436 
437  AudioInfo audioInfo() override {
438  return generator_ptr->audioInfo();
439  }
440 
442  virtual int available() override { return active ? DEFAULT_BUFFER_SIZE*2 : 0; }
443 
445  size_t readBytes(uint8_t *data, size_t len) override {
446  if (!active) return 0;
447  LOGD("GeneratedSoundStream::readBytes: %u", (unsigned int)len);
448  return generator_ptr->readBytes(data, len);
449  }
450 
451  bool isActive() {return active && generator_ptr->isActive();}
452 
453  operator bool() { return isActive(); }
454 
455  void flush() override {}
456 
457  protected:
458  bool active = true; // support for legacy sketches
459  SoundGenerator<T> *generator_ptr;
460  const char* source_not_defined_error = "Source not defined";
461 
462 };
463 
473  public:
474  BufferedStream(size_t buffer_size) {
475  TRACED();
476  buffer.resize(buffer_size);
477  }
478 
479  BufferedStream(size_t buffer_size, Print &out) {
480  TRACED();
481  setOutput(out);
482  buffer.resize(buffer_size);
483  }
484 
485  BufferedStream(size_t buffer_size, Stream &io) {
486  TRACED();
487  setStream(io);
488  buffer.resize(buffer_size);
489  }
490 
491  void setOutput(Print &out){
492  p_out = &out;
493  }
494  void setStream(Print &out){
495  setOutput(out);
496  }
497  void setStream(Stream &io){
498  p_in = &io;
499  p_out = &io;
500  }
501 
503  size_t write(uint8_t c) override {
504  if (buffer.isFull()) {
505  flush();
506  }
507  return buffer.write(c);
508  }
509 
511  size_t write(const uint8_t *data, size_t len) override {
512  LOGD("%s: %zu", LOG_METHOD, len);
513  int result = 0;
514  for (int j=0;j<len;j++){
515  result += write(data[j]);
516  }
517  return result;
518  }
519 
521  void flush() override {
522  // just dump the memory of the buffer and clear it
523  if (buffer.available() > 0) {
524  writeExt(buffer.address(), buffer.available());
525  buffer.reset();
526  }
527  }
528 
530  int read() override {
531  if (buffer.isEmpty()) {
532  refill();
533  }
534  return buffer.read();
535  }
536 
538  int peek() override{
539  if (buffer.isEmpty()) {
540  refill();
541  }
542  return buffer.peek();
543  };
544 
546  size_t readBytes(uint8_t *data, size_t len) override {
547  if (buffer.isEmpty()) {
548  return readExt(data, len);
549  } else {
550  refill();
551  return buffer.readArray(data, len);
552  }
553  }
554 
556  int available() override {
557  if (buffer.isEmpty()) {
558  refill();
559  }
560  return buffer.available();
561  }
562 
564  void clear() { buffer.reset(); }
565 
566  protected:
567  SingleBuffer<uint8_t> buffer;
568  Print* p_out = nullptr;
569  Stream* p_in = nullptr;
570 
571  // refills the buffer with data from i2s
572  void refill() {
573  size_t result = readExt(buffer.address(), buffer.size());
574  buffer.setAvailable(result);
575  }
576 
577  virtual size_t writeExt(const uint8_t *data, size_t len) {
578  return p_out == nullptr ? 0 : p_out->write(data, len);
579  }
580  virtual size_t readExt(uint8_t *data, size_t len) {
581  return p_in == nullptr ? 0 : p_in->readBytes(data, len);
582  }
583 };
584 
585 
594 template<typename T>
596 
597  public:
598  ConverterStream() = default;
599 
600  ConverterStream(BaseConverter &converter) {
601  setConverter(converter);
602  }
603 
604  ConverterStream(Stream &stream, BaseConverter &converter) {
605  setConverter(converter);
606  setStream(stream);
607  }
608 
609  ConverterStream(Print &out, BaseConverter &converter) {
610  setConverter(converter);
611  setOutput(out);
612  }
613 
614  void setStream(Stream &stream){
615  TRACEI();
616  p_stream = &stream;
617  p_out = &stream;
618  }
619 
620  void setOutput(Print &out){
621  TRACEI();
622  p_out = &out;
623  }
624 
625  void setConverter(BaseConverter& cnv){
626  p_converter = &cnv;
627  }
628 
629  virtual int availableForWrite() { return p_out->availableForWrite(); }
630 
631  virtual size_t write(const uint8_t *data, size_t len) {
632  size_t result = p_converter->convert((uint8_t *)data, len);
633  if (result>0) {
634  size_t result_written = p_out->write(data, result);
635  return len * result_written / result;
636  }
637  return 0;
638  }
639 
640  size_t readBytes(uint8_t *data, size_t len) override {
641  if (p_stream==nullptr) return 0;
642  size_t result = p_stream->readBytes(data, len);
643  return p_converter->convert(data, result);
644  }
645 
647  virtual int available() override {
648  if (p_stream==nullptr) return 0;
649  return p_stream->available();
650  }
651 
652  protected:
653  Stream *p_stream = nullptr;
654  Print *p_out = nullptr;
655  BaseConverter *p_converter;
656 
657 };
658 
666  public:
667  MeasuringStream(int count=10, Print *logOut=nullptr){
668  this->count = count;
669  this->max_count = count;
670  p_stream = &null;
671  p_print = &null;
672  start_time = millis();
673  p_logout = logOut;
674  }
675 
676  MeasuringStream(Print &print, int count=10, Print *logOut=nullptr){
677  this->count = count;
678  this->max_count = count;
679  setOutput(print);
680  start_time = millis();
681  p_logout = logOut;
682  }
683 
684  MeasuringStream(Stream &stream, int count=10, Print *logOut=nullptr){
685  this->count = count;
686  this->max_count = count;
687  setStream(stream);
688  start_time = millis();
689  p_logout = logOut;
690  }
691 
693  void setStream(Stream& io) override {
694  p_print = &io;
695  p_stream = &io;
696  };
697 
699  void setOutput(Print& out) override {
700  p_print = &out;
701  }
702 
703 
705  size_t readBytes(uint8_t* data, size_t len) override {
706  return measure(p_stream->readBytes(data, len));
707  }
708 
709  int available() override {
710  return p_stream->available();
711  }
712 
714  virtual size_t write(const uint8_t *data, size_t len) override {
715  return measure(p_print->write(data, len));
716  }
717 
719  virtual int availableForWrite() override {
720  return p_print->availableForWrite();
721  }
722 
725  return bytes_per_second;
726  }
727 
729  uint32_t startTime() {
730  return start_time;
731  }
732 
734  AudioStream::info = info;
735  setFrameSize(info.bits_per_sample / 8 *info.channels);
736  }
737 
738  bool begin(){
739  return AudioStream::begin();
740  }
741 
742  bool begin(AudioInfo info){
743  setAudioInfo(info);
744  return true;
745  }
746 
747  void setFrameSize(int size){
748  frame_size = size;
749  }
750 
752  void setReportBytes(bool flag){
753  report_bytes = flag;
754  }
755 
756  protected:
757  int max_count=0;
758  int count=0;
759  Stream *p_stream=nullptr;
760  Print *p_print=nullptr;
761  uint32_t start_time;
762  int total_bytes = 0;
763  int bytes_per_second = 0;
764  int frame_size = 0;
765  NullStream null;
766  Print *p_logout=nullptr;
767  bool report_bytes = false;
768 
769  size_t measure(size_t len) {
770  count--;
771  total_bytes+=len;
772 
773  if (count<=0){
774  uint32_t end_time = millis();
775  int time_diff = end_time - start_time; // in ms
776  if (time_diff>0){
777  bytes_per_second = total_bytes / time_diff * 1000;
778  printResult();
779  count = max_count;
780  total_bytes = 0;
781  start_time = end_time;
782  }
783  }
784  return len;
785  }
786 
787  void printResult() {
788  char msg[70];
789  if (report_bytes || frame_size==0){
790  snprintf(msg, 70, "==> Bytes per second: %d", bytes_per_second);
791  } else {
792  snprintf(msg, 70, "==> Samples per second: %d", bytes_per_second/frame_size);
793  }
794  if (p_logout!=nullptr){
795  p_logout->println(msg);
796  } else {
797  LOGI("%s",msg);
798  }
799  }
800 };
801 
809  public:
810  size_t total_size = 0;
811 };
820  public:
821  ProgressStream() = default;
822 
823  ProgressStream(Print &print){
824  setPrint(print);
825  }
826 
827  ProgressStream(Stream &stream){
828  setStream(stream);
829  }
830 
831  ProgressStream(AudioStream &stream){
832  setStream(stream);
833  p_info_from = &stream;
834  }
835 
836  ProgressStreamInfo& defaultConfig() {
837  return progress_info;
838  }
839 
840  void setAudioInfo(AudioInfo info) override {
842  progress_info.copyFrom(info);
843  }
844 
845  void setStream(Stream &stream){
846  p_stream =&stream;
847  p_print = &stream;
848  }
849 
850  void setStream(Print &print){
851  p_print =&print;
852  }
853 
854  void setPrint(Print &print){
855  p_print =&print;
856  }
857 
858  bool begin() override {
859  if (p_info_from!=nullptr){
860  setAudioInfo(p_info_from->audioInfo());
861  }
862  return AudioStream::begin();
863  }
864 
866  bool begin(size_t len){
867  setSize(len);
868  return begin();
869  }
870 
871  bool begin(ProgressStreamInfo info){
872  progress_info = info;
873  setAudioInfo(info);
874  return begin();
875  }
876 
878  void setSize(size_t len){
879  total_processed = 0;
880  progress_info.total_size = len;
881  }
882 
884  size_t size(){
885  return progress_info.total_size;
886  }
887 
889  size_t processedBytes() {
890  return total_processed;
891  }
892 
894  size_t processedSecs() {
895  return total_processed / byteRate();
896  }
897 
899  size_t totalBytes() {
900  return progress_info.total_size;
901  }
902 
904  size_t totalSecs() {
905  return totalBytes() / byteRate();
906  }
907 
909  float percentage() {
910  if (progress_info.total_size==0) return 0;
911  return 100.0 * total_processed / progress_info.total_size;
912  }
913 
915  size_t readBytes(uint8_t* data, size_t len) override {
916  if (p_stream==nullptr) return 0;
917  return measure(p_stream->readBytes(data, len));
918  }
919 
920  int available() override {
921  if (p_stream==nullptr) return 0;
922  return p_stream->available();
923  }
924 
926  virtual size_t write(const uint8_t *data, size_t len) override {
927  if (p_print==nullptr) return 0;
928  return measure(p_print->write(data, len));
929  }
930 
932  virtual int availableForWrite() override {
933  if (p_print==nullptr) return 0;
934  return p_print->availableForWrite();
935  }
936 
937  protected:
938  ProgressStreamInfo progress_info;
939  Stream *p_stream=nullptr;
940  Print *p_print=nullptr;
941  AudioInfoSupport *p_info_from=nullptr;
942  size_t total_processed = 0;
943 
944  size_t measure(size_t len) {
945  total_processed += len;
946  return len;
947  }
948 
949  size_t byteRate() {
950  AudioInfo info = audioInfo();
951  int byte_rate = info.sample_rate * info.bits_per_sample * info.channels / 8;
952  if (byte_rate==0){
953  LOGE("Audio Info not defined");
954  return 0;
955  }
956  return byte_rate;
957  }
958 
959 };
960 
966 struct ThrottleConfig : public AudioInfo {
967  ThrottleConfig() {
968  sample_rate = 44100;
969  bits_per_sample = 16;
970  channels = 2;
971  }
972  int correction_us = 0;
973 };
974 
981 class Throttle : public ModifyingStream {
982  public:
983  Throttle() = default;
984  Throttle(Print &out) { setOutput(out); }
985  Throttle(Stream &io) { setStream(io); }
986 
988  void setStream(Stream& io) override {
989  p_out = &io;
990  p_in = &io;
991  };
992 
994  void setOutput(Print& out) override {
995  p_out = &out;
996  }
997 
998  ThrottleConfig defaultConfig() {
999  ThrottleConfig c;
1000  return c;
1001  }
1002 
1003  bool begin(ThrottleConfig cfg) {
1004  LOGI("begin sample_rate: %d, channels: %d, bits: %d", (int) info.sample_rate,(int) info.channels, (int)info.bits_per_sample);
1005  this->info = cfg;
1006  this->cfg = cfg;
1007  return begin();
1008  }
1009 
1010  bool begin(AudioInfo info) {
1011  LOGI("begin sample_rate: %d, channels: %d, bits: %d", (int)info.sample_rate, (int) info.channels, (int)info.bits_per_sample);
1012  this->info = info;
1013  this->cfg.copyFrom(info);
1014  return begin();
1015  }
1016 
1017  bool begin(){
1018  frame_size = cfg.bits_per_sample / 8 * cfg.channels;
1019  startDelay();
1020  return true;
1021  }
1022 
1023  // (re)starts the timing
1024  void startDelay() {
1025  start_time = micros();
1026  sum_frames = 0;
1027  }
1028 
1029  int availableForWrite() {
1030  if (p_out){
1031  return p_out->availableForWrite();
1032  }
1033  return DEFAULT_BUFFER_SIZE;
1034  }
1035 
1036  size_t write(const uint8_t* data, size_t len){
1037  size_t result = p_out->write(data, len);
1038  delayBytes(len);
1039  return result;
1040  }
1041 
1042  int available() {
1043  if (p_in==nullptr) return 0;
1044  return p_in->available();
1045  }
1046 
1047  size_t readBytes(uint8_t* data, size_t len) override{
1048  if (p_in==nullptr) {
1049  delayBytes(len);
1050  return 0;
1051  }
1052  size_t result = p_in->readBytes(data, len);
1053  delayBytes(len);
1054  return result;
1055  }
1056 
1057  // delay
1058  void delayBytes(size_t bytes) { delayFrames(bytes / frame_size); }
1059 
1060  // delay
1061  void delayFrames(size_t frames) {
1062  sum_frames += frames;
1063  uint64_t durationUsEff = micros() - start_time;
1064  uint64_t durationUsToBe = getDelayUs(sum_frames);
1065  int64_t waitUs = durationUsToBe - durationUsEff + cfg.correction_us;
1066  LOGD("wait us: %ld", static_cast<long>(waitUs));
1067  if (waitUs > 0) {
1068  int64_t waitMs = waitUs / 1000;
1069  if (waitMs > 0) delay(waitMs);
1070  delayMicroseconds(waitUs - (waitMs * 1000));
1071  } else {
1072  LOGD("negative delay!")
1073  }
1074  }
1075 
1076  inline int64_t getDelayUs(uint64_t frames){
1077  return (frames * 1000000) / cfg.sample_rate;
1078  }
1079 
1080  inline int64_t getDelayMs(uint64_t frames){
1081  return getDelayUs(frames) / 1000;
1082  }
1083 
1084  inline int64_t getDelaySec(uint64_t frames){
1085  return getDelayUs(frames) / 1000000l;
1086  }
1087 
1088  protected:
1089  uint32_t start_time = 0;
1090  uint32_t sum_frames = 0;
1091  ThrottleConfig cfg;
1092  int frame_size = 0;
1093  Print *p_out = nullptr;
1094  Stream *p_in = nullptr;
1095 };
1096 
1097 
1106 template<typename T>
1107 class InputMixer : public AudioStream {
1108  public:
1109  InputMixer() = default;
1110 
1112  void add(Stream &in, int weight=100){
1113  streams.push_back(&in);
1114  weights.push_back(weight);
1115  total_weights += weight;
1116  }
1117 
1119  void set(int channel, Stream &in){
1120  if (channel<size()){
1121  streams[channel] = &in;
1122  } else {
1123  LOGE("Invalid channel %d - max is %d", channel, size()-1);
1124  }
1125  }
1126 
1127  virtual bool begin(AudioInfo info) {
1128  setAudioInfo(info);
1129  frame_size = info.bits_per_sample/8 * info.channels;
1130  LOGI("frame_size: %d",frame_size);
1131  return frame_size>0;
1132  }
1133 
1135  void setWeight(int channel, int weight){
1136  if (channel<size()){
1137  weights[channel] = weight;
1138  int total = 0;
1139  for (int j=0;j<weights.size();j++){
1140  total += weights[j];
1141  }
1142  total_weights = total;
1143  } else {
1144  LOGE("Invalid channel %d - max is %d", channel, size()-1);
1145  }
1146  }
1147 
1149  void end() override {
1150  streams.clear();
1151  weights.clear();
1152  result_vect.clear();
1153  current_vect.clear();
1154  total_weights = 0.0;
1155  }
1156 
1158  int size() {
1159  return streams.size();
1160  }
1161 
1163  size_t readBytes(uint8_t* data, size_t len) override {
1164  if (total_weights==0 || frame_size==0 || len==0) {
1165  LOGW("readBytes: %d",(int)len);
1166  return 0;
1167  }
1168 
1169  if (limit_available_data){
1170  len = min((int)len, availableBytes());
1171  }
1172 
1173  int result_len = 0;
1174 
1175  if (len > 0) {
1176  // result_len must be full frames
1177  result_len = len * frame_size / frame_size;
1178  // replace sample based with vector based implementation
1179  //readBytesSamples((T*)data, result_len));
1180  result_len = readBytesVector((T*)data, result_len);
1181  }
1182  return result_len;
1183  }
1184 
1186  void setLimitToAvailableData(bool flag){
1187  limit_available_data = flag;
1188  }
1189 
1191  void setRetryCount(int retry){
1192  retry_count = retry;
1193  }
1194 
1195  protected:
1196  Vector<Stream*> streams{0};
1197  Vector<int> weights{0};
1198  int total_weights = 0;
1199  int frame_size = 4;
1200  bool limit_available_data = false;
1201  int retry_count = 5;
1202  Vector<int> result_vect;
1203  Vector<T> current_vect;
1204 
1206  int readBytesVector(T* p_data, int byteCount) {
1207  int samples = byteCount / sizeof(T);
1208  result_vect.resize(samples);
1209  current_vect.resize(samples);
1210  int stream_count = size();
1211  resultClear();
1212  int samples_eff_max = 0;
1213  for (int j=0;j<stream_count;j++){
1214  if (weights[j]>0){
1215  int samples_eff = readSamples(streams[j],current_vect.data(), samples, retry_count);
1216  if (samples_eff > samples_eff_max)
1217  samples_eff_max = samples_eff;
1218  // if all weights are 0.0 we stop to output
1219  float factor = total_weights == 0.0f ? 0.0f : static_cast<float>(weights[j]) / total_weights;
1220  resultAdd(factor);
1221  }
1222  }
1223  // copy result
1224  for (int j=0;j<samples;j++){
1225  p_data[j] = result_vect[j];
1226  }
1227  return samples_eff_max * sizeof(T);
1228  }
1229 
1232  int result = DEFAULT_BUFFER_SIZE;
1233  for (int j=0;j<size();j++){
1234  result = min(result, streams[j]->available());
1235  }
1236  return result;
1237  }
1238 
1239  void resultAdd(float fact){
1240  for (int j=0;j<current_vect.size();j++){
1241  current_vect[j]*=fact;
1242  result_vect[j] += current_vect[j];
1243  }
1244  }
1245 
1246  void resultClear(){
1247  memset(result_vect.data(), 0, sizeof(int)*result_vect.size());
1248  }
1249 
1250 };
1251 
1261 template<typename T>
1262 class InputMerge : public AudioStream {
1263  public:
1265  InputMerge() = default;
1266 
1270  InputMerge(Stream &left, Stream &right) {
1271  add(left);
1272  add(right);
1273  };
1274 
1275  virtual bool begin(AudioInfo info) {
1276  if (size()!=info.channels){
1277  info.channels = size();
1278  LOGW("channels corrected to %d", size());
1279  }
1280  setAudioInfo(info);
1281  return begin();
1282  }
1283 
1284  virtual bool begin() {
1285  // make sure that we use the correct channel count
1286  info.channels = size();
1287  return AudioStream::begin();
1288  }
1289 
1291  size_t readBytes(uint8_t* data, size_t len) override {
1292  LOGD("readBytes: %d",(int)len);
1293  T *p_data = (T*) data;
1294  int result_len = MIN(available(), len/size());
1295  int sample_count = result_len / sizeof(T);
1296  int size_value = size();
1297  int result_idx = 0;
1298  for (int j=0;j<sample_count; j++){
1299  for (int i=0; i<size_value; i++){
1300  p_data[result_idx++] = weights[i] * readSample<T>(streams[i]);
1301  }
1302  }
1303  return result_idx*sizeof(T);
1304  }
1305 
1307  void add(Stream &in, float weight=1.0){
1308  streams.push_back(&in);
1309  weights.push_back(weight);
1310  }
1311 
1313  void setWeight(int channel, float weight){
1314  if (channel<size()){
1315  weights[channel] = weight;
1316  } else {
1317  LOGE("Invalid channel %d - max is %d", channel, size()-1);
1318  }
1319  }
1320 
1322  void end() override {
1323  streams.clear();
1324  weights.clear();
1325  }
1326 
1328  int size() {
1329  return streams.size();
1330  }
1331 
1333  int available() override {
1334  int result = streams[0]->available();
1335  for (int j=1;j<size();j++){
1336  int tmp = streams[j]->available();
1337  if (tmp<result){
1338  result = tmp;
1339  }
1340  }
1341  return result;
1342  }
1343 
1344  protected:
1345  Vector<Stream*> streams{10};
1346  Vector<float> weights{10};
1347 };
1348 
1349 
1358  public:
1359  CallbackStream() = default;
1360 
1362  CallbackStream(Stream &io, size_t (*cb_update)(uint8_t* data, size_t len)) {
1363  p_stream = &io;
1364  p_out = &io;
1365  setUpdateCallback(cb_update);
1366  }
1367 
1369  CallbackStream(Print &out, size_t (*cb_update)(uint8_t* data, size_t len)) {
1370  p_out = &out;
1371  setUpdateCallback(cb_update);
1372  }
1373 
1374  CallbackStream(size_t (*cb_read)(uint8_t* data, size_t len), size_t (*cb_write)(const uint8_t* data, size_t len)) {
1375  setWriteCallback(cb_write);
1376  setReadCallback(cb_read);
1377  }
1378 
1379  void setWriteCallback(size_t (*cb_write)(const uint8_t* data, size_t len)){
1380  this->cb_write = cb_write;
1381  }
1382 
1383  void setReadCallback(size_t (*cb_read)(uint8_t* data, size_t len)){
1384  this->cb_read = cb_read;
1385  }
1386 
1387  void setUpdateCallback(size_t (*cb_update)(uint8_t* data, size_t len)){
1388  this->cb_update = cb_update;
1389  }
1390 
1391  // callback result negative -> no change; callbeack result >=0 provides the result
1392  void setAvailableCallback(int (*cb)()){
1393  this->cb_available = cb;
1394  }
1395 
1396  virtual bool begin(AudioInfo info) {
1397  setAudioInfo(info);
1398  return begin();
1399  }
1400  virtual bool begin() override {
1401  active = true;
1402  return true;
1403  }
1404 
1405  void end() override { active = false;}
1406 
1407  int available() override {
1408  int result = AudioStream::available();
1409  // determine value from opional variable
1410  if (available_bytes>=0)
1411  return available_bytes;
1412  // check if there is a callback
1413  if (cb_available==nullptr)
1414  return result;
1415  // determine value from callback
1416  int tmp_available = cb_available();
1417  if (tmp_available < 0)
1418  return result;
1419 
1420  return tmp_available;
1421  }
1422 
1423  size_t readBytes(uint8_t* data, size_t len) override {
1424  if (!active) return 0;
1425  // provide data from callback
1426  if (cb_read){
1427  return cb_read(data, len);
1428  }
1429  // provide data from source
1430  size_t result = 0;
1431  if (p_stream){
1432  result = p_stream->readBytes(data , len);
1433  }
1434  if (cb_update){
1435  result = cb_update(data, result);
1436  }
1437  return result;
1438  }
1439 
1440  size_t write(const uint8_t* data, size_t len) override {
1441  if (!active) return 0;
1442  // write to callback
1443  if (cb_write){
1444  return cb_write(data, len);
1445  }
1446  // write to output
1447  if(p_out){
1448  size_t result = len;
1449  if (cb_update) {
1450  result = cb_update((uint8_t*)data, len);
1451  }
1452  return p_out->write(data, result);
1453  }
1454  // no processing possible
1455  return 0;
1456  }
1457 
1459  void setStream(Stream &in){
1460  p_stream = &in;
1461  p_out = &in;
1462  }
1463 
1465  void setOutput(Print &out){
1466  p_out = &out;
1467  }
1468 
1470  void setOutput(Stream &in){
1471  p_stream = &in;
1472  p_out = &in;
1473  }
1474 
1476  void setStream(Print &out){
1477  p_out = &out;
1478  }
1479 
1481  void setAvailable(int val){
1482  available_bytes = val;
1483  }
1484 
1485 
1486 
1487  protected:
1488  bool active=true;
1489  size_t (*cb_write)(const uint8_t* data, size_t len) = nullptr;
1490  size_t (*cb_read)(uint8_t* data, size_t len) = nullptr;
1491  size_t (*cb_update)(uint8_t* data, size_t len) = nullptr;
1492  int (*cb_available)() = nullptr;
1493  Stream *p_stream = nullptr;
1494  Print *p_out = nullptr;
1495  int available_bytes = -1;
1496 };
1497 
1498 
1506 template<typename T, class TF>
1508  public:
1509  FilteredStream() = default;
1510  FilteredStream(Stream &stream) : ModifyingStream() {
1511  setStream(stream);
1512  }
1513  FilteredStream(Stream &stream, int channels) : ModifyingStream() {
1514  this->channels = channels;
1515  setStream(stream);
1516  p_converter = new ConverterNChannels<T,TF>(channels);
1517  }
1518  FilteredStream(Print &stream) : ModifyingStream() {
1519  setOutput(stream);
1520  }
1521  FilteredStream(Print &stream, int channels) : ModifyingStream() {
1522  this->channels = channels;
1523  setOutput(stream);
1524  p_converter = new ConverterNChannels<T,TF>(channels);
1525  }
1526 
1527  void setStream(Stream &stream){
1528  p_stream = &stream;
1529  p_print = &stream;
1530  }
1531 
1532  void setOutput(Print &stream){
1533  p_print = &stream;
1534  }
1535 
1536  bool begin(AudioInfo info){
1537  setAudioInfo(info);
1538  this->channels = info.channels;
1539  if (p_converter !=nullptr && info.channels!=channels){
1540  LOGE("Inconsistent number of channels");
1541  return false;
1542  }
1543  return begin();
1544  }
1545 
1546  bool begin() override {
1547  if (channels ==0){
1548  LOGE("channels must not be 0");
1549  return false;
1550  }
1551  if (p_converter==nullptr){
1552  p_converter = new ConverterNChannels<T,TF>(channels);
1553  }
1554  return AudioStream::begin();
1555  }
1556 
1557  virtual size_t write(const uint8_t *data, size_t len) override {
1558  if (p_converter==nullptr) return 0;
1559  size_t result = p_converter->convert((uint8_t *)data, len);
1560  return p_print->write(data, result);
1561  }
1562 
1563  size_t readBytes(uint8_t *data, size_t len) override {
1564  if (p_converter==nullptr) return 0;
1565  if (p_stream==nullptr) return 0;
1566  size_t result = p_stream->readBytes(data, len);
1567  result = p_converter->convert(data, result);
1568  return result;
1569  }
1570 
1571  virtual int available() override {
1572  if (p_stream==nullptr) return 0;
1573  return p_stream->available();
1574  }
1575 
1576  virtual int availableForWrite() override {
1577  return p_print->availableForWrite();
1578  }
1579 
1582  void setFilter(int channel, Filter<TF> *filter) {
1583  if (p_converter!=nullptr){
1584  p_converter->setFilter(channel, filter);
1585  } else {
1586  LOGE("p_converter is null");
1587  }
1588  }
1589 
1592  void setFilter(int channel, Filter<TF> &filter) {
1593  setFilter(channel, &filter);
1594  }
1595 
1596  protected:
1597  int channels=0;
1598  Stream *p_stream = nullptr;
1599  Print *p_print = nullptr;
1600  ConverterNChannels<T,TF> *p_converter;
1601 
1602 };
1603 
1613 public:
1614  VolumeMeter() = default;
1615  VolumeMeter(AudioStream& as) {
1617  setStream(as);
1618  }
1619  VolumeMeter(AudioOutput& ao) {
1621  setOutput(ao);
1622  }
1623  VolumeMeter(Print& print) {
1624  setOutput(print);
1625  }
1626  VolumeMeter(Stream& stream) {
1627  setStream(stream);
1628  }
1629 
1630  bool begin(AudioInfo info){
1631  setAudioInfo(info);
1632  return begin();
1633  }
1634 
1635  bool begin() override {
1636  return true;
1637  }
1638 
1641  if (info.channels > 0) {
1642  volumes.resize(info.channels);
1643  volumes_tmp.resize(info.channels);
1644  }
1645  }
1646 
1647  size_t write(const uint8_t *data, size_t len) {
1648  updateVolumes(data, len);
1649  size_t result = len;
1650  if (p_out!=nullptr){
1651  result = p_out->write(data, len);
1652  }
1653  return result;
1654  }
1655 
1656  size_t readBytes(uint8_t *data, size_t len){
1657  if (p_stream==nullptr) return 0;
1658  size_t result = p_stream->readBytes(data, len);
1659  updateVolumes((const uint8_t*)data, len);
1660  return result;
1661  }
1662 
1665  float volume() { return f_volume; }
1666 
1669  float volume(int channel) {
1670  if (volumes.size() == 0) {
1671  LOGE("begin not called!");
1672  return 0.0f;
1673  }
1674  if (channel >= volumes.size()) {
1675  LOGE("invalid channel %d", channel);
1676  return 0.0f;
1677  }
1678  return volumes[channel];
1679  }
1680 
1681 
1684 
1686  float volumeRatio(int channel) { return volume(channel) / NumberConverter::maxValue(info.bits_per_sample);}
1687 
1689  float volumeDB() {
1690  // prevent infinite value
1691  if (volumeRatio()==0) return -1000;
1692  return 20.0f * log10(volumeRatio());
1693  }
1694 
1696  float volumeDB(int channel) {
1697  // prevent infinite value
1698  if (volumeRatio(channel)==0) return -1000;
1699  return 20.0f * log10(volumeRatio(channel));
1700  }
1701 
1703  float volumePercent() { return 100.0f * volumeRatio();}
1704 
1706  float volumePercent(int channel) { return 100.0f * volumeRatio(channel);}
1707 
1708 
1710  void clear() {
1711  f_volume_tmp = 0;
1712  for (int j = 0; j < info.channels; j++) {
1713  volumes_tmp[j] = 0;
1714  }
1715  }
1716 
1717  void setOutput(Print &out) override {
1718  p_out = &out;
1719  }
1720  void setStream(Stream &io) override {
1721  p_out = &io;
1722  p_stream = &io;
1723  }
1724 
1725 protected:
1726  float f_volume_tmp = 0;
1727  float f_volume = 0;
1728  Vector<float> volumes{0};
1729  Vector<float> volumes_tmp{0};
1730  Print* p_out = nullptr;
1731  Stream* p_stream = nullptr;
1732 
1733  void updateVolumes(const uint8_t *data, size_t len){
1734  clear();
1735  switch (info.bits_per_sample) {
1736  case 16:
1737  updateVolumesT<int16_t>(data, len);
1738  break;
1739  case 24:
1740  updateVolumesT<int24_t>(data, len);
1741  break;
1742  case 32:
1743  updateVolumesT<int32_t>(data, len);
1744  break;
1745  default:
1746  LOGE("Unsupported bits_per_sample: %d", info.bits_per_sample);
1747  break;
1748  }
1749  }
1750 
1751  template <typename T> void updateVolumesT(const uint8_t *buffer, size_t size) {
1752  T *bufferT = (T *)buffer;
1753  int samplesCount = size / sizeof(T);
1754  for (int j = 0; j < samplesCount; j++) {
1755  float tmp = abs(static_cast<float>(bufferT[j]));
1756  updateVolume(tmp, j);
1757  }
1758  commit();
1759  }
1760 
1761  void updateVolume(float tmp, int j) {
1762  if (tmp > f_volume_tmp) {
1763  f_volume_tmp = tmp;
1764  }
1765  if (volumes_tmp.size() > 0 && info.channels > 0) {
1766  int ch = j % info.channels;
1767  if (tmp > volumes_tmp[ch]) {
1768  volumes_tmp[ch] = tmp;
1769  }
1770  }
1771  }
1772 
1773  void commit() {
1774  f_volume = f_volume_tmp;
1775  for (int j = 0; j < info.channels; j++) {
1776  volumes[j] = volumes_tmp[j];
1777  }
1778  }
1779 };
1780 
1781 // legacy names
1782 using VolumePrint = VolumeMeter;
1783 using VolumeOutput = VolumeMeter;
1784 
1785 #ifdef USE_TIMER
1792  RxTxMode rx_tx_mode = RX_MODE;
1793  uint16_t buffer_size = DEFAULT_BUFFER_SIZE;
1794  bool use_timer = true;
1795  int timer_id = -1;
1796  TimerFunction timer_function = DirectTimerCallback;
1797  bool adapt_sample_rate = false;
1798  uint16_t (*callback)(uint8_t *data, uint16_t len) = nullptr;
1799 };
1800 
1801 // forward declaration: relevant only if use_timer == true
1802 static void timerCallback(void *obj);
1813  friend void timerCallback(void *obj);
1814 
1815  public:
1816  TimerCallbackAudioStream() : BufferedStream(80) { TRACED(); }
1817 
1819  TRACED();
1820  if (timer != nullptr) delete timer;
1821  if (buffer != nullptr) delete buffer;
1822  if (frame != nullptr) delete[] frame;
1823  }
1824 
1828  return def;
1829  }
1830 
1832  virtual void setAudioInfo(AudioInfo info) {
1833  TRACED();
1834  if (cfg.sample_rate != info.sample_rate || cfg.channels != info.channels ||
1835  cfg.bits_per_sample != info.bits_per_sample) {
1836  bool do_restart = active;
1837  if (do_restart) end();
1838  cfg.sample_rate = info.sample_rate;
1839  cfg.channels = info.channels;
1840  cfg.bits_per_sample = info.bits_per_sample;
1841  if (do_restart) begin(cfg);
1842  }
1843  }
1844 
1847  AudioInfo audioInfo() { return cfg; }
1848 
1849  void begin(TimerCallbackAudioStreamInfo config) {
1850  LOGD("%s: %s", LOG_METHOD,
1851  config.rx_tx_mode == RX_MODE ? "RX_MODE" : "TX_MODE");
1852  this->cfg = config;
1853  this->frameCallback = config.callback;
1854  if (cfg.use_timer) {
1855  frameSize = cfg.bits_per_sample * cfg.channels / 8;
1856  frame = new uint8_t[frameSize];
1857  buffer = new RingBuffer<uint8_t>(cfg.buffer_size);
1858  timer = new TimerAlarmRepeating();
1859  timer->setTimerFunction(cfg.timer_function);
1860  if (cfg.timer_id>=0){
1861  timer->setTimer(cfg.timer_id);
1862  }
1863  time = AudioTime::toTimeUs(cfg.sample_rate);
1864  LOGI("sample_rate: %u -> time: %u milliseconds", (unsigned int)cfg.sample_rate, (unsigned int)time);
1865  timer->setCallbackParameter(this);
1866  timer->begin(timerCallback, time, TimeUnit::US);
1867  }
1868 
1869  notifyAudioChange(cfg);
1870  active = true;
1871  }
1872 
1874  bool begin() {
1875  TRACED();
1876  if (this->frameCallback != nullptr) {
1877  if (cfg.use_timer) {
1878  timer->begin(timerCallback, time, TimeUnit::US);
1879  }
1880  active = true;
1881  }
1882  return active;
1883  }
1884 
1886  void end() {
1887  TRACED();
1888  if (cfg.use_timer) {
1889  timer->end();
1890  }
1891  active = false;
1892  }
1893 
1895  uint16_t currentSampleRate() { return currentRateValue; }
1896 
1897  protected:
1899  bool active = false;
1900  uint16_t (*frameCallback)(uint8_t *data, uint16_t len);
1901  // below only relevant with timer
1902  TimerAlarmRepeating *timer = nullptr;
1903  RingBuffer<uint8_t> *buffer = nullptr;
1904  uint8_t *frame = nullptr;
1905  uint16_t frameSize = 0;
1906  uint32_t time = 0;
1907  unsigned long lastTimestamp = 0u;
1908  uint32_t currentRateValue = 0;
1909  uint32_t printCount = 0;
1910 
1911  // used for audio sink
1912  virtual size_t writeExt(const uint8_t *data, size_t len) override {
1913  if (!active) return 0;
1914  TRACED();
1915  size_t result = 0;
1916  if (!cfg.use_timer) {
1917  result = frameCallback((uint8_t *)data, len);
1918  } else {
1919  result = buffer->writeArray((uint8_t *)data, len);
1920  }
1921  if (++printCount % 10000 == 0) printSampleRate();
1922  return result;
1923  }
1924 
1925  // used for audio source
1926  virtual size_t readExt(uint8_t *data, size_t len) override {
1927  if (!active) return 0;
1928  TRACED();
1929 
1930  size_t result = 0;
1931  if (!cfg.use_timer) {
1932  result = frameCallback(data, len);
1933  } else {
1934  result = buffer->readArray(data, len);
1935  }
1936  if (++printCount % 10000 == 0) printSampleRate();
1937  return result;
1938  }
1939 
1941  virtual void measureSampleRate() {
1942  unsigned long ms = millis();
1943  if (lastTimestamp > 0u) {
1944  uint32_t diff = ms - lastTimestamp;
1945  if (diff > 0) {
1946  uint16_t rate = 1 * 1000 / diff;
1947 
1948  if (currentRateValue == 0) {
1949  currentRateValue = rate;
1950  } else {
1951  currentRateValue = (currentRateValue + rate) / 2;
1952  }
1953  }
1954  }
1955  lastTimestamp = ms;
1956  }
1957 
1959  virtual void printSampleRate() {
1960  LOGI("effective sample rate: %u", (unsigned int)currentRateValue);
1961  if (cfg.adapt_sample_rate &&
1962  abs((int)currentRateValue - (int)cfg.sample_rate) > 200) {
1963  cfg.sample_rate = currentRateValue;
1964  notifyAudioChange(cfg);
1965  }
1966  }
1967 };
1968 
1969 // relevant only if use_timer == true
1970 void IRAM_ATTR timerCallback(void *obj) {
1971  TimerCallbackAudioStream *src = (TimerCallbackAudioStream *)obj;
1972  if (src != nullptr) {
1973  // LOGD("%s: %s", LOG_METHOD, src->cfg.rx_tx_mode==RX_MODE ?
1974  // "RX_MODE":"TX_MODE");
1975  if (src->cfg.rx_tx_mode == RX_MODE) {
1976  // input
1977  uint16_t available_bytes = src->frameCallback(src->frame, src->frameSize);
1978  uint16_t buffer_available = src->buffer->availableForWrite();
1979  if (buffer_available < available_bytes) {
1980  // if buffer is full make space
1981  uint16_t to_clear = available_bytes - buffer_available;
1982  uint8_t tmp[to_clear];
1983  src->buffer->readArray(tmp, to_clear);
1984  }
1985  if (src->buffer->writeArray(src->frame, available_bytes) !=
1986  available_bytes) {
1987  assert(false);
1988  }
1989  } else {
1990  // output
1991  if (src->buffer != nullptr && src->frame != nullptr &&
1992  src->frameSize > 0) {
1993  uint16_t available_bytes =
1994  src->buffer->readArray(src->frame, src->frameSize);
1995  if (available_bytes !=
1996  src->frameCallback(src->frame, available_bytes)) {
1997  LOGE("data underflow");
1998  }
1999  }
2000  }
2001  src->measureSampleRate();
2002  }
2003 }
2004 
2005 #endif
2006 
2007 } // namespace audio_tools
virtual void addNotifyAudioChange(AudioInfoSupport &bi)
Adds target to be notified about audio changes.
Definition: AudioTypes.h:162
Supports changes to the sampling rate, bits and channels.
Definition: AudioTypes.h:139
virtual AudioInfo audioInfo()=0
provides the actual input AudioInfo
Abstract Audio Ouptut class.
Definition: AudioOutput.h:22
Base class for all Audio Streams. It support the boolean operator to test if the object is ready with...
Definition: BaseStream.h:109
virtual void setAudioInfo(AudioInfo newInfo) override
Defines the input AudioInfo.
Definition: BaseStream.h:117
virtual AudioInfo audioInfo() override
provides the actual input AudioInfo
Definition: BaseStream.h:140
To be used to support implementations where the readBytes is not virtual.
Definition: AudioStreams.h:24
static uint32_t toTimeUs(uint32_t samplingRate, uint8_t limit=10)
converts sampling rate to delay in microseconds (μs)
Definition: AudioTypes.h:256
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:472
void flush() override
empties the buffer
Definition: AudioStreams.h:521
size_t write(uint8_t c) override
writes a byte to the buffer
Definition: AudioStreams.h:503
size_t readBytes(uint8_t *data, size_t len) override
Use this method !!
Definition: AudioStreams.h:546
int peek() override
peeks a byte - to be avoided
Definition: AudioStreams.h:538
int available() override
Returns the available bytes in the buffer: to be avoided.
Definition: AudioStreams.h:556
size_t write(const uint8_t *data, size_t len) override
Use this method: write an array.
Definition: AudioStreams.h:511
void clear()
Clears all the data in the buffer.
Definition: AudioStreams.h:564
int read() override
reads a byte - to be avoided
Definition: AudioStreams.h:530
void setStream(Stream &io)
Defines/Changes the input & output.
Definition: AudioStreams.h:497
void setOutput(Print &out)
Defines/Changes the output target.
Definition: AudioStreams.h:491
CallbackStream: A Stream that allows to register callback methods for accessing and providing data....
Definition: AudioStreams.h:1357
void setOutput(Stream &in)
same as setStream
Definition: AudioStreams.h:1470
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:1369
void setStream(Print &out)
same as set Output
Definition: AudioStreams.h:1476
void setAvailable(int val)
optioinally define available bytes for next read
Definition: AudioStreams.h:1481
void setOutput(Print &out)
Defines/Changes the output target.
Definition: AudioStreams.h:1465
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:1362
void setStream(Stream &in)
Defines/Changes the input & output.
Definition: AudioStreams.h:1459
void setFilter(int channel, Filter< FT > *filter)
defines the filter for an individual channel - the first channel is 0
Definition: BaseConverter.h:1561
Both the data of the read or write operations will be converted with the help of the indicated conver...
Definition: AudioStreams.h:595
void setStream(Stream &stream)
Defines/Changes the input & output.
Definition: AudioStreams.h:614
void setOutput(Print &out)
Defines/Changes the output target.
Definition: AudioStreams.h:620
virtual int available() override
Returns the available bytes in the buffer: to be avoided.
Definition: AudioStreams.h:647
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:1507
void setStream(Stream &stream)
Defines/Changes the input & output.
Definition: AudioStreams.h:1527
void setFilter(int channel, Filter< TF > &filter)
Definition: AudioStreams.h:1592
void setOutput(Print &stream)
Defines/Changes the output target.
Definition: AudioStreams.h:1532
void setFilter(int channel, Filter< TF > *filter)
Definition: AudioStreams.h:1582
Source for reading generated tones. Please note.
Definition: AudioStreams.h:382
void setAudioInfo(AudioInfo newInfo) override
Defines the input AudioInfo.
Definition: AudioStreams.h:397
size_t readBytes(uint8_t *data, size_t len) override
privide the data as byte stream
Definition: AudioStreams.h:445
void end() override
stop the processing
Definition: AudioStreams.h:431
bool begin() override
start the processing
Definition: AudioStreams.h:405
AudioInfo audioInfo() override
provides the actual input AudioInfo
Definition: AudioStreams.h:437
bool begin(AudioInfo cfg)
start the processing
Definition: AudioStreams.h:418
virtual int available() override
This is unbounded so we just return the buffer size.
Definition: AudioStreams.h:442
Merges multiple input channels. The input must be mono! So if you provide 2 mono channels you get a s...
Definition: AudioStreams.h:1262
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:1291
void end() override
Remove all input streams.
Definition: AudioStreams.h:1322
int available() override
Provides the min available data from all streams.
Definition: AudioStreams.h:1333
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:1313
void add(Stream &in, float weight=1.0)
Adds a new input stream.
Definition: AudioStreams.h:1307
InputMerge(Stream &left, Stream &right)
Constructor for stereo signal from to mono input stream.
Definition: AudioStreams.h:1270
int size()
Number of stremams to which are mixed together = number of result channels.
Definition: AudioStreams.h:1328
MixerStream is mixing the input from Multiple Input Streams. All streams must have the same audo form...
Definition: AudioStreams.h:1107
void add(Stream &in, int weight=100)
Adds a new input stream.
Definition: AudioStreams.h:1112
void set(int channel, Stream &in)
Replaces a stream at the indicated channel.
Definition: AudioStreams.h:1119
size_t readBytes(uint8_t *data, size_t len) override
Provides the data from all streams mixed together.
Definition: AudioStreams.h:1163
void end() override
Remove all input streams.
Definition: AudioStreams.h:1149
int availableBytes()
Provides the available bytes from the first stream with data.
Definition: AudioStreams.h:1231
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:1186
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:1191
int readBytesVector(T *p_data, int byteCount)
mixing using a vector of samples
Definition: AudioStreams.h:1206
int size()
Number of stremams to which are mixed together.
Definition: AudioStreams.h:1158
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:1135
Class which measures the thruput.
Definition: AudioStreams.h:665
virtual size_t write(const uint8_t *data, size_t len) override
Writes raw PCM audio data, which will be the input for the volume control.
Definition: AudioStreams.h:714
void setOutput(Print &out) override
Defines/Changes the output target.
Definition: AudioStreams.h:699
size_t readBytes(uint8_t *data, size_t len) override
Provides the data from all streams mixed together.
Definition: AudioStreams.h:705
void setAudioInfo(AudioInfo info)
Defines the input AudioInfo.
Definition: AudioStreams.h:733
virtual int availableForWrite() override
Provides the nubmer of bytes we can write.
Definition: AudioStreams.h:719
void setReportBytes(bool flag)
Report in bytes instead of samples.
Definition: AudioStreams.h:752
uint32_t startTime()
Provides the time when the last measurement was started.
Definition: AudioStreams.h:729
void setStream(Stream &io) override
Defines/Changes the input & output.
Definition: AudioStreams.h:693
int bytesPerSecond()
Returns the actual thrughput in bytes per second.
Definition: AudioStreams.h:724
A simple Stream implementation which is backed by allocated memory.
Definition: AudioStreams.h:84
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:96
virtual void setLoop(bool loop, int rewindPos)
Automatically rewinds to the indicated position when reaching the end.
Definition: AudioStreams.h:259
virtual void clear(bool reset=false)
clears the audio data: sets all values to 0
Definition: AudioStreams.h:230
void setValue(const uint8_t *buffer, int buffer_size, MemoryType memoryType=FLASH_RAM)
Update the values (buffer and size)
Definition: AudioStreams.h:292
MemoryStream(MemoryStream &&source)
Move Constructor.
Definition: AudioStreams.h:109
MemoryStream & operator=(MemoryStream &other)
copy assignement operator
Definition: AudioStreams.h:121
MemoryStream(MemoryStream &source)
Copy Constructor.
Definition: AudioStreams.h:104
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:248
virtual bool resize(size_t size)
Resizes the available memory. Returns false for PROGMEM or when allocation failed.
Definition: AudioStreams.h:265
MemoryStream(int buffer_size, MemoryType memoryType)
Constructor for alloction in RAM.
Definition: AudioStreams.h:87
bool begin() override
resets the read pointer
Definition: AudioStreams.h:136
bool begin(AudioInfo info)
Define some audio info and start the processing.
Definition: AudioStreams.h:130
void setRewindCallback(void(*cb)())
Callback which is executed when we rewind (in loop mode) to the beginning.
Definition: AudioStreams.h:287
Abstract class: Objects can be put into a pipleline.
Definition: AudioStreams.h:69
virtual void setStream(Stream &in)=0
Defines/Changes the input & output.
virtual void setOutput(Print &out)=0
Defines/Changes the output target.
The Arduino Stream which provides silence and simulates a null device when used as audio target or au...
Definition: BaseStream.h:277
static int64_t maxValue(int value_bits_per_sample)
provides the biggest number for the indicated number of bits
Definition: AudioTypes.h:317
Definition: NoArduino.h:58
Generic calss to measure the the total bytes which were processed in order to calculate the progress ...
Definition: AudioStreams.h:819
bool begin(size_t len)
Updates the total size and restarts the percent calculation: Same as calling setSize()
Definition: AudioStreams.h:866
virtual size_t write(const uint8_t *data, size_t len) override
Writes raw PCM audio data, which will be the input for the volume control.
Definition: AudioStreams.h:926
size_t size()
Provides the current total size (defined by setSize)
Definition: AudioStreams.h:884
size_t totalSecs()
Converts the totalBytes() to seconds.
Definition: AudioStreams.h:904
size_t readBytes(uint8_t *data, size_t len) override
Provides the data from all streams mixed together.
Definition: AudioStreams.h:915
size_t processedBytes()
Provides the number of processed bytes.
Definition: AudioStreams.h:889
void setStream(Stream &stream)
Defines/Changes the input & output.
Definition: AudioStreams.h:845
void setSize(size_t len)
Updates the total size and restarts the percent calculation.
Definition: AudioStreams.h:878
virtual int availableForWrite() override
Provides the nubmer of bytes we can write.
Definition: AudioStreams.h:932
float percentage()
Provides the processed percentage: If no size has been defined we return 0.
Definition: AudioStreams.h:909
size_t processedSecs()
Provides the number of processed seconds.
Definition: AudioStreams.h:894
void setAudioInfo(AudioInfo info) override
Defines the input AudioInfo.
Definition: AudioStreams.h:840
size_t totalBytes()
Provides the total_size provided in the configuration.
Definition: AudioStreams.h:899
Configuration for ProgressStream.
Definition: AudioStreams.h:808
An AudioStream backed by a Ringbuffer. We can write to the end and read from the beginning of the str...
Definition: AudioStreams.h:334
T * address() override
Provides address to beginning of the buffer.
Definition: Buffers.h:249
size_t setAvailable(size_t available_size)
Definition: Buffers.h:264
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:981
void setOutput(Print &out) override
Defines/Changes the output target.
Definition: AudioStreams.h:994
void setStream(Stream &io) override
Defines/Changes the input & output.
Definition: AudioStreams.h:988
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:1812
TimerCallbackAudioStreamInfo audioInfoExt()
Provides the current audio information.
Definition: AudioStreams.h:1846
uint16_t currentSampleRate()
Provides the effective sample rate.
Definition: AudioStreams.h:1895
TimerCallbackAudioStreamInfo defaultConfig()
Provides the default configuration.
Definition: AudioStreams.h:1826
bool begin()
Restart the processing.
Definition: AudioStreams.h:1874
AudioInfo audioInfo()
provides the actual input AudioInfo
Definition: AudioStreams.h:1847
virtual void measureSampleRate()
calculates the effective sample rate
Definition: AudioStreams.h:1941
virtual void setAudioInfo(AudioInfo info)
updates the audio information
Definition: AudioStreams.h:1832
virtual void printSampleRate()
log and update effective sample rate
Definition: AudioStreams.h:1959
void end()
Stops the processing.
Definition: AudioStreams.h:1886
Vector implementation which provides the most important methods as defined by std::vector....
Definition: Vector.h:21
A simple class to determine the volume. You can use it as final output or as output or input in your ...
Definition: AudioStreams.h:1612
void setOutput(Print &out) override
Defines/Changes the output target.
Definition: AudioStreams.h:1717
float volumeRatio()
Volume Ratio: max amplitude is 1.0.
Definition: AudioStreams.h:1683
float volume()
Definition: AudioStreams.h:1665
float volumePercent()
Volume in %: max amplitude is 100.
Definition: AudioStreams.h:1703
void setAudioInfo(AudioInfo info)
Defines the input AudioInfo.
Definition: AudioStreams.h:1639
float volumePercent(int channel)
Volume of indicated channel in %: max amplitude is 100.
Definition: AudioStreams.h:1706
void clear()
Resets the actual volume.
Definition: AudioStreams.h:1710
float volumeRatio(int channel)
Volume Ratio of indicated channel: max amplitude is 1.0.
Definition: AudioStreams.h:1686
float volumeDB(int channel)
Volume of indicated channel in db: max amplitude is 0.
Definition: AudioStreams.h:1696
void setStream(Stream &io) override
Defines/Changes the input & output.
Definition: AudioStreams.h:1720
float volumeDB()
Volume in db: max amplitude is 0 (range: -1000 to 0)
Definition: AudioStreams.h:1689
float volume(int channel)
Definition: AudioStreams.h:1669
MemoryType
Memory types.
Definition: AudioTypes.h:35
RxTxMode
The Microcontroller is the Audio Source (TX_MODE) or Audio Sink (RX_MODE). RXTX_MODE is Source and Si...
Definition: AudioTypes.h:28
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition: AudioConfig.h:823
size_t readSamples(Stream *p_stream, T *data, int samples, int retryCount=-1)
guaranteed to return the requested data
Definition: AudioTypes.h:480
uint32_t millis()
Returns the milliseconds since the start.
Definition: Time.h:12
Basic Audio information which drives e.g. I2S.
Definition: AudioTypes.h:52
void copyFrom(AudioInfo info)
Same as set.
Definition: AudioTypes.h:107
sample_rate_t sample_rate
Sample Rate: e.g 44100.
Definition: AudioTypes.h:55
uint16_t channels
Number of channels: 2=stereo, 1=mono.
Definition: AudioTypes.h:57
uint8_t bits_per_sample
Number of bits per sample (int16_t = 16 bits)
Definition: AudioTypes.h:59
Configure Throttle setting.
Definition: AudioStreams.h:966
TimerCallbackAudioStream Configuration.
Definition: AudioStreams.h:1791