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 owns_memory = false;
102 setValue(buffer, buffer_size, memoryType);
103 is_active = isActive;
104 info.clear(); // mark audio info as unknown
105 }
106
108 MemoryStream(MemoryStream &source) : AudioStream() { copy(source); }
109
112 setValue(source.buffer, source.buffer_size, source.memory_type);
113 // clear source data
114 source.setValue(nullptr, 0, source.memory_type);
115 }
116
117 ~MemoryStream() {
118 TRACED();
119 if (memoryCanChange() && owns_memory && buffer != nullptr) free(buffer);
120 }
121
124 copy(other);
125 return *this;
126 }
127
129 operator bool() override { return available() > 0; }
130
132 bool begin(AudioInfo info) {
133 this->info = info;
134 return begin();
135 }
136
138 bool begin() override {
139 TRACED();
140 write_pos = memoryCanChange() ? 0 : buffer_size;
141 if (this->buffer == nullptr && owns_memory && memoryCanChange()) {
142 resize(buffer_size);
143 }
144 read_pos = 0;
145 is_active = this->buffer != nullptr;
146 return is_active;
147 }
148
149 virtual size_t write(uint8_t byte) override {
150 if (!is_active) return 0;
151 if (memory_type == FLASH_RAM) return 0;
152 if (buffer == nullptr) return 0;
153 int result = 0;
154 if (write_pos < buffer_size) {
155 result = 1;
156 buffer[write_pos] = byte;
157 write_pos++;
158 }
159 return result;
160 }
161
162 virtual size_t write(const uint8_t *data, size_t len) override {
163 if (!is_active) return 0;
164 if (memory_type == FLASH_RAM) return 0;
165 size_t result = 0;
166 for (size_t j = 0; j < len; j++) {
167 if (!write(data[j])) {
168 break;
169 }
170 result = j + 1;
171 }
172 return result;
173 }
174
175 virtual int available() override {
176 if (!is_active) return 0;
177 if (buffer == nullptr) return 0;
178 int result = write_pos - read_pos;
179 if (result <= 0 && is_loop) {
180 // rewind to start
181 read_pos = rewind_pos;
182 result = write_pos - read_pos;
183 // call callback
184 if (rewind != nullptr) rewind();
185 }
186 return is_loop ? DEFAULT_BUFFER_SIZE : result;
187 }
188
189 virtual int availableForWrite() override {
190 if (!is_active) return 0;
191 if (memory_type == FLASH_RAM) return 0;
192 return buffer_size - write_pos;
193 }
194
195 virtual int read() override {
196 int result = peek();
197 if (result >= 0) {
198 read_pos++;
199 }
200 return result;
201 }
202
203 virtual size_t readBytes(uint8_t *data, size_t len) override {
204 if (!is_active) return 0;
205 size_t count = 0;
206 while (count < len) {
207 int c = read();
208 if (c < 0) break;
209 *data++ = (char)c;
210 count++;
211 }
212 return count;
213 }
214
215 virtual int peek() override {
216 if (!is_active) return -1;
217 int result = -1;
218 if (available() > 0) {
219 result = buffer[read_pos];
220 }
221 return result;
222 }
223
224 virtual void flush() override {}
225
226 virtual void end() override {
227 read_pos = 0;
228 is_active = false;
229 }
230
232 virtual void clear(bool reset = false) {
233 if (memoryCanChange()) {
234 write_pos = 0;
235 read_pos = 0;
236 if (owns_memory && buffer == nullptr) {
237 resize(buffer_size);
238 }
239 if (reset) {
240 // we clear the buffer data
241 memset(buffer, 0, buffer_size);
242 }
243 } else {
244 read_pos = 0;
245 LOGW("data is read only");
246 }
247 }
248
251 virtual void setLoop(bool loop) {
252 is_loop = loop;
253 rewind_pos = 0;
254 if (buffer != nullptr && buffer_size > 12) {
255 if (memcmp("WAVE", buffer + 8, 4) == 0) {
256 rewind_pos = 44;
257 }
258 }
259 }
260
262 virtual void setLoop(bool loop, int rewindPos) {
263 is_loop = loop;
264 rewind_pos = rewindPos;
265 }
266
269 virtual bool resize(size_t size) {
270 if (!memoryCanChange()) return false;
271 if (!owns_memory) return false;
272
273 buffer_size = size;
274 switch (memory_type) {
275#if defined(USE_PSRAM) && defined(ARDUINO)
276 case PS_RAM:
277 buffer = (buffer == nullptr) ? (uint8_t *)ps_calloc(size, 1)
278 : (uint8_t *)ps_realloc(buffer, size);
279 break;
280#endif
281 default:
282 buffer = (buffer == nullptr) ? (uint8_t *)calloc(size, 1)
283 : (uint8_t *)realloc(buffer, size);
284 break;
285 }
286 return buffer != nullptr;
287 }
288
290 virtual uint8_t *data() { return buffer; }
291
293 virtual void setAvailable(size_t len) { this->write_pos = len; }
294
296 void setRewindCallback(void (*cb)()) { this->rewind = cb; }
297
299 void setValue(const uint8_t *buffer, int buffer_size,
300 MemoryType memoryType = FLASH_RAM) {
301 this->buffer_size = buffer_size;
302 this->read_pos = 0;
303 this->write_pos = buffer_size;
304 this->buffer = (uint8_t *)buffer;
305 this->memory_type = memoryType;
306 }
307
308 protected:
309 int write_pos = 0;
310 int read_pos = 0;
311 int buffer_size = 0;
312 int rewind_pos = 0;
313 uint8_t *buffer = nullptr;
314 MemoryType memory_type = RAM;
315 bool is_loop = false;
316 void (*rewind)() = nullptr;
317 bool is_active = false;
318 bool owns_memory = true;
319
320 bool memoryCanChange() { return memory_type != FLASH_RAM; }
321
322 void copy(MemoryStream &source) {
323 if (this == &source) return;
324 if (source.memory_type == FLASH_RAM) {
325 setValue(source.buffer, source.buffer_size, source.memory_type);
326 } else {
327 setValue(nullptr, source.buffer_size, source.memory_type);
328 resize(buffer_size);
329 memcpy(buffer, source.buffer, buffer_size);
330 }
331 }
332};
333
342 public:
343 RingBufferStream(int size = DEFAULT_BUFFER_SIZE) { resize(size); }
344
345 virtual int available() override {
346 // LOGD("RingBufferStream::available: %zu",buffer->available());
347 return buffer.available();
348 }
349
350 virtual int availableForWrite() override {
351 return buffer.availableForWrite();
352 }
353
354 virtual void flush() override {}
355 virtual int peek() override {
356 uint8_t data = 0;
357 if (!buffer.peek(data)) return -1;
358 return data;
359 }
360 virtual int read() override {
361 uint8_t data = 0;
362 if (!buffer.read(data)) return -1;
363 return data;
364 }
365
366 virtual size_t readBytes(uint8_t *data, size_t len) override {
367 return buffer.readArray(data, len);
368 }
369
370 virtual size_t write(const uint8_t *data, size_t len) override {
371 // LOGD("RingBufferStream::write: %zu",len);
372 return buffer.writeArray(data, len);
373 }
374
375 virtual size_t write(uint8_t c) override { return buffer.write(c); }
376
377 void resize(int size) { buffer.resize(size); }
378
379 size_t size() { return buffer.size(); }
380
381 protected:
382 RingBuffer<uint8_t> buffer{0};
383};
384
396template <class T = int16_t>
398 public:
399 GeneratedSoundStream() = default;
400
402 TRACED();
403 setInput(generator);
404 }
405
406 void setInput(SoundGenerator<T> &generator) {
407 this->generator_ptr = &generator;
408 }
409
410 AudioInfo defaultConfig() { return this->generator_ptr->defaultConfig(); }
411
412 void setAudioInfo(AudioInfo newInfo) override {
413 if (newInfo.bits_per_sample != sizeof(T) * 8) {
414 LOGE("Wrong bits_per_sample: %d", newInfo.bits_per_sample);
415 }
417 }
418
420 bool begin() override {
421 TRACED();
422 if (generator_ptr == nullptr) {
423 LOGE("%s", source_not_defined_error);
424 return false;
425 }
426 generator_ptr->begin();
427 notifyAudioChange(generator_ptr->audioInfo());
428 active = true;
429 return active;
430 }
431
433 bool begin(AudioInfo cfg) {
434 TRACED();
435 if (generator_ptr == nullptr) {
436 LOGE("%s", source_not_defined_error);
437 return false;
438 }
439 generator_ptr->begin(cfg);
440 notifyAudioChange(generator_ptr->audioInfo());
441 active = true;
442 return active;
443 }
444
446 void end() override {
447 TRACED();
448 generator_ptr->end();
449 active = true; // legacy support - most sketches do not call begin
450 }
451
452 AudioInfo audioInfo() override { return generator_ptr->audioInfo(); }
453
455 virtual int available() override { return active ? buffer_size : 0; }
456
458 size_t readBytes(uint8_t *data, size_t len) override {
459 if (!active) return 0;
460 LOGD("GeneratedSoundStream::readBytes: %u", (unsigned int)len);
461 return generator_ptr->readBytes(data, len);
462 }
463
464 bool isActive() { return active && generator_ptr->isActive(); }
465
466 operator bool() override { return isActive(); }
467
468 void flush() override {}
469
471 void resize(int maxReadSize) { buffer_size = maxReadSize; }
472
473 protected:
474 bool active = true; // support for legacy sketches
475 SoundGenerator<T> *generator_ptr;
476 int buffer_size =
477 DEFAULT_BUFFER_SIZE * 100; // there is no reason to limit this
478 const char *source_not_defined_error = "Source not defined";
479};
480
490 public:
491 BufferedStream(size_t buffer_size) {
492 TRACED();
493 if (buffer_size > 0) resize(buffer_size);
494 }
495
496 BufferedStream(Print &out, size_t buffer_size = 1024) {
497 TRACED();
498 setOutput(out);
499 if (buffer_size > 0) resize(buffer_size);
500 }
501
502 BufferedStream(Stream &io, size_t buffer_size = 1024) {
503 TRACED();
504 setStream(io);
505 if (buffer_size > 0) resize(buffer_size);
506 }
507
508 BufferedStream(size_t buffer_size, Print &out) {
509 TRACED();
510 setOutput(out);
511 if (buffer_size > 0) resize(buffer_size);
512 }
513
514 BufferedStream(size_t buffer_size, Stream &io) {
515 TRACED();
516 setStream(io);
517 if (buffer_size > 0) resize(buffer_size);
518 }
519
520 void setOutput(Print &out) override { p_out = &out; }
521 void setStream(Print &out) { setOutput(out); }
522 void setStream(Stream &io) override {
523 p_in = &io;
524 p_out = &io;
525 }
526
528 size_t write(uint8_t c) override {
529 if (buffer.isFull()) {
530 flush();
531 }
532 return buffer.write(c);
533 }
534
536 size_t write(const uint8_t *data, size_t len) override {
537 LOGD("%s: %zu", LOG_METHOD, len);
538 int result = 0;
539 for (int j = 0; j < len; j++) {
540 result += write(data[j]);
541 }
542 return result;
543 }
544
546 void flush() override {
547 // just dump the memory of the buffer and clear it
548 if (buffer.available() > 0) {
549 writeExt(buffer.address(), buffer.available());
550 buffer.reset();
551 }
552 }
553
555 int read() override {
556 if (buffer.isEmpty()) {
557 refill();
558 }
559 uint8_t result = 0;
560 if (!buffer.read(result)) return -1;
561 return result;
562 }
563
565 int peek() override {
566 if (buffer.isEmpty()) {
567 refill();
568 }
569 uint8_t result = 0;
570 if (!buffer.peek(result)) return -1;
571 return result;
572 };
573
575 size_t readBytes(uint8_t *data, size_t len) override {
576 if (buffer.isEmpty() && len >= minReadBufferSize) {
577 return readExt(data, len);
578 } else {
579 refill(len);
580 return buffer.readArray(data, len);
581 }
582 }
583
585 size_t peekBytes(uint8_t *data, size_t len) {
586 if (buffer.isEmpty()) {
587 refill();
588 }
589 return buffer.peekArray(data, len);
590 }
591
593 int available() override {
594 if (p_in == nullptr) return 0;
595 return buffer.available() + p_in->available();
596 }
597
599 void clear() { buffer.reset(); }
600
602 void resize(int size) { buffer.resize(size); }
603
606 void setMinUnbufferedReadSize(size_t size) { minReadBufferSize = size; }
607
608 protected:
609 SingleBuffer<uint8_t> buffer{0};
610 Print *p_out = nullptr;
611 Stream *p_in = nullptr;
612 size_t minReadBufferSize = 1024;
613
615 void refill() {
616 // Preserve any existing unread data then append new bytes
617 buffer.trim();
618 size_t already_available = buffer.available();
619 size_t free_space = buffer.availableForWrite();
620 if (free_space == 0) {
621 // Buffer full – nothing we can append
622 return;
623 }
624 // Read new data directly behind existing bytes
625 size_t added = readExt(buffer.address() + already_available, free_space);
626 buffer.setAvailable(already_available + added);
627 }
628
630 void refill(size_t len) {
631 if (buffer.available() >= len) return;
632 refill();
633 }
634
635 virtual size_t writeExt(const uint8_t *data, size_t len) {
636 return p_out == nullptr ? 0 : p_out->write(data, len);
637 }
638 virtual size_t readExt(uint8_t *data, size_t len) {
639 return p_in == nullptr ? 0 : p_in->readBytes(data, len);
640 }
641};
642
651template <typename T = int16_t>
653 public:
654 ConverterStream() = default;
655
656 ConverterStream(BaseConverter &converter) { setConverter(converter); }
657
658 ConverterStream(Stream &stream, BaseConverter &converter) {
659 setConverter(converter);
660 setStream(stream);
661 }
662
663 ConverterStream(Print &out, BaseConverter &converter) {
664 setConverter(converter);
665 setOutput(out);
666 }
667
668 void setStream(Stream &stream) {
669 TRACEI();
670 p_stream = &stream;
671 p_out = &stream;
672 }
673
674 void setOutput(Print &out) {
675 TRACEI();
676 p_out = &out;
677 }
678
679 void setConverter(BaseConverter &cnv) { p_converter = &cnv; }
680
681 virtual int availableForWrite() { return p_out->availableForWrite(); }
682
683 virtual size_t write(const uint8_t *data, size_t len) {
684 size_t result = p_converter->convert((uint8_t *)data, len);
685 if (result > 0) {
686 size_t result_written = p_out->write(data, result);
687 return len * result_written / result;
688 }
689 return 0;
690 }
691
692 size_t readBytes(uint8_t *data, size_t len) override {
693 if (p_stream == nullptr) return 0;
694 size_t result = p_stream->readBytes(data, len);
695 return p_converter->convert(data, result);
696 }
697
699 virtual int available() override {
700 if (p_stream == nullptr) return 0;
701 return p_stream->available();
702 }
703
704 protected:
705 Stream *p_stream = nullptr;
706 Print *p_out = nullptr;
707 BaseConverter *p_converter;
708};
709
717 public:
718 MeasuringStream(int count = 10, Print *logOut = nullptr) {
719 this->count = count;
720 this->max_count = count;
721 p_stream = &null;
722 p_print = &null;
723 start_time = millis();
724 p_logout = logOut;
725 }
726
727 MeasuringStream(Print &print, int count = 10, Print *logOut = nullptr) {
728 this->count = count;
729 this->max_count = count;
730 setOutput(print);
731 start_time = millis();
732 p_logout = logOut;
733 }
734
735 MeasuringStream(Stream &stream, int count = 10, Print *logOut = nullptr) {
736 this->count = count;
737 this->max_count = count;
738 setStream(stream);
739 start_time = millis();
740 p_logout = logOut;
741 }
742
744 void setLogOutput(Print &out) { p_logout = &out; }
745
747 void setStream(Stream &io) override {
748 p_print = &io;
749 p_stream = &io;
750 };
751
753 void setOutput(Print &out) override { p_print = &out; }
754
756 size_t readBytes(uint8_t *data, size_t len) override {
757 total_bytes_since_begin += len;
758 return measure(p_stream->readBytes(data, len));
759 }
760
761 int available() override { return p_stream->available(); }
762
764 virtual size_t write(const uint8_t *data, size_t len) override {
765 total_bytes_since_begin += len;
766 return measure(p_print->write(data, len));
767 }
768
770 virtual int availableForWrite() override {
771 return p_print->availableForWrite();
772 }
773
775 int bytesPerSecond() { return bytes_per_second; }
776
779 if (frame_size == 0) return 0;
780 return bytes_per_second / frame_size;
781 }
782
784 uint32_t startTime() { return start_time; }
785
786 void setAudioInfo(AudioInfo info) override {
787 AudioStream::info = info;
788 setFrameSize(info.bits_per_sample / 8 * info.channels);
789 }
790
791 bool begin() override {
792 total_bytes_since_begin = 0;
793 ms_at_begin = millis();
794 return AudioStream::begin();
795 }
796
797 bool begin(AudioInfo info) {
798 setAudioInfo(info);
799 return begin();
800 }
801
803 void setFrameSize(int size) { frame_size = size; }
804
806 void setReportBytes(bool flag) { report_bytes = flag; }
807
808 void setName(const char *name) { this->name = name; }
809
811 uint32_t timeSinceBegin() { return millis() - ms_at_begin; }
812
814 uint32_t bytesSinceBegin() { return total_bytes_since_begin; }
815
817 uint32_t estimatedTotalTimeFor(uint32_t totalBytes) {
818 if (bytesSinceBegin() == 0) return 0;
819 return static_cast<float>(timeSinceBegin()) / bytesSinceBegin() *
820 totalBytes;
821 }
822
824 uint32_t estimatedOpenTimeFor(uint32_t totalBytes) {
825 if (bytesSinceBegin() == 0) return 0;
826 return estimatedTotalTimeFor(totalBytes) - timeSinceBegin();
827 }
828
831 bool setProcessedBytes(uint32_t pos) {
832 bool is_regular_update = true;
833 if (pos < total_bytes_since_begin) {
834 begin();
835 is_regular_update = false;
836 }
837 total_bytes_since_begin = pos;
838 return is_regular_update;
839 }
840
841 protected:
842 int max_count = 0;
843 int count = 0;
844 Stream *p_stream = nullptr;
845 Print *p_print = nullptr;
846 uint32_t start_time;
847 int total_bytes = 0;
848 int bytes_per_second = 0;
849 int frame_size = 0;
850 NullStream null;
851 Print *p_logout = nullptr;
852 bool report_bytes = false;
853 const char *name = "";
854 uint32_t ms_at_begin = 0;
855 uint32_t total_bytes_since_begin = 0;
856
857 size_t measure(size_t len) {
858 count--;
859 total_bytes += len;
860
861 if (count <= 0) {
862 uint32_t end_time = millis();
863 int time_diff = end_time - start_time; // in ms
864 if (time_diff > 0) {
865 bytes_per_second = total_bytes / time_diff * 1000;
866 printResult();
867 count = max_count;
868 total_bytes = 0;
869 start_time = end_time;
870 }
871 }
872 return len;
873 }
874
875 void printResult() {
876 char msg[70];
877 if (report_bytes || frame_size == 0) {
878 snprintf(msg, 70, "%s ==> Bytes per second: %d", name, bytes_per_second);
879 } else {
880 snprintf(msg, 70, "%s ==> Samples per second: %d", name,
881 bytes_per_second / frame_size);
882 }
883 if (p_logout != nullptr) {
884 p_logout->println(msg);
885 } else {
886 LOGI("%s", msg);
887 }
888 }
889};
890
898 public:
899 size_t total_size = 0;
900};
909 public:
910 ProgressStream() = default;
911
912 ProgressStream(Print &print) { setPrint(print); }
913
914 ProgressStream(Stream &stream) { setStream(stream); }
915
916 ProgressStream(AudioStream &stream) {
917 setStream(stream);
918 p_info_from = &stream;
919 }
920
921 ProgressStreamInfo &defaultConfig() { return progress_info; }
922
923 void setAudioInfo(AudioInfo info) override {
925 progress_info.copyFrom(info);
926 }
927
928 void setStream(Stream &stream) override {
929 p_stream = &stream;
930 p_print = &stream;
931 }
932
933 void setStream(Print &print) { p_print = &print; }
934
935 void setPrint(Print &print) { p_print = &print; }
936
937 bool begin() override {
938 if (p_info_from != nullptr) {
939 setAudioInfo(p_info_from->audioInfo());
940 }
941 return AudioStream::begin();
942 }
943
946 bool begin(size_t len) {
947 setSize(len);
948 return begin();
949 }
950
951 bool begin(ProgressStreamInfo info) {
952 progress_info = info;
953 setAudioInfo(info);
954 return begin();
955 }
956
958 void setSize(size_t len) {
959 total_processed = 0;
960 progress_info.total_size = len;
961 }
962
964 size_t size() { return progress_info.total_size; }
965
967 size_t processedBytes() { return total_processed; }
968
970 size_t processedSecs() { return total_processed / byteRate(); }
971
973 size_t totalBytes() { return progress_info.total_size; }
974
976 size_t totalSecs() { return totalBytes() / byteRate(); }
977
979 float percentage() {
980 if (progress_info.total_size == 0) return 0;
981 return 100.0 * total_processed / progress_info.total_size;
982 }
983
985 size_t readBytes(uint8_t *data, size_t len) override {
986 if (p_stream == nullptr) return 0;
987 return measure(p_stream->readBytes(data, len));
988 }
989
990 int available() override {
991 if (p_stream == nullptr) return 0;
992 return p_stream->available();
993 }
994
996 virtual size_t write(const uint8_t *data, size_t len) override {
997 if (p_print == nullptr) return 0;
998 return measure(p_print->write(data, len));
999 }
1000
1002 virtual int availableForWrite() override {
1003 if (p_print == nullptr) return 0;
1004 return p_print->availableForWrite();
1005 }
1006
1007 protected:
1008 ProgressStreamInfo progress_info;
1009 Stream *p_stream = nullptr;
1010 Print *p_print = nullptr;
1011 AudioInfoSupport *p_info_from = nullptr;
1012 size_t total_processed = 0;
1013
1014 size_t measure(size_t len) {
1015 total_processed += len;
1016 return len;
1017 }
1018
1019 size_t byteRate() {
1020 AudioInfo info = audioInfo();
1021 int byte_rate = info.sample_rate * info.bits_per_sample * info.channels / 8;
1022 if (byte_rate == 0) {
1023 LOGE("Audio Info not defined");
1024 return 0;
1025 }
1026 return byte_rate;
1027 }
1028};
1029
1035struct ThrottleConfig : public AudioInfo {
1036 ThrottleConfig() {
1037 sample_rate = 44100;
1038 bits_per_sample = 16;
1039 channels = 2;
1040 }
1041 int correction_us = 0;
1042};
1043
1051 public:
1052 Throttle() = default;
1053 Throttle(Print &out) { setOutput(out); }
1054 Throttle(Stream &io) { setStream(io); }
1055
1057 void setStream(Stream &io) override {
1058 p_out = &io;
1059 p_in = &io;
1060 };
1061
1063 void setOutput(Print &out) override { p_out = &out; }
1064
1065 ThrottleConfig defaultConfig() {
1067 return c;
1068 }
1069
1070 bool begin(ThrottleConfig cfg) {
1071 LOGI("begin sample_rate: %d, channels: %d, bits: %d", (int)info.sample_rate,
1072 (int)info.channels, (int)info.bits_per_sample);
1073 this->info = cfg;
1074 this->cfg = cfg;
1075 return begin();
1076 }
1077
1078 bool begin(AudioInfo info) {
1079 LOGI("begin sample_rate: %d, channels: %d, bits: %d", (int)info.sample_rate,
1080 (int)info.channels, (int)info.bits_per_sample);
1081 this->info = info;
1082 this->cfg.copyFrom(info);
1083 return begin();
1084 }
1085
1086 bool begin() override {
1087 frame_size = cfg.bits_per_sample / 8 * cfg.channels;
1088 startDelay();
1089 return true;
1090 }
1091
1092 // (re)starts the timing
1093 void startDelay() {
1094 start_time = micros();
1095 sum_frames = 0;
1096 }
1097
1098 int availableForWrite() override {
1099 if (p_out) {
1100 return p_out->availableForWrite();
1101 }
1102 return DEFAULT_BUFFER_SIZE;
1103 }
1104
1105 size_t write(const uint8_t *data, size_t len) override {
1106 size_t result = p_out->write(data, len);
1107 delayBytes(len);
1108 return result;
1109 }
1110
1111 int available() override {
1112 if (p_in == nullptr) return 0;
1113 return p_in->available();
1114 }
1115
1116 size_t readBytes(uint8_t *data, size_t len) override {
1117 if (p_in == nullptr) {
1118 delayBytes(len);
1119 return 0;
1120 }
1121 size_t result = p_in->readBytes(data, len);
1122 delayBytes(len);
1123 return result;
1124 }
1125
1126 // delay
1127 void delayBytes(size_t bytes) { delayFrames(bytes / frame_size); }
1128
1129 // delay
1130 void delayFrames(size_t frames) {
1131 sum_frames += frames;
1132 uint64_t durationUsEff = micros() - start_time;
1133 uint64_t durationUsToBe = getDelayUs(sum_frames);
1134 int64_t waitUs = durationUsToBe - durationUsEff + cfg.correction_us;
1135 LOGD("wait us: %ld", static_cast<long>(waitUs));
1136 if (waitUs > 0) {
1137 int64_t waitMs = waitUs / 1000;
1138 if (waitMs > 0) delay(waitMs);
1139 delayMicroseconds(waitUs - (waitMs * 1000));
1140 } else {
1141 LOGD("negative delay!")
1142 }
1143 }
1144
1145 inline int64_t getDelayUs(uint64_t frames) {
1146 return (frames * 1000000) / cfg.sample_rate;
1147 }
1148
1149 inline int64_t getDelayMs(uint64_t frames) {
1150 return getDelayUs(frames) / 1000;
1151 }
1152
1153 inline int64_t getDelaySec(uint64_t frames) {
1154 return getDelayUs(frames) / 1000000l;
1155 }
1156
1157 protected:
1158 uint32_t start_time = 0;
1159 uint32_t sum_frames = 0;
1160 ThrottleConfig cfg;
1161 int frame_size = 0;
1162 Print *p_out = nullptr;
1163 Stream *p_in = nullptr;
1164};
1165
1175template <typename T>
1176class InputMixer : public AudioStream {
1177 public:
1178 InputMixer() = default;
1179
1181 int add(Stream &in, int weight = 100) {
1182 streams.push_back(&in);
1183 weights.push_back(weight);
1184 total_weights += weight;
1185 return streams.indexOf(&in);
1186 }
1187
1189 bool set(int index, Stream &in) {
1190 if (index < size()) {
1191 streams[index] = &in;
1192 return true;
1193 } else {
1194 LOGE("Invalid index %d - max is %d", index, size() - 1);
1195 return false;
1196 }
1197 }
1198
1199 virtual bool begin(AudioInfo info) {
1200 setAudioInfo(info);
1201 frame_size = info.bits_per_sample / 8 * info.channels;
1202 LOGI("frame_size: %d", frame_size);
1203 return frame_size > 0;
1204 }
1205
1209 void setWeight(int index, int weight) {
1210 if (index < streams.size()) {
1211 weights[index] = weight;
1213 } else {
1214 LOGE("Invalid index %d - max is %d", index, size() - 1);
1215 }
1216 }
1217
1219 void end() override {
1220 streams.clear();
1221 weights.clear();
1222 result_vect.clear();
1223 current_vect.clear();
1224 total_weights = 0.0;
1225 }
1226
1228 int size() { return streams.size(); }
1229
1231 size_t readBytes(uint8_t *data, size_t len) override {
1232 if (total_weights == 0 || frame_size == 0 || len == 0) {
1233 LOGW("readBytes: %d", (int)len);
1234 return 0;
1235 }
1236
1237 if (limit_available_data) {
1238 len = min((int)len, availableBytes());
1239 }
1240
1241 int result_len = 0;
1242
1243 if (len > 0) {
1244 // result_len must be full frames
1245 result_len = len * frame_size / frame_size;
1246 // replace sample based with vector based implementation
1247 // readBytesSamples((T*)data, result_len));
1248 result_len = readBytesVector((T *)data, result_len);
1249 }
1250 return result_len;
1251 }
1252
1255 void setLimitToAvailableData(bool flag) { limit_available_data = flag; }
1256
1259 void setRetryCount(int retry) { retry_count = retry; }
1260
1262 bool remove(int idx) {
1263 if (idx < 0 || idx >= size()) {
1264 return false;
1265 }
1266 streams.erase(idx);
1267 weights.erase(idx);
1269 return true;
1270 }
1271
1273 bool remove() {
1274 bool rc = false;
1275 int idx = nextEmptyIndex();
1276 while (idx >= 0) {
1277 rc = true;
1278 streams.erase(idx);
1279 weights.erase(idx);
1280 idx = nextEmptyIndex();
1281 }
1283 return rc;
1284 }
1285
1287 int indexOf(Stream &stream) { return streams.indexOf(&stream); }
1288
1290 Stream *operator[](int idx) {
1291 if (idx < 0 || idx >= size()) return nullptr;
1292 return streams[idx];
1293 }
1294
1297 for (int i = 0; i < streams.size(); i++) {
1298 if (streams[i]->available() == 0) {
1299 return i;
1300 }
1301 }
1302 return -1;
1303 }
1304
1305 protected:
1306 Vector<Stream *> streams{0};
1307 Vector<int> weights{0};
1308 int total_weights = 0;
1309 int frame_size = 4;
1310 bool limit_available_data = false;
1311 int retry_count = 5;
1312 Vector<int> result_vect;
1313 Vector<T> current_vect;
1314
1317 int total = 0;
1318 for (int j = 0; j < weights.size(); j++) {
1319 total += weights[j];
1320 }
1321 total_weights = total;
1322 }
1323
1325 int readBytesVector(T *p_data, int byteCount) {
1326 int samples = byteCount / sizeof(T);
1327 result_vect.resize(samples);
1328 current_vect.resize(samples);
1329 int stream_count = size();
1330 resultClear();
1331 int samples_eff_max = 0;
1332 for (int j = 0; j < stream_count; j++) {
1333 if (weights[j] > 0) {
1334 int samples_eff =
1335 readSamples(streams[j], current_vect.data(), samples, retry_count);
1336 if (samples_eff > samples_eff_max) samples_eff_max = samples_eff;
1337 // if all weights are 0.0 we stop to output
1338 float factor = total_weights == 0.0f
1339 ? 0.0f
1340 : static_cast<float>(weights[j]) / total_weights;
1341 resultAdd(factor);
1342 }
1343 }
1344 // copy result
1345 for (int j = 0; j < samples; j++) {
1346 p_data[j] = result_vect[j];
1347 }
1348 return samples_eff_max * sizeof(T);
1349 }
1350
1353 int result = DEFAULT_BUFFER_SIZE;
1354 for (int j = 0; j < size(); j++) {
1355 result = min(result, streams[j]->available());
1356 }
1357 return result;
1358 }
1359
1360 void resultAdd(float fact) {
1361 for (int j = 0; j < current_vect.size(); j++) {
1362 current_vect[j] *= fact;
1363 result_vect[j] += current_vect[j];
1364 }
1365 }
1366
1367 void resultClear() {
1368 memset(result_vect.data(), 0, sizeof(int) * result_vect.size());
1369 }
1370};
1371
1381template <typename T>
1382class InputMerge : public AudioStream {
1383 public:
1385 InputMerge() = default;
1386
1390 InputMerge(Stream &left, Stream &right) {
1391 add(left, 1);
1392 add(right, 1);
1393 };
1394
1398 info.channels = total_channel_count;
1399 return info;
1400 }
1401
1402 virtual bool begin(AudioInfo info) {
1403 setAudioInfo(info);
1404 return begin();
1405 }
1406
1407 virtual bool begin() override {
1408 // make sure that we use the correct channel count
1409 info.channels = channelCount();
1410 return AudioStream::begin();
1411 }
1412
1414 size_t readBytes(uint8_t *data, size_t len) override {
1415 LOGD("readBytes: %d", (int)len);
1416 T *p_data = (T *)data;
1417 int result_len = MIN(available(), len);
1418 int frames = result_len / (sizeof(T) * total_channel_count);
1419 int result_idx = 0;
1420 for (int j = 0; j < frames; j++) {
1421 for (int i = 0; i < records.size(); i++) {
1422 for (int ch = 0; ch < records[i].channels; ch++) {
1423 p_data[result_idx++] =
1424 records[i].weight * readSample<T>(records[i].stream);
1425 }
1426 }
1427 }
1428 return result_idx * sizeof(T);
1429 }
1430
1432 void add(Stream &in, int channelCount, float weight = 1.0) {
1433 MergeRecord rec(&in, channelCount, weight);
1434 records.push_back(rec);
1435 total_channel_count += channelCount;
1436 }
1437
1440 void setWeight(int channel, float weight) {
1441 if (channel < channelCount()) {
1442 records[channel].weight = weight;
1443 } else {
1444 LOGE("Invalid channel %d - max is %d", channel, channelCount() - 1);
1445 }
1446 }
1447
1449 void end() override { records.clear(); }
1450
1452 int channelCount() { return total_channel_count; }
1453
1455 int available() override {
1456 int result = records[0].stream->available();
1457 for (int j = 1; j < channelCount(); j++) {
1458 int tmp = records[j].stream->available();
1459 if (tmp < result) {
1460 result = tmp;
1461 }
1462 }
1463 return result;
1464 }
1465
1466 protected:
1468 Stream *stream = nullptr;
1469 int channels = 0;
1470 float weight = 1.0;
1471 MergeRecord() = default;
1472 MergeRecord(Stream *str, int ch, float w) {
1473 stream = str;
1474 channels = ch;
1475 weight = w;
1476 }
1477 };
1478 Vector<MergeRecord> records;
1479 int total_channel_count = 0;
1480};
1481
1492 public:
1493 CallbackStream() = default;
1494
1497 CallbackStream(Stream &io, size_t (*cb_update)(uint8_t *data, size_t len)) {
1498 p_stream = &io;
1499 p_out = &io;
1500 setUpdateCallback(cb_update);
1501 }
1502
1504 CallbackStream(Print &out, size_t (*cb_update)(uint8_t *data, size_t len)) {
1505 p_out = &out;
1506 setUpdateCallback(cb_update);
1507 }
1508
1509 CallbackStream(size_t (*cb_read)(uint8_t *data, size_t len),
1510 size_t (*cb_write)(const uint8_t *data, size_t len)) {
1511 setWriteCallback(cb_write);
1512 setReadCallback(cb_read);
1513 }
1514
1515 void setWriteCallback(size_t (*cb_write)(const uint8_t *data, size_t len)) {
1516 this->cb_write = cb_write;
1517 }
1518
1519 void setReadCallback(size_t (*cb_read)(uint8_t *data, size_t len)) {
1520 this->cb_read = cb_read;
1521 }
1522
1523 void setUpdateCallback(size_t (*cb_update)(uint8_t *data, size_t len)) {
1524 this->cb_update = cb_update;
1525 }
1526
1527 // callback result negative -> no change; callbeack result >=0 provides the
1528 // result
1529 void setAvailableCallback(int (*cb)()) { this->cb_available = cb; }
1530
1532 void setAudioInfoCallback(void (*cb)(AudioInfo info)) {
1533 this->cb_audio_info = cb;
1534 }
1535
1537 void setAudioInfo(AudioInfo info) override {
1539 if (cb_audio_info != nullptr) {
1540 cb_audio_info(info);
1541 }
1542 }
1543
1544 virtual bool begin(AudioInfo info) {
1545 setAudioInfo(info);
1546 return begin();
1547 }
1548 virtual bool begin() override {
1549 active = true;
1550 return true;
1551 }
1552
1553 void end() override { active = false; }
1554
1555 int available() override {
1556 int result = AudioStream::available();
1557 // determine value from opional variable
1558 if (available_bytes >= 0) return available_bytes;
1559 // check if there is a callback
1560 if (cb_available == nullptr) return result;
1561 // determine value from callback
1562 int tmp_available = cb_available();
1563 if (tmp_available < 0) return result;
1564
1565 return tmp_available;
1566 }
1567
1568 size_t readBytes(uint8_t *data, size_t len) override {
1569 if (!active) return 0;
1570 // provide data from callback
1571 if (cb_read) {
1572 return cb_read(data, len);
1573 }
1574 // provide data from source
1575 size_t result = 0;
1576 if (p_stream) {
1577 result = p_stream->readBytes(data, len);
1578 }
1579 if (cb_update) {
1580 result = cb_update(data, result);
1581 }
1582 return result;
1583 }
1584
1585 size_t write(const uint8_t *data, size_t len) override {
1586 if (!active) return 0;
1587 // write to callback
1588 if (cb_write) {
1589 return cb_write(data, len);
1590 }
1591 // write to output
1592 if (p_out) {
1593 size_t result = len;
1594 if (cb_update) {
1595 result = cb_update((uint8_t *)data, len);
1596 }
1597 return p_out->write(data, result);
1598 }
1599 // no processing possible
1600 return 0;
1601 }
1602
1604 void setStream(Stream &in) override {
1605 p_stream = &in;
1606 p_out = &in;
1607 }
1608
1610 void setOutput(Print &out) override { p_out = &out; }
1611
1613 void setOutput(Stream &in) {
1614 p_stream = &in;
1615 p_out = &in;
1616 }
1617
1619 void setStream(Print &out) { p_out = &out; }
1620
1622 void setAvailable(int val) { available_bytes = val; }
1623
1624 protected:
1625 bool active = true;
1626 size_t (*cb_write)(const uint8_t *data, size_t len) = nullptr;
1627 size_t (*cb_read)(uint8_t *data, size_t len) = nullptr;
1628 size_t (*cb_update)(uint8_t *data, size_t len) = nullptr;
1629 void (*cb_audio_info)(AudioInfo info) = nullptr;
1630 int (*cb_available)() = nullptr;
1631 Stream *p_stream = nullptr;
1632 Print *p_out = nullptr;
1633 int available_bytes = -1;
1634};
1635
1643template <typename T = int16_t, class TF = float>
1645 public:
1646 FilteredStream() = default;
1647 FilteredStream(Stream &stream) : ModifyingStream() { setStream(stream); }
1648 FilteredStream(Stream &stream, int channels) : ModifyingStream() {
1649 this->channels = channels;
1650 setStream(stream);
1651 p_converter = new ConverterNChannels<T, TF>(channels);
1652 }
1653 FilteredStream(Print &stream) : ModifyingStream() { setOutput(stream); }
1654 FilteredStream(Print &stream, int channels) : ModifyingStream() {
1655 this->channels = channels;
1656 setOutput(stream);
1657 p_converter = new ConverterNChannels<T, TF>(channels);
1658 }
1659
1660 virtual ~FilteredStream() { end(); }
1661
1662 void setStream(Stream &stream) override {
1663 p_stream = &stream;
1664 p_print = &stream;
1665 }
1666
1667 void setOutput(Print &stream) override { p_print = &stream; }
1668
1669 bool begin(AudioInfo info) {
1670 setAudioInfo(info);
1671 this->channels = info.channels;
1672 if (p_converter != nullptr && p_converter->getChannels() != channels) {
1673 LOGE("Inconsistent number of channels");
1674 return false;
1675 }
1676 return begin();
1677 }
1678
1679 bool begin() override {
1680 if (channels == 0) {
1681 LOGE("channels must not be 0");
1682 return false;
1683 }
1684 if (p_converter == nullptr) {
1685 p_converter = new ConverterNChannels<T, TF>(channels);
1686 }
1687 return AudioStream::begin();
1688 }
1689
1690 void end() override {
1691 ModifyingStream::end();
1692 if (p_converter != nullptr) {
1693 delete p_converter;
1694 p_converter = nullptr;
1695 }
1696 }
1697
1698 virtual size_t write(const uint8_t *data, size_t len) override {
1699 if (p_converter == nullptr) return 0;
1700 size_t result = p_converter->convert((uint8_t *)data, len);
1701 return p_print->write(data, result);
1702 }
1703
1704 size_t readBytes(uint8_t *data, size_t len) override {
1705 if (p_converter == nullptr) return 0;
1706 if (p_stream == nullptr) return 0;
1707 size_t result = p_stream->readBytes(data, len);
1708 result = p_converter->convert(data, result);
1709 return result;
1710 }
1711
1712 virtual int available() override {
1713 if (p_stream == nullptr) return 0;
1714 return p_stream->available();
1715 }
1716
1717 virtual int availableForWrite() override {
1718 return p_print->availableForWrite();
1719 }
1720
1724 void setFilter(int channel, Filter<TF> *filter) {
1725 if (p_converter != nullptr) {
1726 p_converter->setFilter(channel, filter);
1727 } else {
1728 LOGE("p_converter is null");
1729 }
1730 }
1731
1735 void setFilter(int channel, Filter<TF> &filter) {
1736 setFilter(channel, &filter);
1737 }
1738
1739 protected:
1740 int channels = 0;
1741 Stream *p_stream = nullptr;
1742 Print *p_print = nullptr;
1743 ConverterNChannels<T, TF> *p_converter = nullptr;
1744};
1745
1747using ActivityCallback = void (*)(bool isActive);
1748
1759 public:
1760 VolumeMeter() = default;
1761 VolumeMeter(AudioStream &as) { setStream(as); }
1762 VolumeMeter(AudioOutput &ao) { setOutput(ao); }
1763 VolumeMeter(Print &print) { setOutput(print); }
1764 VolumeMeter(Stream &stream) { setStream(stream); }
1765
1766 bool begin(AudioInfo info) {
1767 setAudioInfo(info);
1768 return begin();
1769 }
1770
1771 bool begin() override {
1773 return true;
1774 }
1775
1776 void setAudioInfo(AudioInfo info) override {
1777 int channels = info.channels;
1778 LOGI("VolumeMeter::setAudioInfo: channels %d", channels);
1780 if (channels > 0) {
1781 volumes.resize(channels);
1782 volumes_tmp.resize(channels);
1783 sum.resize(channels);
1784 sum_tmp.resize(channels);
1785 }
1786 }
1787
1788 size_t write(const uint8_t *data, size_t len) override {
1789 updateVolumes(data, len);
1790 size_t result = len;
1791 if (p_out != nullptr) {
1792 result = p_out->write(data, len);
1793 }
1794 return result;
1795 }
1796
1797 size_t readBytes(uint8_t *data, size_t len) override {
1798 if (p_stream == nullptr) return 0;
1799 size_t result = p_stream->readBytes(data, len);
1800 updateVolumes((const uint8_t *)data, len);
1801 return result;
1802 }
1803
1806 float volume() { return f_volume; }
1807
1810 float volume(int channel) {
1811 if (volumes.size() == 0) {
1812 LOGE("begin not called!");
1813 return 0.0f;
1814 }
1815 if (channel >= volumes.size()) {
1816 LOGE("invalid channel %d", channel);
1817 return 0.0f;
1818 }
1819 return volumes[channel];
1820 }
1821
1823 float volumeRatio() {
1825 }
1826
1828 float volumeRatio(int channel) {
1829 return volume(channel) / NumberConverter::maxValue(info.bits_per_sample);
1830 }
1831
1833 float volumeDB() {
1834 // prevent infinite value
1835 if (volumeRatio() == 0) return -1000;
1836 return 20.0f * log10(volumeRatio());
1837 }
1838
1840 float volumeDB(int channel) {
1841 // prevent infinite value
1842 if (volumeRatio(channel) == 0) return -1000;
1843 return 20.0f * log10(volumeRatio(channel));
1844 }
1845
1847 float volumePercent() { return 100.0f * volumeRatio(); }
1848
1850 float volumePercent(int channel) { return 100.0f * volumeRatio(channel); }
1851
1853 float volumeAvg() {
1854 float total = 0;
1855 size_t count = 0;
1856 for (int j = 0; j < info.channels; j++) {
1857 total += sum[j];
1858 count += sample_count_per_channel;
1859 }
1860 return total / count;
1861 }
1862
1864 float volumeAvg(int channel) {
1865 return sum[channel] / sample_count_per_channel;
1866 }
1867
1869 void clear() {
1870 f_volume_tmp = 0;
1871 for (int j = 0; j < info.channels; j++) {
1872 volumes_tmp[j] = 0;
1873 sum_tmp[j] = 0;
1874 }
1875 }
1876
1881 void setActivityCallback(ActivityCallback callback, float threshold = 0.2, unsigned long duration_ms = 2000) {
1882 activity_callback = callback;
1883 activity_threshold = threshold;
1884 activity_duration_ms = duration_ms;
1885 activity_monitoring_enabled = (callback != nullptr);
1886 }
1887
1890 bool isActive() const {
1891 return is_active;
1892 }
1893
1894 void setOutput(AudioOutput &out) {
1896 setOutput((Print &)out);
1897 }
1898 void setStream(AudioStream &io) {
1900 setStream((Stream &)io);
1901 }
1902 void setOutput(Print &out) override { p_out = &out; }
1903 void setStream(Stream &io) override {
1904 p_out = &io;
1905 p_stream = &io;
1906 }
1907
1908 protected:
1909 float f_volume_tmp = 0;
1910 float f_volume = 0;
1911 Vector<float> volumes{0};
1912 Vector<float> volumes_tmp{0};
1913 Vector<float> sum{0};
1914 Vector<float> sum_tmp{0};
1915 Print *p_out = nullptr;
1916 Stream *p_stream = nullptr;
1917 size_t sample_count_per_channel = 0;
1918
1919 // Activity monitoring
1920 ActivityCallback activity_callback = nullptr;
1921 float activity_threshold = 0.0f;
1922 unsigned long activity_duration_ms = 0;
1923 bool activity_monitoring_enabled = false;
1924 bool is_active = false;
1925 unsigned long inactive_start_time = 0;
1926
1927 void updateVolumes(const uint8_t *data, size_t len) {
1928 if (data == nullptr || len == 0) return;
1929 clear();
1930 switch (info.bits_per_sample) {
1931 case 8:
1932 updateVolumesT<int8_t>(data, len);
1933 break;
1934 case 16:
1935 updateVolumesT<int16_t>(data, len);
1936 break;
1937 case 24:
1938 updateVolumesT<int24_t>(data, len);
1939 break;
1940 case 32:
1941 updateVolumesT<int32_t>(data, len);
1942 break;
1943 default:
1944 LOGE("Unsupported bits_per_sample: %d", info.bits_per_sample);
1945 break;
1946 }
1947 }
1948
1949 template <typename T>
1950 void updateVolumesT(const uint8_t *buffer, size_t size) {
1951 T *bufferT = (T *)buffer;
1952 int samplesCount = size / sizeof(T);
1953 sample_count_per_channel = samplesCount / info.channels;
1954 for (int j = 0; j < samplesCount; j++) {
1955 float tmp = abs(static_cast<float>(bufferT[j]));
1956 updateVolume(tmp, j);
1957 }
1958 commit();
1959 }
1960
1961 void updateVolume(float tmp, int j) {
1962 if (tmp > f_volume_tmp) {
1963 f_volume_tmp = tmp;
1964 }
1965 if (volumes_tmp.size() > 0 && info.channels > 0) {
1966 int ch = j % info.channels;
1967 if (tmp > volumes_tmp[ch]) {
1968 volumes_tmp[ch] = tmp;
1969 sum_tmp[ch] = tmp;
1970 }
1971 }
1972 }
1973
1974 void commit() {
1975 f_volume = f_volume_tmp;
1976 for (int j = 0; j < info.channels; j++) {
1977 volumes[j] = volumes_tmp[j];
1978 sum[j] = sum_tmp[j];
1979 }
1980 updateActivityState();
1981 }
1982
1983 void updateActivityState() {
1984 if (!activity_monitoring_enabled || activity_callback == nullptr) return;
1985
1986 float current_volume_ratio = volumeRatio();
1987 bool above_threshold = current_volume_ratio > activity_threshold;
1988 unsigned long current_time = millis();
1989
1990 if (above_threshold) {
1991 // Volume is above threshold - should be active
1992 if (!is_active) {
1993 is_active = true;
1994 activity_callback(true);
1995 }
1996 inactive_start_time = 0; // Reset inactive timer
1997 } else {
1998 // Volume is below threshold
1999 if (is_active) {
2000 // Currently active, check if we should transition to inactive
2001 if (inactive_start_time == 0) {
2002 // Start timing the inactive period
2003 inactive_start_time = current_time;
2004 } else if (current_time - inactive_start_time >= activity_duration_ms) {
2005 // Been below threshold long enough
2006 is_active = false;
2007 activity_callback(false);
2008 inactive_start_time = 0;
2009 }
2010 }
2011 }
2012 }
2013};
2014
2015// legacy names
2019
2023
2037 public:
2071 setOutput(print);
2072 }
2080 setStream(stream);
2081 }
2086 void setLimitPercent(uint8_t percent) { limit_percent = percent; }
2087
2092 uint8_t limitPercent() const { return limit_percent; }
2093
2099 bool begin(AudioInfo info) {
2100 setAudioInfo(info);
2101 return begin();
2102 }
2103
2108 bool begin() override {
2109 volume_meter.begin(audioInfo());
2110 return true;
2111 }
2112
2117 void setAudioInfo(AudioInfo info) override {
2120 }
2121
2128 size_t write(const uint8_t *data, size_t len) override {
2129 size_t result = volume_meter.write(data, len);
2130 if (result > 0 && volume_meter.volumePercent() > limit_percent) {
2132 }
2133 return result;
2134 }
2135
2142 size_t readBytes(uint8_t *data, size_t len) override {
2143 size_t result = volume_meter.readBytes(data, len);
2144 if (result > 0 && volume_meter.volumePercent() > limit_percent) {
2146 }
2147 return result;
2148 }
2149
2154 void setOutput(Print &out) override { volume_meter.setOutput(out); }
2159 void setOutput(AudioOutput &out) { volume_meter.setOutput(out); }
2164 void setStream(Stream &io) override { volume_meter.setStream(io); }
2169 void setStream(AudioStream &io) { volume_meter.setStream(io); }
2170
2176
2182 bool isActive(uint16_t time_ms = 1000) {
2183 return (millis() - time_over_last_volume_limit) < time_ms;
2184 }
2185
2186protected:
2188 uint8_t limit_percent = 20;
2190};
2191
2192#ifdef USE_TIMER
2199 RxTxMode rx_tx_mode = RX_MODE;
2200 uint16_t buffer_size = DEFAULT_BUFFER_SIZE;
2201 bool use_timer = true;
2202 int timer_id = -1;
2203 TimerFunction timer_function = DirectTimerCallback;
2204 bool adapt_sample_rate = false;
2205 uint16_t (*callback)(uint8_t *data, uint16_t len) = nullptr;
2206};
2207
2208// forward declaration: relevant only if use_timer == true
2209static void timerCallback(void *obj);
2220 friend void timerCallback(void *obj);
2221
2222 public:
2223 TimerCallbackAudioStream() : BufferedStream(80) { TRACED(); }
2224
2226 TRACED();
2227 if (timer != nullptr) delete timer;
2228 if (buffer != nullptr) delete buffer;
2229 if (frame != nullptr) delete[] frame;
2230 }
2231
2237
2239 virtual void setAudioInfo(AudioInfo info) {
2240 TRACED();
2241 if (cfg.sample_rate != info.sample_rate || cfg.channels != info.channels ||
2242 cfg.bits_per_sample != info.bits_per_sample) {
2243 bool do_restart = active;
2244 if (do_restart) end();
2245 cfg.sample_rate = info.sample_rate;
2246 cfg.channels = info.channels;
2247 cfg.bits_per_sample = info.bits_per_sample;
2248 if (do_restart) begin(cfg);
2249 }
2250 }
2251
2254 AudioInfo audioInfo() { return cfg; }
2255
2256 void begin(TimerCallbackAudioStreamInfo config) {
2257 LOGD("%s: %s", LOG_METHOD,
2258 config.rx_tx_mode == RX_MODE ? "RX_MODE" : "TX_MODE");
2259 this->cfg = config;
2260 this->frameCallback = config.callback;
2261 if (cfg.use_timer) {
2262 frameSize = cfg.bits_per_sample * cfg.channels / 8;
2263 frame = new uint8_t[frameSize];
2264 buffer = new RingBuffer<uint8_t>(cfg.buffer_size);
2265 timer = new TimerAlarmRepeating();
2266 timer->setTimerFunction(cfg.timer_function);
2267 if (cfg.timer_id >= 0) {
2268 timer->setTimer(cfg.timer_id);
2269 }
2270 time = AudioTime::toTimeUs(cfg.sample_rate);
2271 LOGI("sample_rate: %u -> time: %u milliseconds",
2272 (unsigned int)cfg.sample_rate, (unsigned int)time);
2273 timer->setCallbackParameter(this);
2274 timer->begin(timerCallback, time, TimeUnit::US);
2275 }
2276
2277 notifyAudioChange(cfg);
2278 active = true;
2279 }
2280
2282 bool begin() {
2283 TRACED();
2284 if (this->frameCallback != nullptr) {
2285 if (cfg.use_timer) {
2286 timer->begin(timerCallback, time, TimeUnit::US);
2287 }
2288 active = true;
2289 }
2290 return active;
2291 }
2292
2294 void end() {
2295 TRACED();
2296 if (cfg.use_timer) {
2297 timer->end();
2298 }
2299 active = false;
2300 }
2301
2303 uint16_t currentSampleRate() { return currentRateValue; }
2304
2305 protected:
2307 bool active = false;
2308 uint16_t (*frameCallback)(uint8_t *data, uint16_t len);
2309 // below only relevant with timer
2310 TimerAlarmRepeating *timer = nullptr;
2311 RingBuffer<uint8_t> *buffer = nullptr;
2312 uint8_t *frame = nullptr;
2313 uint16_t frameSize = 0;
2314 uint32_t time = 0;
2315 unsigned long lastTimestamp = 0u;
2316 uint32_t currentRateValue = 0;
2317 uint32_t printCount = 0;
2318
2319 // used for audio sink
2320 virtual size_t writeExt(const uint8_t *data, size_t len) override {
2321 if (!active) return 0;
2322 TRACED();
2323 size_t result = 0;
2324 if (!cfg.use_timer) {
2325 result = frameCallback((uint8_t *)data, len);
2326 } else {
2327 result = buffer->writeArray((uint8_t *)data, len);
2328 }
2329 if (++printCount % 10000 == 0) printSampleRate();
2330 return result;
2331 }
2332
2333 // used for audio source
2334 virtual size_t readExt(uint8_t *data, size_t len) override {
2335 if (!active) return 0;
2336 TRACED();
2337
2338 size_t result = 0;
2339 if (!cfg.use_timer) {
2340 result = frameCallback(data, len);
2341 } else {
2342 result = buffer->readArray(data, len);
2343 }
2344 if (++printCount % 10000 == 0) printSampleRate();
2345 return result;
2346 }
2347
2349 virtual void measureSampleRate() {
2350 unsigned long ms = millis();
2351 if (lastTimestamp > 0u) {
2352 uint32_t diff = ms - lastTimestamp;
2353 if (diff > 0) {
2354 uint16_t rate = 1 * 1000 / diff;
2355
2356 if (currentRateValue == 0) {
2357 currentRateValue = rate;
2358 } else {
2359 currentRateValue = (currentRateValue + rate) / 2;
2360 }
2361 }
2362 }
2363 lastTimestamp = ms;
2364 }
2365
2367 virtual void printSampleRate() {
2368 LOGI("effective sample rate: %u", (unsigned int)currentRateValue);
2369 if (cfg.adapt_sample_rate &&
2370 abs((int)currentRateValue - (int)cfg.sample_rate) > 200) {
2371 cfg.sample_rate = currentRateValue;
2372 notifyAudioChange(cfg);
2373 }
2374 }
2375};
2376
2377// relevant only if use_timer == true
2378void IRAM_ATTR timerCallback(void *obj) {
2379 TimerCallbackAudioStream *src = (TimerCallbackAudioStream *)obj;
2380 if (src != nullptr) {
2381 // LOGD("%s: %s", LOG_METHOD, src->cfg.rx_tx_mode==RX_MODE ?
2382 // "RX_MODE":"TX_MODE");
2383 if (src->cfg.rx_tx_mode == RX_MODE) {
2384 // input
2385 uint16_t available_bytes = src->frameCallback(src->frame, src->frameSize);
2386 uint16_t buffer_available = src->buffer->availableForWrite();
2387 if (buffer_available < available_bytes) {
2388 // if buffer is full make space
2389 uint16_t to_clear = available_bytes - buffer_available;
2390 uint8_t tmp[to_clear];
2391 src->buffer->readArray(tmp, to_clear);
2392 }
2393 if (src->buffer->writeArray(src->frame, available_bytes) !=
2394 available_bytes) {
2395 assert(false);
2396 }
2397 } else {
2398 // output
2399 if (src->buffer != nullptr && src->frame != nullptr &&
2400 src->frameSize > 0) {
2401 uint16_t available_bytes =
2402 src->buffer->readArray(src->frame, src->frameSize);
2403 if (available_bytes !=
2404 src->frameCallback(src->frame, available_bytes)) {
2405 LOGE("data underflow");
2406 }
2407 }
2408 }
2409 src->measureSampleRate();
2410 }
2411}
2412
2413#endif
2414
2415} // 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:2036
void setOutput(Print &out) override
Set the output target.
Definition AudioStreams.h:2154
void setStream(AudioStream &io)
Set the input stream.
Definition AudioStreams.h:2169
AudioInputMonitor(AudioOutput &ao, uint8_t limitPercent=20)
Construct a new AudioInputMonitor with an output.
Definition AudioStreams.h:2060
uint8_t limit_percent
Threshold percent.
Definition AudioStreams.h:2188
AudioInputMonitor(Print &print, uint8_t limitPercent=20)
Construct a new AudioInputMonitor with a Print output.
Definition AudioStreams.h:2069
bool isActive(uint16_t time_ms=1000)
Returns true if the volume exceeded the limit during the last period.
Definition AudioStreams.h:2182
VolumeMeter volume_meter
Volume calculation.
Definition AudioStreams.h:2187
AudioInputMonitor(uint8_t limitPercent=20)
Construct a new AudioInputMonitor with a volume limit in percent.
Definition AudioStreams.h:2042
void setOutput(AudioOutput &out)
Set the output target.
Definition AudioStreams.h:2159
size_t readBytes(uint8_t *data, size_t len) override
Read audio data from the monitor (same as VolumeMeter)
Definition AudioStreams.h:2142
uint64_t time_over_last_volume_limit
Last over-limit time (ms)
Definition AudioStreams.h:2189
VolumeMeter & getVolumeMeter()
Access the underlying VolumeMeter.
Definition AudioStreams.h:2175
size_t write(const uint8_t *data, size_t len) override
Write audio data to the monitor (same as VolumeMeter)
Definition AudioStreams.h:2128
uint8_t limitPercent() const
Get the current volume threshold as percent.
Definition AudioStreams.h:2092
AudioInputMonitor(Stream &stream, uint8_t limitPercent=20)
Construct a new AudioInputMonitor with a Stream input.
Definition AudioStreams.h:2078
bool begin() override
Begin processing with the current audio information.
Definition AudioStreams.h:2108
void setAudioInfo(AudioInfo info) override
Set the audio information.
Definition AudioStreams.h:2117
void setStream(Stream &io) override
Set the input stream.
Definition AudioStreams.h:2164
void setLimitPercent(uint8_t percent)
Set the volume threshold as percent.
Definition AudioStreams.h:2086
bool begin(AudioInfo info)
Begin processing with the given audio information.
Definition AudioStreams.h:2099
AudioInputMonitor(AudioStream &as, uint8_t limitPercent=20)
Construct a new AudioInputMonitor with an input stream.
Definition AudioStreams.h:2051
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:489
void flush() override
empties the buffer
Definition AudioStreams.h:546
void setOutput(Print &out) override
Defines/Changes the output target.
Definition AudioStreams.h:520
void setMinUnbufferedReadSize(size_t size)
Definition AudioStreams.h:606
size_t write(uint8_t c) override
writes a byte to the buffer
Definition AudioStreams.h:528
size_t readBytes(uint8_t *data, size_t len) override
Use this method !!
Definition AudioStreams.h:575
int peek() override
peeks a byte - to be avoided
Definition AudioStreams.h:565
void refill()
refills the buffer with data from the source
Definition AudioStreams.h:615
int available() override
Returns the available bytes.
Definition AudioStreams.h:593
size_t write(const uint8_t *data, size_t len) override
Use this method: write an array.
Definition AudioStreams.h:536
size_t peekBytes(uint8_t *data, size_t len)
Provides data w/o consuming.
Definition AudioStreams.h:585
void clear()
Clears all the data in the buffer.
Definition AudioStreams.h:599
int read() override
reads a byte - to be avoided
Definition AudioStreams.h:555
void refill(size_t len)
refill only if not enough data
Definition AudioStreams.h:630
void resize(int size)
Resize the buffer.
Definition AudioStreams.h:602
void setStream(Stream &io) override
Defines/Changes the input & output.
Definition AudioStreams.h:522
CallbackStream: A Stream that allows to register callback methods for accessing and providing data....
Definition AudioStreams.h:1491
void setOutput(Print &out) override
Defines/Changes the output target.
Definition AudioStreams.h:1610
void setOutput(Stream &in)
same as setStream
Definition AudioStreams.h:1613
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:1504
void setStream(Print &out)
same as set Output
Definition AudioStreams.h:1619
void setAvailable(int val)
optioinally define available bytes for next read
Definition AudioStreams.h:1622
void setAudioInfo(AudioInfo info) override
Updates the audio info and calls the callback.
Definition AudioStreams.h:1537
void setStream(Stream &in) override
Defines/Changes the input & output.
Definition AudioStreams.h:1604
CallbackStream(Stream &io, size_t(*cb_update)(uint8_t *data, size_t len))
Definition AudioStreams.h:1497
void setAudioInfoCallback(void(*cb)(AudioInfo info))
defines the callback to receive the actual audio info
Definition AudioStreams.h:1532
Converter for n Channels which applies the indicated Filter.
Definition BaseConverter.h:1583
Both the data of the read or write operations will be converted with the help of the indicated conver...
Definition AudioStreams.h:652
void setStream(Stream &stream)
Defines/Changes the input & output.
Definition AudioStreams.h:668
void setOutput(Print &out)
Defines/Changes the output target.
Definition AudioStreams.h:674
virtual int available() override
Returns the available bytes in the buffer: to be avoided.
Definition AudioStreams.h:699
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:1644
void setStream(Stream &stream) override
Defines/Changes the input & output.
Definition AudioStreams.h:1662
void setOutput(Print &stream) override
Defines/Changes the output target.
Definition AudioStreams.h:1667
void setFilter(int channel, Filter< TF > &filter)
Definition AudioStreams.h:1735
void setFilter(int channel, Filter< TF > *filter)
Definition AudioStreams.h:1724
Source for reading generated tones. Please note.
Definition AudioStreams.h:397
void setAudioInfo(AudioInfo newInfo) override
Defines the input AudioInfo.
Definition AudioStreams.h:412
void resize(int maxReadSize)
Redefine the buffer size which is reported in available()
Definition AudioStreams.h:471
size_t readBytes(uint8_t *data, size_t len) override
privide the data as byte stream
Definition AudioStreams.h:458
void end() override
stop the processing
Definition AudioStreams.h:446
bool begin() override
start the processing
Definition AudioStreams.h:420
AudioInfo audioInfo() override
provides the actual input AudioInfo
Definition AudioStreams.h:452
bool begin(AudioInfo cfg)
start the processing
Definition AudioStreams.h:433
virtual int available() override
This is unbounded so we just return the buffer size.
Definition AudioStreams.h:455
Merges multiple input streams. So if you provide 2 mono channels you get a stereo signal as result wi...
Definition AudioStreams.h:1382
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:1414
void end() override
Remove all input streams.
Definition AudioStreams.h:1449
int available() override
Provides the min available data from all streams.
Definition AudioStreams.h:1455
void add(Stream &in, int channelCount, float weight=1.0)
Adds a new input stream with 1 channel.
Definition AudioStreams.h:1432
void setWeight(int channel, float weight)
Definition AudioStreams.h:1440
int channelCount()
Number of channels to which are mixed together = number of result channels.
Definition AudioStreams.h:1452
InputMerge(Stream &left, Stream &right)
Constructor for stereo signal from to mono input stream.
Definition AudioStreams.h:1390
AudioInfo audioInfo() override
Provides the audio info with the total channel count.
Definition AudioStreams.h:1396
MixerStream is mixing the input from Multiple Input Streams. All streams must have the same audo form...
Definition AudioStreams.h:1176
bool remove()
Removes all streams which have no data available.
Definition AudioStreams.h:1273
int nextEmptyIndex()
Provides you the index of the next empty stream. -1 when none is found.
Definition AudioStreams.h:1296
int indexOf(Stream &stream)
Provides the actual index of the stream.
Definition AudioStreams.h:1287
bool set(int index, Stream &in)
Replaces a stream at the indicated index.
Definition AudioStreams.h:1189
size_t readBytes(uint8_t *data, size_t len) override
Provides the data from all streams mixed together.
Definition AudioStreams.h:1231
void recalculateWeights()
Recalculate the weights.
Definition AudioStreams.h:1316
int add(Stream &in, int weight=100)
Adds a new input stream and returns it's actual index position.
Definition AudioStreams.h:1181
void end() override
Remove all input streams.
Definition AudioStreams.h:1219
bool remove(int idx)
Removes a stream by index position.
Definition AudioStreams.h:1262
int availableBytes()
Provides the available bytes from the first stream with data.
Definition AudioStreams.h:1352
void setLimitToAvailableData(bool flag)
Definition AudioStreams.h:1255
void setRetryCount(int retry)
Definition AudioStreams.h:1259
int readBytesVector(T *p_data, int byteCount)
mixing using a vector of samples
Definition AudioStreams.h:1325
void setWeight(int index, int weight)
Definition AudioStreams.h:1209
Stream * operator[](int idx)
Provides the stream pointer at the indicated index.
Definition AudioStreams.h:1290
int size()
Number of stremams to which are mixed together.
Definition AudioStreams.h:1228
Class which measures the thruput.
Definition AudioStreams.h:716
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:764
void setOutput(Print &out) override
Defines/Changes the output target.
Definition AudioStreams.h:753
uint32_t estimatedTotalTimeFor(uint32_t totalBytes)
Provides the estimated runtime in milliseconds for the indicated total.
Definition AudioStreams.h:817
uint32_t timeSinceBegin()
Provides the time in ms since the last call of begin()
Definition AudioStreams.h:811
size_t readBytes(uint8_t *data, size_t len) override
Provides the data from all streams mixed together.
Definition AudioStreams.h:756
int framesPerSecond()
Returns the actual thrughput in frames (samples) per second.
Definition AudioStreams.h:778
uint32_t bytesSinceBegin()
Provides the total processed bytes since the last call of begin()
Definition AudioStreams.h:814
virtual int availableForWrite() override
Provides the nubmer of bytes we can write.
Definition AudioStreams.h:770
void setFrameSize(int size)
Trigger reporting in frames (=samples) per second.
Definition AudioStreams.h:803
void setReportBytes(bool flag)
Report in bytes instead of samples.
Definition AudioStreams.h:806
uint32_t estimatedOpenTimeFor(uint32_t totalBytes)
Provides the estimated time from now to the end in ms.
Definition AudioStreams.h:824
void setLogOutput(Print &out)
Defines the logging output.
Definition AudioStreams.h:744
bool setProcessedBytes(uint32_t pos)
Definition AudioStreams.h:831
uint32_t startTime()
Provides the time when the last measurement was started.
Definition AudioStreams.h:784
void setAudioInfo(AudioInfo info) override
Defines the input AudioInfo.
Definition AudioStreams.h:786
void setStream(Stream &io) override
Defines/Changes the input & output.
Definition AudioStreams.h:747
int bytesPerSecond()
Returns the actual thrughput in bytes per second.
Definition AudioStreams.h:775
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:262
virtual void clear(bool reset=false)
clears the audio data: sets all values to 0
Definition AudioStreams.h:232
virtual uint8_t * data()
Provides access to the data array.
Definition AudioStreams.h:290
virtual void setAvailable(size_t len)
update the write_pos (e.g. when we used data() to update the array)
Definition AudioStreams.h:293
void setValue(const uint8_t *buffer, int buffer_size, MemoryType memoryType=FLASH_RAM)
Update the values (buffer and size)
Definition AudioStreams.h:299
MemoryStream(MemoryStream &&source)
Move Constructor.
Definition AudioStreams.h:111
MemoryStream(MemoryStream &source)
Copy Constructor.
Definition AudioStreams.h:108
virtual void setLoop(bool loop)
Definition AudioStreams.h:251
virtual bool resize(size_t size)
Definition AudioStreams.h:269
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:138
MemoryStream & operator=(MemoryStream &other)
copy assignement operator
Definition AudioStreams.h:123
bool begin(AudioInfo info)
Define some audio info and start the processing.
Definition AudioStreams.h:132
void setRewindCallback(void(*cb)())
Callback which is executed when we rewind (in loop mode) to the beginning.
Definition AudioStreams.h:296
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:908
bool begin(size_t len)
Definition AudioStreams.h:946
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:996
size_t size()
Provides the current total size (defined by setSize)
Definition AudioStreams.h:964
void setStream(Stream &stream) override
Defines/Changes the input & output.
Definition AudioStreams.h:928
size_t totalSecs()
Converts the totalBytes() to seconds.
Definition AudioStreams.h:976
size_t readBytes(uint8_t *data, size_t len) override
Provides the data from all streams mixed together.
Definition AudioStreams.h:985
size_t processedBytes()
Provides the number of processed bytes.
Definition AudioStreams.h:967
void setSize(size_t len)
Updates the total size and restarts the percent calculation.
Definition AudioStreams.h:958
virtual int availableForWrite() override
Provides the nubmer of bytes we can write.
Definition AudioStreams.h:1002
float percentage()
Provides the processed percentage: If no size has been defined we return 0.
Definition AudioStreams.h:979
size_t processedSecs()
Provides the number of processed seconds.
Definition AudioStreams.h:970
void setAudioInfo(AudioInfo info) override
Defines the input AudioInfo.
Definition AudioStreams.h:923
size_t totalBytes()
Provides the total_size provided in the configuration.
Definition AudioStreams.h:973
Configuration for ProgressStream.
Definition AudioStreams.h:897
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:341
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:1050
void setOutput(Print &out) override
Defines/Changes the output target.
Definition AudioStreams.h:1063
void setStream(Stream &io) override
Defines/Changes the input & output.
Definition AudioStreams.h:1057
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:2219
TimerCallbackAudioStreamInfo audioInfoExt()
Provides the current audio information.
Definition AudioStreams.h:2253
uint16_t currentSampleRate()
Provides the effective sample rate.
Definition AudioStreams.h:2303
TimerCallbackAudioStreamInfo defaultConfig()
Provides the default configuration.
Definition AudioStreams.h:2233
bool begin()
Restart the processing.
Definition AudioStreams.h:2282
AudioInfo audioInfo()
provides the actual input AudioInfo
Definition AudioStreams.h:2254
virtual void measureSampleRate()
calculates the effective sample rate
Definition AudioStreams.h:2349
virtual void setAudioInfo(AudioInfo info)
updates the audio information
Definition AudioStreams.h:2239
virtual void printSampleRate()
log and update effective sample rate
Definition AudioStreams.h:2367
void end()
Stops the processing.
Definition AudioStreams.h:2294
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:1758
void setOutput(Print &out) override
Defines/Changes the output target.
Definition AudioStreams.h:1902
float volumeRatio()
Volume Ratio: max amplitude is 1.0.
Definition AudioStreams.h:1823
float volumeAvg(int channel)
Average volume of indicated channel.
Definition AudioStreams.h:1864
float volume()
Definition AudioStreams.h:1806
bool isActive() const
Definition AudioStreams.h:1890
float volumePercent()
Volume in %: max amplitude is 100.
Definition AudioStreams.h:1847
float volumePercent(int channel)
Volume of indicated channel in %: max amplitude is 100.
Definition AudioStreams.h:1850
float volumeAvg()
Average volume of all channels.
Definition AudioStreams.h:1853
void setActivityCallback(ActivityCallback callback, float threshold=0.2, unsigned long duration_ms=2000)
Definition AudioStreams.h:1881
void clear()
Resets the actual volume.
Definition AudioStreams.h:1869
float volumeRatio(int channel)
Volume Ratio of indicated channel: max amplitude is 1.0.
Definition AudioStreams.h:1828
float volumeDB(int channel)
Volume of indicated channel in db: max amplitude is 0.
Definition AudioStreams.h:1840
void setAudioInfo(AudioInfo info) override
Defines the input AudioInfo.
Definition AudioStreams.h:1776
void setStream(Stream &io) override
Defines/Changes the input & output.
Definition AudioStreams.h:1903
float volumeDB()
Volume in db: max amplitude is 0 (range: -1000 to 0)
Definition AudioStreams.h:1833
float volume(int channel)
Definition AudioStreams.h:1810
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:470
void(*)(bool isActive) ActivityCallback
Callback function type for activity state changes.
Definition AudioStreams.h:1747
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:1467
Configure Throttle setting.
Definition AudioStreams.h:1035
TimerCallbackAudioStream Configuration.
Definition AudioStreams.h:2198