arduino-audio-tools
All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends Modules Pages
AudioStreams.h
1#pragma once
2#include "AudioTools/CoreAudio/AudioEffects/SoundGenerator.h"
3#include "AudioTools/CoreAudio/AudioLogger.h"
4#include "AudioTools/CoreAudio/AudioOutput.h"
5#include "AudioTools/CoreAudio/AudioTimer/AudioTimer.h"
6#include "AudioTools/CoreAudio/AudioTypes.h"
7#include "AudioTools/CoreAudio/BaseConverter.h"
8#include "AudioTools/CoreAudio/BaseStream.h"
9#include "AudioTools/CoreAudio/Buffers.h"
10#include "AudioToolsConfig.h"
11
12#ifndef IRAM_ATTR
13#define IRAM_ATTR
14#endif
15
16namespace audio_tools {
17
24 public:
26 TRACED();
27 p_stream = &s;
28 p_stream->setTimeout(clientTimeout);
29 }
30
31 virtual bool begin() { return true; }
32 virtual void end() {}
33
34 virtual size_t readBytes(uint8_t *data, size_t len) {
35 // Serial.print("Timeout audiostream: ");
36 // Serial.println(p_stream->getTimeout());
37 return p_stream->readBytes(data, len);
38 }
39
40 int read() { return p_stream->read(); }
41
42 int peek() { return p_stream->peek(); }
43
44 int available() { return p_stream->available(); }
45
46 virtual size_t write(uint8_t c) { return p_stream->write(c); }
47
48 virtual size_t write(const uint8_t *data, size_t len) {
49 return p_stream->write(data, len);
50 }
51
52 virtual int availableForWrite() { return p_stream->availableForWrite(); }
53
54 virtual void flush() { p_stream->flush(); }
55
56 protected:
57 Stream *p_stream;
58 int32_t clientTimeout = URL_CLIENT_TIMEOUT; // 60000;
59};
60
69 public:
71 virtual void setStream(Stream &in) = 0;
73 virtual void setOutput(Print &out) = 0;
74};
75
83class MemoryStream : public AudioStream {
84 public:
85 // Default constructor
86 MemoryStream() = default;
88 MemoryStream(int buffer_size, MemoryType memoryType) {
89 LOGD("MemoryStream: %d", buffer_size);
90 this->buffer_size = buffer_size;
91 this->memory_type = memoryType;
92 resize(buffer_size);
93 info.clear(); // mark audio info as unknown
94 }
95
98 MemoryStream(const uint8_t *buffer, int buffer_size, bool isActive = true,
99 MemoryType memoryType = FLASH_RAM) {
100 LOGD("MemoryStream: %d", buffer_size);
101 setValue(buffer, buffer_size, memoryType);
102 is_active = isActive;
103 info.clear(); // mark audio info as unknown
104 }
105
107 MemoryStream(MemoryStream &source) : AudioStream() { copy(source); }
108
111 setValue(source.buffer, source.buffer_size, source.memory_type);
112 // clear source data
113 source.setValue(nullptr, 0, source.memory_type);
114 }
115
116 ~MemoryStream() {
117 TRACED();
118 if (memoryCanChange() && buffer != nullptr) free(buffer);
119 }
120
123 copy(other);
124 return *this;
125 }
126
128 operator bool() override { return available() > 0; }
129
131 bool begin(AudioInfo info) {
132 this->info = info;
133 return begin();
134 }
135
137 bool begin() override {
138 TRACED();
139 write_pos = memoryCanChange() ? 0 : buffer_size;
140 if (this->buffer == nullptr && memoryCanChange()) {
141 resize(buffer_size);
142 }
143 read_pos = 0;
144 is_active = true;
145 return true;
146 }
147
148 virtual size_t write(uint8_t byte) override {
149 if (!is_active) return 0;
150 if (memory_type == FLASH_RAM) return 0;
151 if (buffer == nullptr) return 0;
152 int result = 0;
153 if (write_pos < buffer_size) {
154 result = 1;
155 buffer[write_pos] = byte;
156 write_pos++;
157 }
158 return result;
159 }
160
161 virtual size_t write(const uint8_t *data, size_t len) override {
162 if (!is_active) return 0;
163 if (memory_type == FLASH_RAM) return 0;
164 size_t result = 0;
165 for (size_t j = 0; j < len; j++) {
166 if (!write(data[j])) {
167 break;
168 }
169 result = j + 1;
170 }
171 return result;
172 }
173
174 virtual int available() override {
175 if (!is_active) return 0;
176 if (buffer == nullptr) return 0;
177 int result = write_pos - read_pos;
178 if (result <= 0 && is_loop) {
179 // rewind to start
180 read_pos = rewind_pos;
181 result = write_pos - read_pos;
182 // call callback
183 if (rewind != nullptr) rewind();
184 }
185 return is_loop ? DEFAULT_BUFFER_SIZE : result;
186 }
187
188 virtual int availableForWrite() override {
189 if (!is_active) return 0;
190 if (memory_type == FLASH_RAM) return 0;
191 return buffer_size - write_pos;
192 }
193
194 virtual int read() override {
195 int result = peek();
196 if (result >= 0) {
197 read_pos++;
198 }
199 return result;
200 }
201
202 virtual size_t readBytes(uint8_t *data, size_t len) override {
203 if (!is_active) return 0;
204 size_t count = 0;
205 while (count < len) {
206 int c = read();
207 if (c < 0) break;
208 *data++ = (char)c;
209 count++;
210 }
211 return count;
212 }
213
214 virtual int peek() override {
215 if (!is_active) return -1;
216 int result = -1;
217 if (available() > 0) {
218 result = buffer[read_pos];
219 }
220 return result;
221 }
222
223 virtual void flush() override {}
224
225 virtual void end() override {
226 read_pos = 0;
227 is_active = false;
228 }
229
231 virtual void clear(bool reset = false) {
232 if (memoryCanChange()) {
233 write_pos = 0;
234 read_pos = 0;
235 if (buffer == nullptr) {
236 resize(buffer_size);
237 }
238 if (reset) {
239 // we clear the buffer data
240 memset(buffer, 0, buffer_size);
241 }
242 } else {
243 read_pos = 0;
244 LOGW("data is read only");
245 }
246 }
247
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
268 virtual bool resize(size_t size) {
269 if (!memoryCanChange()) return false;
270
271 buffer_size = size;
272 switch (memory_type) {
273#if defined(ESP32) && defined(ARDUINO)
274 case PS_RAM:
275 buffer = (buffer == nullptr) ? (uint8_t *)ps_calloc(size, 1)
276 : (uint8_t *)ps_realloc(buffer, size);
277 break;
278#endif
279 default:
280 buffer = (buffer == nullptr) ? (uint8_t *)calloc(size, 1)
281 : (uint8_t *)realloc(buffer, size);
282 break;
283 }
284 return buffer != nullptr;
285 }
286
288 virtual uint8_t *data() { return buffer; }
289
291 virtual void setAvailable(size_t len) { this->write_pos = len; }
292
294 void setRewindCallback(void (*cb)()) { this->rewind = cb; }
295
297 void setValue(const uint8_t *buffer, int buffer_size,
298 MemoryType memoryType = FLASH_RAM) {
299 this->buffer_size = buffer_size;
300 this->read_pos = 0;
301 this->write_pos = buffer_size;
302 this->buffer = (uint8_t *)buffer;
303 this->memory_type = memoryType;
304 }
305
306 protected:
307 int write_pos = 0;
308 int read_pos = 0;
309 int buffer_size = 0;
310 int rewind_pos = 0;
311 uint8_t *buffer = nullptr;
312 MemoryType memory_type = RAM;
313 bool is_loop = false;
314 void (*rewind)() = nullptr;
315 bool is_active = false;
316
317 bool memoryCanChange() { return memory_type != FLASH_RAM; }
318
319 void copy(MemoryStream &source) {
320 if (this == &source) return;
321 if (source.memory_type == FLASH_RAM) {
322 setValue(source.buffer, source.buffer_size, source.memory_type);
323 } else {
324 setValue(nullptr, source.buffer_size, source.memory_type);
325 resize(buffer_size);
326 memcpy(buffer, source.buffer, buffer_size);
327 }
328 }
329};
330
339 public:
340 RingBufferStream(int size = DEFAULT_BUFFER_SIZE) { resize(size); }
341
342 virtual int available() override {
343 // LOGD("RingBufferStream::available: %zu",buffer->available());
344 return buffer.available();
345 }
346
347 virtual int availableForWrite() override {
348 return buffer.availableForWrite();
349 }
350
351 virtual void flush() override {}
352 virtual int peek() override {
353 uint8_t data = 0;
354 if (!buffer.peek(data)) return -1;
355 return data;
356 }
357 virtual int read() override {
358 uint8_t data = 0;
359 if (!buffer.read(data)) return -1;
360 return data;
361 }
362
363 virtual size_t readBytes(uint8_t *data, size_t len) override {
364 return buffer.readArray(data, len);
365 }
366
367 virtual size_t write(const uint8_t *data, size_t len) override {
368 // LOGD("RingBufferStream::write: %zu",len);
369 return buffer.writeArray(data, len);
370 }
371
372 virtual size_t write(uint8_t c) override { return buffer.write(c); }
373
374 void resize(int size) { buffer.resize(size); }
375
376 size_t size() { return buffer.size(); }
377
378 protected:
379 RingBuffer<uint8_t> buffer{0};
380};
381
393template <class T>
395 public:
396 GeneratedSoundStream() = default;
397
399 TRACED();
400 setInput(generator);
401 }
402
403 void setInput(SoundGenerator<T> &generator) {
404 this->generator_ptr = &generator;
405 }
406
407 AudioInfo defaultConfig() { return this->generator_ptr->defaultConfig(); }
408
409 void setAudioInfo(AudioInfo newInfo) override {
410 if (newInfo.bits_per_sample != sizeof(T) * 8) {
411 LOGE("Wrong bits_per_sample: %d", newInfo.bits_per_sample);
412 }
414 }
415
417 bool begin() override {
418 TRACED();
419 if (generator_ptr == nullptr) {
420 LOGE("%s", source_not_defined_error);
421 return false;
422 }
423 generator_ptr->begin();
424 notifyAudioChange(generator_ptr->audioInfo());
425 active = true;
426 return active;
427 }
428
430 bool begin(AudioInfo cfg) {
431 TRACED();
432 if (generator_ptr == nullptr) {
433 LOGE("%s", source_not_defined_error);
434 return false;
435 }
436 generator_ptr->begin(cfg);
437 notifyAudioChange(generator_ptr->audioInfo());
438 active = true;
439 return active;
440 }
441
443 void end() override {
444 TRACED();
445 generator_ptr->end();
446 active = true; // legacy support - most sketches do not call begin
447 }
448
449 AudioInfo audioInfo() override { return generator_ptr->audioInfo(); }
450
452 virtual int available() override {
453 return active ? DEFAULT_BUFFER_SIZE * 2 : 0;
454 }
455
457 size_t readBytes(uint8_t *data, size_t len) override {
458 if (!active) return 0;
459 LOGD("GeneratedSoundStream::readBytes: %u", (unsigned int)len);
460 return generator_ptr->readBytes(data, len);
461 }
462
463 bool isActive() { return active && generator_ptr->isActive(); }
464
465 operator bool() { return isActive(); }
466
467 void flush() override {}
468
469 protected:
470 bool active = true; // support for legacy sketches
471 SoundGenerator<T> *generator_ptr;
472 const char *source_not_defined_error = "Source not defined";
473};
474
484 public:
485 BufferedStream(size_t buffer_size) {
486 TRACED();
487 buffer.resize(buffer_size);
488 }
489
490 BufferedStream(Print &out, size_t buffer_size = 1024) {
491 TRACED();
492 setOutput(out);
493 buffer.resize(buffer_size);
494 }
495
496 BufferedStream(Stream &io, size_t buffer_size = 1024) {
497 TRACED();
498 setStream(io);
499 buffer.resize(buffer_size);
500 }
501
502 BufferedStream(size_t buffer_size, Print &out) {
503 TRACED();
504 setOutput(out);
505 buffer.resize(buffer_size);
506 }
507
508 BufferedStream(size_t buffer_size, Stream &io) {
509 TRACED();
510 setStream(io);
511 buffer.resize(buffer_size);
512 }
513
514 void setOutput(Print &out) { p_out = &out; }
515 void setStream(Print &out) { setOutput(out); }
516 void setStream(Stream &io) {
517 p_in = &io;
518 p_out = &io;
519 }
520
522 size_t write(uint8_t c) override {
523 if (buffer.isFull()) {
524 flush();
525 }
526 return buffer.write(c);
527 }
528
530 size_t write(const uint8_t *data, size_t len) override {
531 LOGD("%s: %zu", LOG_METHOD, len);
532 int result = 0;
533 for (int j = 0; j < len; j++) {
534 result += write(data[j]);
535 }
536 return result;
537 }
538
540 void flush() override {
541 // just dump the memory of the buffer and clear it
542 if (buffer.available() > 0) {
543 writeExt(buffer.address(), buffer.available());
544 buffer.reset();
545 }
546 }
547
549 int read() override {
550 if (buffer.isEmpty()) {
551 refill();
552 }
553 uint8_t result = 0;
554 if (!buffer.read(result)) return -1;
555 return result;
556 }
557
559 int peek() override {
560 if (buffer.isEmpty()) {
561 refill();
562 }
563 uint8_t result = 0;
564 if (!buffer.peek(result)) return -1;
565 return result;
566 };
567
569 size_t readBytes(uint8_t *data, size_t len) override {
570 if (buffer.isEmpty()) {
571 return readExt(data, len);
572 } else {
573 refill();
574 return buffer.readArray(data, len);
575 }
576 }
577
579 int available() override {
580 if (buffer.isEmpty()) {
581 refill();
582 }
583 return buffer.available();
584 }
585
587 void clear() { buffer.reset(); }
588
589 protected:
591 Print *p_out = nullptr;
592 Stream *p_in = nullptr;
593
594 // refills the buffer with data from the source
595 void refill() {
596 size_t result = readExt(buffer.address(), buffer.size());
597 buffer.setAvailable(result);
598 }
599
600 virtual size_t writeExt(const uint8_t *data, size_t len) {
601 return p_out == nullptr ? 0 : p_out->write(data, len);
602 }
603 virtual size_t readExt(uint8_t *data, size_t len) {
604 return p_in == nullptr ? 0 : p_in->readBytes(data, len);
605 }
606};
607
616template <typename T>
618 public:
619 ConverterStream() = default;
620
621 ConverterStream(BaseConverter &converter) { setConverter(converter); }
622
623 ConverterStream(Stream &stream, BaseConverter &converter) {
624 setConverter(converter);
625 setStream(stream);
626 }
627
628 ConverterStream(Print &out, BaseConverter &converter) {
629 setConverter(converter);
630 setOutput(out);
631 }
632
633 void setStream(Stream &stream) {
634 TRACEI();
635 p_stream = &stream;
636 p_out = &stream;
637 }
638
639 void setOutput(Print &out) {
640 TRACEI();
641 p_out = &out;
642 }
643
644 void setConverter(BaseConverter &cnv) { p_converter = &cnv; }
645
646 virtual int availableForWrite() { return p_out->availableForWrite(); }
647
648 virtual size_t write(const uint8_t *data, size_t len) {
649 size_t result = p_converter->convert((uint8_t *)data, len);
650 if (result > 0) {
651 size_t result_written = p_out->write(data, result);
652 return len * result_written / result;
653 }
654 return 0;
655 }
656
657 size_t readBytes(uint8_t *data, size_t len) override {
658 if (p_stream == nullptr) return 0;
659 size_t result = p_stream->readBytes(data, len);
660 return p_converter->convert(data, result);
661 }
662
664 virtual int available() override {
665 if (p_stream == nullptr) return 0;
666 return p_stream->available();
667 }
668
669 protected:
670 Stream *p_stream = nullptr;
671 Print *p_out = nullptr;
672 BaseConverter *p_converter;
673};
674
682 public:
683 MeasuringStream(int count = 10, Print *logOut = nullptr) {
684 this->count = count;
685 this->max_count = count;
686 p_stream = &null;
687 p_print = &null;
688 start_time = millis();
689 p_logout = logOut;
690 }
691
692 MeasuringStream(Print &print, int count = 10, Print *logOut = nullptr) {
693 this->count = count;
694 this->max_count = count;
695 setOutput(print);
696 start_time = millis();
697 p_logout = logOut;
698 }
699
700 MeasuringStream(Stream &stream, int count = 10, Print *logOut = nullptr) {
701 this->count = count;
702 this->max_count = count;
703 setStream(stream);
704 start_time = millis();
705 p_logout = logOut;
706 }
707
709 void setLogOutput(Print &out) { p_logout = &out; }
710
712 void setStream(Stream &io) override {
713 p_print = &io;
714 p_stream = &io;
715 };
716
718 void setOutput(Print &out) override { p_print = &out; }
719
721 size_t readBytes(uint8_t *data, size_t len) override {
722 total_bytes_since_begin += len;
723 return measure(p_stream->readBytes(data, len));
724 }
725
726 int available() override { return p_stream->available(); }
727
729 virtual size_t write(const uint8_t *data, size_t len) override {
730 total_bytes_since_begin += len;
731 return measure(p_print->write(data, len));
732 }
733
735 virtual int availableForWrite() override {
736 return p_print->availableForWrite();
737 }
738
740 int bytesPerSecond() { return bytes_per_second; }
741
744 if (frame_size == 0) return 0;
745 return bytes_per_second / frame_size;
746 }
747
749 uint32_t startTime() { return start_time; }
750
752 AudioStream::info = info;
753 setFrameSize(info.bits_per_sample / 8 * info.channels);
754 }
755
756 bool begin() {
757 total_bytes_since_begin = 0;
758 ms_at_begin = millis();
759 return AudioStream::begin();
760 }
761
762 bool begin(AudioInfo info) {
763 setAudioInfo(info);
764 return begin();
765 }
766
768 void setFrameSize(int size) { frame_size = size; }
769
771 void setReportBytes(bool flag) { report_bytes = flag; }
772
773 void setName(const char *name) { this->name = name; }
774
776 uint32_t timeSinceBegin() { return millis() - ms_at_begin; }
777
779 uint32_t bytesSinceBegin() { return total_bytes_since_begin; }
780
782 uint32_t estimatedTotalTimeFor(uint32_t totalBytes) {
783 if (bytesSinceBegin() == 0) return 0;
784 return static_cast<float>(timeSinceBegin()) / bytesSinceBegin() *
785 totalBytes;
786 }
787
789 uint32_t estimatedOpenTimeFor(uint32_t totalBytes) {
790 if (bytesSinceBegin() == 0) return 0;
791 return estimatedTotalTimeFor(totalBytes) - timeSinceBegin();
792 }
793
796 bool setProcessedBytes(uint32_t pos) {
797 bool is_regular_update = true;
798 if (pos < total_bytes_since_begin) {
799 begin();
800 is_regular_update = false;
801 }
802 total_bytes_since_begin = pos;
803 return is_regular_update;
804 }
805
806 protected:
807 int max_count = 0;
808 int count = 0;
809 Stream *p_stream = nullptr;
810 Print *p_print = nullptr;
811 uint32_t start_time;
812 int total_bytes = 0;
813 int bytes_per_second = 0;
814 int frame_size = 0;
815 NullStream null;
816 Print *p_logout = nullptr;
817 bool report_bytes = false;
818 const char *name = "";
819 uint32_t ms_at_begin = 0;
820 uint32_t total_bytes_since_begin = 0;
821
822 size_t measure(size_t len) {
823 count--;
824 total_bytes += len;
825
826 if (count <= 0) {
827 uint32_t end_time = millis();
828 int time_diff = end_time - start_time; // in ms
829 if (time_diff > 0) {
830 bytes_per_second = total_bytes / time_diff * 1000;
831 printResult();
832 count = max_count;
833 total_bytes = 0;
834 start_time = end_time;
835 }
836 }
837 return len;
838 }
839
840 void printResult() {
841 char msg[70];
842 if (report_bytes || frame_size == 0) {
843 snprintf(msg, 70, "%s ==> Bytes per second: %d", name, bytes_per_second);
844 } else {
845 snprintf(msg, 70, "%s ==> Samples per second: %d", name,
846 bytes_per_second / frame_size);
847 }
848 if (p_logout != nullptr) {
849 p_logout->println(msg);
850 } else {
851 LOGI("%s", msg);
852 }
853 }
854};
855
863 public:
864 size_t total_size = 0;
865};
874 public:
875 ProgressStream() = default;
876
877 ProgressStream(Print &print) { setPrint(print); }
878
879 ProgressStream(Stream &stream) { setStream(stream); }
880
881 ProgressStream(AudioStream &stream) {
882 setStream(stream);
883 p_info_from = &stream;
884 }
885
886 ProgressStreamInfo &defaultConfig() { return progress_info; }
887
888 void setAudioInfo(AudioInfo info) override {
890 progress_info.copyFrom(info);
891 }
892
893 void setStream(Stream &stream) {
894 p_stream = &stream;
895 p_print = &stream;
896 }
897
898 void setStream(Print &print) { p_print = &print; }
899
900 void setPrint(Print &print) { p_print = &print; }
901
902 bool begin() override {
903 if (p_info_from != nullptr) {
904 setAudioInfo(p_info_from->audioInfo());
905 }
906 return AudioStream::begin();
907 }
908
911 bool begin(size_t len) {
912 setSize(len);
913 return begin();
914 }
915
916 bool begin(ProgressStreamInfo info) {
917 progress_info = info;
918 setAudioInfo(info);
919 return begin();
920 }
921
923 void setSize(size_t len) {
924 total_processed = 0;
925 progress_info.total_size = len;
926 }
927
929 size_t size() { return progress_info.total_size; }
930
932 size_t processedBytes() { return total_processed; }
933
935 size_t processedSecs() { return total_processed / byteRate(); }
936
938 size_t totalBytes() { return progress_info.total_size; }
939
941 size_t totalSecs() { return totalBytes() / byteRate(); }
942
944 float percentage() {
945 if (progress_info.total_size == 0) return 0;
946 return 100.0 * total_processed / progress_info.total_size;
947 }
948
950 size_t readBytes(uint8_t *data, size_t len) override {
951 if (p_stream == nullptr) return 0;
952 return measure(p_stream->readBytes(data, len));
953 }
954
955 int available() override {
956 if (p_stream == nullptr) return 0;
957 return p_stream->available();
958 }
959
961 virtual size_t write(const uint8_t *data, size_t len) override {
962 if (p_print == nullptr) return 0;
963 return measure(p_print->write(data, len));
964 }
965
967 virtual int availableForWrite() override {
968 if (p_print == nullptr) return 0;
969 return p_print->availableForWrite();
970 }
971
972 protected:
973 ProgressStreamInfo progress_info;
974 Stream *p_stream = nullptr;
975 Print *p_print = nullptr;
976 AudioInfoSupport *p_info_from = nullptr;
977 size_t total_processed = 0;
978
979 size_t measure(size_t len) {
980 total_processed += len;
981 return len;
982 }
983
984 size_t byteRate() {
985 AudioInfo info = audioInfo();
986 int byte_rate = info.sample_rate * info.bits_per_sample * info.channels / 8;
987 if (byte_rate == 0) {
988 LOGE("Audio Info not defined");
989 return 0;
990 }
991 return byte_rate;
992 }
993};
994
1000struct ThrottleConfig : public AudioInfo {
1001 ThrottleConfig() {
1002 sample_rate = 44100;
1003 bits_per_sample = 16;
1004 channels = 2;
1005 }
1006 int correction_us = 0;
1007};
1008
1016 public:
1017 Throttle() = default;
1018 Throttle(Print &out) { setOutput(out); }
1019 Throttle(Stream &io) { setStream(io); }
1020
1022 void setStream(Stream &io) override {
1023 p_out = &io;
1024 p_in = &io;
1025 };
1026
1028 void setOutput(Print &out) override { p_out = &out; }
1029
1030 ThrottleConfig defaultConfig() {
1032 return c;
1033 }
1034
1035 bool begin(ThrottleConfig cfg) {
1036 LOGI("begin sample_rate: %d, channels: %d, bits: %d", (int)info.sample_rate,
1037 (int)info.channels, (int)info.bits_per_sample);
1038 this->info = cfg;
1039 this->cfg = cfg;
1040 return begin();
1041 }
1042
1043 bool begin(AudioInfo info) {
1044 LOGI("begin sample_rate: %d, channels: %d, bits: %d", (int)info.sample_rate,
1045 (int)info.channels, (int)info.bits_per_sample);
1046 this->info = info;
1047 this->cfg.copyFrom(info);
1048 return begin();
1049 }
1050
1051 bool begin() {
1052 frame_size = cfg.bits_per_sample / 8 * cfg.channels;
1053 startDelay();
1054 return true;
1055 }
1056
1057 // (re)starts the timing
1058 void startDelay() {
1059 start_time = micros();
1060 sum_frames = 0;
1061 }
1062
1063 int availableForWrite() {
1064 if (p_out) {
1065 return p_out->availableForWrite();
1066 }
1067 return DEFAULT_BUFFER_SIZE;
1068 }
1069
1070 size_t write(const uint8_t *data, size_t len) {
1071 size_t result = p_out->write(data, len);
1072 delayBytes(len);
1073 return result;
1074 }
1075
1076 int available() {
1077 if (p_in == nullptr) return 0;
1078 return p_in->available();
1079 }
1080
1081 size_t readBytes(uint8_t *data, size_t len) override {
1082 if (p_in == nullptr) {
1083 delayBytes(len);
1084 return 0;
1085 }
1086 size_t result = p_in->readBytes(data, len);
1087 delayBytes(len);
1088 return result;
1089 }
1090
1091 // delay
1092 void delayBytes(size_t bytes) { delayFrames(bytes / frame_size); }
1093
1094 // delay
1095 void delayFrames(size_t frames) {
1096 sum_frames += frames;
1097 uint64_t durationUsEff = micros() - start_time;
1098 uint64_t durationUsToBe = getDelayUs(sum_frames);
1099 int64_t waitUs = durationUsToBe - durationUsEff + cfg.correction_us;
1100 LOGD("wait us: %ld", static_cast<long>(waitUs));
1101 if (waitUs > 0) {
1102 int64_t waitMs = waitUs / 1000;
1103 if (waitMs > 0) delay(waitMs);
1104 delayMicroseconds(waitUs - (waitMs * 1000));
1105 } else {
1106 LOGD("negative delay!")
1107 }
1108 }
1109
1110 inline int64_t getDelayUs(uint64_t frames) {
1111 return (frames * 1000000) / cfg.sample_rate;
1112 }
1113
1114 inline int64_t getDelayMs(uint64_t frames) {
1115 return getDelayUs(frames) / 1000;
1116 }
1117
1118 inline int64_t getDelaySec(uint64_t frames) {
1119 return getDelayUs(frames) / 1000000l;
1120 }
1121
1122 protected:
1123 uint32_t start_time = 0;
1124 uint32_t sum_frames = 0;
1125 ThrottleConfig cfg;
1126 int frame_size = 0;
1127 Print *p_out = nullptr;
1128 Stream *p_in = nullptr;
1129};
1130
1140template <typename T>
1141class InputMixer : public AudioStream {
1142 public:
1143 InputMixer() = default;
1144
1146 void add(Stream &in, int weight = 100) {
1147 streams.push_back(&in);
1148 weights.push_back(weight);
1149 total_weights += weight;
1150 }
1151
1153 void set(int channel, Stream &in) {
1154 if (channel < size()) {
1155 streams[channel] = &in;
1156 } else {
1157 LOGE("Invalid channel %d - max is %d", channel, size() - 1);
1158 }
1159 }
1160
1161 virtual bool begin(AudioInfo info) {
1162 setAudioInfo(info);
1163 frame_size = info.bits_per_sample / 8 * info.channels;
1164 LOGI("frame_size: %d", frame_size);
1165 return frame_size > 0;
1166 }
1167
1171 void setWeight(int channel, int weight) {
1172 if (channel < size()) {
1173 weights[channel] = weight;
1174 int total = 0;
1175 for (int j = 0; j < weights.size(); j++) {
1176 total += weights[j];
1177 }
1178 total_weights = total;
1179 } else {
1180 LOGE("Invalid channel %d - max is %d", channel, size() - 1);
1181 }
1182 }
1183
1185 void end() override {
1186 streams.clear();
1187 weights.clear();
1188 result_vect.clear();
1189 current_vect.clear();
1190 total_weights = 0.0;
1191 }
1192
1194 int size() { return streams.size(); }
1195
1197 size_t readBytes(uint8_t *data, size_t len) override {
1198 if (total_weights == 0 || frame_size == 0 || len == 0) {
1199 LOGW("readBytes: %d", (int)len);
1200 return 0;
1201 }
1202
1203 if (limit_available_data) {
1204 len = min((int)len, availableBytes());
1205 }
1206
1207 int result_len = 0;
1208
1209 if (len > 0) {
1210 // result_len must be full frames
1211 result_len = len * frame_size / frame_size;
1212 // replace sample based with vector based implementation
1213 // readBytesSamples((T*)data, result_len));
1214 result_len = readBytesVector((T *)data, result_len);
1215 }
1216 return result_len;
1217 }
1218
1221 void setLimitToAvailableData(bool flag) { limit_available_data = flag; }
1222
1225 void setRetryCount(int retry) { retry_count = retry; }
1226
1227 protected:
1228 Vector<Stream *> streams{0};
1229 Vector<int> weights{0};
1230 int total_weights = 0;
1231 int frame_size = 4;
1232 bool limit_available_data = false;
1233 int retry_count = 5;
1234 Vector<int> result_vect;
1235 Vector<T> current_vect;
1236
1238 int readBytesVector(T *p_data, int byteCount) {
1239 int samples = byteCount / sizeof(T);
1240 result_vect.resize(samples);
1241 current_vect.resize(samples);
1242 int stream_count = size();
1243 resultClear();
1244 int samples_eff_max = 0;
1245 for (int j = 0; j < stream_count; j++) {
1246 if (weights[j] > 0) {
1247 int samples_eff =
1248 readSamples(streams[j], current_vect.data(), samples, retry_count);
1249 if (samples_eff > samples_eff_max) samples_eff_max = samples_eff;
1250 // if all weights are 0.0 we stop to output
1251 float factor = total_weights == 0.0f
1252 ? 0.0f
1253 : static_cast<float>(weights[j]) / total_weights;
1254 resultAdd(factor);
1255 }
1256 }
1257 // copy result
1258 for (int j = 0; j < samples; j++) {
1259 p_data[j] = result_vect[j];
1260 }
1261 return samples_eff_max * sizeof(T);
1262 }
1263
1266 int result = DEFAULT_BUFFER_SIZE;
1267 for (int j = 0; j < size(); j++) {
1268 result = min(result, streams[j]->available());
1269 }
1270 return result;
1271 }
1272
1273 void resultAdd(float fact) {
1274 for (int j = 0; j < current_vect.size(); j++) {
1275 current_vect[j] *= fact;
1276 result_vect[j] += current_vect[j];
1277 }
1278 }
1279
1280 void resultClear() {
1281 memset(result_vect.data(), 0, sizeof(int) * result_vect.size());
1282 }
1283};
1284
1294template <typename T>
1295class InputMerge : public AudioStream {
1296 public:
1298 InputMerge() = default;
1299
1303 InputMerge(Stream &left, Stream &right) {
1304 add(left, 1);
1305 add(right, 1);
1306 };
1307
1311 info.channels = total_channel_count;
1312 return info;
1313 }
1314
1315 virtual bool begin(AudioInfo info) {
1316 setAudioInfo(info);
1317 return begin();
1318 }
1319
1320 virtual bool begin() {
1321 // make sure that we use the correct channel count
1322 info.channels = channelCount();
1323 return AudioStream::begin();
1324 }
1325
1327 size_t readBytes(uint8_t *data, size_t len) override {
1328 LOGD("readBytes: %d", (int)len);
1329 T *p_data = (T *)data;
1330 int result_len = MIN(available(), len);
1331 int frames = result_len / (sizeof(T) * total_channel_count);
1332 int result_idx = 0;
1333 for (int j = 0; j < frames; j++) {
1334 for (int i = 0; i < records.size(); i++) {
1335 for (int ch = 0; ch < records[i].channels; ch++) {
1336 p_data[result_idx++] =
1337 records[i].weight * readSample<T>(records[i].stream);
1338 }
1339 }
1340 }
1341 return result_idx * sizeof(T);
1342 }
1343
1345 void add(Stream &in, int channelCount, float weight = 1.0) {
1346 MergeRecord rec(&in, channelCount, weight);
1347 records.push_back(rec);
1348 total_channel_count += channelCount;
1349 }
1350
1353 void setWeight(int channel, float weight) {
1354 if (channel < channelCount()) {
1355 records[channel].weight = weight;
1356 } else {
1357 LOGE("Invalid channel %d - max is %d", channel, channelCount() - 1);
1358 }
1359 }
1360
1362 void end() override { records.clear(); }
1363
1365 int channelCount() { return total_channel_count; }
1366
1368 int available() override {
1369 int result = records[0].stream->available();
1370 for (int j = 1; j < channelCount(); j++) {
1371 int tmp = records[j].stream->available();
1372 if (tmp < result) {
1373 result = tmp;
1374 }
1375 }
1376 return result;
1377 }
1378
1379 protected:
1381 Stream *stream = nullptr;
1382 int channels = 0;
1383 float weight = 1.0;
1384 MergeRecord() = default;
1385 MergeRecord(Stream *str, int ch, float w) {
1386 stream = str;
1387 channels = ch;
1388 weight = w;
1389 }
1390 };
1391 Vector<MergeRecord> records;
1392 int total_channel_count = 0;
1393};
1394
1405 public:
1406 CallbackStream() = default;
1407
1410 CallbackStream(Stream &io, size_t (*cb_update)(uint8_t *data, size_t len)) {
1411 p_stream = &io;
1412 p_out = &io;
1413 setUpdateCallback(cb_update);
1414 }
1415
1417 CallbackStream(Print &out, size_t (*cb_update)(uint8_t *data, size_t len)) {
1418 p_out = &out;
1419 setUpdateCallback(cb_update);
1420 }
1421
1422 CallbackStream(size_t (*cb_read)(uint8_t *data, size_t len),
1423 size_t (*cb_write)(const uint8_t *data, size_t len)) {
1424 setWriteCallback(cb_write);
1425 setReadCallback(cb_read);
1426 }
1427
1428 void setWriteCallback(size_t (*cb_write)(const uint8_t *data, size_t len)) {
1429 this->cb_write = cb_write;
1430 }
1431
1432 void setReadCallback(size_t (*cb_read)(uint8_t *data, size_t len)) {
1433 this->cb_read = cb_read;
1434 }
1435
1436 void setUpdateCallback(size_t (*cb_update)(uint8_t *data, size_t len)) {
1437 this->cb_update = cb_update;
1438 }
1439
1440 // callback result negative -> no change; callbeack result >=0 provides the
1441 // result
1442 void setAvailableCallback(int (*cb)()) { this->cb_available = cb; }
1443
1445 void setAudioInfoCallback(void (*cb)(AudioInfo info)) {
1446 this->cb_audio_info = cb;
1447 }
1448
1450 void setAudioInfo(AudioInfo info) override {
1452 if (cb_audio_info != nullptr) {
1453 cb_audio_info(info);
1454 }
1455 }
1456
1457 virtual bool begin(AudioInfo info) {
1458 setAudioInfo(info);
1459 return begin();
1460 }
1461 virtual bool begin() override {
1462 active = true;
1463 return true;
1464 }
1465
1466 void end() override { active = false; }
1467
1468 int available() override {
1469 int result = AudioStream::available();
1470 // determine value from opional variable
1471 if (available_bytes >= 0) return available_bytes;
1472 // check if there is a callback
1473 if (cb_available == nullptr) return result;
1474 // determine value from callback
1475 int tmp_available = cb_available();
1476 if (tmp_available < 0) return result;
1477
1478 return tmp_available;
1479 }
1480
1481 size_t readBytes(uint8_t *data, size_t len) override {
1482 if (!active) return 0;
1483 // provide data from callback
1484 if (cb_read) {
1485 return cb_read(data, len);
1486 }
1487 // provide data from source
1488 size_t result = 0;
1489 if (p_stream) {
1490 result = p_stream->readBytes(data, len);
1491 }
1492 if (cb_update) {
1493 result = cb_update(data, result);
1494 }
1495 return result;
1496 }
1497
1498 size_t write(const uint8_t *data, size_t len) override {
1499 if (!active) return 0;
1500 // write to callback
1501 if (cb_write) {
1502 return cb_write(data, len);
1503 }
1504 // write to output
1505 if (p_out) {
1506 size_t result = len;
1507 if (cb_update) {
1508 result = cb_update((uint8_t *)data, len);
1509 }
1510 return p_out->write(data, result);
1511 }
1512 // no processing possible
1513 return 0;
1514 }
1515
1517 void setStream(Stream &in) {
1518 p_stream = &in;
1519 p_out = &in;
1520 }
1521
1523 void setOutput(Print &out) { p_out = &out; }
1524
1526 void setOutput(Stream &in) {
1527 p_stream = &in;
1528 p_out = &in;
1529 }
1530
1532 void setStream(Print &out) { p_out = &out; }
1533
1535 void setAvailable(int val) { available_bytes = val; }
1536
1537 protected:
1538 bool active = true;
1539 size_t (*cb_write)(const uint8_t *data, size_t len) = nullptr;
1540 size_t (*cb_read)(uint8_t *data, size_t len) = nullptr;
1541 size_t (*cb_update)(uint8_t *data, size_t len) = nullptr;
1542 void (*cb_audio_info)(AudioInfo info) = nullptr;
1543 int (*cb_available)() = nullptr;
1544 Stream *p_stream = nullptr;
1545 Print *p_out = nullptr;
1546 int available_bytes = -1;
1547};
1548
1556template <typename T, class TF>
1558 public:
1559 FilteredStream() = default;
1560 FilteredStream(Stream &stream) : ModifyingStream() { setStream(stream); }
1561 FilteredStream(Stream &stream, int channels) : ModifyingStream() {
1562 this->channels = channels;
1563 setStream(stream);
1564 p_converter = new ConverterNChannels<T, TF>(channels);
1565 }
1566 FilteredStream(Print &stream) : ModifyingStream() { setOutput(stream); }
1567 FilteredStream(Print &stream, int channels) : ModifyingStream() {
1568 this->channels = channels;
1569 setOutput(stream);
1570 p_converter = new ConverterNChannels<T, TF>(channels);
1571 }
1572
1573 virtual ~FilteredStream() { end(); }
1574
1575 void setStream(Stream &stream) {
1576 p_stream = &stream;
1577 p_print = &stream;
1578 }
1579
1580 void setOutput(Print &stream) { p_print = &stream; }
1581
1582 bool begin(AudioInfo info) {
1583 setAudioInfo(info);
1584 this->channels = info.channels;
1585 if (p_converter != nullptr && p_converter->getChannels() != channels) {
1586 LOGE("Inconsistent number of channels");
1587 return false;
1588 }
1589 return begin();
1590 }
1591
1592 bool begin() override {
1593 if (channels == 0) {
1594 LOGE("channels must not be 0");
1595 return false;
1596 }
1597 if (p_converter == nullptr) {
1598 p_converter = new ConverterNChannels<T, TF>(channels);
1599 }
1600 return AudioStream::begin();
1601 }
1602
1603 void end() override {
1604 ModifyingStream::end();
1605 if (p_converter != nullptr) {
1606 delete p_converter;
1607 p_converter = nullptr;
1608 }
1609 }
1610
1611 virtual size_t write(const uint8_t *data, size_t len) override {
1612 if (p_converter == nullptr) return 0;
1613 size_t result = p_converter->convert((uint8_t *)data, len);
1614 return p_print->write(data, result);
1615 }
1616
1617 size_t readBytes(uint8_t *data, size_t len) override {
1618 if (p_converter == nullptr) return 0;
1619 if (p_stream == nullptr) return 0;
1620 size_t result = p_stream->readBytes(data, len);
1621 result = p_converter->convert(data, result);
1622 return result;
1623 }
1624
1625 virtual int available() override {
1626 if (p_stream == nullptr) return 0;
1627 return p_stream->available();
1628 }
1629
1630 virtual int availableForWrite() override {
1631 return p_print->availableForWrite();
1632 }
1633
1637 void setFilter(int channel, Filter<TF> *filter) {
1638 if (p_converter != nullptr) {
1639 p_converter->setFilter(channel, filter);
1640 } else {
1641 LOGE("p_converter is null");
1642 }
1643 }
1644
1648 void setFilter(int channel, Filter<TF> &filter) {
1649 setFilter(channel, &filter);
1650 }
1651
1652 protected:
1653 int channels = 0;
1654 Stream *p_stream = nullptr;
1655 Print *p_print = nullptr;
1656 ConverterNChannels<T, TF> *p_converter = nullptr;
1657};
1658
1668 public:
1669 VolumeMeter() = default;
1672 setStream(as);
1673 }
1676 setOutput(ao);
1677 }
1678 VolumeMeter(Print &print) { setOutput(print); }
1679 VolumeMeter(Stream &stream) { setStream(stream); }
1680
1681 bool begin(AudioInfo info) {
1682 setAudioInfo(info);
1683 return begin();
1684 }
1685
1686 bool begin() override { return true; }
1687
1690 if (info.channels > 0) {
1691 volumes.resize(info.channels);
1692 volumes_tmp.resize(info.channels);
1693 }
1694 }
1695
1696 size_t write(const uint8_t *data, size_t len) {
1697 updateVolumes(data, len);
1698 size_t result = len;
1699 if (p_out != nullptr) {
1700 result = p_out->write(data, len);
1701 }
1702 return result;
1703 }
1704
1705 size_t readBytes(uint8_t *data, size_t len) {
1706 if (p_stream == nullptr) return 0;
1707 size_t result = p_stream->readBytes(data, len);
1708 updateVolumes((const uint8_t *)data, len);
1709 return result;
1710 }
1711
1714 float volume() { return f_volume; }
1715
1718 float volume(int channel) {
1719 if (volumes.size() == 0) {
1720 LOGE("begin not called!");
1721 return 0.0f;
1722 }
1723 if (channel >= volumes.size()) {
1724 LOGE("invalid channel %d", channel);
1725 return 0.0f;
1726 }
1727 return volumes[channel];
1728 }
1729
1731 float volumeRatio() {
1733 }
1734
1736 float volumeRatio(int channel) {
1737 return volume(channel) / NumberConverter::maxValue(info.bits_per_sample);
1738 }
1739
1741 float volumeDB() {
1742 // prevent infinite value
1743 if (volumeRatio() == 0) return -1000;
1744 return 20.0f * log10(volumeRatio());
1745 }
1746
1748 float volumeDB(int channel) {
1749 // prevent infinite value
1750 if (volumeRatio(channel) == 0) return -1000;
1751 return 20.0f * log10(volumeRatio(channel));
1752 }
1753
1755 float volumePercent() { return 100.0f * volumeRatio(); }
1756
1758 float volumePercent(int channel) { return 100.0f * volumeRatio(channel); }
1759
1761 float volumeAvg() {
1762 float total = 0;
1763 size_t count = 0;
1764 for (int j = 0; j < info.channels; j++) {
1765 total += sum[j];
1766 count += sample_count_per_channel;
1767 }
1768 return total / count;
1769 }
1770
1772 float volumeAvg(int channel) {
1773 return sum[channel] / sample_count_per_channel;
1774 }
1775
1777 void clear() {
1778 f_volume_tmp = 0;
1779 for (int j = 0; j < info.channels; j++) {
1780 volumes_tmp[j] = 0;
1781 sum_tmp[j] = 0;
1782 }
1783 }
1784
1785 void setOutput(Print &out) override { p_out = &out; }
1786 void setStream(Stream &io) override {
1787 p_out = &io;
1788 p_stream = &io;
1789 }
1790
1791 protected:
1792 float f_volume_tmp = 0;
1793 float f_volume = 0;
1794 Vector<float> volumes{0};
1795 Vector<float> volumes_tmp{0};
1796 Vector<float> sum{0};
1797 Vector<float> sum_tmp{0};
1798 Print *p_out = nullptr;
1799 Stream *p_stream = nullptr;
1800 size_t sample_count_per_channel = 0;
1801
1802 void updateVolumes(const uint8_t *data, size_t len) {
1803 clear();
1804 switch (info.bits_per_sample) {
1805 case 8:
1806 updateVolumesT<int8_t>(data, len);
1807 break;
1808 case 16:
1809 updateVolumesT<int16_t>(data, len);
1810 break;
1811 case 24:
1812 updateVolumesT<int24_t>(data, len);
1813 break;
1814 case 32:
1815 updateVolumesT<int32_t>(data, len);
1816 break;
1817 default:
1818 LOGE("Unsupported bits_per_sample: %d", info.bits_per_sample);
1819 break;
1820 }
1821 }
1822
1823 template <typename T>
1824 void updateVolumesT(const uint8_t *buffer, size_t size) {
1825 T *bufferT = (T *)buffer;
1826 int samplesCount = size / sizeof(T);
1827 sample_count_per_channel = samplesCount / info.channels;
1828 for (int j = 0; j < samplesCount; j++) {
1829 float tmp = abs(static_cast<float>(bufferT[j]));
1830 updateVolume(tmp, j);
1831 }
1832 commit();
1833 }
1834
1835 void updateVolume(float tmp, int j) {
1836 if (tmp > f_volume_tmp) {
1837 f_volume_tmp = tmp;
1838 }
1839 if (volumes_tmp.size() > 0 && info.channels > 0) {
1840 int ch = j % info.channels;
1841 if (tmp > volumes_tmp[ch]) {
1842 volumes_tmp[ch] = tmp;
1843 sum_tmp[ch] = tmp;
1844 }
1845 }
1846 }
1847
1848 void commit() {
1849 f_volume = f_volume_tmp;
1850 for (int j = 0; j < info.channels; j++) {
1851 volumes[j] = volumes_tmp[j];
1852 sum[j] = sum_tmp[j];
1853 }
1854 }
1855};
1856
1857// legacy names
1858using VolumePrint = VolumeMeter;
1859using VolumeOutput = VolumeMeter;
1860
1861#ifdef USE_TIMER
1868 RxTxMode rx_tx_mode = RX_MODE;
1869 uint16_t buffer_size = DEFAULT_BUFFER_SIZE;
1870 bool use_timer = true;
1871 int timer_id = -1;
1872 TimerFunction timer_function = DirectTimerCallback;
1873 bool adapt_sample_rate = false;
1874 uint16_t (*callback)(uint8_t *data, uint16_t len) = nullptr;
1875};
1876
1877// forward declaration: relevant only if use_timer == true
1878static void timerCallback(void *obj);
1889 friend void timerCallback(void *obj);
1890
1891 public:
1892 TimerCallbackAudioStream() : BufferedStream(80) { TRACED(); }
1893
1895 TRACED();
1896 if (timer != nullptr) delete timer;
1897 if (buffer != nullptr) delete buffer;
1898 if (frame != nullptr) delete[] frame;
1899 }
1900
1906
1908 virtual void setAudioInfo(AudioInfo info) {
1909 TRACED();
1910 if (cfg.sample_rate != info.sample_rate || cfg.channels != info.channels ||
1911 cfg.bits_per_sample != info.bits_per_sample) {
1912 bool do_restart = active;
1913 if (do_restart) end();
1914 cfg.sample_rate = info.sample_rate;
1915 cfg.channels = info.channels;
1916 cfg.bits_per_sample = info.bits_per_sample;
1917 if (do_restart) begin(cfg);
1918 }
1919 }
1920
1923 AudioInfo audioInfo() { return cfg; }
1924
1925 void begin(TimerCallbackAudioStreamInfo config) {
1926 LOGD("%s: %s", LOG_METHOD,
1927 config.rx_tx_mode == RX_MODE ? "RX_MODE" : "TX_MODE");
1928 this->cfg = config;
1929 this->frameCallback = config.callback;
1930 if (cfg.use_timer) {
1931 frameSize = cfg.bits_per_sample * cfg.channels / 8;
1932 frame = new uint8_t[frameSize];
1933 buffer = new RingBuffer<uint8_t>(cfg.buffer_size);
1934 timer = new TimerAlarmRepeating();
1935 timer->setTimerFunction(cfg.timer_function);
1936 if (cfg.timer_id >= 0) {
1937 timer->setTimer(cfg.timer_id);
1938 }
1939 time = AudioTime::toTimeUs(cfg.sample_rate);
1940 LOGI("sample_rate: %u -> time: %u milliseconds",
1941 (unsigned int)cfg.sample_rate, (unsigned int)time);
1942 timer->setCallbackParameter(this);
1943 timer->begin(timerCallback, time, TimeUnit::US);
1944 }
1945
1946 notifyAudioChange(cfg);
1947 active = true;
1948 }
1949
1951 bool begin() {
1952 TRACED();
1953 if (this->frameCallback != nullptr) {
1954 if (cfg.use_timer) {
1955 timer->begin(timerCallback, time, TimeUnit::US);
1956 }
1957 active = true;
1958 }
1959 return active;
1960 }
1961
1963 void end() {
1964 TRACED();
1965 if (cfg.use_timer) {
1966 timer->end();
1967 }
1968 active = false;
1969 }
1970
1972 uint16_t currentSampleRate() { return currentRateValue; }
1973
1974 protected:
1976 bool active = false;
1977 uint16_t (*frameCallback)(uint8_t *data, uint16_t len);
1978 // below only relevant with timer
1979 TimerAlarmRepeating *timer = nullptr;
1980 RingBuffer<uint8_t> *buffer = nullptr;
1981 uint8_t *frame = nullptr;
1982 uint16_t frameSize = 0;
1983 uint32_t time = 0;
1984 unsigned long lastTimestamp = 0u;
1985 uint32_t currentRateValue = 0;
1986 uint32_t printCount = 0;
1987
1988 // used for audio sink
1989 virtual size_t writeExt(const uint8_t *data, size_t len) override {
1990 if (!active) return 0;
1991 TRACED();
1992 size_t result = 0;
1993 if (!cfg.use_timer) {
1994 result = frameCallback((uint8_t *)data, len);
1995 } else {
1996 result = buffer->writeArray((uint8_t *)data, len);
1997 }
1998 if (++printCount % 10000 == 0) printSampleRate();
1999 return result;
2000 }
2001
2002 // used for audio source
2003 virtual size_t readExt(uint8_t *data, size_t len) override {
2004 if (!active) return 0;
2005 TRACED();
2006
2007 size_t result = 0;
2008 if (!cfg.use_timer) {
2009 result = frameCallback(data, len);
2010 } else {
2011 result = buffer->readArray(data, len);
2012 }
2013 if (++printCount % 10000 == 0) printSampleRate();
2014 return result;
2015 }
2016
2018 virtual void measureSampleRate() {
2019 unsigned long ms = millis();
2020 if (lastTimestamp > 0u) {
2021 uint32_t diff = ms - lastTimestamp;
2022 if (diff > 0) {
2023 uint16_t rate = 1 * 1000 / diff;
2024
2025 if (currentRateValue == 0) {
2026 currentRateValue = rate;
2027 } else {
2028 currentRateValue = (currentRateValue + rate) / 2;
2029 }
2030 }
2031 }
2032 lastTimestamp = ms;
2033 }
2034
2036 virtual void printSampleRate() {
2037 LOGI("effective sample rate: %u", (unsigned int)currentRateValue);
2038 if (cfg.adapt_sample_rate &&
2039 abs((int)currentRateValue - (int)cfg.sample_rate) > 200) {
2040 cfg.sample_rate = currentRateValue;
2041 notifyAudioChange(cfg);
2042 }
2043 }
2044};
2045
2046// relevant only if use_timer == true
2047void IRAM_ATTR timerCallback(void *obj) {
2048 TimerCallbackAudioStream *src = (TimerCallbackAudioStream *)obj;
2049 if (src != nullptr) {
2050 // LOGD("%s: %s", LOG_METHOD, src->cfg.rx_tx_mode==RX_MODE ?
2051 // "RX_MODE":"TX_MODE");
2052 if (src->cfg.rx_tx_mode == RX_MODE) {
2053 // input
2054 uint16_t available_bytes = src->frameCallback(src->frame, src->frameSize);
2055 uint16_t buffer_available = src->buffer->availableForWrite();
2056 if (buffer_available < available_bytes) {
2057 // if buffer is full make space
2058 uint16_t to_clear = available_bytes - buffer_available;
2059 uint8_t tmp[to_clear];
2060 src->buffer->readArray(tmp, to_clear);
2061 }
2062 if (src->buffer->writeArray(src->frame, available_bytes) !=
2063 available_bytes) {
2064 assert(false);
2065 }
2066 } else {
2067 // output
2068 if (src->buffer != nullptr && src->frame != nullptr &&
2069 src->frameSize > 0) {
2070 uint16_t available_bytes =
2071 src->buffer->readArray(src->frame, src->frameSize);
2072 if (available_bytes !=
2073 src->frameCallback(src->frame, available_bytes)) {
2074 LOGE("data underflow");
2075 }
2076 }
2077 }
2078 src->measureSampleRate();
2079 }
2080}
2081
2082#endif
2083
2084} // namespace audio_tools
virtual void addNotifyAudioChange(AudioInfoSupport &bi)
Adds target to be notified about audio changes.
Definition AudioTypes.h:151
Supports changes to the sampling rate, bits and channels.
Definition AudioTypes.h:133
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:119
virtual void setAudioInfo(AudioInfo newInfo) override
Defines the input AudioInfo.
Definition BaseStream.h:127
virtual AudioInfo audioInfo() override
provides the actual input AudioInfo
Definition BaseStream.h:150
To be used to support implementations where the readBytes is not virtual.
Definition AudioStreams.h:23
static uint32_t toTimeUs(uint32_t samplingRate, uint8_t limit=10)
converts sampling rate to delay in microseconds (μs)
Definition AudioTypes.h:240
virtual int readArray(T data[], int len)
reads multiple values
Definition Buffers.h:37
virtual int writeArray(const T data[], int len)
Fills the buffer data.
Definition Buffers.h:59
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:483
void flush() override
empties the buffer
Definition AudioStreams.h:540
size_t write(uint8_t c) override
writes a byte to the buffer
Definition AudioStreams.h:522
size_t readBytes(uint8_t *data, size_t len) override
Use this method !!
Definition AudioStreams.h:569
int peek() override
peeks a byte - to be avoided
Definition AudioStreams.h:559
int available() override
Returns the available bytes in the buffer: to be avoided.
Definition AudioStreams.h:579
size_t write(const uint8_t *data, size_t len) override
Use this method: write an array.
Definition AudioStreams.h:530
void clear()
Clears all the data in the buffer.
Definition AudioStreams.h:587
int read() override
reads a byte - to be avoided
Definition AudioStreams.h:549
void setStream(Stream &io)
Defines/Changes the input & output.
Definition AudioStreams.h:516
void setOutput(Print &out)
Defines/Changes the output target.
Definition AudioStreams.h:514
CallbackStream: A Stream that allows to register callback methods for accessing and providing data....
Definition AudioStreams.h:1404
void setOutput(Stream &in)
same as setStream
Definition AudioStreams.h:1526
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:1417
void setStream(Print &out)
same as set Output
Definition AudioStreams.h:1532
void setAvailable(int val)
optioinally define available bytes for next read
Definition AudioStreams.h:1535
void setAudioInfo(AudioInfo info) override
Updates the audio info and calls the callback.
Definition AudioStreams.h:1450
void setOutput(Print &out)
Defines/Changes the output target.
Definition AudioStreams.h:1523
CallbackStream(Stream &io, size_t(*cb_update)(uint8_t *data, size_t len))
Definition AudioStreams.h:1410
void setAudioInfoCallback(void(*cb)(AudioInfo info))
defines the callback to receive the actual audio info
Definition AudioStreams.h:1445
void setStream(Stream &in)
Defines/Changes the input & output.
Definition AudioStreams.h:1517
Converter for n Channels which applies the indicated Filter.
Definition BaseConverter.h:1580
void setFilter(int channel, Filter< FT > *filter)
defines the filter for an individual channel - the first channel is 0
Definition BaseConverter.h:1604
Both the data of the read or write operations will be converted with the help of the indicated conver...
Definition AudioStreams.h:617
void setStream(Stream &stream)
Defines/Changes the input & output.
Definition AudioStreams.h:633
void setOutput(Print &out)
Defines/Changes the output target.
Definition AudioStreams.h:639
virtual int available() override
Returns the available bytes in the buffer: to be avoided.
Definition AudioStreams.h:664
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:1557
void setStream(Stream &stream)
Defines/Changes the input & output.
Definition AudioStreams.h:1575
void setFilter(int channel, Filter< TF > &filter)
Definition AudioStreams.h:1648
void setOutput(Print &stream)
Defines/Changes the output target.
Definition AudioStreams.h:1580
void setFilter(int channel, Filter< TF > *filter)
Definition AudioStreams.h:1637
Source for reading generated tones. Please note.
Definition AudioStreams.h:394
void setAudioInfo(AudioInfo newInfo) override
Defines the input AudioInfo.
Definition AudioStreams.h:409
size_t readBytes(uint8_t *data, size_t len) override
privide the data as byte stream
Definition AudioStreams.h:457
void end() override
stop the processing
Definition AudioStreams.h:443
bool begin() override
start the processing
Definition AudioStreams.h:417
AudioInfo audioInfo() override
provides the actual input AudioInfo
Definition AudioStreams.h:449
bool begin(AudioInfo cfg)
start the processing
Definition AudioStreams.h:430
virtual int available() override
This is unbounded so we just return the buffer size.
Definition AudioStreams.h:452
Merges multiple input streams. So if you provide 2 mono channels you get a stereo signal as result wi...
Definition AudioStreams.h:1295
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:1327
void end() override
Remove all input streams.
Definition AudioStreams.h:1362
int available() override
Provides the min available data from all streams.
Definition AudioStreams.h:1368
void add(Stream &in, int channelCount, float weight=1.0)
Adds a new input stream with 1 channel.
Definition AudioStreams.h:1345
void setWeight(int channel, float weight)
Definition AudioStreams.h:1353
int channelCount()
Number of channels to which are mixed together = number of result channels.
Definition AudioStreams.h:1365
InputMerge(Stream &left, Stream &right)
Constructor for stereo signal from to mono input stream.
Definition AudioStreams.h:1303
AudioInfo audioInfo() override
Provides the audio info with the total channel count.
Definition AudioStreams.h:1309
MixerStream is mixing the input from Multiple Input Streams. All streams must have the same audo form...
Definition AudioStreams.h:1141
void add(Stream &in, int weight=100)
Adds a new input stream.
Definition AudioStreams.h:1146
void set(int channel, Stream &in)
Replaces a stream at the indicated channel.
Definition AudioStreams.h:1153
size_t readBytes(uint8_t *data, size_t len) override
Provides the data from all streams mixed together.
Definition AudioStreams.h:1197
void end() override
Remove all input streams.
Definition AudioStreams.h:1185
int availableBytes()
Provides the available bytes from the first stream with data.
Definition AudioStreams.h:1265
void setLimitToAvailableData(bool flag)
Definition AudioStreams.h:1221
void setRetryCount(int retry)
Definition AudioStreams.h:1225
int readBytesVector(T *p_data, int byteCount)
mixing using a vector of samples
Definition AudioStreams.h:1238
int size()
Number of stremams to which are mixed together.
Definition AudioStreams.h:1194
void setWeight(int channel, int weight)
Definition AudioStreams.h:1171
Class which measures the thruput.
Definition AudioStreams.h:681
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:729
void setOutput(Print &out) override
Defines/Changes the output target.
Definition AudioStreams.h:718
uint32_t estimatedTotalTimeFor(uint32_t totalBytes)
Provides the estimated runtime in milliseconds for the indicated total.
Definition AudioStreams.h:782
uint32_t timeSinceBegin()
Provides the time in ms since the last call of begin()
Definition AudioStreams.h:776
size_t readBytes(uint8_t *data, size_t len) override
Provides the data from all streams mixed together.
Definition AudioStreams.h:721
int framesPerSecond()
Returns the actual thrughput in frames (samples) per second.
Definition AudioStreams.h:743
void setAudioInfo(AudioInfo info)
Defines the input AudioInfo.
Definition AudioStreams.h:751
uint32_t bytesSinceBegin()
Provides the total processed bytes since the last call of begin()
Definition AudioStreams.h:779
virtual int availableForWrite() override
Provides the nubmer of bytes we can write.
Definition AudioStreams.h:735
void setFrameSize(int size)
Trigger reporting in frames (=samples) per second.
Definition AudioStreams.h:768
void setReportBytes(bool flag)
Report in bytes instead of samples.
Definition AudioStreams.h:771
uint32_t estimatedOpenTimeFor(uint32_t totalBytes)
Provides the estimated time from now to the end in ms.
Definition AudioStreams.h:789
void setLogOutput(Print &out)
Defines the logging output.
Definition AudioStreams.h:709
bool setProcessedBytes(uint32_t pos)
Definition AudioStreams.h:796
uint32_t startTime()
Provides the time when the last measurement was started.
Definition AudioStreams.h:749
void setStream(Stream &io) override
Defines/Changes the input & output.
Definition AudioStreams.h:712
int bytesPerSecond()
Returns the actual thrughput in bytes per second.
Definition AudioStreams.h:740
A simple Stream implementation which is backed by allocated memory.
Definition AudioStreams.h:83
MemoryStream(const uint8_t *buffer, int buffer_size, bool isActive=true, MemoryType memoryType=FLASH_RAM)
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:231
virtual uint8_t * data()
Provides access to the data array.
Definition AudioStreams.h:288
virtual void setAvailable(size_t len)
update the write_pos (e.g. when we used data() to update the array)
Definition AudioStreams.h:291
void setValue(const uint8_t *buffer, int buffer_size, MemoryType memoryType=FLASH_RAM)
Update the values (buffer and size)
Definition AudioStreams.h:297
MemoryStream(MemoryStream &&source)
Move Constructor.
Definition AudioStreams.h:110
MemoryStream(MemoryStream &source)
Copy Constructor.
Definition AudioStreams.h:107
virtual void setLoop(bool loop)
Definition AudioStreams.h:250
virtual bool resize(size_t size)
Definition AudioStreams.h:268
MemoryStream(int buffer_size, MemoryType memoryType)
Constructor for alloction in RAM.
Definition AudioStreams.h:88
bool begin() override
resets the read pointer
Definition AudioStreams.h:137
MemoryStream & operator=(MemoryStream &other)
copy assignement operator
Definition AudioStreams.h:122
bool begin(AudioInfo info)
Define some audio info and start the processing.
Definition AudioStreams.h:131
void setRewindCallback(void(*cb)())
Callback which is executed when we rewind (in loop mode) to the beginning.
Definition AudioStreams.h:294
Abstract class: Objects can be put into a pipleline.
Definition AudioStreams.h:68
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:289
static int64_t maxValue(int value_bits_per_sample)
provides the biggest number for the indicated number of bits
Definition AudioTypes.h:299
Definition NoArduino.h:62
Generic calss to measure the the total bytes which were processed in order to calculate the progress ...
Definition AudioStreams.h:873
bool begin(size_t len)
Definition AudioStreams.h:911
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:961
size_t size()
Provides the current total size (defined by setSize)
Definition AudioStreams.h:929
size_t totalSecs()
Converts the totalBytes() to seconds.
Definition AudioStreams.h:941
size_t readBytes(uint8_t *data, size_t len) override
Provides the data from all streams mixed together.
Definition AudioStreams.h:950
size_t processedBytes()
Provides the number of processed bytes.
Definition AudioStreams.h:932
void setStream(Stream &stream)
Defines/Changes the input & output.
Definition AudioStreams.h:893
void setSize(size_t len)
Updates the total size and restarts the percent calculation.
Definition AudioStreams.h:923
virtual int availableForWrite() override
Provides the nubmer of bytes we can write.
Definition AudioStreams.h:967
float percentage()
Provides the processed percentage: If no size has been defined we return 0.
Definition AudioStreams.h:944
size_t processedSecs()
Provides the number of processed seconds.
Definition AudioStreams.h:935
void setAudioInfo(AudioInfo info) override
Defines the input AudioInfo.
Definition AudioStreams.h:888
size_t totalBytes()
Provides the total_size provided in the configuration.
Definition AudioStreams.h:938
Configuration for ProgressStream.
Definition AudioStreams.h:862
Implements a typed Ringbuffer.
Definition Buffers.h:308
An AudioStream backed by a Ringbuffer. We can write to the end and read from the beginning of the str...
Definition AudioStreams.h:338
A simple Buffer implementation which just uses a (dynamically sized) array.
Definition Buffers.h:175
size_t setAvailable(size_t available_size)
Definition Buffers.h:273
T * address() override
Provides address to beginning of the buffer.
Definition Buffers.h:258
Base class to define the abstract interface for the sound generating classes.
Definition SoundGenerator.h:28
Definition NoArduino.h:142
Throttle the sending or receiving of the audio data to limit it to the indicated sample rate.
Definition AudioStreams.h:1015
void setOutput(Print &out) override
Defines/Changes the output target.
Definition AudioStreams.h:1028
void setStream(Stream &io) override
Defines/Changes the input & output.
Definition AudioStreams.h:1022
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:1888
TimerCallbackAudioStreamInfo audioInfoExt()
Provides the current audio information.
Definition AudioStreams.h:1922
uint16_t currentSampleRate()
Provides the effective sample rate.
Definition AudioStreams.h:1972
TimerCallbackAudioStreamInfo defaultConfig()
Provides the default configuration.
Definition AudioStreams.h:1902
bool begin()
Restart the processing.
Definition AudioStreams.h:1951
AudioInfo audioInfo()
provides the actual input AudioInfo
Definition AudioStreams.h:1923
virtual void measureSampleRate()
calculates the effective sample rate
Definition AudioStreams.h:2018
virtual void setAudioInfo(AudioInfo info)
updates the audio information
Definition AudioStreams.h:1908
virtual void printSampleRate()
log and update effective sample rate
Definition AudioStreams.h:2036
void end()
Stops the processing.
Definition AudioStreams.h:1963
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:1667
void setOutput(Print &out) override
Defines/Changes the output target.
Definition AudioStreams.h:1785
float volumeRatio()
Volume Ratio: max amplitude is 1.0.
Definition AudioStreams.h:1731
float volumeAvg(int channel)
Average volume of indicated channel.
Definition AudioStreams.h:1772
float volume()
Definition AudioStreams.h:1714
float volumePercent()
Volume in %: max amplitude is 100.
Definition AudioStreams.h:1755
void setAudioInfo(AudioInfo info)
Defines the input AudioInfo.
Definition AudioStreams.h:1688
float volumePercent(int channel)
Volume of indicated channel in %: max amplitude is 100.
Definition AudioStreams.h:1758
float volumeAvg()
Average volume of all channels.
Definition AudioStreams.h:1761
void clear()
Resets the actual volume.
Definition AudioStreams.h:1777
float volumeRatio(int channel)
Volume Ratio of indicated channel: max amplitude is 1.0.
Definition AudioStreams.h:1736
float volumeDB(int channel)
Volume of indicated channel in db: max amplitude is 0.
Definition AudioStreams.h:1748
void setStream(Stream &io) override
Defines/Changes the input & output.
Definition AudioStreams.h:1786
float volumeDB()
Volume in db: max amplitude is 0 (range: -1000 to 0)
Definition AudioStreams.h:1741
float volume(int channel)
Definition AudioStreams.h:1718
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 AudioCodecsBase.h:10
size_t readSamples(Stream *p_stream, T *data, int samples, int retryCount=-1)
guaranteed to return the requested data
Definition AudioTypes.h:466
uint32_t millis()
Returns the milliseconds since the start.
Definition Time.h:12
Basic Audio information which drives e.g. I2S.
Definition AudioTypes.h:53
void copyFrom(AudioInfo info)
Same as set.
Definition AudioTypes.h:103
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
Definition AudioStreams.h:1380
Configure Throttle setting.
Definition AudioStreams.h:1000
TimerCallbackAudioStream Configuration.
Definition AudioStreams.h:1867