arduino-audio-tools
Loading...
Searching...
No Matches
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
17namespace 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
70 public:
72 virtual void setStream(Stream& in) = 0;
74 virtual void setOutput(Print& out) = 0;
75};
76
84class MemoryStream : public AudioStream {
85 public:
86 // Default constructor
87 MemoryStream() = default;
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
389template <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
406 if (newInfo.bits_per_sample != sizeof(T)*8){
407 LOGE("Wrong bits_per_sample: %d", newInfo.bits_per_sample);
408 }
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:
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
602template<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 setLogOutput(Print &out){
702 p_logout = &out;
703 }
704
706 void setStream(Stream& io) override {
707 p_print = &io;
708 p_stream = &io;
709 };
710
712 void setOutput(Print& out) override {
713 p_print = &out;
714 }
715
716
718 size_t readBytes(uint8_t* data, size_t len) override {
719 total_bytes_since_begin += len;
720 return measure(p_stream->readBytes(data, len));
721 }
722
723 int available() override {
724 return p_stream->available();
725 }
726
728 virtual size_t write(const uint8_t *data, size_t len) override {
729 total_bytes_since_begin += len;
730 return measure(p_print->write(data, len));
731 }
732
734 virtual int availableForWrite() override {
735 return p_print->availableForWrite();
736 }
737
740 return bytes_per_second;
741 }
742
745 if (frame_size==0) return 0;
746 return bytes_per_second/frame_size;
747 }
748
751 return start_time;
752 }
753
755 AudioStream::info = info;
756 setFrameSize(info.bits_per_sample / 8 *info.channels);
757 }
758
759 bool begin(){
760 total_bytes_since_begin = 0;
761 ms_at_begin = millis();
762 return AudioStream::begin();
763 }
764
765 bool begin(AudioInfo info){
766 setAudioInfo(info);
767 return begin();
768 }
769
771 void setFrameSize(int size){
772 frame_size = size;
773 }
774
777 report_bytes = flag;
778 }
779
780 void setName(const char* name){
781 this->name = name;
782 }
783
786 return millis() - ms_at_begin;
787 }
788
791 return total_bytes_since_begin;
792 }
793
796 if (bytesSinceBegin()==0) return 0;
797 return static_cast<float>(timeSinceBegin()) / bytesSinceBegin() * totalBytes;
798 }
799
802 if (bytesSinceBegin()==0) return 0;
803 return estimatedTotalTimeFor(totalBytes) - timeSinceBegin();
804 }
805
808 bool is_regular_update = true;
809 if (pos < total_bytes_since_begin) {
810 begin();
811 is_regular_update = false;
812 }
813 total_bytes_since_begin = pos;
814 return is_regular_update;
815 }
816
817 protected:
818 int max_count=0;
819 int count=0;
820 Stream *p_stream=nullptr;
821 Print *p_print=nullptr;
822 uint32_t start_time;
823 int total_bytes = 0;
824 int bytes_per_second = 0;
825 int frame_size = 0;
826 NullStream null;
827 Print *p_logout=nullptr;
828 bool report_bytes = false;
829 const char* name = "";
830 uint32_t ms_at_begin = 0;
831 uint32_t total_bytes_since_begin = 0;
832
833 size_t measure(size_t len) {
834 count--;
835 total_bytes+=len;
836
837 if (count<=0){
839 int time_diff = end_time - start_time; // in ms
840 if (time_diff>0){
841 bytes_per_second = total_bytes / time_diff * 1000;
842 printResult();
843 count = max_count;
844 total_bytes = 0;
845 start_time = end_time;
846 }
847 }
848 return len;
849 }
850
851 void printResult() {
852 char msg[70];
853 if (report_bytes || frame_size==0){
854 snprintf(msg, 70, "%s ==> Bytes per second: %d", name, bytes_per_second);
855 } else {
856 snprintf(msg, 70, "%s ==> Samples per second: %d", name, bytes_per_second/frame_size);
857 }
858 if (p_logout!=nullptr){
859 p_logout->println(msg);
860 } else {
861 LOGI("%s",msg);
862 }
863 }
864};
865
873 public:
874 size_t total_size = 0;
875};
884 public:
885 ProgressStream() = default;
886
887 ProgressStream(Print &print){
888 setPrint(print);
889 }
890
891 ProgressStream(Stream &stream){
892 setStream(stream);
893 }
894
896 setStream(stream);
897 p_info_from = &stream;
898 }
899
900 ProgressStreamInfo& defaultConfig() {
901 return progress_info;
902 }
903
904 void setAudioInfo(AudioInfo info) override {
906 progress_info.copyFrom(info);
907 }
908
909 void setStream(Stream &stream){
910 p_stream =&stream;
911 p_print = &stream;
912 }
913
914 void setStream(Print &print){
915 p_print =&print;
916 }
917
918 void setPrint(Print &print){
919 p_print =&print;
920 }
921
922 bool begin() override {
923 if (p_info_from!=nullptr){
924 setAudioInfo(p_info_from->audioInfo());
925 }
926 return AudioStream::begin();
927 }
928
930 bool begin(size_t len){
931 setSize(len);
932 return begin();
933 }
934
935 bool begin(ProgressStreamInfo info){
936 progress_info = info;
937 setAudioInfo(info);
938 return begin();
939 }
940
942 void setSize(size_t len){
943 total_processed = 0;
944 progress_info.total_size = len;
945 }
946
948 size_t size(){
949 return progress_info.total_size;
950 }
951
953 size_t processedBytes() {
954 return total_processed;
955 }
956
958 size_t processedSecs() {
959 return total_processed / byteRate();
960 }
961
963 size_t totalBytes() {
964 return progress_info.total_size;
965 }
966
968 size_t totalSecs() {
969 return totalBytes() / byteRate();
970 }
971
973 float percentage() {
974 if (progress_info.total_size==0) return 0;
975 return 100.0 * total_processed / progress_info.total_size;
976 }
977
979 size_t readBytes(uint8_t* data, size_t len) override {
980 if (p_stream==nullptr) return 0;
981 return measure(p_stream->readBytes(data, len));
982 }
983
984 int available() override {
985 if (p_stream==nullptr) return 0;
986 return p_stream->available();
987 }
988
990 virtual size_t write(const uint8_t *data, size_t len) override {
991 if (p_print==nullptr) return 0;
992 return measure(p_print->write(data, len));
993 }
994
996 virtual int availableForWrite() override {
997 if (p_print==nullptr) return 0;
998 return p_print->availableForWrite();
999 }
1000
1001 protected:
1002 ProgressStreamInfo progress_info;
1003 Stream *p_stream=nullptr;
1004 Print *p_print=nullptr;
1005 AudioInfoSupport *p_info_from=nullptr;
1006 size_t total_processed = 0;
1007
1008 size_t measure(size_t len) {
1009 total_processed += len;
1010 return len;
1011 }
1012
1013 size_t byteRate() {
1014 AudioInfo info = audioInfo();
1015 int byte_rate = info.sample_rate * info.bits_per_sample * info.channels / 8;
1016 if (byte_rate==0){
1017 LOGE("Audio Info not defined");
1018 return 0;
1019 }
1020 return byte_rate;
1021 }
1022
1023};
1024
1030struct ThrottleConfig : public AudioInfo {
1031 ThrottleConfig() {
1032 sample_rate = 44100;
1033 bits_per_sample = 16;
1034 channels = 2;
1035 }
1036 int correction_us = 0;
1037};
1038
1046 public:
1047 Throttle() = default;
1048 Throttle(Print &out) { setOutput(out); }
1049 Throttle(Stream &io) { setStream(io); }
1050
1052 void setStream(Stream& io) override {
1053 p_out = &io;
1054 p_in = &io;
1055 };
1056
1058 void setOutput(Print& out) override {
1059 p_out = &out;
1060 }
1061
1062 ThrottleConfig defaultConfig() {
1064 return c;
1065 }
1066
1067 bool begin(ThrottleConfig cfg) {
1068 LOGI("begin sample_rate: %d, channels: %d, bits: %d", (int) info.sample_rate,(int) info.channels, (int)info.bits_per_sample);
1069 this->info = cfg;
1070 this->cfg = cfg;
1071 return begin();
1072 }
1073
1074 bool begin(AudioInfo info) {
1075 LOGI("begin sample_rate: %d, channels: %d, bits: %d", (int)info.sample_rate, (int) info.channels, (int)info.bits_per_sample);
1076 this->info = info;
1077 this->cfg.copyFrom(info);
1078 return begin();
1079 }
1080
1081 bool begin(){
1082 frame_size = cfg.bits_per_sample / 8 * cfg.channels;
1083 startDelay();
1084 return true;
1085 }
1086
1087 // (re)starts the timing
1088 void startDelay() {
1089 start_time = micros();
1090 sum_frames = 0;
1091 }
1092
1093 int availableForWrite() {
1094 if (p_out){
1095 return p_out->availableForWrite();
1096 }
1097 return DEFAULT_BUFFER_SIZE;
1098 }
1099
1100 size_t write(const uint8_t* data, size_t len){
1101 size_t result = p_out->write(data, len);
1102 delayBytes(len);
1103 return result;
1104 }
1105
1106 int available() {
1107 if (p_in==nullptr) return 0;
1108 return p_in->available();
1109 }
1110
1111 size_t readBytes(uint8_t* data, size_t len) override{
1112 if (p_in==nullptr) {
1113 delayBytes(len);
1114 return 0;
1115 }
1116 size_t result = p_in->readBytes(data, len);
1117 delayBytes(len);
1118 return result;
1119 }
1120
1121 // delay
1122 void delayBytes(size_t bytes) { delayFrames(bytes / frame_size); }
1123
1124 // delay
1125 void delayFrames(size_t frames) {
1126 sum_frames += frames;
1127 uint64_t durationUsEff = micros() - start_time;
1128 uint64_t durationUsToBe = getDelayUs(sum_frames);
1129 int64_t waitUs = durationUsToBe - durationUsEff + cfg.correction_us;
1130 LOGD("wait us: %ld", static_cast<long>(waitUs));
1131 if (waitUs > 0) {
1132 int64_t waitMs = waitUs / 1000;
1133 if (waitMs > 0) delay(waitMs);
1134 delayMicroseconds(waitUs - (waitMs * 1000));
1135 } else {
1136 LOGD("negative delay!")
1137 }
1138 }
1139
1140 inline int64_t getDelayUs(uint64_t frames){
1141 return (frames * 1000000) / cfg.sample_rate;
1142 }
1143
1144 inline int64_t getDelayMs(uint64_t frames){
1145 return getDelayUs(frames) / 1000;
1146 }
1147
1148 inline int64_t getDelaySec(uint64_t frames){
1149 return getDelayUs(frames) / 1000000l;
1150 }
1151
1152 protected:
1153 uint32_t start_time = 0;
1154 uint32_t sum_frames = 0;
1155 ThrottleConfig cfg;
1156 int frame_size = 0;
1157 Print *p_out = nullptr;
1158 Stream *p_in = nullptr;
1159};
1160
1161
1170template<typename T>
1171class InputMixer : public AudioStream {
1172 public:
1173 InputMixer() = default;
1174
1176 void add(Stream &in, int weight=100){
1177 streams.push_back(&in);
1178 weights.push_back(weight);
1179 total_weights += weight;
1180 }
1181
1183 void set(int channel, Stream &in){
1184 if (channel<size()){
1185 streams[channel] = &in;
1186 } else {
1187 LOGE("Invalid channel %d - max is %d", channel, size()-1);
1188 }
1189 }
1190
1191 virtual bool begin(AudioInfo info) {
1192 setAudioInfo(info);
1193 frame_size = info.bits_per_sample/8 * info.channels;
1194 LOGI("frame_size: %d",frame_size);
1195 return frame_size>0;
1196 }
1197
1199 void setWeight(int channel, int weight){
1200 if (channel<size()){
1201 weights[channel] = weight;
1202 int total = 0;
1203 for (int j=0;j<weights.size();j++){
1204 total += weights[j];
1205 }
1206 total_weights = total;
1207 } else {
1208 LOGE("Invalid channel %d - max is %d", channel, size()-1);
1209 }
1210 }
1211
1213 void end() override {
1214 streams.clear();
1215 weights.clear();
1216 result_vect.clear();
1217 current_vect.clear();
1218 total_weights = 0.0;
1219 }
1220
1222 int size() {
1223 return streams.size();
1224 }
1225
1227 size_t readBytes(uint8_t* data, size_t len) override {
1228 if (total_weights==0 || frame_size==0 || len==0) {
1229 LOGW("readBytes: %d",(int)len);
1230 return 0;
1231 }
1232
1233 if (limit_available_data){
1234 len = min((int)len, availableBytes());
1235 }
1236
1237 int result_len = 0;
1238
1239 if (len > 0) {
1240 // result_len must be full frames
1241 result_len = len * frame_size / frame_size;
1242 // replace sample based with vector based implementation
1243 //readBytesSamples((T*)data, result_len));
1245 }
1246 return result_len;
1247 }
1248
1251 limit_available_data = flag;
1252 }
1253
1256 retry_count = retry;
1257 }
1258
1259 protected:
1260 Vector<Stream*> streams{0};
1261 Vector<int> weights{0};
1262 int total_weights = 0;
1263 int frame_size = 4;
1264 bool limit_available_data = false;
1265 int retry_count = 5;
1266 Vector<int> result_vect;
1267 Vector<T> current_vect;
1268
1270 int readBytesVector(T* p_data, int byteCount) {
1271 int samples = byteCount / sizeof(T);
1272 result_vect.resize(samples);
1273 current_vect.resize(samples);
1274 int stream_count = size();
1275 resultClear();
1276 int samples_eff_max = 0;
1277 for (int j=0;j<stream_count;j++){
1278 if (weights[j]>0){
1279 int samples_eff = readSamples(streams[j],current_vect.data(), samples, retry_count);
1282 // if all weights are 0.0 we stop to output
1283 float factor = total_weights == 0.0f ? 0.0f : static_cast<float>(weights[j]) / total_weights;
1284 resultAdd(factor);
1285 }
1286 }
1287 // copy result
1288 for (int j=0;j<samples;j++){
1289 p_data[j] = result_vect[j];
1290 }
1291 return samples_eff_max * sizeof(T);
1292 }
1293
1296 int result = DEFAULT_BUFFER_SIZE;
1297 for (int j=0;j<size();j++){
1298 result = min(result, streams[j]->available());
1299 }
1300 return result;
1301 }
1302
1303 void resultAdd(float fact){
1304 for (int j=0;j<current_vect.size();j++){
1305 current_vect[j]*=fact;
1306 result_vect[j] += current_vect[j];
1307 }
1308 }
1309
1310 void resultClear(){
1311 memset(result_vect.data(), 0, sizeof(int)*result_vect.size());
1312 }
1313
1314};
1315
1325template<typename T>
1326class InputMerge : public AudioStream {
1327 public:
1329 InputMerge() = default;
1330
1334 InputMerge(Stream &left, Stream &right) {
1335 add(left);
1336 add(right);
1337 };
1338
1339 virtual bool begin(AudioInfo info) {
1340 if (size()!=info.channels){
1341 info.channels = size();
1342 LOGW("channels corrected to %d", size());
1343 }
1344 setAudioInfo(info);
1345 return begin();
1346 }
1347
1348 virtual bool begin() {
1349 // make sure that we use the correct channel count
1350 info.channels = size();
1351 return AudioStream::begin();
1352 }
1353
1355 size_t readBytes(uint8_t* data, size_t len) override {
1356 LOGD("readBytes: %d",(int)len);
1357 T *p_data = (T*) data;
1358 int result_len = MIN(available(), len/size());
1359 int sample_count = result_len / sizeof(T);
1360 int size_value = size();
1361 int result_idx = 0;
1362 for (int j=0;j<sample_count; j++){
1363 for (int i=0; i<size_value; i++){
1364 p_data[result_idx++] = weights[i] * readSample<T>(streams[i]);
1365 }
1366 }
1367 return result_idx*sizeof(T);
1368 }
1369
1371 void add(Stream &in, float weight=1.0){
1372 streams.push_back(&in);
1373 weights.push_back(weight);
1374 }
1375
1377 void setWeight(int channel, float weight){
1378 if (channel<size()){
1379 weights[channel] = weight;
1380 } else {
1381 LOGE("Invalid channel %d - max is %d", channel, size()-1);
1382 }
1383 }
1384
1386 void end() override {
1387 streams.clear();
1388 weights.clear();
1389 }
1390
1392 int size() {
1393 return streams.size();
1394 }
1395
1397 int available() override {
1398 int result = streams[0]->available();
1399 for (int j=1;j<size();j++){
1400 int tmp = streams[j]->available();
1401 if (tmp<result){
1402 result = tmp;
1403 }
1404 }
1405 return result;
1406 }
1407
1408 protected:
1409 Vector<Stream*> streams{10};
1410 Vector<float> weights{10};
1411};
1412
1413
1422 public:
1423 CallbackStream() = default;
1424
1426 CallbackStream(Stream &io, size_t (*cb_update)(uint8_t* data, size_t len)) {
1427 p_stream = &io;
1428 p_out = &io;
1429 setUpdateCallback(cb_update);
1430 }
1431
1433 CallbackStream(Print &out, size_t (*cb_update)(uint8_t* data, size_t len)) {
1434 p_out = &out;
1435 setUpdateCallback(cb_update);
1436 }
1437
1438 CallbackStream(size_t (*cb_read)(uint8_t* data, size_t len), size_t (*cb_write)(const uint8_t* data, size_t len)) {
1439 setWriteCallback(cb_write);
1440 setReadCallback(cb_read);
1441 }
1442
1443 void setWriteCallback(size_t (*cb_write)(const uint8_t* data, size_t len)){
1444 this->cb_write = cb_write;
1445 }
1446
1447 void setReadCallback(size_t (*cb_read)(uint8_t* data, size_t len)){
1448 this->cb_read = cb_read;
1449 }
1450
1451 void setUpdateCallback(size_t (*cb_update)(uint8_t* data, size_t len)){
1452 this->cb_update = cb_update;
1453 }
1454
1455 // callback result negative -> no change; callbeack result >=0 provides the result
1456 void setAvailableCallback(int (*cb)()){
1457 this->cb_available = cb;
1458 }
1459
1460 virtual bool begin(AudioInfo info) {
1461 setAudioInfo(info);
1462 return begin();
1463 }
1464 virtual bool begin() override {
1465 active = true;
1466 return true;
1467 }
1468
1469 void end() override { active = false;}
1470
1471 int available() override {
1472 int result = AudioStream::available();
1473 // determine value from opional variable
1474 if (available_bytes>=0)
1475 return available_bytes;
1476 // check if there is a callback
1477 if (cb_available==nullptr)
1478 return result;
1479 // determine value from callback
1480 int tmp_available = cb_available();
1481 if (tmp_available < 0)
1482 return result;
1483
1484 return tmp_available;
1485 }
1486
1487 size_t readBytes(uint8_t* data, size_t len) override {
1488 if (!active) return 0;
1489 // provide data from callback
1490 if (cb_read){
1491 return cb_read(data, len);
1492 }
1493 // provide data from source
1494 size_t result = 0;
1495 if (p_stream){
1496 result = p_stream->readBytes(data , len);
1497 }
1498 if (cb_update){
1499 result = cb_update(data, result);
1500 }
1501 return result;
1502 }
1503
1504 size_t write(const uint8_t* data, size_t len) override {
1505 if (!active) return 0;
1506 // write to callback
1507 if (cb_write){
1508 return cb_write(data, len);
1509 }
1510 // write to output
1511 if(p_out){
1512 size_t result = len;
1513 if (cb_update) {
1514 result = cb_update((uint8_t*)data, len);
1515 }
1516 return p_out->write(data, result);
1517 }
1518 // no processing possible
1519 return 0;
1520 }
1521
1524 p_stream = &in;
1525 p_out = &in;
1526 }
1527
1529 void setOutput(Print &out){
1530 p_out = &out;
1531 }
1532
1535 p_stream = &in;
1536 p_out = &in;
1537 }
1538
1540 void setStream(Print &out){
1541 p_out = &out;
1542 }
1543
1546 available_bytes = val;
1547 }
1548
1549
1550
1551 protected:
1552 bool active=true;
1553 size_t (*cb_write)(const uint8_t* data, size_t len) = nullptr;
1554 size_t (*cb_read)(uint8_t* data, size_t len) = nullptr;
1555 size_t (*cb_update)(uint8_t* data, size_t len) = nullptr;
1556 int (*cb_available)() = nullptr;
1557 Stream *p_stream = nullptr;
1558 Print *p_out = nullptr;
1559 int available_bytes = -1;
1560};
1561
1562
1570template<typename T, class TF>
1572 public:
1573 FilteredStream() = default;
1575 setStream(stream);
1576 }
1577 FilteredStream(Stream &stream, int channels) : ModifyingStream() {
1578 this->channels = channels;
1579 setStream(stream);
1580 p_converter = new ConverterNChannels<T,TF>(channels);
1581 }
1582 FilteredStream(Print &stream) : ModifyingStream() {
1583 setOutput(stream);
1584 }
1585 FilteredStream(Print &stream, int channels) : ModifyingStream() {
1586 this->channels = channels;
1587 setOutput(stream);
1588 p_converter = new ConverterNChannels<T,TF>(channels);
1589 }
1590
1591 void setStream(Stream &stream){
1592 p_stream = &stream;
1593 p_print = &stream;
1594 }
1595
1596 void setOutput(Print &stream){
1597 p_print = &stream;
1598 }
1599
1600 bool begin(AudioInfo info){
1601 setAudioInfo(info);
1602 this->channels = info.channels;
1603 if (p_converter !=nullptr && p_converter->getChannels()!=channels){
1604 LOGE("Inconsistent number of channels");
1605 return false;
1606 }
1607 return begin();
1608 }
1609
1610 bool begin() override {
1611 if (channels ==0){
1612 LOGE("channels must not be 0");
1613 return false;
1614 }
1615 if (p_converter==nullptr){
1616 p_converter = new ConverterNChannels<T,TF>(channels);
1617 }
1618 return AudioStream::begin();
1619 }
1620
1621 virtual size_t write(const uint8_t *data, size_t len) override {
1622 if (p_converter==nullptr) return 0;
1623 size_t result = p_converter->convert((uint8_t *)data, len);
1624 return p_print->write(data, result);
1625 }
1626
1627 size_t readBytes(uint8_t *data, size_t len) override {
1628 if (p_converter==nullptr) return 0;
1629 if (p_stream==nullptr) return 0;
1630 size_t result = p_stream->readBytes(data, len);
1631 result = p_converter->convert(data, result);
1632 return result;
1633 }
1634
1635 virtual int available() override {
1636 if (p_stream==nullptr) return 0;
1637 return p_stream->available();
1638 }
1639
1640 virtual int availableForWrite() override {
1641 return p_print->availableForWrite();
1642 }
1643
1646 void setFilter(int channel, Filter<TF> *filter) {
1647 if (p_converter!=nullptr){
1648 p_converter->setFilter(channel, filter);
1649 } else {
1650 LOGE("p_converter is null");
1651 }
1652 }
1653
1656 void setFilter(int channel, Filter<TF> &filter) {
1657 setFilter(channel, &filter);
1658 }
1659
1660 protected:
1661 int channels=0;
1662 Stream *p_stream = nullptr;
1663 Print *p_print = nullptr;
1664 ConverterNChannels<T,TF> *p_converter = nullptr;
1665
1666};
1667
1677public:
1678 VolumeMeter() = default;
1681 setStream(as);
1682 }
1685 setOutput(ao);
1686 }
1687 VolumeMeter(Print& print) {
1688 setOutput(print);
1689 }
1690 VolumeMeter(Stream& stream) {
1691 setStream(stream);
1692 }
1693
1694 bool begin(AudioInfo info){
1695 setAudioInfo(info);
1696 return begin();
1697 }
1698
1699 bool begin() override {
1700 return true;
1701 }
1702
1705 if (info.channels > 0) {
1706 volumes.resize(info.channels);
1707 volumes_tmp.resize(info.channels);
1708 }
1709 }
1710
1711 size_t write(const uint8_t *data, size_t len) {
1712 updateVolumes(data, len);
1713 size_t result = len;
1714 if (p_out!=nullptr){
1715 result = p_out->write(data, len);
1716 }
1717 return result;
1718 }
1719
1720 size_t readBytes(uint8_t *data, size_t len){
1721 if (p_stream==nullptr) return 0;
1722 size_t result = p_stream->readBytes(data, len);
1723 updateVolumes((const uint8_t*)data, len);
1724 return result;
1725 }
1726
1729 float volume() { return f_volume; }
1730
1733 float volume(int channel) {
1734 if (volumes.size() == 0) {
1735 LOGE("begin not called!");
1736 return 0.0f;
1737 }
1738 if (channel >= volumes.size()) {
1739 LOGE("invalid channel %d", channel);
1740 return 0.0f;
1741 }
1742 return volumes[channel];
1743 }
1744
1745
1748
1750 float volumeRatio(int channel) { return volume(channel) / NumberConverter::maxValue(info.bits_per_sample);}
1751
1753 float volumeDB() {
1754 // prevent infinite value
1755 if (volumeRatio()==0) return -1000;
1756 return 20.0f * log10(volumeRatio());
1757 }
1758
1760 float volumeDB(int channel) {
1761 // prevent infinite value
1762 if (volumeRatio(channel)==0) return -1000;
1763 return 20.0f * log10(volumeRatio(channel));
1764 }
1765
1767 float volumePercent() { return 100.0f * volumeRatio();}
1768
1770 float volumePercent(int channel) { return 100.0f * volumeRatio(channel);}
1771
1773 float volumeAvg() {
1774 float total = 0;
1775 size_t count = 0;
1776 for (int j=0;j<info.channels;j++){
1777 total += sum[j];
1778 count += sample_count_per_channel;
1779 }
1780 return total / count;
1781 }
1782
1784 float volumeAvg(int channel) {
1785 return sum[channel] / sample_count_per_channel;
1786 }
1787
1788
1790 void clear() {
1791 f_volume_tmp = 0;
1792 for (int j = 0; j < info.channels; j++) {
1793 volumes_tmp[j] = 0;
1794 sum_tmp[j] = 0;
1795 }
1796 }
1797
1798 void setOutput(Print &out) override {
1799 p_out = &out;
1800 }
1801 void setStream(Stream &io) override {
1802 p_out = &io;
1803 p_stream = &io;
1804 }
1805
1806protected:
1807 float f_volume_tmp = 0;
1808 float f_volume = 0;
1809 Vector<float> volumes{0};
1810 Vector<float> volumes_tmp{0};
1811 Vector<float> sum{0};
1812 Vector<float> sum_tmp{0};
1813 Print* p_out = nullptr;
1814 Stream* p_stream = nullptr;
1815 size_t sample_count_per_channel = 0;
1816
1817 void updateVolumes(const uint8_t *data, size_t len){
1818 clear();
1819 switch (info.bits_per_sample) {
1820 case 8:
1821 updateVolumesT<int8_t>(data, len);
1822 break;
1823 case 16:
1824 updateVolumesT<int16_t>(data, len);
1825 break;
1826 case 24:
1827 updateVolumesT<int24_t>(data, len);
1828 break;
1829 case 32:
1830 updateVolumesT<int32_t>(data, len);
1831 break;
1832 default:
1833 LOGE("Unsupported bits_per_sample: %d", info.bits_per_sample);
1834 break;
1835 }
1836 }
1837
1838 template <typename T> void updateVolumesT(const uint8_t *buffer, size_t size) {
1839 T *bufferT = (T *)buffer;
1840 int samplesCount = size / sizeof(T);
1841 sample_count_per_channel = samplesCount / info.channels;
1842 for (int j = 0; j < samplesCount; j++) {
1843 float tmp = abs(static_cast<float>(bufferT[j]));
1844 updateVolume(tmp, j);
1845 }
1846 commit();
1847 }
1848
1849 void updateVolume(float tmp, int j) {
1850 if (tmp > f_volume_tmp) {
1851 f_volume_tmp = tmp;
1852 }
1853 if (volumes_tmp.size() > 0 && info.channels > 0) {
1854 int ch = j % info.channels;
1855 if (tmp > volumes_tmp[ch]) {
1856 volumes_tmp[ch] = tmp;
1857 sum_tmp[ch] = tmp;
1858 }
1859 }
1860 }
1861
1862 void commit() {
1863 f_volume = f_volume_tmp;
1864 for (int j = 0; j < info.channels; j++) {
1865 volumes[j] = volumes_tmp[j];
1866 sum[j] = sum_tmp[j];
1867 }
1868 }
1869};
1870
1871// legacy names
1872using VolumePrint = VolumeMeter;
1873using VolumeOutput = VolumeMeter;
1874
1875#ifdef USE_TIMER
1882 RxTxMode rx_tx_mode = RX_MODE;
1883 uint16_t buffer_size = DEFAULT_BUFFER_SIZE;
1884 bool use_timer = true;
1885 int timer_id = -1;
1886 TimerFunction timer_function = DirectTimerCallback;
1887 bool adapt_sample_rate = false;
1888 uint16_t (*callback)(uint8_t *data, uint16_t len) = nullptr;
1889};
1890
1891// forward declaration: relevant only if use_timer == true
1892static void timerCallback(void *obj);
1903 friend void timerCallback(void *obj);
1904
1905 public:
1906 TimerCallbackAudioStream() : BufferedStream(80) { TRACED(); }
1907
1909 TRACED();
1910 if (timer != nullptr) delete timer;
1911 if (buffer != nullptr) delete buffer;
1912 if (frame != nullptr) delete[] frame;
1913 }
1914
1920
1922 virtual void setAudioInfo(AudioInfo info) {
1923 TRACED();
1924 if (cfg.sample_rate != info.sample_rate || cfg.channels != info.channels ||
1925 cfg.bits_per_sample != info.bits_per_sample) {
1926 bool do_restart = active;
1927 if (do_restart) end();
1928 cfg.sample_rate = info.sample_rate;
1929 cfg.channels = info.channels;
1930 cfg.bits_per_sample = info.bits_per_sample;
1931 if (do_restart) begin(cfg);
1932 }
1933 }
1934
1937 AudioInfo audioInfo() { return cfg; }
1938
1939 void begin(TimerCallbackAudioStreamInfo config) {
1940 LOGD("%s: %s", LOG_METHOD,
1941 config.rx_tx_mode == RX_MODE ? "RX_MODE" : "TX_MODE");
1942 this->cfg = config;
1943 this->frameCallback = config.callback;
1944 if (cfg.use_timer) {
1945 frameSize = cfg.bits_per_sample * cfg.channels / 8;
1946 frame = new uint8_t[frameSize];
1947 buffer = new RingBuffer<uint8_t>(cfg.buffer_size);
1948 timer = new TimerAlarmRepeating();
1949 timer->setTimerFunction(cfg.timer_function);
1950 if (cfg.timer_id>=0){
1951 timer->setTimer(cfg.timer_id);
1952 }
1953 time = AudioTime::toTimeUs(cfg.sample_rate);
1954 LOGI("sample_rate: %u -> time: %u milliseconds", (unsigned int)cfg.sample_rate, (unsigned int)time);
1955 timer->setCallbackParameter(this);
1956 timer->begin(timerCallback, time, TimeUnit::US);
1957 }
1958
1959 notifyAudioChange(cfg);
1960 active = true;
1961 }
1962
1964 bool begin() {
1965 TRACED();
1966 if (this->frameCallback != nullptr) {
1967 if (cfg.use_timer) {
1968 timer->begin(timerCallback, time, TimeUnit::US);
1969 }
1970 active = true;
1971 }
1972 return active;
1973 }
1974
1976 void end() {
1977 TRACED();
1978 if (cfg.use_timer) {
1979 timer->end();
1980 }
1981 active = false;
1982 }
1983
1985 uint16_t currentSampleRate() { return currentRateValue; }
1986
1987 protected:
1989 bool active = false;
1990 uint16_t (*frameCallback)(uint8_t *data, uint16_t len);
1991 // below only relevant with timer
1992 TimerAlarmRepeating *timer = nullptr;
1993 RingBuffer<uint8_t> *buffer = nullptr;
1994 uint8_t *frame = nullptr;
1995 uint16_t frameSize = 0;
1996 uint32_t time = 0;
1997 unsigned long lastTimestamp = 0u;
1998 uint32_t currentRateValue = 0;
1999 uint32_t printCount = 0;
2000
2001 // used for audio sink
2002 virtual size_t writeExt(const uint8_t *data, size_t len) override {
2003 if (!active) return 0;
2004 TRACED();
2005 size_t result = 0;
2006 if (!cfg.use_timer) {
2007 result = frameCallback((uint8_t *)data, len);
2008 } else {
2009 result = buffer->writeArray((uint8_t *)data, len);
2010 }
2011 if (++printCount % 10000 == 0) printSampleRate();
2012 return result;
2013 }
2014
2015 // used for audio source
2016 virtual size_t readExt(uint8_t *data, size_t len) override {
2017 if (!active) return 0;
2018 TRACED();
2019
2020 size_t result = 0;
2021 if (!cfg.use_timer) {
2022 result = frameCallback(data, len);
2023 } else {
2024 result = buffer->readArray(data, len);
2025 }
2026 if (++printCount % 10000 == 0) printSampleRate();
2027 return result;
2028 }
2029
2031 virtual void measureSampleRate() {
2032 unsigned long ms = millis();
2033 if (lastTimestamp > 0u) {
2034 uint32_t diff = ms - lastTimestamp;
2035 if (diff > 0) {
2036 uint16_t rate = 1 * 1000 / diff;
2037
2038 if (currentRateValue == 0) {
2039 currentRateValue = rate;
2040 } else {
2041 currentRateValue = (currentRateValue + rate) / 2;
2042 }
2043 }
2044 }
2045 lastTimestamp = ms;
2046 }
2047
2049 virtual void printSampleRate() {
2050 LOGI("effective sample rate: %u", (unsigned int)currentRateValue);
2051 if (cfg.adapt_sample_rate &&
2052 abs((int)currentRateValue - (int)cfg.sample_rate) > 200) {
2053 cfg.sample_rate = currentRateValue;
2054 notifyAudioChange(cfg);
2055 }
2056 }
2057};
2058
2059// relevant only if use_timer == true
2060void IRAM_ATTR timerCallback(void *obj) {
2061 TimerCallbackAudioStream *src = (TimerCallbackAudioStream *)obj;
2062 if (src != nullptr) {
2063 // LOGD("%s: %s", LOG_METHOD, src->cfg.rx_tx_mode==RX_MODE ?
2064 // "RX_MODE":"TX_MODE");
2065 if (src->cfg.rx_tx_mode == RX_MODE) {
2066 // input
2067 uint16_t available_bytes = src->frameCallback(src->frame, src->frameSize);
2068 uint16_t buffer_available = src->buffer->availableForWrite();
2069 if (buffer_available < available_bytes) {
2070 // if buffer is full make space
2071 uint16_t to_clear = available_bytes - buffer_available;
2072 uint8_t tmp[to_clear];
2073 src->buffer->readArray(tmp, to_clear);
2074 }
2075 if (src->buffer->writeArray(src->frame, available_bytes) !=
2076 available_bytes) {
2077 assert(false);
2078 }
2079 } else {
2080 // output
2081 if (src->buffer != nullptr && src->frame != nullptr &&
2082 src->frameSize > 0) {
2083 uint16_t available_bytes =
2084 src->buffer->readArray(src->frame, src->frameSize);
2085 if (available_bytes !=
2086 src->frameCallback(src->frame, available_bytes)) {
2087 LOGE("data underflow");
2088 }
2089 }
2090 }
2091 src->measureSampleRate();
2092 }
2093}
2094
2095#endif
2096
2097} // namespace audio_tools
virtual void addNotifyAudioChange(AudioInfoSupport &bi)
Adds target to be notified about audio changes.
Definition AudioTypes.h:156
Supports changes to the sampling rate, bits and channels.
Definition AudioTypes.h:139
virtual AudioInfo audioInfo()=0
provides the actual input AudioInfo
virtual void setAudioInfo(AudioInfo info)=0
Defines the 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:115
virtual void setAudioInfo(AudioInfo newInfo) override
Defines the input AudioInfo.
Definition BaseStream.h:123
virtual AudioInfo audioInfo() override
provides the actual input AudioInfo
Definition BaseStream.h:146
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:250
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:1421
void setOutput(Stream &in)
same as setStream
Definition AudioStreams.h:1534
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:1433
void setStream(Print &out)
same as set Output
Definition AudioStreams.h:1540
void setAvailable(int val)
optioinally define available bytes for next read
Definition AudioStreams.h:1545
void setOutput(Print &out)
Defines/Changes the output target.
Definition AudioStreams.h:1529
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:1426
void setStream(Stream &in)
Defines/Changes the input & output.
Definition AudioStreams.h:1523
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
Stream to which we can apply Filters for each channel. The filter might change the result size!
Definition AudioStreams.h:1571
void setStream(Stream &stream)
Defines/Changes the input & output.
Definition AudioStreams.h:1591
void setFilter(int channel, Filter< TF > &filter)
Definition AudioStreams.h:1656
void setOutput(Print &stream)
Defines/Changes the output target.
Definition AudioStreams.h:1596
void setFilter(int channel, Filter< TF > *filter)
Definition AudioStreams.h:1646
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:1326
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:1355
void end() override
Remove all input streams.
Definition AudioStreams.h:1386
int available() override
Provides the min available data from all streams.
Definition AudioStreams.h:1397
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:1377
void add(Stream &in, float weight=1.0)
Adds a new input stream.
Definition AudioStreams.h:1371
InputMerge(Stream &left, Stream &right)
Constructor for stereo signal from to mono input stream.
Definition AudioStreams.h:1334
int size()
Number of stremams to which are mixed together = number of result channels.
Definition AudioStreams.h:1392
MixerStream is mixing the input from Multiple Input Streams. All streams must have the same audo form...
Definition AudioStreams.h:1171
void add(Stream &in, int weight=100)
Adds a new input stream.
Definition AudioStreams.h:1176
void set(int channel, Stream &in)
Replaces a stream at the indicated channel.
Definition AudioStreams.h:1183
size_t readBytes(uint8_t *data, size_t len) override
Provides the data from all streams mixed together.
Definition AudioStreams.h:1227
void end() override
Remove all input streams.
Definition AudioStreams.h:1213
int availableBytes()
Provides the available bytes from the first stream with data.
Definition AudioStreams.h:1295
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:1250
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:1255
int readBytesVector(T *p_data, int byteCount)
mixing using a vector of samples
Definition AudioStreams.h:1270
int size()
Number of stremams to which are mixed together.
Definition AudioStreams.h:1222
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:1199
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:728
void setOutput(Print &out) override
Defines/Changes the output target.
Definition AudioStreams.h:712
uint32_t estimatedTotalTimeFor(uint32_t totalBytes)
Provides the estimated runtime in milliseconds for the indicated total.
Definition AudioStreams.h:795
uint32_t timeSinceBegin()
Provides the time in ms since the last call of begin()
Definition AudioStreams.h:785
size_t readBytes(uint8_t *data, size_t len) override
Provides the data from all streams mixed together.
Definition AudioStreams.h:718
int framesPerSecond()
Returns the actual thrughput in frames (samples) per second.
Definition AudioStreams.h:744
void setAudioInfo(AudioInfo info)
Defines the input AudioInfo.
Definition AudioStreams.h:754
uint32_t bytesSinceBegin()
Provides the total processed bytes since the last call of begin()
Definition AudioStreams.h:790
virtual int availableForWrite() override
Provides the nubmer of bytes we can write.
Definition AudioStreams.h:734
void setFrameSize(int size)
Trigger reporting in frames (=samples) per second.
Definition AudioStreams.h:771
void setReportBytes(bool flag)
Report in bytes instead of samples.
Definition AudioStreams.h:776
uint32_t estimatedOpenTimeFor(uint32_t totalBytes)
Provides the estimated time from now to the end in ms.
Definition AudioStreams.h:801
void setLogOutput(Print &out)
Defines the logging output.
Definition AudioStreams.h:701
bool setProcessedBytes(uint32_t pos)
Alternative update method: e.g report actual file positon: returns true if the file position was incr...
Definition AudioStreams.h:807
uint32_t startTime()
Provides the time when the last measurement was started.
Definition AudioStreams.h:750
void setStream(Stream &io) override
Defines/Changes the input & output.
Definition AudioStreams.h:706
int bytesPerSecond()
Returns the actual thrughput in bytes per second.
Definition AudioStreams.h:739
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 uint8_t * data()
Provides access to the data array.
Definition AudioStreams.h:285
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(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
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
MemoryStream & operator=(MemoryStream &other)
copy assignement operator
Definition AudioStreams.h:123
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:285
static int64_t maxValue(int value_bits_per_sample)
provides the biggest number for the indicated number of bits
Definition AudioTypes.h:311
Definition NoArduino.h:62
Generic calss to measure the the total bytes which were processed in order to calculate the progress ...
Definition AudioStreams.h:883
bool begin(size_t len)
Updates the total size and restarts the percent calculation: Same as calling setSize()
Definition AudioStreams.h:930
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:990
size_t size()
Provides the current total size (defined by setSize)
Definition AudioStreams.h:948
size_t totalSecs()
Converts the totalBytes() to seconds.
Definition AudioStreams.h:968
size_t readBytes(uint8_t *data, size_t len) override
Provides the data from all streams mixed together.
Definition AudioStreams.h:979
size_t processedBytes()
Provides the number of processed bytes.
Definition AudioStreams.h:953
void setStream(Stream &stream)
Defines/Changes the input & output.
Definition AudioStreams.h:909
void setSize(size_t len)
Updates the total size and restarts the percent calculation.
Definition AudioStreams.h:942
virtual int availableForWrite() override
Provides the nubmer of bytes we can write.
Definition AudioStreams.h:996
float percentage()
Provides the processed percentage: If no size has been defined we return 0.
Definition AudioStreams.h:973
size_t processedSecs()
Provides the number of processed seconds.
Definition AudioStreams.h:958
void setAudioInfo(AudioInfo info) override
Defines the input AudioInfo.
Definition AudioStreams.h:904
size_t totalBytes()
Provides the total_size provided in the configuration.
Definition AudioStreams.h:963
Configuration for ProgressStream.
Definition AudioStreams.h:872
An AudioStream backed by a Ringbuffer. We can write to the end and read from the beginning of the str...
Definition AudioStreams.h:342
Definition NoArduino.h:142
Throttle the sending or receiving of the audio data to limit it to the indicated sample rate.
Definition AudioStreams.h:1045
void setOutput(Print &out) override
Defines/Changes the output target.
Definition AudioStreams.h:1058
void setStream(Stream &io) override
Defines/Changes the input & output.
Definition AudioStreams.h:1052
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:1902
TimerCallbackAudioStreamInfo audioInfoExt()
Provides the current audio information.
Definition AudioStreams.h:1936
uint16_t currentSampleRate()
Provides the effective sample rate.
Definition AudioStreams.h:1985
TimerCallbackAudioStreamInfo defaultConfig()
Provides the default configuration.
Definition AudioStreams.h:1916
bool begin()
Restart the processing.
Definition AudioStreams.h:1964
AudioInfo audioInfo()
provides the actual input AudioInfo
Definition AudioStreams.h:1937
virtual void measureSampleRate()
calculates the effective sample rate
Definition AudioStreams.h:2031
virtual void setAudioInfo(AudioInfo info)
updates the audio information
Definition AudioStreams.h:1922
virtual void printSampleRate()
log and update effective sample rate
Definition AudioStreams.h:2049
void end()
Stops the processing.
Definition AudioStreams.h:1976
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:1676
void setOutput(Print &out) override
Defines/Changes the output target.
Definition AudioStreams.h:1798
float volumeRatio()
Volume Ratio: max amplitude is 1.0.
Definition AudioStreams.h:1747
float volumeAvg(int channel)
Average volume of indicated channel.
Definition AudioStreams.h:1784
float volume()
Definition AudioStreams.h:1729
float volumePercent()
Volume in %: max amplitude is 100.
Definition AudioStreams.h:1767
void setAudioInfo(AudioInfo info)
Defines the input AudioInfo.
Definition AudioStreams.h:1703
float volumePercent(int channel)
Volume of indicated channel in %: max amplitude is 100.
Definition AudioStreams.h:1770
float volumeAvg()
Average volume of all channels.
Definition AudioStreams.h:1773
void clear()
Resets the actual volume.
Definition AudioStreams.h:1790
float volumeRatio(int channel)
Volume Ratio of indicated channel: max amplitude is 1.0.
Definition AudioStreams.h:1750
float volumeDB(int channel)
Volume of indicated channel in db: max amplitude is 0.
Definition AudioStreams.h:1760
void setStream(Stream &io) override
Defines/Changes the input & output.
Definition AudioStreams.h:1801
float volumeDB()
Volume in db: max amplitude is 0 (range: -1000 to 0)
Definition AudioStreams.h:1753
float volume(int channel)
Definition AudioStreams.h:1733
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:885
size_t readSamples(Stream *p_stream, T *data, int samples, int retryCount=-1)
guaranteed to return the requested data
Definition AudioTypes.h:474
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:1030
TimerCallbackAudioStream Configuration.
Definition AudioStreams.h:1881