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:
86  // Default constructor
87  MemoryStream() = default;
89  MemoryStream(int buffer_size, MemoryType memoryType) {
90  LOGD("MemoryStream: %d", buffer_size);
91  this->buffer_size = buffer_size;
92  this->memory_type = memoryType;
93  resize(buffer_size);
94  info.clear(); // mark audio info as unknown
95  }
96 
98  MemoryStream(const uint8_t *buffer, int buffer_size, bool isActive=true, MemoryType memoryType = FLASH_RAM) {
99  LOGD("MemoryStream: %d", buffer_size);
100  setValue(buffer, buffer_size, memoryType);
101  is_active = isActive;
102  info.clear(); // mark audio info as unknown
103  }
104 
107  copy(source);
108  }
109 
112  setValue(source.buffer, source.buffer_size, source.memory_type);
113  // clear source data
114  source.setValue(nullptr, 0, source.memory_type);
115  }
116 
117  ~MemoryStream() {
118  TRACED();
119  if (memoryCanChange() && buffer!=nullptr) free(buffer);
120  }
121 
124  copy(other);
125  return *this;
126  }
127 
129  operator bool() override { return available() > 0; }
130 
132  bool begin(AudioInfo info){
133  this->info = info;
134  return begin();
135  }
136 
138  bool begin() override {
139  TRACED();
140  write_pos = memoryCanChange() ? 0 : buffer_size;
141  if (this->buffer==nullptr && memoryCanChange()){
142  resize(buffer_size);
143  }
144  read_pos = 0;
145  is_active = true;
146  return true;
147  }
148 
149  virtual size_t write(uint8_t byte) override {
150  if (!is_active) return 0;
151  if (memory_type == FLASH_RAM) return 0;
152  if (buffer==nullptr) return 0;
153  int result = 0;
154  if (write_pos < buffer_size) {
155  result = 1;
156  buffer[write_pos] = byte;
157  write_pos++;
158  }
159  return result;
160  }
161 
162  virtual size_t write(const uint8_t *data, size_t len) override {
163  if (!is_active) return 0;
164  if (memory_type == FLASH_RAM) return 0;
165  size_t result = 0;
166  for (size_t j = 0; j < len; j++) {
167  if (!write(data[j])) {
168  break;
169  }
170  result = j + 1;
171  }
172  return result;
173  }
174 
175  virtual int available() override {
176  if (!is_active) return 0;
177  if (buffer==nullptr) return 0;
178  int result = write_pos - read_pos;
179  if (result<=0 && is_loop){
180  // rewind to start
181  read_pos = rewind_pos;
182  result = write_pos - read_pos;
183  // call callback
184  if (rewind!=nullptr) rewind();
185  }
186  return is_loop ? DEFAULT_BUFFER_SIZE : result;
187  }
188 
189  virtual int availableForWrite() override {
190  if (!is_active) return 0;
191  if (memory_type == FLASH_RAM) return 0;
192  return buffer_size - write_pos;
193  }
194 
195  virtual int read() override {
196  int result = peek();
197  if (result >= 0) {
198  read_pos++;
199  }
200  return result;
201  }
202 
203  virtual size_t readBytes(uint8_t *data, size_t len) override {
204  if (!is_active) return 0;
205  size_t count = 0;
206  while (count < len) {
207  int c = read();
208  if (c < 0) break;
209  *data++ = (char)c;
210  count++;
211  }
212  return count;
213  }
214 
215  virtual int peek() override {
216  if (!is_active) return -1;
217  int result = -1;
218  if (available() > 0) {
219  result = buffer[read_pos];
220  }
221  return result;
222  }
223 
224  virtual void flush() override {}
225 
226  virtual void end() override {
227  read_pos = 0;
228  is_active = false;
229  }
230 
232  virtual void clear(bool reset = false) {
233  if (memoryCanChange()){
234  write_pos = 0;
235  read_pos = 0;
236  if (buffer==nullptr){
237  resize(buffer_size);
238  }
239  if (reset) {
240  // we clear the buffer data
241  memset(buffer, 0, buffer_size);
242  }
243  } else {
244  read_pos = 0;
245  LOGW("data is read only");
246  }
247  }
248 
250  virtual void setLoop(bool loop){
251  is_loop = loop;
252  rewind_pos = 0;
253  if (buffer!=nullptr && buffer_size > 12){
254  if (memcmp("WAVE", buffer+8, 4)==0){
255  rewind_pos = 44;
256  }
257  }
258  }
259 
261  virtual void setLoop(bool loop, int rewindPos){
262  is_loop = loop;
263  rewind_pos = rewindPos;
264  }
265 
267  virtual bool resize(size_t size){
268  if (!memoryCanChange()) return false;
269 
270  buffer_size = size;
271  switch(memory_type){
272 #if defined(ESP32) && defined(ARDUINO)
273  case PS_RAM:
274  buffer = (buffer==nullptr) ? (uint8_t*)ps_calloc(size,1) : (uint8_t*)ps_realloc(buffer, size);
275  break;
276 #endif
277  default:
278  buffer = (buffer==nullptr) ? (uint8_t*)calloc(size,1) : (uint8_t*)realloc(buffer, size);
279  break;
280  }
281  return buffer != nullptr;
282  }
283 
285  virtual uint8_t* data(){
286  return buffer;
287  }
288 
290  virtual void setAvailable(size_t len) {
291  this->write_pos = len;
292  }
293 
295  void setRewindCallback(void (*cb)()){
296  this->rewind = cb;
297  }
298 
300  void setValue(const uint8_t *buffer, int buffer_size, MemoryType memoryType = FLASH_RAM) {
301  this->buffer_size = buffer_size;
302  this->read_pos = 0;
303  this->write_pos = buffer_size;
304  this->buffer = (uint8_t *)buffer;
305  this->memory_type = memoryType;
306  }
307 
308  protected:
309  int write_pos = 0;
310  int read_pos = 0;
311  int buffer_size = 0;
312  int rewind_pos = 0;
313  uint8_t *buffer = nullptr;
314  MemoryType memory_type = RAM;
315  bool is_loop = false;
316  void (*rewind)() = nullptr;
317  bool is_active = false;
318 
319  bool memoryCanChange() {
320  return memory_type!=FLASH_RAM;
321  }
322 
323  void copy(MemoryStream& source) {
324  if (this == &source) return;
325  if (source.memory_type == FLASH_RAM){
326  setValue(source.buffer, source.buffer_size, source.memory_type);
327  } else {
328  setValue(nullptr, source.buffer_size, source.memory_type);
329  resize(buffer_size);
330  memcpy(buffer, source.buffer, buffer_size);
331  }
332  }
333 };
334 
343  public:
344  RingBufferStream(int size = DEFAULT_BUFFER_SIZE) { resize(size); }
345 
346  virtual int available() override {
347  // LOGD("RingBufferStream::available: %zu",buffer->available());
348  return buffer.available();
349  }
350 
351  virtual int availableForWrite() override {
352  return buffer.availableForWrite();
353  }
354 
355  virtual void flush() override {}
356  virtual int peek() override { return buffer.peek(); }
357  virtual int read() override { return buffer.read(); }
358 
359  virtual size_t readBytes(uint8_t *data, size_t len) override {
360  return buffer.readArray(data, len);
361  }
362 
363  virtual size_t write(const uint8_t *data, size_t len) override {
364  // LOGD("RingBufferStream::write: %zu",len);
365  return buffer.writeArray(data, len);
366  }
367 
368  virtual size_t write(uint8_t c) override { return buffer.write(c); }
369 
370  void resize(int size) { buffer.resize(size); }
371 
372  size_t size() { return buffer.size(); }
373 
374  protected:
375  RingBuffer<uint8_t> buffer{0};
376 };
377 
389 template <class T>
391  public:
392  GeneratedSoundStream() = default;
393 
395  TRACED();
396  setInput(generator);
397  }
398 
399  void setInput(SoundGenerator<T> &generator){
400  this->generator_ptr = &generator;
401  }
402 
403  AudioInfo defaultConfig() { return this->generator_ptr->defaultConfig(); }
404 
405  void setAudioInfo(AudioInfo newInfo) override {
406  if (newInfo.bits_per_sample != sizeof(T)*8){
407  LOGE("Wrong bits_per_sample: %d", newInfo.bits_per_sample);
408  }
409  AudioStream::setAudioInfo(newInfo);
410  }
411 
413  bool begin() override {
414  TRACED();
415  if (generator_ptr==nullptr){
416  LOGE("%s",source_not_defined_error);
417  return false;
418  }
419  generator_ptr->begin();
420  notifyAudioChange(generator_ptr->audioInfo());
421  active = true;
422  return active;
423  }
424 
426  bool begin(AudioInfo cfg) {
427  TRACED();
428  if (generator_ptr==nullptr){
429  LOGE("%s",source_not_defined_error);
430  return false;
431  }
432  generator_ptr->begin(cfg);
433  notifyAudioChange(generator_ptr->audioInfo());
434  active = true;
435  return active;
436  }
437 
439  void end() override {
440  TRACED();
441  generator_ptr->end();
442  active = true; // legacy support - most sketches do not call begin
443  }
444 
445  AudioInfo audioInfo() override {
446  return generator_ptr->audioInfo();
447  }
448 
450  virtual int available() override { return active ? DEFAULT_BUFFER_SIZE*2 : 0; }
451 
453  size_t readBytes(uint8_t *data, size_t len) override {
454  if (!active) return 0;
455  LOGD("GeneratedSoundStream::readBytes: %u", (unsigned int)len);
456  return generator_ptr->readBytes(data, len);
457  }
458 
459  bool isActive() {return active && generator_ptr->isActive();}
460 
461  operator bool() { return isActive(); }
462 
463  void flush() override {}
464 
465  protected:
466  bool active = true; // support for legacy sketches
467  SoundGenerator<T> *generator_ptr;
468  const char* source_not_defined_error = "Source not defined";
469 
470 };
471 
481  public:
482  BufferedStream(size_t buffer_size) {
483  TRACED();
484  buffer.resize(buffer_size);
485  }
486 
487  BufferedStream(size_t buffer_size, Print &out) {
488  TRACED();
489  setOutput(out);
490  buffer.resize(buffer_size);
491  }
492 
493  BufferedStream(size_t buffer_size, Stream &io) {
494  TRACED();
495  setStream(io);
496  buffer.resize(buffer_size);
497  }
498 
499  void setOutput(Print &out){
500  p_out = &out;
501  }
502  void setStream(Print &out){
503  setOutput(out);
504  }
505  void setStream(Stream &io){
506  p_in = &io;
507  p_out = &io;
508  }
509 
511  size_t write(uint8_t c) override {
512  if (buffer.isFull()) {
513  flush();
514  }
515  return buffer.write(c);
516  }
517 
519  size_t write(const uint8_t *data, size_t len) override {
520  LOGD("%s: %zu", LOG_METHOD, len);
521  int result = 0;
522  for (int j=0;j<len;j++){
523  result += write(data[j]);
524  }
525  return result;
526  }
527 
529  void flush() override {
530  // just dump the memory of the buffer and clear it
531  if (buffer.available() > 0) {
532  writeExt(buffer.address(), buffer.available());
533  buffer.reset();
534  }
535  }
536 
538  int read() override {
539  if (buffer.isEmpty()) {
540  refill();
541  }
542  return buffer.read();
543  }
544 
546  int peek() override{
547  if (buffer.isEmpty()) {
548  refill();
549  }
550  return buffer.peek();
551  };
552 
554  size_t readBytes(uint8_t *data, size_t len) override {
555  if (buffer.isEmpty()) {
556  return readExt(data, len);
557  } else {
558  refill();
559  return buffer.readArray(data, len);
560  }
561  }
562 
564  int available() override {
565  if (buffer.isEmpty()) {
566  refill();
567  }
568  return buffer.available();
569  }
570 
572  void clear() { buffer.reset(); }
573 
574  protected:
575  SingleBuffer<uint8_t> buffer;
576  Print* p_out = nullptr;
577  Stream* p_in = nullptr;
578 
579  // refills the buffer with data from i2s
580  void refill() {
581  size_t result = readExt(buffer.address(), buffer.size());
582  buffer.setAvailable(result);
583  }
584 
585  virtual size_t writeExt(const uint8_t *data, size_t len) {
586  return p_out == nullptr ? 0 : p_out->write(data, len);
587  }
588  virtual size_t readExt(uint8_t *data, size_t len) {
589  return p_in == nullptr ? 0 : p_in->readBytes(data, len);
590  }
591 };
592 
593 
602 template<typename T>
604 
605  public:
606  ConverterStream() = default;
607 
608  ConverterStream(BaseConverter &converter) {
609  setConverter(converter);
610  }
611 
612  ConverterStream(Stream &stream, BaseConverter &converter) {
613  setConverter(converter);
614  setStream(stream);
615  }
616 
617  ConverterStream(Print &out, BaseConverter &converter) {
618  setConverter(converter);
619  setOutput(out);
620  }
621 
622  void setStream(Stream &stream){
623  TRACEI();
624  p_stream = &stream;
625  p_out = &stream;
626  }
627 
628  void setOutput(Print &out){
629  TRACEI();
630  p_out = &out;
631  }
632 
633  void setConverter(BaseConverter& cnv){
634  p_converter = &cnv;
635  }
636 
637  virtual int availableForWrite() { return p_out->availableForWrite(); }
638 
639  virtual size_t write(const uint8_t *data, size_t len) {
640  size_t result = p_converter->convert((uint8_t *)data, len);
641  if (result>0) {
642  size_t result_written = p_out->write(data, result);
643  return len * result_written / result;
644  }
645  return 0;
646  }
647 
648  size_t readBytes(uint8_t *data, size_t len) override {
649  if (p_stream==nullptr) return 0;
650  size_t result = p_stream->readBytes(data, len);
651  return p_converter->convert(data, result);
652  }
653 
655  virtual int available() override {
656  if (p_stream==nullptr) return 0;
657  return p_stream->available();
658  }
659 
660  protected:
661  Stream *p_stream = nullptr;
662  Print *p_out = nullptr;
663  BaseConverter *p_converter;
664 
665 };
666 
674  public:
675  MeasuringStream(int count=10, Print *logOut=nullptr){
676  this->count = count;
677  this->max_count = count;
678  p_stream = &null;
679  p_print = &null;
680  start_time = millis();
681  p_logout = logOut;
682  }
683 
684  MeasuringStream(Print &print, int count=10, Print *logOut=nullptr){
685  this->count = count;
686  this->max_count = count;
687  setOutput(print);
688  start_time = millis();
689  p_logout = logOut;
690  }
691 
692  MeasuringStream(Stream &stream, int count=10, Print *logOut=nullptr){
693  this->count = count;
694  this->max_count = count;
695  setStream(stream);
696  start_time = millis();
697  p_logout = logOut;
698  }
699 
701  void setStream(Stream& io) override {
702  p_print = &io;
703  p_stream = &io;
704  };
705 
707  void setOutput(Print& out) override {
708  p_print = &out;
709  }
710 
711 
713  size_t readBytes(uint8_t* data, size_t len) override {
714  return measure(p_stream->readBytes(data, len));
715  }
716 
717  int available() override {
718  return p_stream->available();
719  }
720 
722  virtual size_t write(const uint8_t *data, size_t len) override {
723  return measure(p_print->write(data, len));
724  }
725 
727  virtual int availableForWrite() override {
728  return p_print->availableForWrite();
729  }
730 
733  return bytes_per_second;
734  }
735 
737  uint32_t startTime() {
738  return start_time;
739  }
740 
742  AudioStream::info = info;
743  setFrameSize(info.bits_per_sample / 8 *info.channels);
744  }
745 
746  bool begin(){
747  return AudioStream::begin();
748  }
749 
750  bool begin(AudioInfo info){
751  setAudioInfo(info);
752  return true;
753  }
754 
756  void setFrameSize(int size){
757  frame_size = size;
758  }
759 
761  void setReportBytes(bool flag){
762  report_bytes = flag;
763  }
764 
765  protected:
766  int max_count=0;
767  int count=0;
768  Stream *p_stream=nullptr;
769  Print *p_print=nullptr;
770  uint32_t start_time;
771  int total_bytes = 0;
772  int bytes_per_second = 0;
773  int frame_size = 0;
774  NullStream null;
775  Print *p_logout=nullptr;
776  bool report_bytes = false;
777 
778  size_t measure(size_t len) {
779  count--;
780  total_bytes+=len;
781 
782  if (count<=0){
783  uint32_t end_time = millis();
784  int time_diff = end_time - start_time; // in ms
785  if (time_diff>0){
786  bytes_per_second = total_bytes / time_diff * 1000;
787  printResult();
788  count = max_count;
789  total_bytes = 0;
790  start_time = end_time;
791  }
792  }
793  return len;
794  }
795 
796  void printResult() {
797  char msg[70];
798  if (report_bytes || frame_size==0){
799  snprintf(msg, 70, "==> Bytes per second: %d", bytes_per_second);
800  } else {
801  snprintf(msg, 70, "==> Samples per second: %d", bytes_per_second/frame_size);
802  }
803  if (p_logout!=nullptr){
804  p_logout->println(msg);
805  } else {
806  LOGI("%s",msg);
807  }
808  }
809 };
810 
818  public:
819  size_t total_size = 0;
820 };
829  public:
830  ProgressStream() = default;
831 
832  ProgressStream(Print &print){
833  setPrint(print);
834  }
835 
836  ProgressStream(Stream &stream){
837  setStream(stream);
838  }
839 
840  ProgressStream(AudioStream &stream){
841  setStream(stream);
842  p_info_from = &stream;
843  }
844 
845  ProgressStreamInfo& defaultConfig() {
846  return progress_info;
847  }
848 
849  void setAudioInfo(AudioInfo info) override {
851  progress_info.copyFrom(info);
852  }
853 
854  void setStream(Stream &stream){
855  p_stream =&stream;
856  p_print = &stream;
857  }
858 
859  void setStream(Print &print){
860  p_print =&print;
861  }
862 
863  void setPrint(Print &print){
864  p_print =&print;
865  }
866 
867  bool begin() override {
868  if (p_info_from!=nullptr){
869  setAudioInfo(p_info_from->audioInfo());
870  }
871  return AudioStream::begin();
872  }
873 
875  bool begin(size_t len){
876  setSize(len);
877  return begin();
878  }
879 
880  bool begin(ProgressStreamInfo info){
881  progress_info = info;
882  setAudioInfo(info);
883  return begin();
884  }
885 
887  void setSize(size_t len){
888  total_processed = 0;
889  progress_info.total_size = len;
890  }
891 
893  size_t size(){
894  return progress_info.total_size;
895  }
896 
898  size_t processedBytes() {
899  return total_processed;
900  }
901 
903  size_t processedSecs() {
904  return total_processed / byteRate();
905  }
906 
908  size_t totalBytes() {
909  return progress_info.total_size;
910  }
911 
913  size_t totalSecs() {
914  return totalBytes() / byteRate();
915  }
916 
918  float percentage() {
919  if (progress_info.total_size==0) return 0;
920  return 100.0 * total_processed / progress_info.total_size;
921  }
922 
924  size_t readBytes(uint8_t* data, size_t len) override {
925  if (p_stream==nullptr) return 0;
926  return measure(p_stream->readBytes(data, len));
927  }
928 
929  int available() override {
930  if (p_stream==nullptr) return 0;
931  return p_stream->available();
932  }
933 
935  virtual size_t write(const uint8_t *data, size_t len) override {
936  if (p_print==nullptr) return 0;
937  return measure(p_print->write(data, len));
938  }
939 
941  virtual int availableForWrite() override {
942  if (p_print==nullptr) return 0;
943  return p_print->availableForWrite();
944  }
945 
946  protected:
947  ProgressStreamInfo progress_info;
948  Stream *p_stream=nullptr;
949  Print *p_print=nullptr;
950  AudioInfoSupport *p_info_from=nullptr;
951  size_t total_processed = 0;
952 
953  size_t measure(size_t len) {
954  total_processed += len;
955  return len;
956  }
957 
958  size_t byteRate() {
959  AudioInfo info = audioInfo();
960  int byte_rate = info.sample_rate * info.bits_per_sample * info.channels / 8;
961  if (byte_rate==0){
962  LOGE("Audio Info not defined");
963  return 0;
964  }
965  return byte_rate;
966  }
967 
968 };
969 
975 struct ThrottleConfig : public AudioInfo {
976  ThrottleConfig() {
977  sample_rate = 44100;
978  bits_per_sample = 16;
979  channels = 2;
980  }
981  int correction_us = 0;
982 };
983 
990 class Throttle : public ModifyingStream {
991  public:
992  Throttle() = default;
993  Throttle(Print &out) { setOutput(out); }
994  Throttle(Stream &io) { setStream(io); }
995 
997  void setStream(Stream& io) override {
998  p_out = &io;
999  p_in = &io;
1000  };
1001 
1003  void setOutput(Print& out) override {
1004  p_out = &out;
1005  }
1006 
1007  ThrottleConfig defaultConfig() {
1008  ThrottleConfig c;
1009  return c;
1010  }
1011 
1012  bool begin(ThrottleConfig cfg) {
1013  LOGI("begin sample_rate: %d, channels: %d, bits: %d", (int) info.sample_rate,(int) info.channels, (int)info.bits_per_sample);
1014  this->info = cfg;
1015  this->cfg = cfg;
1016  return begin();
1017  }
1018 
1019  bool begin(AudioInfo info) {
1020  LOGI("begin sample_rate: %d, channels: %d, bits: %d", (int)info.sample_rate, (int) info.channels, (int)info.bits_per_sample);
1021  this->info = info;
1022  this->cfg.copyFrom(info);
1023  return begin();
1024  }
1025 
1026  bool begin(){
1027  frame_size = cfg.bits_per_sample / 8 * cfg.channels;
1028  startDelay();
1029  return true;
1030  }
1031 
1032  // (re)starts the timing
1033  void startDelay() {
1034  start_time = micros();
1035  sum_frames = 0;
1036  }
1037 
1038  int availableForWrite() {
1039  if (p_out){
1040  return p_out->availableForWrite();
1041  }
1042  return DEFAULT_BUFFER_SIZE;
1043  }
1044 
1045  size_t write(const uint8_t* data, size_t len){
1046  size_t result = p_out->write(data, len);
1047  delayBytes(len);
1048  return result;
1049  }
1050 
1051  int available() {
1052  if (p_in==nullptr) return 0;
1053  return p_in->available();
1054  }
1055 
1056  size_t readBytes(uint8_t* data, size_t len) override{
1057  if (p_in==nullptr) {
1058  delayBytes(len);
1059  return 0;
1060  }
1061  size_t result = p_in->readBytes(data, len);
1062  delayBytes(len);
1063  return result;
1064  }
1065 
1066  // delay
1067  void delayBytes(size_t bytes) { delayFrames(bytes / frame_size); }
1068 
1069  // delay
1070  void delayFrames(size_t frames) {
1071  sum_frames += frames;
1072  uint64_t durationUsEff = micros() - start_time;
1073  uint64_t durationUsToBe = getDelayUs(sum_frames);
1074  int64_t waitUs = durationUsToBe - durationUsEff + cfg.correction_us;
1075  LOGD("wait us: %ld", static_cast<long>(waitUs));
1076  if (waitUs > 0) {
1077  int64_t waitMs = waitUs / 1000;
1078  if (waitMs > 0) delay(waitMs);
1079  delayMicroseconds(waitUs - (waitMs * 1000));
1080  } else {
1081  LOGD("negative delay!")
1082  }
1083  }
1084 
1085  inline int64_t getDelayUs(uint64_t frames){
1086  return (frames * 1000000) / cfg.sample_rate;
1087  }
1088 
1089  inline int64_t getDelayMs(uint64_t frames){
1090  return getDelayUs(frames) / 1000;
1091  }
1092 
1093  inline int64_t getDelaySec(uint64_t frames){
1094  return getDelayUs(frames) / 1000000l;
1095  }
1096 
1097  protected:
1098  uint32_t start_time = 0;
1099  uint32_t sum_frames = 0;
1100  ThrottleConfig cfg;
1101  int frame_size = 0;
1102  Print *p_out = nullptr;
1103  Stream *p_in = nullptr;
1104 };
1105 
1106 
1115 template<typename T>
1116 class InputMixer : public AudioStream {
1117  public:
1118  InputMixer() = default;
1119 
1121  void add(Stream &in, int weight=100){
1122  streams.push_back(&in);
1123  weights.push_back(weight);
1124  total_weights += weight;
1125  }
1126 
1128  void set(int channel, Stream &in){
1129  if (channel<size()){
1130  streams[channel] = &in;
1131  } else {
1132  LOGE("Invalid channel %d - max is %d", channel, size()-1);
1133  }
1134  }
1135 
1136  virtual bool begin(AudioInfo info) {
1137  setAudioInfo(info);
1138  frame_size = info.bits_per_sample/8 * info.channels;
1139  LOGI("frame_size: %d",frame_size);
1140  return frame_size>0;
1141  }
1142 
1144  void setWeight(int channel, int weight){
1145  if (channel<size()){
1146  weights[channel] = weight;
1147  int total = 0;
1148  for (int j=0;j<weights.size();j++){
1149  total += weights[j];
1150  }
1151  total_weights = total;
1152  } else {
1153  LOGE("Invalid channel %d - max is %d", channel, size()-1);
1154  }
1155  }
1156 
1158  void end() override {
1159  streams.clear();
1160  weights.clear();
1161  result_vect.clear();
1162  current_vect.clear();
1163  total_weights = 0.0;
1164  }
1165 
1167  int size() {
1168  return streams.size();
1169  }
1170 
1172  size_t readBytes(uint8_t* data, size_t len) override {
1173  if (total_weights==0 || frame_size==0 || len==0) {
1174  LOGW("readBytes: %d",(int)len);
1175  return 0;
1176  }
1177 
1178  if (limit_available_data){
1179  len = min((int)len, availableBytes());
1180  }
1181 
1182  int result_len = 0;
1183 
1184  if (len > 0) {
1185  // result_len must be full frames
1186  result_len = len * frame_size / frame_size;
1187  // replace sample based with vector based implementation
1188  //readBytesSamples((T*)data, result_len));
1189  result_len = readBytesVector((T*)data, result_len);
1190  }
1191  return result_len;
1192  }
1193 
1195  void setLimitToAvailableData(bool flag){
1196  limit_available_data = flag;
1197  }
1198 
1200  void setRetryCount(int retry){
1201  retry_count = retry;
1202  }
1203 
1204  protected:
1205  Vector<Stream*> streams{0};
1206  Vector<int> weights{0};
1207  int total_weights = 0;
1208  int frame_size = 4;
1209  bool limit_available_data = false;
1210  int retry_count = 5;
1211  Vector<int> result_vect;
1212  Vector<T> current_vect;
1213 
1215  int readBytesVector(T* p_data, int byteCount) {
1216  int samples = byteCount / sizeof(T);
1217  result_vect.resize(samples);
1218  current_vect.resize(samples);
1219  int stream_count = size();
1220  resultClear();
1221  int samples_eff_max = 0;
1222  for (int j=0;j<stream_count;j++){
1223  if (weights[j]>0){
1224  int samples_eff = readSamples(streams[j],current_vect.data(), samples, retry_count);
1225  if (samples_eff > samples_eff_max)
1226  samples_eff_max = samples_eff;
1227  // if all weights are 0.0 we stop to output
1228  float factor = total_weights == 0.0f ? 0.0f : static_cast<float>(weights[j]) / total_weights;
1229  resultAdd(factor);
1230  }
1231  }
1232  // copy result
1233  for (int j=0;j<samples;j++){
1234  p_data[j] = result_vect[j];
1235  }
1236  return samples_eff_max * sizeof(T);
1237  }
1238 
1241  int result = DEFAULT_BUFFER_SIZE;
1242  for (int j=0;j<size();j++){
1243  result = min(result, streams[j]->available());
1244  }
1245  return result;
1246  }
1247 
1248  void resultAdd(float fact){
1249  for (int j=0;j<current_vect.size();j++){
1250  current_vect[j]*=fact;
1251  result_vect[j] += current_vect[j];
1252  }
1253  }
1254 
1255  void resultClear(){
1256  memset(result_vect.data(), 0, sizeof(int)*result_vect.size());
1257  }
1258 
1259 };
1260 
1270 template<typename T>
1271 class InputMerge : public AudioStream {
1272  public:
1274  InputMerge() = default;
1275 
1279  InputMerge(Stream &left, Stream &right) {
1280  add(left);
1281  add(right);
1282  };
1283 
1284  virtual bool begin(AudioInfo info) {
1285  if (size()!=info.channels){
1286  info.channels = size();
1287  LOGW("channels corrected to %d", size());
1288  }
1289  setAudioInfo(info);
1290  return begin();
1291  }
1292 
1293  virtual bool begin() {
1294  // make sure that we use the correct channel count
1295  info.channels = size();
1296  return AudioStream::begin();
1297  }
1298 
1300  size_t readBytes(uint8_t* data, size_t len) override {
1301  LOGD("readBytes: %d",(int)len);
1302  T *p_data = (T*) data;
1303  int result_len = MIN(available(), len/size());
1304  int sample_count = result_len / sizeof(T);
1305  int size_value = size();
1306  int result_idx = 0;
1307  for (int j=0;j<sample_count; j++){
1308  for (int i=0; i<size_value; i++){
1309  p_data[result_idx++] = weights[i] * readSample<T>(streams[i]);
1310  }
1311  }
1312  return result_idx*sizeof(T);
1313  }
1314 
1316  void add(Stream &in, float weight=1.0){
1317  streams.push_back(&in);
1318  weights.push_back(weight);
1319  }
1320 
1322  void setWeight(int channel, float weight){
1323  if (channel<size()){
1324  weights[channel] = weight;
1325  } else {
1326  LOGE("Invalid channel %d - max is %d", channel, size()-1);
1327  }
1328  }
1329 
1331  void end() override {
1332  streams.clear();
1333  weights.clear();
1334  }
1335 
1337  int size() {
1338  return streams.size();
1339  }
1340 
1342  int available() override {
1343  int result = streams[0]->available();
1344  for (int j=1;j<size();j++){
1345  int tmp = streams[j]->available();
1346  if (tmp<result){
1347  result = tmp;
1348  }
1349  }
1350  return result;
1351  }
1352 
1353  protected:
1354  Vector<Stream*> streams{10};
1355  Vector<float> weights{10};
1356 };
1357 
1358 
1367  public:
1368  CallbackStream() = default;
1369 
1371  CallbackStream(Stream &io, size_t (*cb_update)(uint8_t* data, size_t len)) {
1372  p_stream = &io;
1373  p_out = &io;
1374  setUpdateCallback(cb_update);
1375  }
1376 
1378  CallbackStream(Print &out, size_t (*cb_update)(uint8_t* data, size_t len)) {
1379  p_out = &out;
1380  setUpdateCallback(cb_update);
1381  }
1382 
1383  CallbackStream(size_t (*cb_read)(uint8_t* data, size_t len), size_t (*cb_write)(const uint8_t* data, size_t len)) {
1384  setWriteCallback(cb_write);
1385  setReadCallback(cb_read);
1386  }
1387 
1388  void setWriteCallback(size_t (*cb_write)(const uint8_t* data, size_t len)){
1389  this->cb_write = cb_write;
1390  }
1391 
1392  void setReadCallback(size_t (*cb_read)(uint8_t* data, size_t len)){
1393  this->cb_read = cb_read;
1394  }
1395 
1396  void setUpdateCallback(size_t (*cb_update)(uint8_t* data, size_t len)){
1397  this->cb_update = cb_update;
1398  }
1399 
1400  // callback result negative -> no change; callbeack result >=0 provides the result
1401  void setAvailableCallback(int (*cb)()){
1402  this->cb_available = cb;
1403  }
1404 
1405  virtual bool begin(AudioInfo info) {
1406  setAudioInfo(info);
1407  return begin();
1408  }
1409  virtual bool begin() override {
1410  active = true;
1411  return true;
1412  }
1413 
1414  void end() override { active = false;}
1415 
1416  int available() override {
1417  int result = AudioStream::available();
1418  // determine value from opional variable
1419  if (available_bytes>=0)
1420  return available_bytes;
1421  // check if there is a callback
1422  if (cb_available==nullptr)
1423  return result;
1424  // determine value from callback
1425  int tmp_available = cb_available();
1426  if (tmp_available < 0)
1427  return result;
1428 
1429  return tmp_available;
1430  }
1431 
1432  size_t readBytes(uint8_t* data, size_t len) override {
1433  if (!active) return 0;
1434  // provide data from callback
1435  if (cb_read){
1436  return cb_read(data, len);
1437  }
1438  // provide data from source
1439  size_t result = 0;
1440  if (p_stream){
1441  result = p_stream->readBytes(data , len);
1442  }
1443  if (cb_update){
1444  result = cb_update(data, result);
1445  }
1446  return result;
1447  }
1448 
1449  size_t write(const uint8_t* data, size_t len) override {
1450  if (!active) return 0;
1451  // write to callback
1452  if (cb_write){
1453  return cb_write(data, len);
1454  }
1455  // write to output
1456  if(p_out){
1457  size_t result = len;
1458  if (cb_update) {
1459  result = cb_update((uint8_t*)data, len);
1460  }
1461  return p_out->write(data, result);
1462  }
1463  // no processing possible
1464  return 0;
1465  }
1466 
1468  void setStream(Stream &in){
1469  p_stream = &in;
1470  p_out = &in;
1471  }
1472 
1474  void setOutput(Print &out){
1475  p_out = &out;
1476  }
1477 
1479  void setOutput(Stream &in){
1480  p_stream = &in;
1481  p_out = &in;
1482  }
1483 
1485  void setStream(Print &out){
1486  p_out = &out;
1487  }
1488 
1490  void setAvailable(int val){
1491  available_bytes = val;
1492  }
1493 
1494 
1495 
1496  protected:
1497  bool active=true;
1498  size_t (*cb_write)(const uint8_t* data, size_t len) = nullptr;
1499  size_t (*cb_read)(uint8_t* data, size_t len) = nullptr;
1500  size_t (*cb_update)(uint8_t* data, size_t len) = nullptr;
1501  int (*cb_available)() = nullptr;
1502  Stream *p_stream = nullptr;
1503  Print *p_out = nullptr;
1504  int available_bytes = -1;
1505 };
1506 
1507 
1515 template<typename T, class TF>
1517  public:
1518  FilteredStream() = default;
1519  FilteredStream(Stream &stream) : ModifyingStream() {
1520  setStream(stream);
1521  }
1522  FilteredStream(Stream &stream, int channels) : ModifyingStream() {
1523  this->channels = channels;
1524  setStream(stream);
1525  p_converter = new ConverterNChannels<T,TF>(channels);
1526  }
1527  FilteredStream(Print &stream) : ModifyingStream() {
1528  setOutput(stream);
1529  }
1530  FilteredStream(Print &stream, int channels) : ModifyingStream() {
1531  this->channels = channels;
1532  setOutput(stream);
1533  p_converter = new ConverterNChannels<T,TF>(channels);
1534  }
1535 
1536  void setStream(Stream &stream){
1537  p_stream = &stream;
1538  p_print = &stream;
1539  }
1540 
1541  void setOutput(Print &stream){
1542  p_print = &stream;
1543  }
1544 
1545  bool begin(AudioInfo info){
1546  setAudioInfo(info);
1547  this->channels = info.channels;
1548  if (p_converter !=nullptr && info.channels!=channels){
1549  LOGE("Inconsistent number of channels");
1550  return false;
1551  }
1552  return begin();
1553  }
1554 
1555  bool begin() override {
1556  if (channels ==0){
1557  LOGE("channels must not be 0");
1558  return false;
1559  }
1560  if (p_converter==nullptr){
1561  p_converter = new ConverterNChannels<T,TF>(channels);
1562  }
1563  return AudioStream::begin();
1564  }
1565 
1566  virtual size_t write(const uint8_t *data, size_t len) override {
1567  if (p_converter==nullptr) return 0;
1568  size_t result = p_converter->convert((uint8_t *)data, len);
1569  return p_print->write(data, result);
1570  }
1571 
1572  size_t readBytes(uint8_t *data, size_t len) override {
1573  if (p_converter==nullptr) return 0;
1574  if (p_stream==nullptr) return 0;
1575  size_t result = p_stream->readBytes(data, len);
1576  result = p_converter->convert(data, result);
1577  return result;
1578  }
1579 
1580  virtual int available() override {
1581  if (p_stream==nullptr) return 0;
1582  return p_stream->available();
1583  }
1584 
1585  virtual int availableForWrite() override {
1586  return p_print->availableForWrite();
1587  }
1588 
1591  void setFilter(int channel, Filter<TF> *filter) {
1592  if (p_converter!=nullptr){
1593  p_converter->setFilter(channel, filter);
1594  } else {
1595  LOGE("p_converter is null");
1596  }
1597  }
1598 
1601  void setFilter(int channel, Filter<TF> &filter) {
1602  setFilter(channel, &filter);
1603  }
1604 
1605  protected:
1606  int channels=0;
1607  Stream *p_stream = nullptr;
1608  Print *p_print = nullptr;
1609  ConverterNChannels<T,TF> *p_converter;
1610 
1611 };
1612 
1622 public:
1623  VolumeMeter() = default;
1624  VolumeMeter(AudioStream& as) {
1626  setStream(as);
1627  }
1628  VolumeMeter(AudioOutput& ao) {
1630  setOutput(ao);
1631  }
1632  VolumeMeter(Print& print) {
1633  setOutput(print);
1634  }
1635  VolumeMeter(Stream& stream) {
1636  setStream(stream);
1637  }
1638 
1639  bool begin(AudioInfo info){
1640  setAudioInfo(info);
1641  return begin();
1642  }
1643 
1644  bool begin() override {
1645  return true;
1646  }
1647 
1650  if (info.channels > 0) {
1651  volumes.resize(info.channels);
1652  volumes_tmp.resize(info.channels);
1653  }
1654  }
1655 
1656  size_t write(const uint8_t *data, size_t len) {
1657  updateVolumes(data, len);
1658  size_t result = len;
1659  if (p_out!=nullptr){
1660  result = p_out->write(data, len);
1661  }
1662  return result;
1663  }
1664 
1665  size_t readBytes(uint8_t *data, size_t len){
1666  if (p_stream==nullptr) return 0;
1667  size_t result = p_stream->readBytes(data, len);
1668  updateVolumes((const uint8_t*)data, len);
1669  return result;
1670  }
1671 
1674  float volume() { return f_volume; }
1675 
1678  float volume(int channel) {
1679  if (volumes.size() == 0) {
1680  LOGE("begin not called!");
1681  return 0.0f;
1682  }
1683  if (channel >= volumes.size()) {
1684  LOGE("invalid channel %d", channel);
1685  return 0.0f;
1686  }
1687  return volumes[channel];
1688  }
1689 
1690 
1693 
1695  float volumeRatio(int channel) { return volume(channel) / NumberConverter::maxValue(info.bits_per_sample);}
1696 
1698  float volumeDB() {
1699  // prevent infinite value
1700  if (volumeRatio()==0) return -1000;
1701  return 20.0f * log10(volumeRatio());
1702  }
1703 
1705  float volumeDB(int channel) {
1706  // prevent infinite value
1707  if (volumeRatio(channel)==0) return -1000;
1708  return 20.0f * log10(volumeRatio(channel));
1709  }
1710 
1712  float volumePercent() { return 100.0f * volumeRatio();}
1713 
1715  float volumePercent(int channel) { return 100.0f * volumeRatio(channel);}
1716 
1717 
1719  void clear() {
1720  f_volume_tmp = 0;
1721  for (int j = 0; j < info.channels; j++) {
1722  volumes_tmp[j] = 0;
1723  }
1724  }
1725 
1726  void setOutput(Print &out) override {
1727  p_out = &out;
1728  }
1729  void setStream(Stream &io) override {
1730  p_out = &io;
1731  p_stream = &io;
1732  }
1733 
1734 protected:
1735  float f_volume_tmp = 0;
1736  float f_volume = 0;
1737  Vector<float> volumes{0};
1738  Vector<float> volumes_tmp{0};
1739  Print* p_out = nullptr;
1740  Stream* p_stream = nullptr;
1741 
1742  void updateVolumes(const uint8_t *data, size_t len){
1743  clear();
1744  switch (info.bits_per_sample) {
1745  case 16:
1746  updateVolumesT<int16_t>(data, len);
1747  break;
1748  case 24:
1749  updateVolumesT<int24_t>(data, len);
1750  break;
1751  case 32:
1752  updateVolumesT<int32_t>(data, len);
1753  break;
1754  default:
1755  LOGE("Unsupported bits_per_sample: %d", info.bits_per_sample);
1756  break;
1757  }
1758  }
1759 
1760  template <typename T> void updateVolumesT(const uint8_t *buffer, size_t size) {
1761  T *bufferT = (T *)buffer;
1762  int samplesCount = size / sizeof(T);
1763  for (int j = 0; j < samplesCount; j++) {
1764  float tmp = abs(static_cast<float>(bufferT[j]));
1765  updateVolume(tmp, j);
1766  }
1767  commit();
1768  }
1769 
1770  void updateVolume(float tmp, int j) {
1771  if (tmp > f_volume_tmp) {
1772  f_volume_tmp = tmp;
1773  }
1774  if (volumes_tmp.size() > 0 && info.channels > 0) {
1775  int ch = j % info.channels;
1776  if (tmp > volumes_tmp[ch]) {
1777  volumes_tmp[ch] = tmp;
1778  }
1779  }
1780  }
1781 
1782  void commit() {
1783  f_volume = f_volume_tmp;
1784  for (int j = 0; j < info.channels; j++) {
1785  volumes[j] = volumes_tmp[j];
1786  }
1787  }
1788 };
1789 
1790 // legacy names
1791 using VolumePrint = VolumeMeter;
1792 using VolumeOutput = VolumeMeter;
1793 
1794 #ifdef USE_TIMER
1801  RxTxMode rx_tx_mode = RX_MODE;
1802  uint16_t buffer_size = DEFAULT_BUFFER_SIZE;
1803  bool use_timer = true;
1804  int timer_id = -1;
1805  TimerFunction timer_function = DirectTimerCallback;
1806  bool adapt_sample_rate = false;
1807  uint16_t (*callback)(uint8_t *data, uint16_t len) = nullptr;
1808 };
1809 
1810 // forward declaration: relevant only if use_timer == true
1811 static void timerCallback(void *obj);
1822  friend void timerCallback(void *obj);
1823 
1824  public:
1825  TimerCallbackAudioStream() : BufferedStream(80) { TRACED(); }
1826 
1828  TRACED();
1829  if (timer != nullptr) delete timer;
1830  if (buffer != nullptr) delete buffer;
1831  if (frame != nullptr) delete[] frame;
1832  }
1833 
1837  return def;
1838  }
1839 
1841  virtual void setAudioInfo(AudioInfo info) {
1842  TRACED();
1843  if (cfg.sample_rate != info.sample_rate || cfg.channels != info.channels ||
1844  cfg.bits_per_sample != info.bits_per_sample) {
1845  bool do_restart = active;
1846  if (do_restart) end();
1847  cfg.sample_rate = info.sample_rate;
1848  cfg.channels = info.channels;
1849  cfg.bits_per_sample = info.bits_per_sample;
1850  if (do_restart) begin(cfg);
1851  }
1852  }
1853 
1856  AudioInfo audioInfo() { return cfg; }
1857 
1858  void begin(TimerCallbackAudioStreamInfo config) {
1859  LOGD("%s: %s", LOG_METHOD,
1860  config.rx_tx_mode == RX_MODE ? "RX_MODE" : "TX_MODE");
1861  this->cfg = config;
1862  this->frameCallback = config.callback;
1863  if (cfg.use_timer) {
1864  frameSize = cfg.bits_per_sample * cfg.channels / 8;
1865  frame = new uint8_t[frameSize];
1866  buffer = new RingBuffer<uint8_t>(cfg.buffer_size);
1867  timer = new TimerAlarmRepeating();
1868  timer->setTimerFunction(cfg.timer_function);
1869  if (cfg.timer_id>=0){
1870  timer->setTimer(cfg.timer_id);
1871  }
1872  time = AudioTime::toTimeUs(cfg.sample_rate);
1873  LOGI("sample_rate: %u -> time: %u milliseconds", (unsigned int)cfg.sample_rate, (unsigned int)time);
1874  timer->setCallbackParameter(this);
1875  timer->begin(timerCallback, time, TimeUnit::US);
1876  }
1877 
1878  notifyAudioChange(cfg);
1879  active = true;
1880  }
1881 
1883  bool begin() {
1884  TRACED();
1885  if (this->frameCallback != nullptr) {
1886  if (cfg.use_timer) {
1887  timer->begin(timerCallback, time, TimeUnit::US);
1888  }
1889  active = true;
1890  }
1891  return active;
1892  }
1893 
1895  void end() {
1896  TRACED();
1897  if (cfg.use_timer) {
1898  timer->end();
1899  }
1900  active = false;
1901  }
1902 
1904  uint16_t currentSampleRate() { return currentRateValue; }
1905 
1906  protected:
1908  bool active = false;
1909  uint16_t (*frameCallback)(uint8_t *data, uint16_t len);
1910  // below only relevant with timer
1911  TimerAlarmRepeating *timer = nullptr;
1912  RingBuffer<uint8_t> *buffer = nullptr;
1913  uint8_t *frame = nullptr;
1914  uint16_t frameSize = 0;
1915  uint32_t time = 0;
1916  unsigned long lastTimestamp = 0u;
1917  uint32_t currentRateValue = 0;
1918  uint32_t printCount = 0;
1919 
1920  // used for audio sink
1921  virtual size_t writeExt(const uint8_t *data, size_t len) override {
1922  if (!active) return 0;
1923  TRACED();
1924  size_t result = 0;
1925  if (!cfg.use_timer) {
1926  result = frameCallback((uint8_t *)data, len);
1927  } else {
1928  result = buffer->writeArray((uint8_t *)data, len);
1929  }
1930  if (++printCount % 10000 == 0) printSampleRate();
1931  return result;
1932  }
1933 
1934  // used for audio source
1935  virtual size_t readExt(uint8_t *data, size_t len) override {
1936  if (!active) return 0;
1937  TRACED();
1938 
1939  size_t result = 0;
1940  if (!cfg.use_timer) {
1941  result = frameCallback(data, len);
1942  } else {
1943  result = buffer->readArray(data, len);
1944  }
1945  if (++printCount % 10000 == 0) printSampleRate();
1946  return result;
1947  }
1948 
1950  virtual void measureSampleRate() {
1951  unsigned long ms = millis();
1952  if (lastTimestamp > 0u) {
1953  uint32_t diff = ms - lastTimestamp;
1954  if (diff > 0) {
1955  uint16_t rate = 1 * 1000 / diff;
1956 
1957  if (currentRateValue == 0) {
1958  currentRateValue = rate;
1959  } else {
1960  currentRateValue = (currentRateValue + rate) / 2;
1961  }
1962  }
1963  }
1964  lastTimestamp = ms;
1965  }
1966 
1968  virtual void printSampleRate() {
1969  LOGI("effective sample rate: %u", (unsigned int)currentRateValue);
1970  if (cfg.adapt_sample_rate &&
1971  abs((int)currentRateValue - (int)cfg.sample_rate) > 200) {
1972  cfg.sample_rate = currentRateValue;
1973  notifyAudioChange(cfg);
1974  }
1975  }
1976 };
1977 
1978 // relevant only if use_timer == true
1979 void IRAM_ATTR timerCallback(void *obj) {
1980  TimerCallbackAudioStream *src = (TimerCallbackAudioStream *)obj;
1981  if (src != nullptr) {
1982  // LOGD("%s: %s", LOG_METHOD, src->cfg.rx_tx_mode==RX_MODE ?
1983  // "RX_MODE":"TX_MODE");
1984  if (src->cfg.rx_tx_mode == RX_MODE) {
1985  // input
1986  uint16_t available_bytes = src->frameCallback(src->frame, src->frameSize);
1987  uint16_t buffer_available = src->buffer->availableForWrite();
1988  if (buffer_available < available_bytes) {
1989  // if buffer is full make space
1990  uint16_t to_clear = available_bytes - buffer_available;
1991  uint8_t tmp[to_clear];
1992  src->buffer->readArray(tmp, to_clear);
1993  }
1994  if (src->buffer->writeArray(src->frame, available_bytes) !=
1995  available_bytes) {
1996  assert(false);
1997  }
1998  } else {
1999  // output
2000  if (src->buffer != nullptr && src->frame != nullptr &&
2001  src->frameSize > 0) {
2002  uint16_t available_bytes =
2003  src->buffer->readArray(src->frame, src->frameSize);
2004  if (available_bytes !=
2005  src->frameCallback(src->frame, available_bytes)) {
2006  LOGE("data underflow");
2007  }
2008  }
2009  }
2010  src->measureSampleRate();
2011  }
2012 }
2013 
2014 #endif
2015 
2016 } // 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:480
void flush() override
empties the buffer
Definition: AudioStreams.h:529
size_t write(uint8_t c) override
writes a byte to the buffer
Definition: AudioStreams.h:511
size_t readBytes(uint8_t *data, size_t len) override
Use this method !!
Definition: AudioStreams.h:554
int peek() override
peeks a byte - to be avoided
Definition: AudioStreams.h:546
int available() override
Returns the available bytes in the buffer: to be avoided.
Definition: AudioStreams.h:564
size_t write(const uint8_t *data, size_t len) override
Use this method: write an array.
Definition: AudioStreams.h:519
void clear()
Clears all the data in the buffer.
Definition: AudioStreams.h:572
int read() override
reads a byte - to be avoided
Definition: AudioStreams.h:538
void setStream(Stream &io)
Defines/Changes the input & output.
Definition: AudioStreams.h:505
void setOutput(Print &out)
Defines/Changes the output target.
Definition: AudioStreams.h:499
CallbackStream: A Stream that allows to register callback methods for accessing and providing data....
Definition: AudioStreams.h:1366
void setOutput(Stream &in)
same as setStream
Definition: AudioStreams.h:1479
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:1378
void setStream(Print &out)
same as set Output
Definition: AudioStreams.h:1485
void setAvailable(int val)
optioinally define available bytes for next read
Definition: AudioStreams.h:1490
void setOutput(Print &out)
Defines/Changes the output target.
Definition: AudioStreams.h:1474
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:1371
void setStream(Stream &in)
Defines/Changes the input & output.
Definition: AudioStreams.h:1468
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:603
void setStream(Stream &stream)
Defines/Changes the input & output.
Definition: AudioStreams.h:622
void setOutput(Print &out)
Defines/Changes the output target.
Definition: AudioStreams.h:628
virtual int available() override
Returns the available bytes in the buffer: to be avoided.
Definition: AudioStreams.h:655
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:1516
void setStream(Stream &stream)
Defines/Changes the input & output.
Definition: AudioStreams.h:1536
void setFilter(int channel, Filter< TF > &filter)
Definition: AudioStreams.h:1601
void setOutput(Print &stream)
Defines/Changes the output target.
Definition: AudioStreams.h:1541
void setFilter(int channel, Filter< TF > *filter)
Definition: AudioStreams.h:1591
Source for reading generated tones. Please note.
Definition: AudioStreams.h:390
void setAudioInfo(AudioInfo newInfo) override
Defines the input AudioInfo.
Definition: AudioStreams.h:405
size_t readBytes(uint8_t *data, size_t len) override
privide the data as byte stream
Definition: AudioStreams.h:453
void end() override
stop the processing
Definition: AudioStreams.h:439
bool begin() override
start the processing
Definition: AudioStreams.h:413
AudioInfo audioInfo() override
provides the actual input AudioInfo
Definition: AudioStreams.h:445
bool begin(AudioInfo cfg)
start the processing
Definition: AudioStreams.h:426
virtual int available() override
This is unbounded so we just return the buffer size.
Definition: AudioStreams.h:450
Merges multiple input channels. The input must be mono! So if you provide 2 mono channels you get a s...
Definition: AudioStreams.h:1271
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:1300
void end() override
Remove all input streams.
Definition: AudioStreams.h:1331
int available() override
Provides the min available data from all streams.
Definition: AudioStreams.h:1342
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:1322
void add(Stream &in, float weight=1.0)
Adds a new input stream.
Definition: AudioStreams.h:1316
InputMerge(Stream &left, Stream &right)
Constructor for stereo signal from to mono input stream.
Definition: AudioStreams.h:1279
int size()
Number of stremams to which are mixed together = number of result channels.
Definition: AudioStreams.h:1337
MixerStream is mixing the input from Multiple Input Streams. All streams must have the same audo form...
Definition: AudioStreams.h:1116
void add(Stream &in, int weight=100)
Adds a new input stream.
Definition: AudioStreams.h:1121
void set(int channel, Stream &in)
Replaces a stream at the indicated channel.
Definition: AudioStreams.h:1128
size_t readBytes(uint8_t *data, size_t len) override
Provides the data from all streams mixed together.
Definition: AudioStreams.h:1172
void end() override
Remove all input streams.
Definition: AudioStreams.h:1158
int availableBytes()
Provides the available bytes from the first stream with data.
Definition: AudioStreams.h:1240
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:1195
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:1200
int readBytesVector(T *p_data, int byteCount)
mixing using a vector of samples
Definition: AudioStreams.h:1215
int size()
Number of stremams to which are mixed together.
Definition: AudioStreams.h:1167
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:1144
Class which measures the thruput.
Definition: AudioStreams.h:673
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:722
void setOutput(Print &out) override
Defines/Changes the output target.
Definition: AudioStreams.h:707
size_t readBytes(uint8_t *data, size_t len) override
Provides the data from all streams mixed together.
Definition: AudioStreams.h:713
void setAudioInfo(AudioInfo info)
Defines the input AudioInfo.
Definition: AudioStreams.h:741
virtual int availableForWrite() override
Provides the nubmer of bytes we can write.
Definition: AudioStreams.h:727
void setFrameSize(int size)
Trigger reporting in frames (=samples) per second.
Definition: AudioStreams.h:756
void setReportBytes(bool flag)
Report in bytes instead of samples.
Definition: AudioStreams.h:761
uint32_t startTime()
Provides the time when the last measurement was started.
Definition: AudioStreams.h:737
void setStream(Stream &io) override
Defines/Changes the input & output.
Definition: AudioStreams.h:701
int bytesPerSecond()
Returns the actual thrughput in bytes per second.
Definition: AudioStreams.h:732
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:98
virtual void setLoop(bool loop, int rewindPos)
Automatically rewinds to the indicated position when reaching the end.
Definition: AudioStreams.h:261
virtual void clear(bool reset=false)
clears the audio data: sets all values to 0
Definition: AudioStreams.h:232
virtual void setAvailable(size_t len)
update the write_pos (e.g. when we used data() to update the array)
Definition: AudioStreams.h:290
void setValue(const uint8_t *buffer, int buffer_size, MemoryType memoryType=FLASH_RAM)
Update the values (buffer and size)
Definition: AudioStreams.h:300
MemoryStream(MemoryStream &&source)
Move Constructor.
Definition: AudioStreams.h:111
MemoryStream & operator=(MemoryStream &other)
copy assignement operator
Definition: AudioStreams.h:123
MemoryStream(MemoryStream &source)
Copy Constructor.
Definition: AudioStreams.h:106
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:250
virtual bool resize(size_t size)
Resizes the available memory. Returns false for PROGMEM or when allocation failed.
Definition: AudioStreams.h:267
virtual uint8_t * data()
Provides access to the data array.
Definition: AudioStreams.h:285
MemoryStream(int buffer_size, MemoryType memoryType)
Constructor for alloction in RAM.
Definition: AudioStreams.h:89
bool begin() override
resets the read pointer
Definition: AudioStreams.h:138
bool begin(AudioInfo info)
Define some audio info and start the processing.
Definition: AudioStreams.h:132
void setRewindCallback(void(*cb)())
Callback which is executed when we rewind (in loop mode) to the beginning.
Definition: AudioStreams.h:295
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:828
bool begin(size_t len)
Updates the total size and restarts the percent calculation: Same as calling setSize()
Definition: AudioStreams.h:875
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:935
size_t size()
Provides the current total size (defined by setSize)
Definition: AudioStreams.h:893
size_t totalSecs()
Converts the totalBytes() to seconds.
Definition: AudioStreams.h:913
size_t readBytes(uint8_t *data, size_t len) override
Provides the data from all streams mixed together.
Definition: AudioStreams.h:924
size_t processedBytes()
Provides the number of processed bytes.
Definition: AudioStreams.h:898
void setStream(Stream &stream)
Defines/Changes the input & output.
Definition: AudioStreams.h:854
void setSize(size_t len)
Updates the total size and restarts the percent calculation.
Definition: AudioStreams.h:887
virtual int availableForWrite() override
Provides the nubmer of bytes we can write.
Definition: AudioStreams.h:941
float percentage()
Provides the processed percentage: If no size has been defined we return 0.
Definition: AudioStreams.h:918
size_t processedSecs()
Provides the number of processed seconds.
Definition: AudioStreams.h:903
void setAudioInfo(AudioInfo info) override
Defines the input AudioInfo.
Definition: AudioStreams.h:849
size_t totalBytes()
Provides the total_size provided in the configuration.
Definition: AudioStreams.h:908
Configuration for ProgressStream.
Definition: AudioStreams.h:817
An AudioStream backed by a Ringbuffer. We can write to the end and read from the beginning of the str...
Definition: AudioStreams.h:342
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:990
void setOutput(Print &out) override
Defines/Changes the output target.
Definition: AudioStreams.h:1003
void setStream(Stream &io) override
Defines/Changes the input & output.
Definition: AudioStreams.h:997
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:1821
TimerCallbackAudioStreamInfo audioInfoExt()
Provides the current audio information.
Definition: AudioStreams.h:1855
uint16_t currentSampleRate()
Provides the effective sample rate.
Definition: AudioStreams.h:1904
TimerCallbackAudioStreamInfo defaultConfig()
Provides the default configuration.
Definition: AudioStreams.h:1835
bool begin()
Restart the processing.
Definition: AudioStreams.h:1883
AudioInfo audioInfo()
provides the actual input AudioInfo
Definition: AudioStreams.h:1856
virtual void measureSampleRate()
calculates the effective sample rate
Definition: AudioStreams.h:1950
virtual void setAudioInfo(AudioInfo info)
updates the audio information
Definition: AudioStreams.h:1841
virtual void printSampleRate()
log and update effective sample rate
Definition: AudioStreams.h:1968
void end()
Stops the processing.
Definition: AudioStreams.h:1895
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:1621
void setOutput(Print &out) override
Defines/Changes the output target.
Definition: AudioStreams.h:1726
float volumeRatio()
Volume Ratio: max amplitude is 1.0.
Definition: AudioStreams.h:1692
float volume()
Definition: AudioStreams.h:1674
float volumePercent()
Volume in %: max amplitude is 100.
Definition: AudioStreams.h:1712
void setAudioInfo(AudioInfo info)
Defines the input AudioInfo.
Definition: AudioStreams.h:1648
float volumePercent(int channel)
Volume of indicated channel in %: max amplitude is 100.
Definition: AudioStreams.h:1715
void clear()
Resets the actual volume.
Definition: AudioStreams.h:1719
float volumeRatio(int channel)
Volume Ratio of indicated channel: max amplitude is 1.0.
Definition: AudioStreams.h:1695
float volumeDB(int channel)
Volume of indicated channel in db: max amplitude is 0.
Definition: AudioStreams.h:1705
void setStream(Stream &io) override
Defines/Changes the input & output.
Definition: AudioStreams.h:1729
float volumeDB()
Volume in db: max amplitude is 0 (range: -1000 to 0)
Definition: AudioStreams.h:1698
float volume(int channel)
Definition: AudioStreams.h:1678
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:868
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:975
TimerCallbackAudioStream Configuration.
Definition: AudioStreams.h:1800