arduino-audio-tools
Loading...
Searching...
No Matches
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 = int16_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 { return active ? buffer_size : 0; }
453
455 size_t readBytes(uint8_t *data, size_t len) override {
456 if (!active) return 0;
457 LOGD("GeneratedSoundStream::readBytes: %u", (unsigned int)len);
458 return generator_ptr->readBytes(data, len);
459 }
460
461 bool isActive() { return active && generator_ptr->isActive(); }
462
463 operator bool() override { return isActive(); }
464
465 void flush() override {}
466
468 void resize(int maxReadSize) { buffer_size = maxReadSize; }
469
470 protected:
471 bool active = true; // support for legacy sketches
472 SoundGenerator<T> *generator_ptr;
473 int buffer_size =
474 DEFAULT_BUFFER_SIZE * 100; // there is no reason to limit this
475 const char *source_not_defined_error = "Source not defined";
476};
477
487 public:
488 BufferedStream(size_t buffer_size) {
489 TRACED();
490 if (buffer_size > 0) resize(buffer_size);
491 }
492
493 BufferedStream(Print &out, size_t buffer_size = 1024) {
494 TRACED();
495 setOutput(out);
496 if (buffer_size > 0) resize(buffer_size);
497 }
498
499 BufferedStream(Stream &io, size_t buffer_size = 1024) {
500 TRACED();
501 setStream(io);
502 if (buffer_size > 0) resize(buffer_size);
503 }
504
505 BufferedStream(size_t buffer_size, Print &out) {
506 TRACED();
507 setOutput(out);
508 if (buffer_size > 0) resize(buffer_size);
509 }
510
511 BufferedStream(size_t buffer_size, Stream &io) {
512 TRACED();
513 setStream(io);
514 if (buffer_size > 0) resize(buffer_size);
515 }
516
517 void setOutput(Print &out) override { p_out = &out; }
518 void setStream(Print &out) { setOutput(out); }
519 void setStream(Stream &io) override {
520 p_in = &io;
521 p_out = &io;
522 }
523
525 size_t write(uint8_t c) override {
526 if (buffer.isFull()) {
527 flush();
528 }
529 return buffer.write(c);
530 }
531
533 size_t write(const uint8_t *data, size_t len) override {
534 LOGD("%s: %zu", LOG_METHOD, len);
535 int result = 0;
536 for (int j = 0; j < len; j++) {
537 result += write(data[j]);
538 }
539 return result;
540 }
541
543 void flush() override {
544 // just dump the memory of the buffer and clear it
545 if (buffer.available() > 0) {
546 writeExt(buffer.address(), buffer.available());
547 buffer.reset();
548 }
549 }
550
552 int read() override {
553 if (buffer.isEmpty()) {
554 refill();
555 }
556 uint8_t result = 0;
557 if (!buffer.read(result)) return -1;
558 return result;
559 }
560
562 int peek() override {
563 if (buffer.isEmpty()) {
564 refill();
565 }
566 uint8_t result = 0;
567 if (!buffer.peek(result)) return -1;
568 return result;
569 };
570
572 size_t readBytes(uint8_t *data, size_t len) override {
573 if (buffer.isEmpty() && len >= minReadBufferSize) {
574 return readExt(data, len);
575 } else {
576 refill(len);
577 return buffer.readArray(data, len);
578 }
579 }
580
582 size_t peekBytes(uint8_t *data, size_t len) {
583 if (buffer.isEmpty()) {
584 refill();
585 }
586 return buffer.peekArray(data, len);
587 }
588
590 int available() override {
591 if (p_in == nullptr) return 0;
592 return buffer.available() + p_in->available();
593 }
594
596 void clear() { buffer.reset(); }
597
599 void resize(int size) { buffer.resize(size); }
600
603 void setMinUnbufferedReadSize(size_t size) { minReadBufferSize = size; }
604
605 protected:
606 SingleBuffer<uint8_t> buffer{0};
607 Print *p_out = nullptr;
608 Stream *p_in = nullptr;
609 size_t minReadBufferSize = 1024;
610
612 void refill() {
613 // Preserve any existing unread data then append new bytes
614 buffer.trim();
615 size_t already_available = buffer.available();
616 size_t free_space = buffer.availableForWrite();
617 if (free_space == 0) {
618 // Buffer full – nothing we can append
619 return;
620 }
621 // Read new data directly behind existing bytes
622 size_t added = readExt(buffer.address() + already_available, free_space);
623 buffer.setAvailable(already_available + added);
624 }
625
627 void refill(size_t len) {
628 if (buffer.available() >= len) return;
629 refill();
630 }
631
632 virtual size_t writeExt(const uint8_t *data, size_t len) {
633 return p_out == nullptr ? 0 : p_out->write(data, len);
634 }
635 virtual size_t readExt(uint8_t *data, size_t len) {
636 return p_in == nullptr ? 0 : p_in->readBytes(data, len);
637 }
638};
639
648template <typename T>
650 public:
651 ConverterStream() = default;
652
653 ConverterStream(BaseConverter &converter) { setConverter(converter); }
654
655 ConverterStream(Stream &stream, BaseConverter &converter) {
656 setConverter(converter);
657 setStream(stream);
658 }
659
660 ConverterStream(Print &out, BaseConverter &converter) {
661 setConverter(converter);
662 setOutput(out);
663 }
664
665 void setStream(Stream &stream) {
666 TRACEI();
667 p_stream = &stream;
668 p_out = &stream;
669 }
670
671 void setOutput(Print &out) {
672 TRACEI();
673 p_out = &out;
674 }
675
676 void setConverter(BaseConverter &cnv) { p_converter = &cnv; }
677
678 virtual int availableForWrite() { return p_out->availableForWrite(); }
679
680 virtual size_t write(const uint8_t *data, size_t len) {
681 size_t result = p_converter->convert((uint8_t *)data, len);
682 if (result > 0) {
683 size_t result_written = p_out->write(data, result);
684 return len * result_written / result;
685 }
686 return 0;
687 }
688
689 size_t readBytes(uint8_t *data, size_t len) override {
690 if (p_stream == nullptr) return 0;
691 size_t result = p_stream->readBytes(data, len);
692 return p_converter->convert(data, result);
693 }
694
696 virtual int available() override {
697 if (p_stream == nullptr) return 0;
698 return p_stream->available();
699 }
700
701 protected:
702 Stream *p_stream = nullptr;
703 Print *p_out = nullptr;
704 BaseConverter *p_converter;
705};
706
714 public:
715 MeasuringStream(int count = 10, Print *logOut = nullptr) {
716 this->count = count;
717 this->max_count = count;
718 p_stream = &null;
719 p_print = &null;
720 start_time = millis();
721 p_logout = logOut;
722 }
723
724 MeasuringStream(Print &print, int count = 10, Print *logOut = nullptr) {
725 this->count = count;
726 this->max_count = count;
727 setOutput(print);
728 start_time = millis();
729 p_logout = logOut;
730 }
731
732 MeasuringStream(Stream &stream, int count = 10, Print *logOut = nullptr) {
733 this->count = count;
734 this->max_count = count;
735 setStream(stream);
736 start_time = millis();
737 p_logout = logOut;
738 }
739
741 void setLogOutput(Print &out) { p_logout = &out; }
742
744 void setStream(Stream &io) override {
745 p_print = &io;
746 p_stream = &io;
747 };
748
750 void setOutput(Print &out) override { p_print = &out; }
751
753 size_t readBytes(uint8_t *data, size_t len) override {
754 total_bytes_since_begin += len;
755 return measure(p_stream->readBytes(data, len));
756 }
757
758 int available() override { return p_stream->available(); }
759
761 virtual size_t write(const uint8_t *data, size_t len) override {
762 total_bytes_since_begin += len;
763 return measure(p_print->write(data, len));
764 }
765
767 virtual int availableForWrite() override {
768 return p_print->availableForWrite();
769 }
770
772 int bytesPerSecond() { return bytes_per_second; }
773
776 if (frame_size == 0) return 0;
777 return bytes_per_second / frame_size;
778 }
779
781 uint32_t startTime() { return start_time; }
782
783 void setAudioInfo(AudioInfo info) override {
784 AudioStream::info = info;
785 setFrameSize(info.bits_per_sample / 8 * info.channels);
786 }
787
788 bool begin() override {
789 total_bytes_since_begin = 0;
790 ms_at_begin = millis();
791 return AudioStream::begin();
792 }
793
794 bool begin(AudioInfo info) {
795 setAudioInfo(info);
796 return begin();
797 }
798
800 void setFrameSize(int size) { frame_size = size; }
801
803 void setReportBytes(bool flag) { report_bytes = flag; }
804
805 void setName(const char *name) { this->name = name; }
806
808 uint32_t timeSinceBegin() { return millis() - ms_at_begin; }
809
811 uint32_t bytesSinceBegin() { return total_bytes_since_begin; }
812
814 uint32_t estimatedTotalTimeFor(uint32_t totalBytes) {
815 if (bytesSinceBegin() == 0) return 0;
816 return static_cast<float>(timeSinceBegin()) / bytesSinceBegin() *
817 totalBytes;
818 }
819
821 uint32_t estimatedOpenTimeFor(uint32_t totalBytes) {
822 if (bytesSinceBegin() == 0) return 0;
823 return estimatedTotalTimeFor(totalBytes) - timeSinceBegin();
824 }
825
828 bool setProcessedBytes(uint32_t pos) {
829 bool is_regular_update = true;
830 if (pos < total_bytes_since_begin) {
831 begin();
832 is_regular_update = false;
833 }
834 total_bytes_since_begin = pos;
835 return is_regular_update;
836 }
837
838 protected:
839 int max_count = 0;
840 int count = 0;
841 Stream *p_stream = nullptr;
842 Print *p_print = nullptr;
843 uint32_t start_time;
844 int total_bytes = 0;
845 int bytes_per_second = 0;
846 int frame_size = 0;
847 NullStream null;
848 Print *p_logout = nullptr;
849 bool report_bytes = false;
850 const char *name = "";
851 uint32_t ms_at_begin = 0;
852 uint32_t total_bytes_since_begin = 0;
853
854 size_t measure(size_t len) {
855 count--;
856 total_bytes += len;
857
858 if (count <= 0) {
859 uint32_t end_time = millis();
860 int time_diff = end_time - start_time; // in ms
861 if (time_diff > 0) {
862 bytes_per_second = total_bytes / time_diff * 1000;
863 printResult();
864 count = max_count;
865 total_bytes = 0;
866 start_time = end_time;
867 }
868 }
869 return len;
870 }
871
872 void printResult() {
873 char msg[70];
874 if (report_bytes || frame_size == 0) {
875 snprintf(msg, 70, "%s ==> Bytes per second: %d", name, bytes_per_second);
876 } else {
877 snprintf(msg, 70, "%s ==> Samples per second: %d", name,
878 bytes_per_second / frame_size);
879 }
880 if (p_logout != nullptr) {
881 p_logout->println(msg);
882 } else {
883 LOGI("%s", msg);
884 }
885 }
886};
887
895 public:
896 size_t total_size = 0;
897};
906 public:
907 ProgressStream() = default;
908
909 ProgressStream(Print &print) { setPrint(print); }
910
911 ProgressStream(Stream &stream) { setStream(stream); }
912
913 ProgressStream(AudioStream &stream) {
914 setStream(stream);
915 p_info_from = &stream;
916 }
917
918 ProgressStreamInfo &defaultConfig() { return progress_info; }
919
920 void setAudioInfo(AudioInfo info) override {
922 progress_info.copyFrom(info);
923 }
924
925 void setStream(Stream &stream) override {
926 p_stream = &stream;
927 p_print = &stream;
928 }
929
930 void setStream(Print &print) { p_print = &print; }
931
932 void setPrint(Print &print) { p_print = &print; }
933
934 bool begin() override {
935 if (p_info_from != nullptr) {
936 setAudioInfo(p_info_from->audioInfo());
937 }
938 return AudioStream::begin();
939 }
940
943 bool begin(size_t len) {
944 setSize(len);
945 return begin();
946 }
947
948 bool begin(ProgressStreamInfo info) {
949 progress_info = info;
950 setAudioInfo(info);
951 return begin();
952 }
953
955 void setSize(size_t len) {
956 total_processed = 0;
957 progress_info.total_size = len;
958 }
959
961 size_t size() { return progress_info.total_size; }
962
964 size_t processedBytes() { return total_processed; }
965
967 size_t processedSecs() { return total_processed / byteRate(); }
968
970 size_t totalBytes() { return progress_info.total_size; }
971
973 size_t totalSecs() { return totalBytes() / byteRate(); }
974
976 float percentage() {
977 if (progress_info.total_size == 0) return 0;
978 return 100.0 * total_processed / progress_info.total_size;
979 }
980
982 size_t readBytes(uint8_t *data, size_t len) override {
983 if (p_stream == nullptr) return 0;
984 return measure(p_stream->readBytes(data, len));
985 }
986
987 int available() override {
988 if (p_stream == nullptr) return 0;
989 return p_stream->available();
990 }
991
993 virtual size_t write(const uint8_t *data, size_t len) override {
994 if (p_print == nullptr) return 0;
995 return measure(p_print->write(data, len));
996 }
997
999 virtual int availableForWrite() override {
1000 if (p_print == nullptr) return 0;
1001 return p_print->availableForWrite();
1002 }
1003
1004 protected:
1005 ProgressStreamInfo progress_info;
1006 Stream *p_stream = nullptr;
1007 Print *p_print = nullptr;
1008 AudioInfoSupport *p_info_from = nullptr;
1009 size_t total_processed = 0;
1010
1011 size_t measure(size_t len) {
1012 total_processed += len;
1013 return len;
1014 }
1015
1016 size_t byteRate() {
1017 AudioInfo info = audioInfo();
1018 int byte_rate = info.sample_rate * info.bits_per_sample * info.channels / 8;
1019 if (byte_rate == 0) {
1020 LOGE("Audio Info not defined");
1021 return 0;
1022 }
1023 return byte_rate;
1024 }
1025};
1026
1032struct ThrottleConfig : public AudioInfo {
1033 ThrottleConfig() {
1034 sample_rate = 44100;
1035 bits_per_sample = 16;
1036 channels = 2;
1037 }
1038 int correction_us = 0;
1039};
1040
1048 public:
1049 Throttle() = default;
1050 Throttle(Print &out) { setOutput(out); }
1051 Throttle(Stream &io) { setStream(io); }
1052
1054 void setStream(Stream &io) override {
1055 p_out = &io;
1056 p_in = &io;
1057 };
1058
1060 void setOutput(Print &out) override { p_out = &out; }
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,
1069 (int)info.channels, (int)info.bits_per_sample);
1070 this->info = cfg;
1071 this->cfg = cfg;
1072 return begin();
1073 }
1074
1075 bool begin(AudioInfo info) {
1076 LOGI("begin sample_rate: %d, channels: %d, bits: %d", (int)info.sample_rate,
1077 (int)info.channels, (int)info.bits_per_sample);
1078 this->info = info;
1079 this->cfg.copyFrom(info);
1080 return begin();
1081 }
1082
1083 bool begin() override {
1084 frame_size = cfg.bits_per_sample / 8 * cfg.channels;
1085 startDelay();
1086 return true;
1087 }
1088
1089 // (re)starts the timing
1090 void startDelay() {
1091 start_time = micros();
1092 sum_frames = 0;
1093 }
1094
1095 int availableForWrite() override {
1096 if (p_out) {
1097 return p_out->availableForWrite();
1098 }
1099 return DEFAULT_BUFFER_SIZE;
1100 }
1101
1102 size_t write(const uint8_t *data, size_t len) override {
1103 size_t result = p_out->write(data, len);
1104 delayBytes(len);
1105 return result;
1106 }
1107
1108 int available() override {
1109 if (p_in == nullptr) return 0;
1110 return p_in->available();
1111 }
1112
1113 size_t readBytes(uint8_t *data, size_t len) override {
1114 if (p_in == nullptr) {
1115 delayBytes(len);
1116 return 0;
1117 }
1118 size_t result = p_in->readBytes(data, len);
1119 delayBytes(len);
1120 return result;
1121 }
1122
1123 // delay
1124 void delayBytes(size_t bytes) { delayFrames(bytes / frame_size); }
1125
1126 // delay
1127 void delayFrames(size_t frames) {
1128 sum_frames += frames;
1129 uint64_t durationUsEff = micros() - start_time;
1130 uint64_t durationUsToBe = getDelayUs(sum_frames);
1131 int64_t waitUs = durationUsToBe - durationUsEff + cfg.correction_us;
1132 LOGD("wait us: %ld", static_cast<long>(waitUs));
1133 if (waitUs > 0) {
1134 int64_t waitMs = waitUs / 1000;
1135 if (waitMs > 0) delay(waitMs);
1136 delayMicroseconds(waitUs - (waitMs * 1000));
1137 } else {
1138 LOGD("negative delay!")
1139 }
1140 }
1141
1142 inline int64_t getDelayUs(uint64_t frames) {
1143 return (frames * 1000000) / cfg.sample_rate;
1144 }
1145
1146 inline int64_t getDelayMs(uint64_t frames) {
1147 return getDelayUs(frames) / 1000;
1148 }
1149
1150 inline int64_t getDelaySec(uint64_t frames) {
1151 return getDelayUs(frames) / 1000000l;
1152 }
1153
1154 protected:
1155 uint32_t start_time = 0;
1156 uint32_t sum_frames = 0;
1157 ThrottleConfig cfg;
1158 int frame_size = 0;
1159 Print *p_out = nullptr;
1160 Stream *p_in = nullptr;
1161};
1162
1172template <typename T>
1173class InputMixer : public AudioStream {
1174 public:
1175 InputMixer() = default;
1176
1178 int add(Stream &in, int weight = 100) {
1179 streams.push_back(&in);
1180 weights.push_back(weight);
1181 total_weights += weight;
1182 return streams.indexOf(&in);
1183 }
1184
1186 bool set(int index, Stream &in) {
1187 if (index < size()) {
1188 streams[index] = &in;
1189 return true;
1190 } else {
1191 LOGE("Invalid index %d - max is %d", index, size() - 1);
1192 return false;
1193 }
1194 }
1195
1196 virtual bool begin(AudioInfo info) {
1197 setAudioInfo(info);
1198 frame_size = info.bits_per_sample / 8 * info.channels;
1199 LOGI("frame_size: %d", frame_size);
1200 return frame_size > 0;
1201 }
1202
1206 void setWeight(int index, int weight) {
1207 if (index < streams.size()) {
1208 weights[index] = weight;
1210 } else {
1211 LOGE("Invalid index %d - max is %d", index, size() - 1);
1212 }
1213 }
1214
1216 void end() override {
1217 streams.clear();
1218 weights.clear();
1219 result_vect.clear();
1220 current_vect.clear();
1221 total_weights = 0.0;
1222 }
1223
1225 int size() { return streams.size(); }
1226
1228 size_t readBytes(uint8_t *data, size_t len) override {
1229 if (total_weights == 0 || frame_size == 0 || len == 0) {
1230 LOGW("readBytes: %d", (int)len);
1231 return 0;
1232 }
1233
1234 if (limit_available_data) {
1235 len = min((int)len, availableBytes());
1236 }
1237
1238 int result_len = 0;
1239
1240 if (len > 0) {
1241 // result_len must be full frames
1242 result_len = len * frame_size / frame_size;
1243 // replace sample based with vector based implementation
1244 // readBytesSamples((T*)data, result_len));
1245 result_len = readBytesVector((T *)data, result_len);
1246 }
1247 return result_len;
1248 }
1249
1252 void setLimitToAvailableData(bool flag) { limit_available_data = flag; }
1253
1256 void setRetryCount(int retry) { retry_count = retry; }
1257
1259 bool remove(int idx) {
1260 if (idx < 0 || idx >= size()) {
1261 return false;
1262 }
1263 streams.erase(idx);
1264 weights.erase(idx);
1266 return true;
1267 }
1268
1270 bool remove() {
1271 bool rc = false;
1272 int idx = nextEmptyIndex();
1273 while (idx >= 0) {
1274 rc = true;
1275 streams.erase(idx);
1276 weights.erase(idx);
1277 idx = nextEmptyIndex();
1278 }
1280 return rc;
1281 }
1282
1284 int indexOf(Stream &stream) { return streams.indexOf(&stream); }
1285
1287 Stream *operator[](int idx) {
1288 if (idx < 0 || idx >= size()) return nullptr;
1289 return streams[idx];
1290 }
1291
1294 for (int i = 0; i < streams.size(); i++) {
1295 if (streams[i]->available() == 0) {
1296 return i;
1297 }
1298 }
1299 return -1;
1300 }
1301
1302 protected:
1303 Vector<Stream *> streams{0};
1304 Vector<int> weights{0};
1305 int total_weights = 0;
1306 int frame_size = 4;
1307 bool limit_available_data = false;
1308 int retry_count = 5;
1309 Vector<int> result_vect;
1310 Vector<T> current_vect;
1311
1314 int total = 0;
1315 for (int j = 0; j < weights.size(); j++) {
1316 total += weights[j];
1317 }
1318 total_weights = total;
1319 }
1320
1322 int readBytesVector(T *p_data, int byteCount) {
1323 int samples = byteCount / sizeof(T);
1324 result_vect.resize(samples);
1325 current_vect.resize(samples);
1326 int stream_count = size();
1327 resultClear();
1328 int samples_eff_max = 0;
1329 for (int j = 0; j < stream_count; j++) {
1330 if (weights[j] > 0) {
1331 int samples_eff =
1332 readSamples(streams[j], current_vect.data(), samples, retry_count);
1333 if (samples_eff > samples_eff_max) samples_eff_max = samples_eff;
1334 // if all weights are 0.0 we stop to output
1335 float factor = total_weights == 0.0f
1336 ? 0.0f
1337 : static_cast<float>(weights[j]) / total_weights;
1338 resultAdd(factor);
1339 }
1340 }
1341 // copy result
1342 for (int j = 0; j < samples; j++) {
1343 p_data[j] = result_vect[j];
1344 }
1345 return samples_eff_max * sizeof(T);
1346 }
1347
1350 int result = DEFAULT_BUFFER_SIZE;
1351 for (int j = 0; j < size(); j++) {
1352 result = min(result, streams[j]->available());
1353 }
1354 return result;
1355 }
1356
1357 void resultAdd(float fact) {
1358 for (int j = 0; j < current_vect.size(); j++) {
1359 current_vect[j] *= fact;
1360 result_vect[j] += current_vect[j];
1361 }
1362 }
1363
1364 void resultClear() {
1365 memset(result_vect.data(), 0, sizeof(int) * result_vect.size());
1366 }
1367};
1368
1378template <typename T>
1379class InputMerge : public AudioStream {
1380 public:
1382 InputMerge() = default;
1383
1387 InputMerge(Stream &left, Stream &right) {
1388 add(left, 1);
1389 add(right, 1);
1390 };
1391
1395 info.channels = total_channel_count;
1396 return info;
1397 }
1398
1399 virtual bool begin(AudioInfo info) {
1400 setAudioInfo(info);
1401 return begin();
1402 }
1403
1404 virtual bool begin() override {
1405 // make sure that we use the correct channel count
1406 info.channels = channelCount();
1407 return AudioStream::begin();
1408 }
1409
1411 size_t readBytes(uint8_t *data, size_t len) override {
1412 LOGD("readBytes: %d", (int)len);
1413 T *p_data = (T *)data;
1414 int result_len = MIN(available(), len);
1415 int frames = result_len / (sizeof(T) * total_channel_count);
1416 int result_idx = 0;
1417 for (int j = 0; j < frames; j++) {
1418 for (int i = 0; i < records.size(); i++) {
1419 for (int ch = 0; ch < records[i].channels; ch++) {
1420 p_data[result_idx++] =
1421 records[i].weight * readSample<T>(records[i].stream);
1422 }
1423 }
1424 }
1425 return result_idx * sizeof(T);
1426 }
1427
1429 void add(Stream &in, int channelCount, float weight = 1.0) {
1430 MergeRecord rec(&in, channelCount, weight);
1431 records.push_back(rec);
1432 total_channel_count += channelCount;
1433 }
1434
1437 void setWeight(int channel, float weight) {
1438 if (channel < channelCount()) {
1439 records[channel].weight = weight;
1440 } else {
1441 LOGE("Invalid channel %d - max is %d", channel, channelCount() - 1);
1442 }
1443 }
1444
1446 void end() override { records.clear(); }
1447
1449 int channelCount() { return total_channel_count; }
1450
1452 int available() override {
1453 int result = records[0].stream->available();
1454 for (int j = 1; j < channelCount(); j++) {
1455 int tmp = records[j].stream->available();
1456 if (tmp < result) {
1457 result = tmp;
1458 }
1459 }
1460 return result;
1461 }
1462
1463 protected:
1465 Stream *stream = nullptr;
1466 int channels = 0;
1467 float weight = 1.0;
1468 MergeRecord() = default;
1469 MergeRecord(Stream *str, int ch, float w) {
1470 stream = str;
1471 channels = ch;
1472 weight = w;
1473 }
1474 };
1475 Vector<MergeRecord> records;
1476 int total_channel_count = 0;
1477};
1478
1489 public:
1490 CallbackStream() = default;
1491
1494 CallbackStream(Stream &io, size_t (*cb_update)(uint8_t *data, size_t len)) {
1495 p_stream = &io;
1496 p_out = &io;
1497 setUpdateCallback(cb_update);
1498 }
1499
1501 CallbackStream(Print &out, size_t (*cb_update)(uint8_t *data, size_t len)) {
1502 p_out = &out;
1503 setUpdateCallback(cb_update);
1504 }
1505
1506 CallbackStream(size_t (*cb_read)(uint8_t *data, size_t len),
1507 size_t (*cb_write)(const uint8_t *data, size_t len)) {
1508 setWriteCallback(cb_write);
1509 setReadCallback(cb_read);
1510 }
1511
1512 void setWriteCallback(size_t (*cb_write)(const uint8_t *data, size_t len)) {
1513 this->cb_write = cb_write;
1514 }
1515
1516 void setReadCallback(size_t (*cb_read)(uint8_t *data, size_t len)) {
1517 this->cb_read = cb_read;
1518 }
1519
1520 void setUpdateCallback(size_t (*cb_update)(uint8_t *data, size_t len)) {
1521 this->cb_update = cb_update;
1522 }
1523
1524 // callback result negative -> no change; callbeack result >=0 provides the
1525 // result
1526 void setAvailableCallback(int (*cb)()) { this->cb_available = cb; }
1527
1529 void setAudioInfoCallback(void (*cb)(AudioInfo info)) {
1530 this->cb_audio_info = cb;
1531 }
1532
1534 void setAudioInfo(AudioInfo info) override {
1536 if (cb_audio_info != nullptr) {
1537 cb_audio_info(info);
1538 }
1539 }
1540
1541 virtual bool begin(AudioInfo info) {
1542 setAudioInfo(info);
1543 return begin();
1544 }
1545 virtual bool begin() override {
1546 active = true;
1547 return true;
1548 }
1549
1550 void end() override { active = false; }
1551
1552 int available() override {
1553 int result = AudioStream::available();
1554 // determine value from opional variable
1555 if (available_bytes >= 0) return available_bytes;
1556 // check if there is a callback
1557 if (cb_available == nullptr) return result;
1558 // determine value from callback
1559 int tmp_available = cb_available();
1560 if (tmp_available < 0) return result;
1561
1562 return tmp_available;
1563 }
1564
1565 size_t readBytes(uint8_t *data, size_t len) override {
1566 if (!active) return 0;
1567 // provide data from callback
1568 if (cb_read) {
1569 return cb_read(data, len);
1570 }
1571 // provide data from source
1572 size_t result = 0;
1573 if (p_stream) {
1574 result = p_stream->readBytes(data, len);
1575 }
1576 if (cb_update) {
1577 result = cb_update(data, result);
1578 }
1579 return result;
1580 }
1581
1582 size_t write(const uint8_t *data, size_t len) override {
1583 if (!active) return 0;
1584 // write to callback
1585 if (cb_write) {
1586 return cb_write(data, len);
1587 }
1588 // write to output
1589 if (p_out) {
1590 size_t result = len;
1591 if (cb_update) {
1592 result = cb_update((uint8_t *)data, len);
1593 }
1594 return p_out->write(data, result);
1595 }
1596 // no processing possible
1597 return 0;
1598 }
1599
1601 void setStream(Stream &in) override {
1602 p_stream = &in;
1603 p_out = &in;
1604 }
1605
1607 void setOutput(Print &out) override { p_out = &out; }
1608
1610 void setOutput(Stream &in) {
1611 p_stream = &in;
1612 p_out = &in;
1613 }
1614
1616 void setStream(Print &out) { p_out = &out; }
1617
1619 void setAvailable(int val) { available_bytes = val; }
1620
1621 protected:
1622 bool active = true;
1623 size_t (*cb_write)(const uint8_t *data, size_t len) = nullptr;
1624 size_t (*cb_read)(uint8_t *data, size_t len) = nullptr;
1625 size_t (*cb_update)(uint8_t *data, size_t len) = nullptr;
1626 void (*cb_audio_info)(AudioInfo info) = nullptr;
1627 int (*cb_available)() = nullptr;
1628 Stream *p_stream = nullptr;
1629 Print *p_out = nullptr;
1630 int available_bytes = -1;
1631};
1632
1640template <typename T, class TF>
1642 public:
1643 FilteredStream() = default;
1644 FilteredStream(Stream &stream) : ModifyingStream() { setStream(stream); }
1645 FilteredStream(Stream &stream, int channels) : ModifyingStream() {
1646 this->channels = channels;
1647 setStream(stream);
1648 p_converter = new ConverterNChannels<T, TF>(channels);
1649 }
1650 FilteredStream(Print &stream) : ModifyingStream() { setOutput(stream); }
1651 FilteredStream(Print &stream, int channels) : ModifyingStream() {
1652 this->channels = channels;
1653 setOutput(stream);
1654 p_converter = new ConverterNChannels<T, TF>(channels);
1655 }
1656
1657 virtual ~FilteredStream() { end(); }
1658
1659 void setStream(Stream &stream) override {
1660 p_stream = &stream;
1661 p_print = &stream;
1662 }
1663
1664 void setOutput(Print &stream) override { p_print = &stream; }
1665
1666 bool begin(AudioInfo info) {
1667 setAudioInfo(info);
1668 this->channels = info.channels;
1669 if (p_converter != nullptr && p_converter->getChannels() != channels) {
1670 LOGE("Inconsistent number of channels");
1671 return false;
1672 }
1673 return begin();
1674 }
1675
1676 bool begin() override {
1677 if (channels == 0) {
1678 LOGE("channels must not be 0");
1679 return false;
1680 }
1681 if (p_converter == nullptr) {
1682 p_converter = new ConverterNChannels<T, TF>(channels);
1683 }
1684 return AudioStream::begin();
1685 }
1686
1687 void end() override {
1688 ModifyingStream::end();
1689 if (p_converter != nullptr) {
1690 delete p_converter;
1691 p_converter = nullptr;
1692 }
1693 }
1694
1695 virtual size_t write(const uint8_t *data, size_t len) override {
1696 if (p_converter == nullptr) return 0;
1697 size_t result = p_converter->convert((uint8_t *)data, len);
1698 return p_print->write(data, result);
1699 }
1700
1701 size_t readBytes(uint8_t *data, size_t len) override {
1702 if (p_converter == nullptr) return 0;
1703 if (p_stream == nullptr) return 0;
1704 size_t result = p_stream->readBytes(data, len);
1705 result = p_converter->convert(data, result);
1706 return result;
1707 }
1708
1709 virtual int available() override {
1710 if (p_stream == nullptr) return 0;
1711 return p_stream->available();
1712 }
1713
1714 virtual int availableForWrite() override {
1715 return p_print->availableForWrite();
1716 }
1717
1721 void setFilter(int channel, Filter<TF> *filter) {
1722 if (p_converter != nullptr) {
1723 p_converter->setFilter(channel, filter);
1724 } else {
1725 LOGE("p_converter is null");
1726 }
1727 }
1728
1732 void setFilter(int channel, Filter<TF> &filter) {
1733 setFilter(channel, &filter);
1734 }
1735
1736 protected:
1737 int channels = 0;
1738 Stream *p_stream = nullptr;
1739 Print *p_print = nullptr;
1740 ConverterNChannels<T, TF> *p_converter = nullptr;
1741};
1742
1752 public:
1753 VolumeMeter() = default;
1754 VolumeMeter(AudioStream &as) { setStream(as); }
1755 VolumeMeter(AudioOutput &ao) { setOutput(ao); }
1756 VolumeMeter(Print &print) { setOutput(print); }
1757 VolumeMeter(Stream &stream) { setStream(stream); }
1758
1759 bool begin(AudioInfo info) {
1760 setAudioInfo(info);
1761 return begin();
1762 }
1763
1764 bool begin() override {
1766 return true;
1767 }
1768
1769 void setAudioInfo(AudioInfo info) override {
1770 int channels = info.channels;
1771 LOGI("VolumeMeter::setAudioInfo: channels %d", channels);
1773 if (channels > 0) {
1774 volumes.resize(channels);
1775 volumes_tmp.resize(channels);
1776 sum.resize(channels);
1777 sum_tmp.resize(channels);
1778 }
1779 }
1780
1781 size_t write(const uint8_t *data, size_t len) override {
1782 updateVolumes(data, len);
1783 size_t result = len;
1784 if (p_out != nullptr) {
1785 result = p_out->write(data, len);
1786 }
1787 return result;
1788 }
1789
1790 size_t readBytes(uint8_t *data, size_t len) override {
1791 if (p_stream == nullptr) return 0;
1792 size_t result = p_stream->readBytes(data, len);
1793 updateVolumes((const uint8_t *)data, len);
1794 return result;
1795 }
1796
1799 float volume() { return f_volume; }
1800
1803 float volume(int channel) {
1804 if (volumes.size() == 0) {
1805 LOGE("begin not called!");
1806 return 0.0f;
1807 }
1808 if (channel >= volumes.size()) {
1809 LOGE("invalid channel %d", channel);
1810 return 0.0f;
1811 }
1812 return volumes[channel];
1813 }
1814
1816 float volumeRatio() {
1818 }
1819
1821 float volumeRatio(int channel) {
1822 return volume(channel) / NumberConverter::maxValue(info.bits_per_sample);
1823 }
1824
1826 float volumeDB() {
1827 // prevent infinite value
1828 if (volumeRatio() == 0) return -1000;
1829 return 20.0f * log10(volumeRatio());
1830 }
1831
1833 float volumeDB(int channel) {
1834 // prevent infinite value
1835 if (volumeRatio(channel) == 0) return -1000;
1836 return 20.0f * log10(volumeRatio(channel));
1837 }
1838
1840 float volumePercent() { return 100.0f * volumeRatio(); }
1841
1843 float volumePercent(int channel) { return 100.0f * volumeRatio(channel); }
1844
1846 float volumeAvg() {
1847 float total = 0;
1848 size_t count = 0;
1849 for (int j = 0; j < info.channels; j++) {
1850 total += sum[j];
1851 count += sample_count_per_channel;
1852 }
1853 return total / count;
1854 }
1855
1857 float volumeAvg(int channel) {
1858 return sum[channel] / sample_count_per_channel;
1859 }
1860
1862 void clear() {
1863 f_volume_tmp = 0;
1864 for (int j = 0; j < info.channels; j++) {
1865 volumes_tmp[j] = 0;
1866 sum_tmp[j] = 0;
1867 }
1868 }
1869
1870 void setOutput(AudioOutput &out) {
1872 setOutput((Print &)out);
1873 }
1874 void setStream(AudioStream &io) {
1876 setStream((Stream &)io);
1877 }
1878 void setOutput(Print &out) override { p_out = &out; }
1879 void setStream(Stream &io) override {
1880 p_out = &io;
1881 p_stream = &io;
1882 }
1883
1884 protected:
1885 float f_volume_tmp = 0;
1886 float f_volume = 0;
1887 Vector<float> volumes{0};
1888 Vector<float> volumes_tmp{0};
1889 Vector<float> sum{0};
1890 Vector<float> sum_tmp{0};
1891 Print *p_out = nullptr;
1892 Stream *p_stream = nullptr;
1893 size_t sample_count_per_channel = 0;
1894
1895 void updateVolumes(const uint8_t *data, size_t len) {
1896 if (data == nullptr || len == 0) return;
1897 clear();
1898 switch (info.bits_per_sample) {
1899 case 8:
1900 updateVolumesT<int8_t>(data, len);
1901 break;
1902 case 16:
1903 updateVolumesT<int16_t>(data, len);
1904 break;
1905 case 24:
1906 updateVolumesT<int24_t>(data, len);
1907 break;
1908 case 32:
1909 updateVolumesT<int32_t>(data, len);
1910 break;
1911 default:
1912 LOGE("Unsupported bits_per_sample: %d", info.bits_per_sample);
1913 break;
1914 }
1915 }
1916
1917 template <typename T>
1918 void updateVolumesT(const uint8_t *buffer, size_t size) {
1919 T *bufferT = (T *)buffer;
1920 int samplesCount = size / sizeof(T);
1921 sample_count_per_channel = samplesCount / info.channels;
1922 for (int j = 0; j < samplesCount; j++) {
1923 float tmp = abs(static_cast<float>(bufferT[j]));
1924 updateVolume(tmp, j);
1925 }
1926 commit();
1927 }
1928
1929 void updateVolume(float tmp, int j) {
1930 if (tmp > f_volume_tmp) {
1931 f_volume_tmp = tmp;
1932 }
1933 if (volumes_tmp.size() > 0 && info.channels > 0) {
1934 int ch = j % info.channels;
1935 if (tmp > volumes_tmp[ch]) {
1936 volumes_tmp[ch] = tmp;
1937 sum_tmp[ch] = tmp;
1938 }
1939 }
1940 }
1941
1942 void commit() {
1943 f_volume = f_volume_tmp;
1944 for (int j = 0; j < info.channels; j++) {
1945 volumes[j] = volumes_tmp[j];
1946 sum[j] = sum_tmp[j];
1947 }
1948 }
1949};
1950
1951// legacy names
1955
1959
1973 public:
2007 setOutput(print);
2008 }
2016 setStream(stream);
2017 }
2022 void setLimitPercent(uint8_t percent) { limit_percent = percent; }
2023
2028 uint8_t limitPercent() const { return limit_percent; }
2029
2035 bool begin(AudioInfo info) {
2036 setAudioInfo(info);
2037 return begin();
2038 }
2039
2044 bool begin() override {
2045 volume_meter.begin(audioInfo());
2046 return true;
2047 }
2048
2053 void setAudioInfo(AudioInfo info) override {
2056 }
2057
2064 size_t write(const uint8_t *data, size_t len) override {
2065 size_t result = volume_meter.write(data, len);
2066 if (result > 0 && volume_meter.volumePercent() > limit_percent) {
2068 }
2069 return result;
2070 }
2071
2078 size_t readBytes(uint8_t *data, size_t len) override {
2079 size_t result = volume_meter.readBytes(data, len);
2080 if (result > 0 && volume_meter.volumePercent() > limit_percent) {
2082 }
2083 return result;
2084 }
2085
2090 void setOutput(Print &out) override { volume_meter.setOutput(out); }
2095 void setOutput(AudioOutput &out) { volume_meter.setOutput(out); }
2100 void setStream(Stream &io) override { volume_meter.setStream(io); }
2105 void setStream(AudioStream &io) { volume_meter.setStream(io); }
2106
2112
2118 bool isActive(uint16_t time_ms = 1000) {
2119 return (millis() - time_over_last_volume_limit) < time_ms;
2120 }
2121
2122protected:
2124 uint8_t limit_percent = 20;
2126};
2127
2128#ifdef USE_TIMER
2135 RxTxMode rx_tx_mode = RX_MODE;
2136 uint16_t buffer_size = DEFAULT_BUFFER_SIZE;
2137 bool use_timer = true;
2138 int timer_id = -1;
2139 TimerFunction timer_function = DirectTimerCallback;
2140 bool adapt_sample_rate = false;
2141 uint16_t (*callback)(uint8_t *data, uint16_t len) = nullptr;
2142};
2143
2144// forward declaration: relevant only if use_timer == true
2145static void timerCallback(void *obj);
2156 friend void timerCallback(void *obj);
2157
2158 public:
2159 TimerCallbackAudioStream() : BufferedStream(80) { TRACED(); }
2160
2162 TRACED();
2163 if (timer != nullptr) delete timer;
2164 if (buffer != nullptr) delete buffer;
2165 if (frame != nullptr) delete[] frame;
2166 }
2167
2173
2175 virtual void setAudioInfo(AudioInfo info) {
2176 TRACED();
2177 if (cfg.sample_rate != info.sample_rate || cfg.channels != info.channels ||
2178 cfg.bits_per_sample != info.bits_per_sample) {
2179 bool do_restart = active;
2180 if (do_restart) end();
2181 cfg.sample_rate = info.sample_rate;
2182 cfg.channels = info.channels;
2183 cfg.bits_per_sample = info.bits_per_sample;
2184 if (do_restart) begin(cfg);
2185 }
2186 }
2187
2190 AudioInfo audioInfo() { return cfg; }
2191
2192 void begin(TimerCallbackAudioStreamInfo config) {
2193 LOGD("%s: %s", LOG_METHOD,
2194 config.rx_tx_mode == RX_MODE ? "RX_MODE" : "TX_MODE");
2195 this->cfg = config;
2196 this->frameCallback = config.callback;
2197 if (cfg.use_timer) {
2198 frameSize = cfg.bits_per_sample * cfg.channels / 8;
2199 frame = new uint8_t[frameSize];
2200 buffer = new RingBuffer<uint8_t>(cfg.buffer_size);
2201 timer = new TimerAlarmRepeating();
2202 timer->setTimerFunction(cfg.timer_function);
2203 if (cfg.timer_id >= 0) {
2204 timer->setTimer(cfg.timer_id);
2205 }
2206 time = AudioTime::toTimeUs(cfg.sample_rate);
2207 LOGI("sample_rate: %u -> time: %u milliseconds",
2208 (unsigned int)cfg.sample_rate, (unsigned int)time);
2209 timer->setCallbackParameter(this);
2210 timer->begin(timerCallback, time, TimeUnit::US);
2211 }
2212
2213 notifyAudioChange(cfg);
2214 active = true;
2215 }
2216
2218 bool begin() {
2219 TRACED();
2220 if (this->frameCallback != nullptr) {
2221 if (cfg.use_timer) {
2222 timer->begin(timerCallback, time, TimeUnit::US);
2223 }
2224 active = true;
2225 }
2226 return active;
2227 }
2228
2230 void end() {
2231 TRACED();
2232 if (cfg.use_timer) {
2233 timer->end();
2234 }
2235 active = false;
2236 }
2237
2239 uint16_t currentSampleRate() { return currentRateValue; }
2240
2241 protected:
2243 bool active = false;
2244 uint16_t (*frameCallback)(uint8_t *data, uint16_t len);
2245 // below only relevant with timer
2246 TimerAlarmRepeating *timer = nullptr;
2247 RingBuffer<uint8_t> *buffer = nullptr;
2248 uint8_t *frame = nullptr;
2249 uint16_t frameSize = 0;
2250 uint32_t time = 0;
2251 unsigned long lastTimestamp = 0u;
2252 uint32_t currentRateValue = 0;
2253 uint32_t printCount = 0;
2254
2255 // used for audio sink
2256 virtual size_t writeExt(const uint8_t *data, size_t len) override {
2257 if (!active) return 0;
2258 TRACED();
2259 size_t result = 0;
2260 if (!cfg.use_timer) {
2261 result = frameCallback((uint8_t *)data, len);
2262 } else {
2263 result = buffer->writeArray((uint8_t *)data, len);
2264 }
2265 if (++printCount % 10000 == 0) printSampleRate();
2266 return result;
2267 }
2268
2269 // used for audio source
2270 virtual size_t readExt(uint8_t *data, size_t len) override {
2271 if (!active) return 0;
2272 TRACED();
2273
2274 size_t result = 0;
2275 if (!cfg.use_timer) {
2276 result = frameCallback(data, len);
2277 } else {
2278 result = buffer->readArray(data, len);
2279 }
2280 if (++printCount % 10000 == 0) printSampleRate();
2281 return result;
2282 }
2283
2285 virtual void measureSampleRate() {
2286 unsigned long ms = millis();
2287 if (lastTimestamp > 0u) {
2288 uint32_t diff = ms - lastTimestamp;
2289 if (diff > 0) {
2290 uint16_t rate = 1 * 1000 / diff;
2291
2292 if (currentRateValue == 0) {
2293 currentRateValue = rate;
2294 } else {
2295 currentRateValue = (currentRateValue + rate) / 2;
2296 }
2297 }
2298 }
2299 lastTimestamp = ms;
2300 }
2301
2303 virtual void printSampleRate() {
2304 LOGI("effective sample rate: %u", (unsigned int)currentRateValue);
2305 if (cfg.adapt_sample_rate &&
2306 abs((int)currentRateValue - (int)cfg.sample_rate) > 200) {
2307 cfg.sample_rate = currentRateValue;
2308 notifyAudioChange(cfg);
2309 }
2310 }
2311};
2312
2313// relevant only if use_timer == true
2314void IRAM_ATTR timerCallback(void *obj) {
2315 TimerCallbackAudioStream *src = (TimerCallbackAudioStream *)obj;
2316 if (src != nullptr) {
2317 // LOGD("%s: %s", LOG_METHOD, src->cfg.rx_tx_mode==RX_MODE ?
2318 // "RX_MODE":"TX_MODE");
2319 if (src->cfg.rx_tx_mode == RX_MODE) {
2320 // input
2321 uint16_t available_bytes = src->frameCallback(src->frame, src->frameSize);
2322 uint16_t buffer_available = src->buffer->availableForWrite();
2323 if (buffer_available < available_bytes) {
2324 // if buffer is full make space
2325 uint16_t to_clear = available_bytes - buffer_available;
2326 uint8_t tmp[to_clear];
2327 src->buffer->readArray(tmp, to_clear);
2328 }
2329 if (src->buffer->writeArray(src->frame, available_bytes) !=
2330 available_bytes) {
2331 assert(false);
2332 }
2333 } else {
2334 // output
2335 if (src->buffer != nullptr && src->frame != nullptr &&
2336 src->frameSize > 0) {
2337 uint16_t available_bytes =
2338 src->buffer->readArray(src->frame, src->frameSize);
2339 if (available_bytes !=
2340 src->frameCallback(src->frame, available_bytes)) {
2341 LOGE("data underflow");
2342 }
2343 }
2344 }
2345 src->measureSampleRate();
2346 }
2347}
2348
2349#endif
2350
2351} // namespace audio_tools
virtual void addNotifyAudioChange(AudioInfoSupport &bi)
Adds target to be notified about audio changes.
Definition AudioTypes.h:153
Supports changes to the sampling rate, bits and channels.
Definition AudioTypes.h:135
virtual AudioInfo audioInfo()=0
provides the actual input AudioInfo
virtual void setAudioInfo(AudioInfo info)=0
Defines the input AudioInfo.
Monitors audio input and reports if the volume exceeds a specified limit within a given period.
Definition AudioStreams.h:1972
void setOutput(Print &out) override
Set the output target.
Definition AudioStreams.h:2090
void setStream(AudioStream &io)
Set the input stream.
Definition AudioStreams.h:2105
AudioInputMonitor(AudioOutput &ao, uint8_t limitPercent=20)
Construct a new AudioInputMonitor with an output.
Definition AudioStreams.h:1996
uint8_t limit_percent
Threshold percent.
Definition AudioStreams.h:2124
AudioInputMonitor(Print &print, uint8_t limitPercent=20)
Construct a new AudioInputMonitor with a Print output.
Definition AudioStreams.h:2005
bool isActive(uint16_t time_ms=1000)
Returns true if the volume exceeded the limit during the last period.
Definition AudioStreams.h:2118
VolumeMeter volume_meter
Volume calculation.
Definition AudioStreams.h:2123
AudioInputMonitor(uint8_t limitPercent=20)
Construct a new AudioInputMonitor with a volume limit in percent.
Definition AudioStreams.h:1978
void setOutput(AudioOutput &out)
Set the output target.
Definition AudioStreams.h:2095
size_t readBytes(uint8_t *data, size_t len) override
Read audio data from the monitor (same as VolumeMeter)
Definition AudioStreams.h:2078
uint64_t time_over_last_volume_limit
Last over-limit time (ms)
Definition AudioStreams.h:2125
VolumeMeter & getVolumeMeter()
Access the underlying VolumeMeter.
Definition AudioStreams.h:2111
size_t write(const uint8_t *data, size_t len) override
Write audio data to the monitor (same as VolumeMeter)
Definition AudioStreams.h:2064
uint8_t limitPercent() const
Get the current volume threshold as percent.
Definition AudioStreams.h:2028
AudioInputMonitor(Stream &stream, uint8_t limitPercent=20)
Construct a new AudioInputMonitor with a Stream input.
Definition AudioStreams.h:2014
bool begin() override
Begin processing with the current audio information.
Definition AudioStreams.h:2044
void setAudioInfo(AudioInfo info) override
Set the audio information.
Definition AudioStreams.h:2053
void setStream(Stream &io) override
Set the input stream.
Definition AudioStreams.h:2100
void setLimitPercent(uint8_t percent)
Set the volume threshold as percent.
Definition AudioStreams.h:2022
bool begin(AudioInfo info)
Begin processing with the given audio information.
Definition AudioStreams.h:2035
AudioInputMonitor(AudioStream &as, uint8_t limitPercent=20)
Construct a new AudioInputMonitor with an input stream.
Definition AudioStreams.h:1987
Abstract Audio Ouptut class.
Definition AudioOutput.h:25
Base class for all Audio Streams. It support the boolean operator to test if the object is ready with...
Definition BaseStream.h:122
virtual void setAudioInfo(AudioInfo newInfo) override
Defines the input AudioInfo.
Definition BaseStream.h:130
virtual AudioInfo audioInfo() override
provides the actual input AudioInfo
Definition BaseStream.h:153
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:242
virtual int readArray(T data[], int len)
reads multiple values
Definition Buffers.h:33
virtual int writeArray(const T data[], int len)
Fills the buffer data.
Definition Buffers.h:55
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:486
void flush() override
empties the buffer
Definition AudioStreams.h:543
void setOutput(Print &out) override
Defines/Changes the output target.
Definition AudioStreams.h:517
void setMinUnbufferedReadSize(size_t size)
Definition AudioStreams.h:603
size_t write(uint8_t c) override
writes a byte to the buffer
Definition AudioStreams.h:525
size_t readBytes(uint8_t *data, size_t len) override
Use this method !!
Definition AudioStreams.h:572
int peek() override
peeks a byte - to be avoided
Definition AudioStreams.h:562
void refill()
refills the buffer with data from the source
Definition AudioStreams.h:612
int available() override
Returns the available bytes.
Definition AudioStreams.h:590
size_t write(const uint8_t *data, size_t len) override
Use this method: write an array.
Definition AudioStreams.h:533
size_t peekBytes(uint8_t *data, size_t len)
Provides data w/o consuming.
Definition AudioStreams.h:582
void clear()
Clears all the data in the buffer.
Definition AudioStreams.h:596
int read() override
reads a byte - to be avoided
Definition AudioStreams.h:552
void refill(size_t len)
refill only if not enough data
Definition AudioStreams.h:627
void resize(int size)
Resize the buffer.
Definition AudioStreams.h:599
void setStream(Stream &io) override
Defines/Changes the input & output.
Definition AudioStreams.h:519
CallbackStream: A Stream that allows to register callback methods for accessing and providing data....
Definition AudioStreams.h:1488
void setOutput(Print &out) override
Defines/Changes the output target.
Definition AudioStreams.h:1607
void setOutput(Stream &in)
same as setStream
Definition AudioStreams.h:1610
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:1501
void setStream(Print &out)
same as set Output
Definition AudioStreams.h:1616
void setAvailable(int val)
optioinally define available bytes for next read
Definition AudioStreams.h:1619
void setAudioInfo(AudioInfo info) override
Updates the audio info and calls the callback.
Definition AudioStreams.h:1534
void setStream(Stream &in) override
Defines/Changes the input & output.
Definition AudioStreams.h:1601
CallbackStream(Stream &io, size_t(*cb_update)(uint8_t *data, size_t len))
Definition AudioStreams.h:1494
void setAudioInfoCallback(void(*cb)(AudioInfo info))
defines the callback to receive the actual audio info
Definition AudioStreams.h:1529
Converter for n Channels which applies the indicated Filter.
Definition BaseConverter.h:1565
void setFilter(int channel, Filter< FT > *filter)
defines the filter for an individual channel - the first channel is 0
Definition BaseConverter.h:1589
Both the data of the read or write operations will be converted with the help of the indicated conver...
Definition AudioStreams.h:649
void setStream(Stream &stream)
Defines/Changes the input & output.
Definition AudioStreams.h:665
void setOutput(Print &out)
Defines/Changes the output target.
Definition AudioStreams.h:671
virtual int available() override
Returns the available bytes in the buffer: to be avoided.
Definition AudioStreams.h:696
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:1641
void setStream(Stream &stream) override
Defines/Changes the input & output.
Definition AudioStreams.h:1659
void setOutput(Print &stream) override
Defines/Changes the output target.
Definition AudioStreams.h:1664
void setFilter(int channel, Filter< TF > &filter)
Definition AudioStreams.h:1732
void setFilter(int channel, Filter< TF > *filter)
Definition AudioStreams.h:1721
Source for reading generated tones. Please note.
Definition AudioStreams.h:394
void setAudioInfo(AudioInfo newInfo) override
Defines the input AudioInfo.
Definition AudioStreams.h:409
void resize(int maxReadSize)
Redefine the buffer size which is reported in available()
Definition AudioStreams.h:468
size_t readBytes(uint8_t *data, size_t len) override
privide the data as byte stream
Definition AudioStreams.h:455
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:1379
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:1411
void end() override
Remove all input streams.
Definition AudioStreams.h:1446
int available() override
Provides the min available data from all streams.
Definition AudioStreams.h:1452
void add(Stream &in, int channelCount, float weight=1.0)
Adds a new input stream with 1 channel.
Definition AudioStreams.h:1429
void setWeight(int channel, float weight)
Definition AudioStreams.h:1437
int channelCount()
Number of channels to which are mixed together = number of result channels.
Definition AudioStreams.h:1449
InputMerge(Stream &left, Stream &right)
Constructor for stereo signal from to mono input stream.
Definition AudioStreams.h:1387
AudioInfo audioInfo() override
Provides the audio info with the total channel count.
Definition AudioStreams.h:1393
MixerStream is mixing the input from Multiple Input Streams. All streams must have the same audo form...
Definition AudioStreams.h:1173
bool remove()
Removes all streams which have no data available.
Definition AudioStreams.h:1270
int nextEmptyIndex()
Provides you the index of the next empty stream. -1 when none is found.
Definition AudioStreams.h:1293
int indexOf(Stream &stream)
Provides the actual index of the stream.
Definition AudioStreams.h:1284
bool set(int index, Stream &in)
Replaces a stream at the indicated index.
Definition AudioStreams.h:1186
size_t readBytes(uint8_t *data, size_t len) override
Provides the data from all streams mixed together.
Definition AudioStreams.h:1228
void recalculateWeights()
Recalculate the weights.
Definition AudioStreams.h:1313
int add(Stream &in, int weight=100)
Adds a new input stream and returns it's actual index position.
Definition AudioStreams.h:1178
void end() override
Remove all input streams.
Definition AudioStreams.h:1216
bool remove(int idx)
Removes a stream by index position.
Definition AudioStreams.h:1259
int availableBytes()
Provides the available bytes from the first stream with data.
Definition AudioStreams.h:1349
void setLimitToAvailableData(bool flag)
Definition AudioStreams.h:1252
void setRetryCount(int retry)
Definition AudioStreams.h:1256
int readBytesVector(T *p_data, int byteCount)
mixing using a vector of samples
Definition AudioStreams.h:1322
void setWeight(int index, int weight)
Definition AudioStreams.h:1206
Stream * operator[](int idx)
Provides the stream pointer at the indicated index.
Definition AudioStreams.h:1287
int size()
Number of stremams to which are mixed together.
Definition AudioStreams.h:1225
Class which measures the thruput.
Definition AudioStreams.h:713
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:761
void setOutput(Print &out) override
Defines/Changes the output target.
Definition AudioStreams.h:750
uint32_t estimatedTotalTimeFor(uint32_t totalBytes)
Provides the estimated runtime in milliseconds for the indicated total.
Definition AudioStreams.h:814
uint32_t timeSinceBegin()
Provides the time in ms since the last call of begin()
Definition AudioStreams.h:808
size_t readBytes(uint8_t *data, size_t len) override
Provides the data from all streams mixed together.
Definition AudioStreams.h:753
int framesPerSecond()
Returns the actual thrughput in frames (samples) per second.
Definition AudioStreams.h:775
uint32_t bytesSinceBegin()
Provides the total processed bytes since the last call of begin()
Definition AudioStreams.h:811
virtual int availableForWrite() override
Provides the nubmer of bytes we can write.
Definition AudioStreams.h:767
void setFrameSize(int size)
Trigger reporting in frames (=samples) per second.
Definition AudioStreams.h:800
void setReportBytes(bool flag)
Report in bytes instead of samples.
Definition AudioStreams.h:803
uint32_t estimatedOpenTimeFor(uint32_t totalBytes)
Provides the estimated time from now to the end in ms.
Definition AudioStreams.h:821
void setLogOutput(Print &out)
Defines the logging output.
Definition AudioStreams.h:741
bool setProcessedBytes(uint32_t pos)
Definition AudioStreams.h:828
uint32_t startTime()
Provides the time when the last measurement was started.
Definition AudioStreams.h:781
void setAudioInfo(AudioInfo info) override
Defines the input AudioInfo.
Definition AudioStreams.h:783
void setStream(Stream &io) override
Defines/Changes the input & output.
Definition AudioStreams.h:744
int bytesPerSecond()
Returns the actual thrughput in bytes per second.
Definition AudioStreams.h:772
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:292
static int64_t maxValue(int value_bits_per_sample)
provides the biggest number for the indicated number of bits
Definition AudioTypes.h:301
Definition NoArduino.h:62
Generic calss to measure the the total bytes which were processed in order to calculate the progress ...
Definition AudioStreams.h:905
bool begin(size_t len)
Definition AudioStreams.h:943
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:993
size_t size()
Provides the current total size (defined by setSize)
Definition AudioStreams.h:961
void setStream(Stream &stream) override
Defines/Changes the input & output.
Definition AudioStreams.h:925
size_t totalSecs()
Converts the totalBytes() to seconds.
Definition AudioStreams.h:973
size_t readBytes(uint8_t *data, size_t len) override
Provides the data from all streams mixed together.
Definition AudioStreams.h:982
size_t processedBytes()
Provides the number of processed bytes.
Definition AudioStreams.h:964
void setSize(size_t len)
Updates the total size and restarts the percent calculation.
Definition AudioStreams.h:955
virtual int availableForWrite() override
Provides the nubmer of bytes we can write.
Definition AudioStreams.h:999
float percentage()
Provides the processed percentage: If no size has been defined we return 0.
Definition AudioStreams.h:976
size_t processedSecs()
Provides the number of processed seconds.
Definition AudioStreams.h:967
void setAudioInfo(AudioInfo info) override
Defines the input AudioInfo.
Definition AudioStreams.h:920
size_t totalBytes()
Provides the total_size provided in the configuration.
Definition AudioStreams.h:970
Configuration for ProgressStream.
Definition AudioStreams.h:894
Implements a typed Ringbuffer.
Definition Buffers.h:341
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:172
Base class to define the abstract interface for the sound generating classes.
Definition SoundGenerator.h:28
virtual size_t readBytes(uint8_t *data, size_t len)
Provides the data as byte array with the requested number of channels.
Definition SoundGenerator.h:62
virtual bool isActive()
Definition SoundGenerator.h:56
virtual AudioInfo audioInfo()
Provides the AudioInfo.
Definition SoundGenerator.h:87
virtual void end()
ends the processing
Definition SoundGenerator.h:52
virtual AudioInfo defaultConfig()
Provides the default configuration.
Definition SoundGenerator.h:75
Definition NoArduino.h:142
Throttle the sending or receiving of the audio data to limit it to the indicated sample rate.
Definition AudioStreams.h:1047
void setOutput(Print &out) override
Defines/Changes the output target.
Definition AudioStreams.h:1060
void setStream(Stream &io) override
Defines/Changes the input & output.
Definition AudioStreams.h:1054
Common Interface definition for TimerAlarmRepeating.
Definition AudioTimer.h:29
Callback driven Audio Source (rx_tx_mode==RX_MODE) or Audio Sink (rx_tx_mode==TX_MODE)....
Definition AudioStreams.h:2155
TimerCallbackAudioStreamInfo audioInfoExt()
Provides the current audio information.
Definition AudioStreams.h:2189
uint16_t currentSampleRate()
Provides the effective sample rate.
Definition AudioStreams.h:2239
TimerCallbackAudioStreamInfo defaultConfig()
Provides the default configuration.
Definition AudioStreams.h:2169
bool begin()
Restart the processing.
Definition AudioStreams.h:2218
AudioInfo audioInfo()
provides the actual input AudioInfo
Definition AudioStreams.h:2190
virtual void measureSampleRate()
calculates the effective sample rate
Definition AudioStreams.h:2285
virtual void setAudioInfo(AudioInfo info)
updates the audio information
Definition AudioStreams.h:2175
virtual void printSampleRate()
log and update effective sample rate
Definition AudioStreams.h:2303
void end()
Stops the processing.
Definition AudioStreams.h:2230
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:1751
void setOutput(Print &out) override
Defines/Changes the output target.
Definition AudioStreams.h:1878
float volumeRatio()
Volume Ratio: max amplitude is 1.0.
Definition AudioStreams.h:1816
float volumeAvg(int channel)
Average volume of indicated channel.
Definition AudioStreams.h:1857
float volume()
Definition AudioStreams.h:1799
float volumePercent()
Volume in %: max amplitude is 100.
Definition AudioStreams.h:1840
float volumePercent(int channel)
Volume of indicated channel in %: max amplitude is 100.
Definition AudioStreams.h:1843
float volumeAvg()
Average volume of all channels.
Definition AudioStreams.h:1846
void clear()
Resets the actual volume.
Definition AudioStreams.h:1862
float volumeRatio(int channel)
Volume Ratio of indicated channel: max amplitude is 1.0.
Definition AudioStreams.h:1821
float volumeDB(int channel)
Volume of indicated channel in db: max amplitude is 0.
Definition AudioStreams.h:1833
void setAudioInfo(AudioInfo info) override
Defines the input AudioInfo.
Definition AudioStreams.h:1769
void setStream(Stream &io) override
Defines/Changes the input & output.
Definition AudioStreams.h:1879
float volumeDB()
Volume in db: max amplitude is 0 (range: -1000 to 0)
Definition AudioStreams.h:1826
float volume(int channel)
Definition AudioStreams.h:1803
MemoryType
Memory types.
Definition AudioTypes.h:37
RxTxMode
The Microcontroller is the Audio Source (TX_MODE) or Audio Sink (RX_MODE). RXTX_MODE is Source and Si...
Definition AudioTypes.h:30
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:468
uint32_t millis()
Returns the milliseconds since the start.
Definition Time.h:12
Basic Audio information which drives e.g. I2S.
Definition AudioTypes.h:55
void copyFrom(AudioInfo info)
Same as set.
Definition AudioTypes.h:105
sample_rate_t sample_rate
Sample Rate: e.g 44100.
Definition AudioTypes.h:57
uint16_t channels
Number of channels: 2=stereo, 1=mono.
Definition AudioTypes.h:59
uint8_t bits_per_sample
Number of bits per sample (int16_t = 16 bits)
Definition AudioTypes.h:61
Definition AudioStreams.h:1464
Configure Throttle setting.
Definition AudioStreams.h:1032
TimerCallbackAudioStream Configuration.
Definition AudioStreams.h:2134