arduino-audio-tools
Loading...
Searching...
No Matches
AudioIO.h
Go to the documentation of this file.
1#pragma once
5
6#ifndef MAX_ZERO_READ_COUNT
7#define MAX_ZERO_READ_COUNT 3
8#endif
9
10#ifndef CHANNEL_SELECT_BUFFER_SIZE
11#define CHANNEL_SELECT_BUFFER_SIZE 256
12#endif
13
14namespace audio_tools {
22template <class T>
24 public:
29 void begin(T* transform, Stream* source) {
30 TRACED();
31 active = true;
32 is_eof = false;
35 p_stream = source;
36 p_transform = transform;
37 if (transform == nullptr) {
38 LOGE("transform is NULL");
39 active = false;
40 }
41 if (p_stream == nullptr) {
42 LOGE("p_stream is NULL");
43 active = false;
44 }
45 }
46
47 size_t readBytes(uint8_t* data, size_t len) {
48 LOGD("TransformationReader::readBytes: %d", (int)len);
49 if (!active) {
50 LOGE("inactive");
51 return 0;
52 }
53 if (p_stream == nullptr) {
54 LOGE("p_stream is NULL");
55 return 0;
56 }
57
58 setupBuffers(len);
59
60 if (!is_eof) {
61 fillResultQueue(len);
62 }
63
64 int result_len = min((int)len, result_queue.available());
65 result_len = result_queue.readBytes(data, result_len);
66 LOGD("TransformationReader::readBytes: %d -> %d", (int)len, result_len);
67 total_bytes_read += result_len;
68 return result_len;
69 }
70
73 int available() {
74 if (!active || p_stream == nullptr || p_transform == nullptr) return 0;
75 if (is_eof) return result_queue.available();
78 int available_bytes = result_queue.available();
79 LOGD("TransformationReader::available: %d", available_bytes);
80 return available_bytes > max_read_size ? max_read_size : available_bytes;
81 }
82
83 void end() {
85 buffer.resize(0);
87 active = false;
88 }
89
91 void setResultQueueFactor(int factor) { result_queue_factor = factor; }
92
94 void resizeResultQueue(int size) {
97 }
98
99 void setMaxReadSize(int size) { max_read_size = size; }
100
101 size_t getTotalBytesRead() const { return total_bytes_read; }
102
111 void setEofOnZeroReads(bool flag) { eof_on_zero_reads = flag; }
112
122 void setZeroReadDelay(uint32_t delay_ms) { zero_read_delay_ms = delay_ms; }
123
124 protected:
127 Stream* p_stream = nullptr;
128 Vector<uint8_t> buffer{0}; // we allocate memory only when needed
129 T* p_transform = nullptr;
130 bool active = false;
134 float last_byte_factor = 0.0f;
135 bool is_eof = false;
136 bool eof_on_zero_reads = true;
137 uint32_t zero_read_delay_ms = 5;
139
141 void resizeReadBuffer(int size) { buffer.resize(size); }
142
143 void setupBuffers(size_t len) {
144 float byte_factor = p_transform->getByteFactor();
145 if (byte_factor <= 0.0f) {
146 LOGE("Invalid byte factor: %f", byte_factor);
147 byte_factor = 1.0f;
148 }
149 // Recompute if the requested length changed, or if the transform's byte
150 // factor drifted meaningfully since the read chunk size was last sized
151 // (e.g. a live-adjusted resampling step size). For a transform with a
152 // constant byte factor (the common decoder/encoder case) this check
153 // never re-triggers after the first call, so behavior there is
154 // unchanged; it only matters for transforms whose byte factor changes
155 // at runtime, where a stale chunk size would otherwise silently distort
156 // the consumption/production ratio.
157 bool byte_factor_changed =
158 fabsf(byte_factor - last_byte_factor) > 0.01f * last_byte_factor;
159 if (len == last_setup_buffer_size && !byte_factor_changed) return;
160 LOGD("setupBuffers: %d", (int)len);
161 last_byte_factor = byte_factor;
162
163 // we read half the necessary bytes
164 int size = (0.5f / byte_factor * len);
165 // process full samples/frames
166 size = size / 4 * 4;
167 if (size <= 0) size = 4;
168 if (buffer.size() < size) {
169 LOGI("read size: %d", size);
170 buffer.resize(size);
171 }
172
173 if (result_queue_buffer.size() == 0) {
174 // make sure that the ring buffer is big enough
175 int rb_size = len * result_queue_factor;
176 LOGI("buffer size: %d", rb_size);
179 }
181 }
182
185 void fillResultQueue(size_t len) {
186 if (is_eof) return;
187 if (result_queue.available() >= len) return;
188 LOGD("fillResultQueue: %d", (int)len);
189
190 // Detect misconfigured buffer: if the ring buffer capacity is smaller than
191 // the requested len bytes we can never satisfy the condition and will loop
192 // forever. Issue an error and bail out early.
193 if ((int)len > result_queue_buffer.size()) {
194 LOGE("fillResultQueue: result_queue_buffer too small: %d < %d. "
195 "Increase result_queue_factor or call resizeReadResultQueue().",
196 result_queue_buffer.size(), (int)len);
197 return;
198 }
199
200 Print* tmp = setupOutput();
201 int zero_count = 0;
202 while (result_queue.available() < len) {
203 // Detect buffer-full stall: if we can't write any more data but the
204 // queue is still below len, we must stop to avoid an endless loop.
206 LOGE("fillResultQueue: result_queue full (%d) but target not reached "
207 "(%d/%d). Increase result_queue_factor or call "
208 "resizeReadResultQueue().",
210 break;
211 }
212 int read_size = buffer.size();
213 int read_eff = p_stream->readBytes(buffer.data(), read_size);
214 LOGD("readBytes from source: %d -> %d", read_size,read_eff);
215 if (read_eff > 0) {
216 zero_count = 0; // reset 0 count
217 if (read_eff != buffer.size()) {
218 LOGD("readBytes %d -> %d", buffer.size(), read_eff);
219 }
220 int write_eff = p_transform->write(buffer.data(), read_eff);
221 if (write_eff != read_eff) {
222 LOGE("TransformationReader::write %d -> %d", read_eff, write_eff);
223 }
224 } else {
225 // limit the number of reads which provide 0;
226 if (++zero_count > MAX_ZERO_READ_COUNT) {
227 if (eof_on_zero_reads) {
228 is_eof = true;
229 // Flush any buffered/final encoder bytes into result_queue.
230 p_transform->flush();
231 }
232 // Otherwise the source is just a momentarily empty live
233 // producer (buffer underflow, not end of stream): stop trying
234 // for this call, but leave is_eof false so the next call
235 // retries once more data has arrived.
236 break;
237 }
238 // wait for some more data
240 }
241 }
242 LOGD("fillResultQueue available: %d", result_queue.available());
243 restoreOutput(tmp);
244 }
245
250 Print* result = p_transform->getPrint();
251 p_transform->setOutput((Print&)result_queue);
252
253 return result;
254 }
257 void restoreOutput(Print* out) {
258 if (out) p_transform->setOutput(*out);
259 }
260};
261
269 public:
270 virtual void setStream(Stream& stream) override {
271 TRACED();
272 p_io = &stream;
273 p_out = &stream;
274 }
275
276 virtual void setStream(AudioStream& stream) {
277 TRACED();
278 p_io = &stream;
279 p_out = &stream;
280 // setNotifyOnOutput(stream);
281 addNotifyAudioChange(stream);
282 }
283
284 virtual void setOutput(AudioOutput& print) {
285 TRACED();
286 p_out = &print;
288 }
289
290 virtual void setOutput(Print& print) override {
291 TRACED();
292 p_out = &print;
293 }
294
295 virtual Print* getPrint() { return p_out; }
296
297 virtual Stream* getStream() { return p_io; }
298
299 size_t readBytes(uint8_t* data, size_t len) override {
300 LOGD("ReformatBaseStream::readBytes: %d", (int)len);
301 return reader.readBytes(data, len);
302 }
303
304 int available() override {
305 return reader.available();
306 }
307
308 int availableForWrite() override {
309 return DEFAULT_BUFFER_SIZE; // reader.availableForWrite();
310 }
311
312 virtual float getByteFactor() = 0;
313
319 virtual void flush() {}
320
321 void end() override {
322 TRACED();
324 reader.end();
325 }
326
329 void resizeReadResultQueue(int size) { reader.resizeResultQueue(size); }
330
332 void setReadResultQueueSize(int size) { reader.resizeResultQueue(size); }
333
335 void setMaxReadSize(int size) { reader.setMaxReadSize(size); }
336
341
342
343 protected:
345 Stream* p_io = nullptr;
346 Print* p_out = nullptr;
347
348 void setupReader() {
349 if (getStream() != nullptr) {
350 reader.begin(this, getStream());
351 }
352 }
353};
354
360
366 public:
369 void setStream(Print& out) { p_print = &out; }
370 void setAudioInfo(AudioInfo info) { cfg = info; }
371 size_t write(const uint8_t* data, size_t len) {
372 return p_print->write(data, len);
373 }
375 virtual bool isDeletable() { return true; }
376
377 AudioInfo audioInfo() { return cfg; }
378
379 protected:
380 Print* p_print = nullptr;
382};
383
389 public:
391
393
394 void setStream(AudioStream& stream) { p_stream = &stream; }
395
396 void setAudioInfo(AudioInfo info) override {
397 if (p_stream != nullptr) p_stream->setAudioInfo(info);
398 }
399
400 AudioInfo audioInfo() override {
401 return p_stream != nullptr ? p_stream->audioInfo() : AudioInfo();
402 }
403
404 size_t write(const uint8_t* data, size_t len) override {
405 return p_stream != nullptr ? p_stream->write(data, len) : 0;
406 }
407
408 int availableForWrite() override {
409 return p_stream != nullptr ? p_stream->availableForWrite() : 0;
410 }
411
412 bool begin() override { return p_stream != nullptr && p_stream->begin(); }
413
414 void end() override {
415 if (p_stream != nullptr) p_stream->end();
416 }
417
419 virtual bool isDeletable() override { return true; }
420
421 operator bool() override { return p_stream != nullptr && *p_stream; }
422
423 protected:
425};
426
432 public:
434
436
437 void setOutput(AudioOutput& stream) { p_stream = &stream; }
438
439 void setAudioInfo(AudioInfo info) override {
440 if (p_stream != nullptr) p_stream->setAudioInfo(info);
441 }
442
443 AudioInfo audioInfo() override {
444 return p_stream != nullptr ? p_stream->audioInfo() : AudioInfo();
445 }
446
447 size_t write(const uint8_t* data, size_t len) override {
448 return p_stream != nullptr ? p_stream->write(data, len) : 0;
449 }
450
451 bool begin() override { return p_stream != nullptr && p_stream->begin(); }
452
453 void end() override {
454 if (p_stream != nullptr) p_stream->end();
455 }
456
458 virtual bool isDeletable() { return true; }
459
460 operator bool() override { return p_stream != nullptr && *p_stream; }
461
462 protected:
464};
465
473 public:
475 MultiOutput() = default;
476
477 MultiOutput(Print& out) { add(out); }
478
481
483
486 add(out1);
487 add(out2);
488 }
489
492 add(out1);
493 add(out2);
494 }
495
498 MultiOutput(Print& out1, Print& out2) {
499 add(out1);
500 add(out2);
501 }
502
503 virtual ~MultiOutput() { clear(); }
504
506 void add(AudioOutput& out) {
507 vector.push_back({&out, &out, Kind::AudioOutputKind});
508 }
509
511 void add(AudioStream& stream) {
512 vector.push_back({&stream, &stream, Kind::AudioStreamKind});
513 }
514
516 void add(Client& client) {
517 vector.push_back({&client, nullptr, Kind::ClientKind});
518 }
519
522 void add(Print& print) { vector.push_back({&print, nullptr, Kind::PrintKind}); }
523
525 void remove(Print& print) {
526 for (int j = 0; j < vector.size(); j++) {
527 if (vector[j].print == &print) {
528 vector.erase(j);
529 return;
530 }
531 }
532 }
533
534 void flush() {
535 for (int j = 0; j < vector.size(); j++) {
536 vector[j].print->flush();
537 }
538 }
539
541 for (int j = 0; j < vector.size(); j++) {
542 if (vector[j].info != nullptr) {
543 vector[j].info->setAudioInfo(info);
544 }
545 }
546 }
547
548 size_t write(const uint8_t* data, size_t len) override {
549 for (auto& rec : vector) {
550 int open = len;
551 int start = 0;
552 // create copy of data to avoid that one output changes the data for the
553 // other outputs
554 uint8_t copy[len];
555 memcpy(copy, data, len);
556 while (open > 0) {
557 int written = rec.print->write(copy + start, open);
558 open -= written;
559 start += written;
560 }
561 }
562 return len;
563 }
564
565 size_t write(uint8_t ch) override {
566 for (int j = 0; j < vector.size(); j++) {
567 int open = 1;
568 while (open > 0) {
569 open -= vector[j].print->write(ch);
570 }
571 }
572 return 1;
573 }
574
578 void clear() { vector.clear(); }
579
585 for (int j = vector.size() - 1; j >= 0; j--) {
586 if (!isActive(vector[j])) {
587 vector.erase(j);
588 }
589 }
590 }
591
592 protected:
596
611
613
618 switch (rec.kind) {
619 case Kind::ClientKind:
620 return (bool)*static_cast<Client*>(rec.print);
622 return (bool)*static_cast<AudioStream*>(rec.print);
624 return (bool)*static_cast<AudioOutput*>(rec.print);
625 default:
626 return true;
627 }
628 }
629
631 void setOutput(Print& out) { add(out); }
632};
633
644 public:
645 TimedStream() = default;
646
647 TimedStream(AudioStream& io, long startSeconds = 0, long endSeconds = -1) {
648 p_io = &io;
649 p_out = &io;
650 p_info = &io;
651 setStartSec(startSeconds);
652 setEndSec(endSeconds);
653 }
654
655 TimedStream(AudioOutput& o, long startSeconds = 0, long endSeconds = -1) {
656 p_out = &o;
657 p_info = &o;
658 setStartSec(startSeconds);
659 setEndSec(endSeconds);
660 }
661
662 TimedStream(Stream& io, long startSeconds = 0, long endSeconds = -1) {
663 p_io = &io;
664 p_out = &io;
665 setStartSec(startSeconds);
666 setEndSec(endSeconds);
667 }
668
669 TimedStream(Print& o, long startSeconds = 0, long endSeconds = -1) {
670 p_out = &o;
671 setStartSec(startSeconds);
672 setEndSec(endSeconds);
673 }
674
677 void setStartSec(uint32_t startSeconds) {
678 start_ms = startSeconds * 1000;
680 }
681
683 void setStartMs(uint32_t ms) {
684 start_ms = ms;
686 }
687
690 void setEndSec(uint32_t endSeconds) {
691 end_ms = endSeconds * 1000;
693 }
694
696 void setEndMs(uint32_t ms) {
697 end_ms = ms;
699 }
700
702 bool isPlaying() {
703 if (current_bytes < start_bytes) return false;
704 if (end_bytes > 0 && current_bytes > end_bytes) return false;
705 return true;
706 }
707
709 bool isActive() {
710 return (current_bytes < end_bytes && current_bytes >= start_bytes);
711 }
712
715 return begin();
716 }
717
718 bool begin() override {
720 current_bytes = 0;
721 LOGI("byte range %u - %u", (unsigned)start_bytes, (unsigned)end_bytes);
722 return true;
723 }
724
725 operator bool() override { return isActive(); }
726
730 size_t readBytes(uint8_t* data, size_t len) override {
731 // if reading is not supported we stop
732 if (p_io == nullptr) return 0;
733 // Positioin to start
736 }
737 // if we are past the end we stop
738 if (!isActive()) return 0;
739 // read the data now
740 size_t result = 0;
741 do {
742 result = p_io->readBytes(data, len);
743 current_bytes += len;
744 // ignore data before start time
745 } while (result > 0 && current_bytes < start_bytes);
746 return isPlaying() ? result : 0;
747 }
748
750 size_t write(const uint8_t* data, size_t len) override {
751 if (current_bytes >= end_bytes) return 0;
752 current_bytes += len;
753 if (current_bytes < start_bytes) return len;
754 return p_out->write(data, len);
755 }
756
758 int available() override {
759 if (p_io == nullptr) return 0;
760 return current_bytes < end_bytes ? p_io->available() : 0;
761 }
762
769
770 int availableForWrite() override {
772 }
773
774 void flush() override {
775 if (p_out != nullptr) p_out->flush();
776 }
777
780 void setCompressionRatio(float ratio) { compression_ratio = ratio; }
781
786
787 void setOutput(Print& out) override { p_out = &out; }
788
789 void setStream(Stream& stream) override {
790 p_out = &stream;
791 p_io = &stream;
792 }
793
795 p_out = &out;
796 p_info = &out;
797 }
798
800 p_out = &out;
801 p_info = &out;
802 }
803
804 void setStream(AudioStream& stream) {
805 p_out = &stream;
806 p_io = &stream;
807 p_info = &stream;
808 }
809
810 size_t size() { return end_bytes - start_bytes; }
811
812 protected:
813 Stream* p_io = nullptr;
814 Print* p_out = nullptr;
816 uint32_t start_ms = 0;
817 uint32_t end_ms = UINT32_MAX;
818 uint32_t start_bytes = 0;
819 uint32_t end_bytes = UINT32_MAX;
820 uint32_t current_bytes = 0;
821 float compression_ratio = 1.0;
822
823 void consumeBytes(uint32_t len) {
824 int open = len;
825 uint8_t buffer[1024];
826 while (open > 0) {
827 int toread = min(1024, open);
828 p_io->readBytes(buffer, toread);
829 open -= toread;
830 }
831 current_bytes += len;
832 LOGD("consumed %u -> %u", (unsigned)len, (unsigned)current_bytes);
833 }
834
836 float bytes_per_second = bytesPerSecond();
837 if (bytes_per_second > 0) {
838 start_bytes = bytes_per_second * start_ms / compression_ratio / 1000;
839 end_bytes = bytes_per_second * end_ms / compression_ratio / 1000;
840 } else {
841 LOGE("AudioInfo not defined");
842 }
843 }
844};
845
856 public:
858
859 bool begin(AudioInfo info) override {
860 setAudioInfo(info);
861 return begin();
862 }
863
864 bool begin() override {
866 // make sure that selected channels are valid
867 for (auto& out : out_channels) {
868 for (auto& ch : out.channels) {
869 if (ch > cfg.channels - 1) {
870 LOGE("Channel '%d' not valid for max %d channels", ch, cfg.channels);
871 return false;
872 }
873 }
874 }
875 return true;
876 }
877
880 void addOutput(AudioOutput& out, uint16_t channel) {
881 Vector<uint16_t> channels;
882 channels.push_back(channel);
884 def.channels = channels;
885 def.p_out = &out;
886 def.p_audio_info = &out;
887 out_channels.push_back(def);
888 }
889
892 void addOutput(AudioStream& out, uint16_t channel) {
893 Vector<uint16_t> channels;
894 channels.push_back(channel);
896 def.channels = channels;
897 def.p_out = &out;
898 def.p_audio_info = &out;
899 out_channels.push_back(def);
900 }
901
904 void addOutput(Print& out, uint16_t channel) {
905 Vector<uint16_t> channels;
906 channels.push_back(channel);
908 def.channels = channels;
909 def.p_out = &out;
910 out_channels.push_back(def);
911 }
912
915 void addOutput(Print& out, uint16_t left, uint16_t right) {
916 Vector<uint16_t> channels;
917 channels.push_back(left);
918 channels.push_back(right);
920 def.channels = channels;
921 def.p_out = &out;
922 out_channels.push_back(def);
923 }
924
927 void addOutput(AudioOutput& out, uint16_t left, uint16_t right) {
928 Vector<uint16_t> channels;
929 channels.push_back(left);
930 channels.push_back(right);
932 def.channels = channels;
933 def.p_out = &out;
934 def.p_audio_info = &out;
935 out_channels.push_back(def);
936 }
937
940 void addOutput(AudioStream& out, uint16_t left, uint16_t right) {
941 Vector<uint16_t> channels;
942 channels.push_back(left);
943 channels.push_back(right);
945 def.channels = channels;
946 def.p_out = &out;
947 def.p_audio_info = &out;
948 out_channels.push_back(def);
949 }
950
951 size_t write(const uint8_t* data, size_t len) override {
952 if (!is_active) return false;
953 LOGD("write %d", (int)len);
954 switch (cfg.bits_per_sample) {
955 case 16:
956 return writeT<int16_t>(data, len);
957 case 24:
958 return writeT<int24_t>(data, len);
959 case 32:
960 return writeT<int32_t>(data, len);
961 default:
962 return 0;
963 }
964 }
965
966 void setAudioInfo(AudioInfo ai) override {
967 this->cfg = ai;
968 // notifyAudioChange(ai);
969 for (auto& info : out_channels) {
970 auto p_notify = info.p_audio_info;
971 if (p_notify != nullptr) {
972 AudioInfo result{ai};
973 result.channels = info.channels.size();
974 p_notify->setAudioInfo(result);
975 }
976 }
977 }
978
979 protected:
987
988 template <typename T>
989 size_t writeT(const uint8_t* buffer, size_t size) {
990 if (!is_active) return 0;
991 int sample_count = size / sizeof(T);
992 // int result_size = sample_count / cfg.channels;
993 T* data = (T*)buffer;
994
995 for (int i = 0; i < sample_count; i += cfg.channels) {
996 T* frame = data + i;
997 for (auto& out : out_channels) {
998 T out_frame[out.channels.size()];
999 int ch_out = 0;
1000 for (auto& ch : out.channels) {
1001 // make sure we have a valid channel
1002 int channel = (ch < cfg.channels) ? ch : cfg.channels - 1;
1003 out_frame[ch_out++] = frame[channel];
1004 }
1005 // write to buffer
1006 size_t written = out.buffer.writeArray((const uint8_t*)&out_frame,
1007 sizeof(out_frame));
1008 // write buffer to final output
1009 if (out.buffer.availableForWrite() < sizeof(out_frame)) {
1010 out.p_out->write(out.buffer.data(), out.buffer.available());
1011 out.buffer.reset();
1012 }
1013 // if (written != sizeof(out_frame)) {
1014 // LOGW("Could not write all samples %d -> %d", sizeof(out_frame),
1015 // written);
1016 // }
1017 }
1018 }
1019 return size;
1020 }
1021
1023 int getChannels(Print* out, int defaultChannels) {
1024 for (auto& channels_select : out_channels) {
1025 if (channels_select.p_out == out) return channels_select.channels.size();
1026 }
1027 return defaultChannels;
1028 }
1029};
1030
1043 public:
1049
1057 bool begin() {
1058 bool result = AudioStream::begin();
1059 if (result) {
1060 resetTime();
1061 }
1062 return result;
1063 }
1064
1065 size_t readBytes(uint8_t* data, size_t len) override {
1066 if (time_callback_before != nullptr) {
1068 }
1069 // Forward to the configured source (set via setStream()) rather than
1070 // AudioStream::readBytes(), which is just an "unsupported" stub with
1071 // no knowledge of p_stream.
1072 size_t result = p_stream != nullptr ? p_stream->readBytes(data, len) : 0;
1073 if (result > 0) {
1074 updateTime(result);
1075 }
1076 return result;
1077 }
1078
1079 size_t write(const uint8_t* data, size_t len) override {
1080 if (time_callback_before != nullptr) {
1082 }
1083 // Forward to the configured target (set via setOutput()/setStream())
1084 // rather than AudioStream::write(), which is just an "unsupported"
1085 // stub with no knowledge of p_out - this class exists specifically to
1086 // sit transparently between a decoder and the real audio sink.
1087 size_t result = p_out != nullptr ? p_out->write(data, len) : 0;
1088 if (result > 0) {
1089 updateTime(result);
1090 }
1091 return result;
1092 }
1093
1103 uint32_t playbackTime() override { return playback_time_ms; }
1104
1105 void setOutput(Print& out) {
1106 p_out = &out;
1107 }
1109 p_out = &out;
1111 }
1112 void setStream(Stream& stream) {
1113 p_stream = &stream;
1114 p_out = &stream;
1115 }
1116 void setStream(AudioStream& stream) {
1117 p_stream = &stream;
1118 p_out = &stream;
1119 addNotifyAudioChange(stream);
1120 }
1122 void setTimeCallback(void (*cb)(uint32_t time_ms)) { time_callback_before = cb; }
1124 void setTimeCallbackAfter(void (*cb)(uint32_t time_ms)) { time_callback_after = cb; }
1125
1126 protected:
1127 Print *p_out = nullptr;
1128 Stream *p_stream = nullptr;
1129 // Pure running total of byte-derived durations - see playbackTime().
1130 // Never touched by wall-clock time.
1131 uint32_t playback_time_ms = 0;
1132 void (*time_callback_before)(uint32_t time_ms) = nullptr;
1133 void (*time_callback_after)(uint32_t time_ms) = nullptr;
1134
1136
1137 void updateTime(size_t bytes) {
1139 uint32_t bytes_per_second = info.sample_rate * info.channels * info.bits_per_sample / 8;
1140 if (bytes_per_second == 0) return;
1141 uint32_t added_ms = (uint32_t)(((uint64_t)bytes * 1000) / bytes_per_second);
1142 playback_time_ms += added_ms;
1143 if (time_callback_after != nullptr) {
1145 }
1146 }
1147};
1148
1149
1150} // namespace audio_tools
#define CHANNEL_SELECT_BUFFER_SIZE
Definition AudioIO.h:11
#define MAX_ZERO_READ_COUNT
Definition AudioIO.h:7
#define TRACED()
Definition AudioLoggerIDF.h:31
#define LOGI(...)
Definition AudioLoggerIDF.h:28
#define LOGD(...)
Definition AudioLoggerIDF.h:27
#define LOGE(...)
Definition AudioLoggerIDF.h:30
#define DEFAULT_BUFFER_SIZE
Definition avr.h:20
Definition Arduino.h:162
Definition Arduino.h:56
virtual int availableForWrite()
Definition Arduino.h:128
virtual size_t write(const uint8_t *data, size_t len)
Definition Arduino.h:120
virtual void flush()
Definition Arduino.h:130
Definition Arduino.h:136
virtual size_t readBytes(uint8_t *data, size_t len)
Definition Arduino.h:140
virtual int available()
Definition Arduino.h:139
Wrapper which converts a AudioStream to a AudioOutput.
Definition AudioIO.h:431
void setOutput(AudioOutput &stream)
Definition AudioIO.h:437
virtual bool isDeletable()
If true we need to release the related memory in the destructor.
Definition AudioIO.h:458
AdapterAudioOutputToAudioStream(AudioOutput &stream)
Definition AudioIO.h:435
void end() override
Definition AudioIO.h:453
size_t write(const uint8_t *data, size_t len) override
Definition AudioIO.h:447
AudioOutput * p_stream
Definition AudioIO.h:463
bool begin() override
Definition AudioIO.h:451
void setAudioInfo(AudioInfo info) override
Defines the input AudioInfo.
Definition AudioIO.h:439
AudioInfo audioInfo() override
provides the actual input AudioInfo
Definition AudioIO.h:443
Wrapper which converts a AudioStream to a AudioOutput.
Definition AudioIO.h:388
void setStream(AudioStream &stream)
Definition AudioIO.h:394
virtual bool isDeletable() override
If true we need to release the related memory in the destructor.
Definition AudioIO.h:419
void end() override
Definition AudioIO.h:414
size_t write(const uint8_t *data, size_t len) override
Definition AudioIO.h:404
AdapterAudioStreamToAudioOutput(AudioStream &stream)
Definition AudioIO.h:392
int availableForWrite() override
Definition AudioIO.h:408
AudioStream * p_stream
Definition AudioIO.h:424
bool begin() override
Definition AudioIO.h:412
void setAudioInfo(AudioInfo info) override
Defines the input AudioInfo.
Definition AudioIO.h:396
AudioInfo audioInfo() override
provides the actual input AudioInfo
Definition AudioIO.h:400
Wrapper which converts a Print to a AudioOutput.
Definition AudioIO.h:365
AdapterPrintToAudioOutput(Print &print)
Definition AudioIO.h:368
AudioInfo cfg
Definition AudioIO.h:381
virtual bool isDeletable()
If true we need to release the related memory in the destructor.
Definition AudioIO.h:375
void setAudioInfo(AudioInfo info)
Defines the input AudioInfo.
Definition AudioIO.h:370
void setStream(Print &out)
Definition AudioIO.h:369
AudioInfo audioInfo()
provides the actual input AudioInfo
Definition AudioIO.h:377
Print * p_print
Definition AudioIO.h:380
size_t write(const uint8_t *data, size_t len)
Definition AudioIO.h:371
virtual void addNotifyAudioChange(AudioInfoSupport &bi)
Adds target to be notified about audio changes.
Definition AudioTypes.h:150
Supports changes to the sampling rate, bits and channels.
Definition AudioTypes.h:132
virtual void setAudioInfo(AudioInfo info)=0
Defines the input AudioInfo.
Base class for Output Adpapters.
Definition AudioIO.h:359
Abstract Audio Ouptut class.
Definition AudioOutput.h:25
AudioInfo cfg
Definition AudioOutput.h:88
bool is_active
Definition AudioOutput.h:90
virtual bool begin(AudioInfo info)
Definition AudioOutput.h:73
virtual bool begin()
Definition AudioOutput.h:78
virtual void setAudioInfo(AudioInfo newInfo) override
Defines the input AudioInfo.
Definition AudioOutput.h:49
virtual void end()
Definition AudioOutput.h:82
virtual size_t write(const uint8_t *data, size_t len) override=0
virtual AudioInfo audioInfo() override
provides the actual input AudioInfo
Definition AudioOutput.h:62
Base class for all Audio Streams. It support the boolean operator to test if the object is ready with...
Definition BaseStream.h:120
virtual size_t write(const uint8_t *data, size_t len) override
Definition BaseStream.h:146
AudioInfo info
Definition BaseStream.h:171
virtual void setAudioInfo(AudioInfo newInfo) override
Defines the input AudioInfo.
Definition BaseStream.h:128
virtual AudioInfo audioInfo() override
provides the actual input AudioInfo
Definition BaseStream.h:151
AudioTimeSourceStream: A stream that provides time information based on the audio data actually proce...
Definition AudioIO.h:1042
uint32_t playbackTime() override
Definition AudioIO.h:1103
AudioTimeSourceStream(AudioOutput &out)
Definition AudioIO.h:1046
void setTimeCallbackAfter(void(*cb)(uint32_t time_ms))
Defines a callback function to be called whenever the time is updated.
Definition AudioIO.h:1124
void setOutput(AudioOutput &out)
Definition AudioIO.h:1108
AudioTimeSourceStream(AudioStream &stream)
Definition AudioIO.h:1045
size_t readBytes(uint8_t *data, size_t len) override
Definition AudioIO.h:1065
void setStream(Stream &stream)
Definition AudioIO.h:1112
void setStream(AudioStream &stream)
Definition AudioIO.h:1116
bool begin()
Definition AudioIO.h:1057
AudioTimeSourceStream(Print &print)
Definition AudioIO.h:1047
void(* time_callback_before)(uint32_t time_ms)
Definition AudioIO.h:1132
uint32_t playback_time_ms
Definition AudioIO.h:1131
AudioTimeSourceStream(Stream &stream)
Definition AudioIO.h:1048
size_t write(const uint8_t *data, size_t len) override
Definition AudioIO.h:1079
Stream * p_stream
Definition AudioIO.h:1128
void(* time_callback_after)(uint32_t time_ms)
Definition AudioIO.h:1133
void setTimeCallback(void(*cb)(uint32_t time_ms))
Defines a callback function to be called whenever the time is updated.
Definition AudioIO.h:1122
Print * p_out
Definition AudioIO.h:1127
void resetTime()
Definition AudioIO.h:1135
void setOutput(Print &out)
Definition AudioIO.h:1105
void updateTime(size_t bytes)
Definition AudioIO.h:1137
virtual bool begin()
Definition BaseStream.h:40
virtual int availableForWrite() override
Definition BaseStream.h:57
virtual void end()
Definition BaseStream.h:41
Flexible functionality to extract one or more channels from a multichannel signal....
Definition AudioIO.h:855
void addOutput(Print &out, uint16_t left, uint16_t right)
Definition AudioIO.h:915
void setAudioInfo(AudioInfo ai) override
Defines the input AudioInfo.
Definition AudioIO.h:966
void addOutput(Print &out, uint16_t channel)
Definition AudioIO.h:904
Vector< ChannelSelectionOutputDef > out_channels
Definition AudioIO.h:986
void addOutput(AudioOutput &out, uint16_t channel)
Definition AudioIO.h:880
int getChannels(Print *out, int defaultChannels)
Determine number of channels for destination.
Definition AudioIO.h:1023
size_t write(const uint8_t *data, size_t len) override
Definition AudioIO.h:951
size_t writeT(const uint8_t *buffer, size_t size)
Definition AudioIO.h:989
bool begin(AudioInfo info) override
Definition AudioIO.h:859
bool begin() override
Definition AudioIO.h:864
void addOutput(AudioStream &out, uint16_t channel)
Definition AudioIO.h:892
void addOutput(AudioStream &out, uint16_t left, uint16_t right)
Definition AudioIO.h:940
void addOutput(AudioOutput &out, uint16_t left, uint16_t right)
Definition AudioIO.h:927
Abstract class: Objects can be put into a pipleline.
Definition AudioOutput.h:100
Abstract class: Objects can be put into a pipleline.
Definition AudioStreams.h:68
Replicates the output to multiple destinations.
Definition AudioIO.h:472
bool isActive(MultiOutputRecord &rec)
Definition AudioIO.h:617
void remove(Print &print)
Removes the indicated output.
Definition AudioIO.h:525
void add(AudioOutput &out)
Add an additional AudioOutput output.
Definition AudioIO.h:506
void clearInactive()
Definition AudioIO.h:584
MultiOutput(Print &out)
Definition AudioIO.h:477
Vector< MultiOutputRecord > vector
Definition AudioIO.h:612
size_t write(uint8_t ch) override
Definition AudioIO.h:565
void setAudioInfo(AudioInfo info)
Defines the input AudioInfo.
Definition AudioIO.h:540
void add(AudioStream &stream)
Add an AudioStream to the output.
Definition AudioIO.h:511
MultiOutput(AudioStream &out1, AudioStream &out2)
Defines a MultiOutput with 2 final outputs.
Definition AudioIO.h:491
size_t write(const uint8_t *data, size_t len) override
Definition AudioIO.h:548
void add(Print &print)
Definition AudioIO.h:522
void add(Client &client)
Add a (network) Client as output: e.g. WiFiClient, EthernetClient...
Definition AudioIO.h:516
MultiOutput(AudioOutput &out1, AudioOutput &out2)
Defines a MultiOutput with 2 final outputs.
Definition AudioIO.h:485
MultiOutput(AudioOutput &out)
Defines a MultiOutput with a single final outputs,.
Definition AudioIO.h:480
Kind
Definition AudioIO.h:595
MultiOutput(AudioStream &out)
Definition AudioIO.h:482
virtual ~MultiOutput()
Definition AudioIO.h:503
void clear()
Definition AudioIO.h:578
void flush()
Definition AudioIO.h:534
void setOutput(Print &out)
support for Pipleline
Definition AudioIO.h:631
MultiOutput(Print &out1, Print &out2)
Definition AudioIO.h:498
MultiOutput()=default
Defines a MultiOutput with no final output: Define your outputs with add()
Stream class which stores the data in a temporary queue buffer. The queue can be consumed e....
Definition BaseStream.h:359
virtual bool begin() override
Activates the output.
Definition BaseStream.h:387
virtual size_t readBytes(uint8_t *data, size_t len) override
Definition BaseStream.h:445
int available() override
Definition BaseStream.h:411
Base class for chained converting streams.
Definition AudioIO.h:268
void setMaxReadSize(int size)
Defines the read buffer size for individual reads: same as transformationReader()....
Definition AudioIO.h:335
virtual void setStream(AudioStream &stream)
Defines/Changes the input & output and registers for audio change notifications.
Definition AudioIO.h:276
virtual void setStream(Stream &stream) override
Defines/Changes the input & output.
Definition AudioIO.h:270
TransformationReader< ReformatBaseStream > reader
Definition AudioIO.h:344
virtual float getByteFactor()=0
virtual void setOutput(Print &print) override
Defines/Changes the output target.
Definition AudioIO.h:290
size_t readBytes(uint8_t *data, size_t len) override
Definition AudioIO.h:299
void end() override
Definition AudioIO.h:321
int available() override
Definition AudioIO.h:304
virtual Stream * getStream()
Definition AudioIO.h:297
virtual void setOutput(AudioOutput &print)
Defines/Changes the output target and registers for audio change notifications.
Definition AudioIO.h:284
virtual TransformationReader< ReformatBaseStream > & transformationReader()
Provides access to the TransformationReader.
Definition AudioIO.h:338
int availableForWrite() override
Definition AudioIO.h:308
void setReadResultQueueSize(int size)
same as resizeReadResultQueue(size)
Definition AudioIO.h:332
Print * p_out
Definition AudioIO.h:346
virtual Print * getPrint()
Definition AudioIO.h:295
virtual void flush()
Definition AudioIO.h:319
void setupReader()
Definition AudioIO.h:348
void resizeReadResultQueue(int size)
Definition AudioIO.h:329
Stream * p_io
Definition AudioIO.h:345
Implements a typed Ringbuffer.
Definition Buffers.h:363
virtual size_t size() override
Returns the maximum capacity of the buffer.
Definition Buffers.h:493
virtual bool resize(size_t len)
Resizes the buffer if supported: returns false if not supported.
Definition Buffers.h:483
A simple Buffer implementation which just uses a (dynamically sized) array.
Definition Buffers.h:194
Interface for classes that can provide time information - two distinct notions of "now",...
Definition AudioTypes.h:580
AudioStream class that can define a start and (an optional) stop time Usually it is used to wrap an A...
Definition AudioIO.h:643
TimedStream(Print &o, long startSeconds=0, long endSeconds=-1)
Definition AudioIO.h:669
void flush() override
Definition AudioIO.h:774
void setOutput(Print &out) override
Defines/Changes the output target.
Definition AudioIO.h:787
size_t size()
Definition AudioIO.h:810
void setStream(Stream &stream) override
Defines/Changes the input & output.
Definition AudioIO.h:789
uint32_t end_ms
Definition AudioIO.h:817
void setEndSec(uint32_t endSeconds)
Definition AudioIO.h:690
uint32_t start_bytes
Definition AudioIO.h:818
void setEndMs(uint32_t ms)
Defines the (optional) end time in milliseconds.
Definition AudioIO.h:696
uint32_t current_bytes
Definition AudioIO.h:820
void setStream(AudioOutput &out)
Definition AudioIO.h:799
void setCompressionRatio(float ratio)
Definition AudioIO.h:780
uint32_t start_ms
Definition AudioIO.h:816
void setOutput(AudioOutput &out)
Defines/Changes the output target and registers for audio change notifications.
Definition AudioIO.h:794
size_t readBytes(uint8_t *data, size_t len) override
Definition AudioIO.h:730
void setStartSec(uint32_t startSeconds)
Definition AudioIO.h:677
TimedStream(Stream &io, long startSeconds=0, long endSeconds=-1)
Definition AudioIO.h:662
void setStream(AudioStream &stream)
Defines/Changes the input & output and registers for audio change notifications.
Definition AudioIO.h:804
TimedStream(AudioStream &io, long startSeconds=0, long endSeconds=-1)
Definition AudioIO.h:647
void consumeBytes(uint32_t len)
Definition AudioIO.h:823
int available() override
Provides the available bytes until the end time has reached.
Definition AudioIO.h:758
size_t write(const uint8_t *data, size_t len) override
Plays only data for the indiated start and end time.
Definition AudioIO.h:750
void setStartMs(uint32_t ms)
Defines the start time in milliseconds.
Definition AudioIO.h:683
bool isPlaying()
Returns true if we are in a valid time range and are still playing sound.
Definition AudioIO.h:702
int availableForWrite() override
Definition AudioIO.h:770
AudioInfoSupport * p_info
Definition AudioIO.h:815
bool isActive()
Returns true if we are not past the end time;.
Definition AudioIO.h:709
Print * p_out
Definition AudioIO.h:814
void calculateByteLimits()
Definition AudioIO.h:835
bool begin() override
Definition AudioIO.h:718
uint32_t end_bytes
Definition AudioIO.h:819
TimedStream(AudioOutput &o, long startSeconds=0, long endSeconds=-1)
Definition AudioIO.h:655
void setAudioInfo(AudioInfo info) override
Updates the AudioInfo in the current object and in the source or target.
Definition AudioIO.h:764
float compression_ratio
Definition AudioIO.h:821
bool begin(AudioInfo info)
Definition AudioIO.h:713
int bytesPerSecond()
Calculates the bytes per second from the AudioInfo.
Definition AudioIO.h:783
Stream * p_io
Definition AudioIO.h:813
ConverterStream Helper class which implements the readBytes with the help of write.
Definition AudioIO.h:23
bool active
Definition AudioIO.h:130
QueueStream< uint8_t > result_queue
Definition AudioIO.h:126
void setupBuffers(size_t len)
Definition AudioIO.h:143
void setMaxReadSize(int size)
Definition AudioIO.h:99
void begin(T *transform, Stream *source)
setup of the TransformationReader class
Definition AudioIO.h:29
void resizeReadBuffer(int size)
Defines the read buffer size for individual reads.
Definition AudioIO.h:141
int last_setup_buffer_size
Definition AudioIO.h:133
float last_byte_factor
Definition AudioIO.h:134
void setEofOnZeroReads(bool flag)
Definition AudioIO.h:111
RingBuffer< uint8_t > result_queue_buffer
Definition AudioIO.h:125
T * p_transform
Definition AudioIO.h:129
int available()
Definition AudioIO.h:73
void restoreOutput(Print *out)
restores the original output in the converter class
Definition AudioIO.h:257
bool is_eof
Definition AudioIO.h:135
size_t total_bytes_read
Definition AudioIO.h:138
Stream * p_stream
Definition AudioIO.h:127
void fillResultQueue(size_t len)
Definition AudioIO.h:185
size_t readBytes(uint8_t *data, size_t len)
Definition AudioIO.h:47
Print * setupOutput()
Definition AudioIO.h:249
size_t getTotalBytesRead() const
Definition AudioIO.h:101
void end()
Definition AudioIO.h:83
uint32_t zero_read_delay_ms
Definition AudioIO.h:137
bool eof_on_zero_reads
Definition AudioIO.h:136
int max_read_size
Definition AudioIO.h:132
void setZeroReadDelay(uint32_t delay_ms)
Definition AudioIO.h:122
void resizeResultQueue(int size)
Defines the queue size for result.
Definition AudioIO.h:94
void setResultQueueFactor(int factor)
Defines the queue size dependent on the read size.
Definition AudioIO.h:91
int result_queue_factor
Definition AudioIO.h:131
Vector< uint8_t > buffer
Definition AudioIO.h:128
Vector implementation which provides the most important methods as defined by std::vector....
Definition Vector.h:21
void push_back(T &&value)
Definition Vector.h:182
bool resize(size_t newSize, T value)
Definition Vector.h:266
T * data()
Definition Vector.h:316
int size()
Definition Vector.h:178
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition LMSEchoCancellationStream.h:6
void delay(uint32_t ms)
Definition Arduino.h:259
Basic Audio information which drives e.g. I2S.
Definition AudioTypes.h:51
sample_rate_t sample_rate
Sample Rate: e.g 44100.
Definition AudioTypes.h:53
uint16_t channels
Number of channels: 2=stereo, 1=mono.
Definition AudioTypes.h:55
uint8_t bits_per_sample
Number of bits per sample (int16_t = 16 bits)
Definition AudioTypes.h:57
AudioInfoSupport * p_audio_info
Definition AudioIO.h:982
Vector< uint16_t > channels
Definition AudioIO.h:984
SingleBuffer< uint8_t > buffer
Definition AudioIO.h:983
Record describing a single replicated output.
Definition AudioIO.h:598
Print * print
Target to which the data is actually written.
Definition AudioIO.h:600
AudioInfoSupport * info
Definition AudioIO.h:603
MultiOutputRecord(Print *print=nullptr, AudioInfoSupport *info=nullptr, Kind kind=Kind::PrintKind)
Definition AudioIO.h:607
Kind kind
Actual type of the object behind print.
Definition AudioIO.h:605