arduino-audio-tools
Loading...
Searching...
No Matches
AudioOutput.h
Go to the documentation of this file.
1#pragma once
5#include "AudioToolsConfig.h"
6#if defined(USE_ESP32_DSP)
7#include "esp_dsp.h"
8#endif
9
10namespace audio_tools {
11
12#if USE_PRINT_FLUSH
13#define PRINT_FLUSH_OVERRIDE override
14#else
15#define PRINT_FLUSH_OVERRIDE
16#endif
17
23class AudioOutput : public Print,
24 public AudioInfoSupport,
25 public AudioInfoSource {
26 public:
27 virtual ~AudioOutput() = default;
28
29 virtual size_t write(const uint8_t *data, size_t len) override = 0;
30
31 virtual size_t write(uint8_t ch) override {
32 if (tmp.isFull()) {
33 flush();
34 }
35 return tmp.write(ch);
36 }
37
38 virtual int availableForWrite() override { return DEFAULT_BUFFER_SIZE; }
39
40 // removed override because some old implementation did not define this method
41 // as virtual
42 virtual void flush() PRINT_FLUSH_OVERRIDE {
43 if (tmp.available() > 0) {
44 write((const uint8_t *)tmp.address(), tmp.available());
45 }
46 }
47
48 // overwrite to do something useful
49 virtual void setAudioInfo(AudioInfo newInfo) override {
50 TRACED();
51 if (cfg != newInfo) {
52 cfg = newInfo;
53 cfg.logInfo();
54 }
55 AudioInfo out = audioInfoOut();
56 if (out) notifyAudioChange(out);
57 }
58
60 virtual bool isDeletable() { return false; }
61
62 virtual AudioInfo audioInfo() override { return cfg; }
63
66 virtual void writeSilence(size_t len) {
67 int16_t zero = 0;
68 for (int j = 0; j < len / 2; j++) {
69 write((uint8_t *)&zero, 2);
70 }
71 }
72
73 virtual bool begin(AudioInfo info) {
74 setAudioInfo(info);
75 return begin();
76 }
77
78 virtual bool begin() {
79 is_active = true;
80 return true;
81 }
82 virtual void end() { is_active = false; }
83
84 virtual operator bool() { return is_active; }
85
86 protected:
87 int tmpPos = 0;
90 bool is_active = false;
91};
92
101 public:
103 virtual void setOutput(Print &out) = 0;
104};
105
115template <typename T = int16_t>
116class CsvOutput : public AudioOutput {
117 public:
118 CsvOutput(int buffer_size = DEFAULT_BUFFER_SIZE, bool active = true) {
119 this->is_active = active;
120 }
121
123 CsvOutput(Print &out, int channels = 2, int buffer_size = DEFAULT_BUFFER_SIZE,
124 bool active = true) {
125 this->out_ptr = &out;
126 this->is_active = active;
127 cfg.channels = channels;
128 }
129
131 void setDelimiter(const char *del) { delimiter_str = del; }
132
134 const char *delimiter() { return delimiter_str; }
135
137
140 AudioInfo info;
141 info.channels = 2;
142 info.sample_rate = 44100;
143 info.bits_per_sample = sizeof(T) * 8;
144 return info;
145 }
146
148 bool begin(AudioInfo info) override { return begin(info.channels); }
149
151 bool begin(int channels) {
152 TRACED();
153 cfg.channels = channels;
154 return begin();
155 }
156
158 bool begin() override {
159 this->is_active = true;
160 // if (out_ptr == &Serial){
161 // Serial.setTimeout(60000);
162 // }
163 return true;
164 }
165
167 virtual void setAudioInfo(AudioInfo info) override {
168 TRACEI();
169 this->is_active = true;
170 info.logInfo();
171 cfg = info;
172 };
173
175 virtual size_t write(const uint8_t *data, size_t len) override {
176 LOGD("CsvOutput::write: %d", (int)len);
177 if (!is_active) {
178 LOGE("is not active");
179 return 0;
180 }
181
182 if (len == 0) {
183 return 0;
184 }
185
186 if (cfg.channels == 0) {
187 LOGW("Channels not defined: using 2");
188 cfg.channels = 2;
189 }
190 size_t lenChannels = len / (sizeof(T) * cfg.channels);
191 if (lenChannels > 0) {
192 writeFrames((T *)data, lenChannels);
193 } else if (len == sizeof(T)) {
194 // if the write contains less then a frame we buffer the data
195 T *data_value = (T *)data;
196 out_ptr->print(data_value[0]);
197 channel++;
198 if (channel == cfg.channels) {
199 out_ptr->println();
200 channel = 0;
201 } else {
202 out_ptr->print(delimiter_str);
203 }
204 } else {
205 LOGE("Unsupported size: %d for channels %d and bits: %d", (int)len,
207 }
208#if USE_PRINT_FLUSH
209 out_ptr->flush();
210#endif
211 return len;
212 }
213
214 int availableForWrite() override { return 1024; }
215
216 protected:
219 int channel = 0;
220 const char *delimiter_str = ",";
221
222 void writeFrames(T *data_ptr, int frameCount) {
223 for (size_t j = 0; j < frameCount; j++) {
224 for (int ch = 0; ch < cfg.channels; ch++) {
225 if (out_ptr != nullptr && data_ptr != nullptr) {
226 T value = *data_ptr;
227 out_ptr->print(value);
228 }
229 data_ptr++;
230 if (ch < cfg.channels - 1) this->out_ptr->print(delimiter_str);
231 }
232 this->out_ptr->println();
233 }
234 }
235};
236
244 public:
245 HexDumpOutput(int buffer_size = DEFAULT_BUFFER_SIZE, bool active = true) {
246 this->is_active = active;
247 }
248
250 HexDumpOutput(Print &out, int buffer_size = DEFAULT_BUFFER_SIZE,
251 bool active = true) {
252 this->out_ptr = &out;
253 this->is_active = active;
254 }
255
256 bool begin() override {
257 TRACED();
258 this->is_active = true;
259 pos = 0;
260 return is_active;
261 }
262
263 void flush() override {
264 out_ptr->println();
265 pos = 0;
266 }
267
268 virtual size_t write(const uint8_t *data, size_t len) override {
269 if (!is_active) return 0;
270 TRACED();
271 for (size_t j = 0; j < len; j++) {
272 out_ptr->print(data[j], HEX);
273 out_ptr->print(" ");
274 pos++;
275 if (pos == 8) {
276 out_ptr->print(" - ");
277 }
278 if (pos == 16) {
279 out_ptr->println();
280 pos = 0;
281 }
282 }
283 return len;
284 }
285
286 //
288 AudioInfo info;
289 return info;
290 }
291
292 protected:
294 int pos = 0;
295};
296
378template <typename T>
379struct MixGain {
380 float value = 0;
381 MixGain() = default;
382 MixGain(float f) : value(f) {}
383 T scale(T sample) const { return static_cast<T>(value * sample); }
384};
385
386#if PREFER_FIXEDPOINT
387template <>
388struct MixGain<int16_t> {
389 q1_14_t value;
390 MixGain() = default;
391 MixGain(float f) : value(f) {}
392 int16_t scale(int16_t sample) const { return value.scale(sample); }
393};
394template <>
395struct MixGain<int24_t> {
396 q1_14_t value;
397 MixGain() = default;
398 MixGain(float f) : value(f) {}
399 int24_t scale(int24_t sample) const { return value.scale(sample); }
400};
401template <>
402struct MixGain<int32_t> {
403 q1_14_t value;
404 MixGain() = default;
405 MixGain(float f) : value(f) {}
406 int32_t scale(int32_t sample) const { return value.scale(sample); }
407};
408#endif
409
410template <typename T = int16_t>
411class OutputMixer : public Print {
412 public:
421
431 OutputMixer(Print &finalOutput, int outputStreamCount,
434 setOutput(finalOutput);
435 setOutputCount(outputStreamCount);
436 }
437
439
441 void setOutput(Print &finalOutput) { p_final_output = &finalOutput; }
442
444 void setOutputCount(int count) {
445 // release any buffers allocated for a previous configuration
446 for (int i = 0; i < buffers.size(); i++) {
447 if (buffers[i] != nullptr) {
448 delete buffers[i];
449 buffers[i] = nullptr;
450 }
451 }
452 output_count = count;
453 buffers.resize(count);
454 for (int i = 0; i < count; i++) {
455 buffers[i] = nullptr;
456 }
457 weights.resize(count);
458 for (int i = 0; i < count; i++) {
459 weights[i] = 1.0;
460 }
461
463 }
464
467 void setWeight(int channel, float weight) {
468 if (channel >= 0 && channel < size()) {
469 weights[channel] = weight;
470 } else {
471 LOGE("Invalid channel %d - max is %d", channel, size() - 1);
472 }
474 }
475
477 bool begin(int copy_buffer_size_bytes = DEFAULT_BUFFER_SIZE) {
478 is_active = true;
479 size_bytes = copy_buffer_size_bytes;
480 stream_idx = 0;
483 return true;
484 }
485
487 void end() {
488 total_weights = 0.0;
489 is_active = false;
490 // release memory for buffers
491 free_buffers();
492 }
493
495 int size() { return output_count; }
496
498 size_t write(uint8_t) override { return 0; }
499
502 size_t write(const uint8_t *data, size_t len) override {
503 size_t result = write(stream_idx, data, len);
504 // after writing the last stream we flush
505 if (is_auto_index) {
506 stream_idx++;
507 if (stream_idx >= output_count) {
508 flushMixer();
509 }
510 }
511 return result;
512 }
513
515 size_t write(int idx, const uint8_t *buffer_c, size_t bytes) {
516 LOGD("write idx %d: %d", idx, (int)bytes);
517 size_t result = 0;
518 BaseBuffer<T> *p_buffer =
519 (idx >= 0 && idx < output_count) ? buffers[idx] : nullptr;
520 if (p_buffer == nullptr) {
521 LOGE("Invalid stream idx %d - max is %d", idx, output_count - 1);
522 return 0;
523 }
524 size_t samples = bytes / sizeof(T);
525 if (p_buffer->availableForWrite() >= samples) {
526 result = p_buffer->writeArray((T *)buffer_c, samples) * sizeof(T);
527 } else {
528 LOGW(
529 "Available Buffer %d too small %d: requested: %d -> increase the "
530 "buffer size",
531 (int)idx, static_cast<int>(p_buffer->availableForWrite() * sizeof(T)),
532 (int)bytes);
533 }
534 return result;
535 }
536
538 int availableForWrite() override {
540 }
541
543 int availableForWrite(int idx) {
544 if (idx < 0 || idx >= output_count) return 0;
545 BaseBuffer<T> *p_buffer = buffers[idx];
546 if (p_buffer == nullptr) return 0;
547 return p_buffer->availableForWrite() * sizeof(T);
548 }
549
551 int available(int idx) {
552 if (idx < 0 || idx >= output_count) return 0;
553 BaseBuffer<T> *p_buffer = buffers[idx];
554 if (p_buffer == nullptr) return 0;
555 return p_buffer->available() * sizeof(T);
556 }
557
559 int availablePercent(int idx) { return 100.0 * available(idx) / size_bytes; }
560
562 bool flushMixer() {
563 LOGD("flush");
564 if (p_final_output == nullptr) {
565 return false;
566 }
567 bool result = false;
568
569 // determine ringbuffer with mininum available data
570 size_t samples = availableSamples();
571 // sum up samples
572 if (samples > 0) {
573 result = true;
574 mixSamples(samples);
575 // write output
576 LOGD("write to final out: %d", static_cast<int>(samples * sizeof(T)));
577 p_final_output->write((uint8_t *)output.data(), samples * sizeof(T));
578 }
579 stream_idx = 0;
580 return result;
581 }
582
583
584
587 if (output_count == 0) return 0;
588 size_t samples = size_bytes / sizeof(T);
589 for (int j = 0; j < output_count; j++) {
590 size_t available_samples = buffers[j]->available();
591 samples = min(samples, available_samples);
592 }
593 return samples;
594 }
595
597 bool resize(size_t sizeBytes) {
598 bool result = true;
599 if (sizeBytes != size_bytes) {
600 result = allocate_buffers(sizeBytes);
601 if (result) {
602 size_bytes = sizeBytes;
603 }
604 }
605 return result;
606 }
607
609 size_t writeSilence(size_t bytes) {
610 if (bytes == 0) return 0;
611 uint8_t silence[bytes];
612 memset(silence, 0, bytes);
613 return write(stream_idx, silence, bytes);
614 }
615
617 size_t writeSilence(int idx, size_t bytes) {
618 if (bytes == 0) return 0;
619 uint8_t silence[bytes];
620 memset(silence, 0, bytes);
621 return write(idx, silence, bytes);
622 }
623
625 void setAutoIndex(bool flag) { is_auto_index = flag; }
626
628 void setIndex(int idx) { stream_idx = idx; }
629
631 void next() { stream_idx++; }
632
635 create_buffer_cb = cb;
636 }
637
640 return (idx >= 0 && idx < output_count) ? buffers[idx] : nullptr;
641 }
642
643 protected:
649 float total_weights = 0.0;
650 bool is_active = false;
651 int stream_idx = 0;
652 int size_bytes = 0;
654 void *p_memory = nullptr;
655 bool is_auto_index = true;
656 BaseBuffer<T> *(*create_buffer_cb)(int size,
658
661 return new RingBuffer<T>(sizeBytes / sizeof(T), allocator);
662 }
663
665 inline void mixSamples(size_t samples) {
666#if defined(USE_ESP32_DSP)
667 // Temporary float buffers for mixing
668 float mix_out[samples] = {0.0f};
669 float temp[samples] = {0.0f};
670
671 for (uint8_t j = 0; j < output_count; j++) {
672 const float factor = total_weights != 0.0f ? weights[j] / total_weights : 0.0f;
673 // Read int16_t samples and convert to float
674 for (uint16_t i = 0; i < samples; i++) {
675 T s = 0;
676 buffers[j]->read(s);
677 temp[i] = static_cast<float>(s) * factor;
678 }
679 // Add to output
680 dsps_add_f32(mix_out, temp, mix_out, samples, 1, 1, 1);
681 }
682 // Convert back to int16_t with clamping
683 output.resize(samples);
684 for (size_t i = 0; i < samples; i++) {
685 float v = mix_out[i];
686 output[i] = static_cast<T>(v);
687 }
688#else
689 // Fallback: original scalar code
690 output.resize(samples);
691 memset(output.data(), 0, samples * sizeof(T));
692 for (int j = 0; j < output_count; j++) {
693 MixGain<T> factor(total_weights != 0.0f ? weights[j] / total_weights : 0.0f);
694 for (int i = 0; i < samples; i++) {
695 T sample = 0;
696 buffers[j]->read(sample);
697 output[i] += factor.scale(sample);
698 }
699 }
700#endif
701 }
702
705 total_weights = 0.0;
706 for (int j = 0; j < weights.size(); j++) {
708 }
709 }
710
712 bool allocate_buffers(int sizeBytes) {
713 // allocate ringbuffers for each output
714 for (int j = 0; j < output_count; j++) {
715 if (buffers[j] != nullptr) {
716 delete buffers[j];
717 }
718 buffers[j] = create_buffer(sizeBytes, allocator);
719 if (buffers[j] == nullptr) {
720 return false;
721 }
722 }
723 return true;
724 }
725
728 // allocate ringbuffers for each output
729 for (int j = 0; j < output_count; j++) {
730 if (buffers[j] != nullptr) {
731 delete buffers[j];
732 buffers[j] = nullptr;
733 }
734 }
735 }
736};
737
742class MemoryOutput : public AudioOutput {
743 public:
744 MemoryOutput(uint8_t *start, int len) {
745 p_start = start;
746 p_next = start;
747 max_size = len;
748 is_active = true;
749 if (p_next == nullptr) {
750 LOGE("start must not be null");
751 }
752 }
753
754 bool begin() override {
755 is_active = true;
756 p_next = p_start;
757 pos = 0;
758 return true;
759 }
760
761 size_t write(const uint8_t *data, size_t len) override {
762 if (p_next == nullptr) return 0;
763 if (pos + len <= max_size) {
764 memcpy(p_next, data, len);
765 pos += len;
766 p_next += len;
767 return len;
768 } else {
769 LOGE("Buffer too small: pos:%d, size: %d ", pos, (int)max_size);
770 return 0;
771 }
772 }
773
774 int availableForWrite() override { return max_size - pos; }
775
776 int size() { return max_size; }
777
778 protected:
779 int pos = 0;
780 uint8_t *p_start = nullptr;
781 uint8_t *p_next = nullptr;
782 size_t max_size;
783};
784
794 public:
796
797 ChannelSplitOutput(Print &out, int channel) { addOutput(out, channel); }
798
801 void addOutput(Print &out, int channel) {
803 def.channel = channel;
804 def.p_out = &out;
805 out_channels.push_back(def);
806 }
807
808 size_t write(const uint8_t *data, size_t len) override {
809 switch (cfg.bits_per_sample) {
810 case 16:
811 return writeT<int16_t>(data, len);
812 case 24:
813 return writeT<int24_t>(data, len);
814 case 32:
815 return writeT<int32_t>(data, len);
816 default:
817 return 0;
818 }
819 }
820
821 protected:
823 Print *p_out = nullptr;
825 };
827
828 template <typename T = int16_t>
829 size_t writeT(const uint8_t *buffer, size_t size) {
830 int sample_count = size / sizeof(T);
831 int result_size = sample_count / cfg.channels;
832 T *data = (T *)buffer;
833 T result[result_size];
834
835 for (int ch = 0; ch < out_channels.size(); ch++) {
837 // extract mono result
838 int i = 0;
839 for (int j = def.channel; j < sample_count; j += cfg.channels) {
840 result[i++] = data[j];
841 }
842 // write mono result
843 size_t written =
844 def.p_out->write((uint8_t *)result, result_size * sizeof(T));
845 if (written != result_size * sizeof(T)) {
846 LOGW("Could not write all samples");
847 }
848 }
849 return size;
850 }
851};
852
853} // namespace audio_tools
static HardwareSerial Serial
Definition Arduino.h:179
@ HEX
Definition Arduino.h:54
#define LOGW(...)
Definition AudioLoggerIDF.h:29
#define TRACEI()
Definition AudioLoggerIDF.h:32
#define TRACED()
Definition AudioLoggerIDF.h:31
#define LOGD(...)
Definition AudioLoggerIDF.h:27
#define LOGE(...)
Definition AudioLoggerIDF.h:30
#define PRINT_FLUSH_OVERRIDE
Definition AudioOutput.h:15
#define MAX_SINGLE_CHARS
Definition AudioToolsConfig.h:143
#define DEFAULT_BUFFER_SIZE
Definition avr.h:20
Definition Arduino.h:56
virtual size_t write(const uint8_t *data, size_t len)
Definition Arduino.h:120
virtual void flush()
Definition Arduino.h:130
Memory allocateator which uses malloc.
Definition Allocator.h:25
Supports the subscription to audio change notifications.
Definition AudioTypes.h:147
void notifyAudioChange(AudioInfo info)
Definition AudioTypes.h:175
Supports changes to the sampling rate, bits and channels.
Definition AudioTypes.h:132
virtual AudioInfo audioInfoOut()
Definition AudioTypes.h:140
Abstract Audio Ouptut class.
Definition AudioOutput.h:25
SingleBuffer< uint8_t > tmp
Definition AudioOutput.h:89
AudioInfo cfg
Definition AudioOutput.h:88
virtual bool isDeletable()
If true we need to release the related memory in the destructor.
Definition AudioOutput.h:60
bool is_active
Definition AudioOutput.h:90
virtual bool begin(AudioInfo info)
Definition AudioOutput.h:73
virtual bool begin()
Definition AudioOutput.h:78
int tmpPos
Definition AudioOutput.h:87
virtual int availableForWrite() override
Definition AudioOutput.h:38
virtual ~AudioOutput()=default
virtual void setAudioInfo(AudioInfo newInfo) override
Defines the input AudioInfo.
Definition AudioOutput.h:49
virtual void flush()
Definition AudioOutput.h:42
virtual void writeSilence(size_t len)
Definition AudioOutput.h:66
virtual void end()
Definition AudioOutput.h:82
virtual size_t write(uint8_t ch) override
Definition AudioOutput.h:31
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
Shared functionality of all buffers.
Definition Buffers.h:23
virtual int writeArray(const T data[], int len)
Fills the buffer data.
Definition Buffers.h:56
virtual int availableForWrite()=0
provides the number of entries that are available to write
virtual int available()=0
provides the number of entries that are available to read
Simple functionality to extract mono streams from a multichannel (e.g. stereo) signal.
Definition AudioOutput.h:793
Vector< ChannelSelectionOutputDef > out_channels
Definition AudioOutput.h:826
ChannelSplitOutput(Print &out, int channel)
Definition AudioOutput.h:797
size_t write(const uint8_t *data, size_t len) override
Definition AudioOutput.h:808
void addOutput(Print &out, int channel)
Definition AudioOutput.h:801
size_t writeT(const uint8_t *buffer, size_t size)
Definition AudioOutput.h:829
Stream Wrapper which can be used to print the values as readable ASCII to the screen to be analyzed i...
Definition AudioOutput.h:116
virtual size_t write(const uint8_t *data, size_t len) override
Writes the data - formatted as CSV - to the output stream.
Definition AudioOutput.h:175
void writeFrames(T *data_ptr, int frameCount)
Definition AudioOutput.h:222
CsvOutput(int buffer_size=DEFAULT_BUFFER_SIZE, bool active=true)
Definition AudioOutput.h:118
const char * delimiter_str
Definition AudioOutput.h:220
AudioInfo defaultConfig()
Provides the default configuration.
Definition AudioOutput.h:139
bool begin(int channels)
Starts the processing with the defined number of channels.
Definition AudioOutput.h:151
int availableForWrite() override
Definition AudioOutput.h:214
CsvOutput(Print &out, int channels=2, int buffer_size=DEFAULT_BUFFER_SIZE, bool active=true)
Constructor.
Definition AudioOutput.h:123
AudioInfo defaultConfig(RxTxMode mode)
Definition AudioOutput.h:136
Print * out_ptr
Definition AudioOutput.h:218
virtual void setAudioInfo(AudioInfo info) override
defines the number of channels
Definition AudioOutput.h:167
T * data_ptr
Definition AudioOutput.h:217
bool begin(AudioInfo info) override
Starts the processing with the defined number of channels.
Definition AudioOutput.h:148
bool begin() override
(Re)start (e.g. if channels is set in constructor)
Definition AudioOutput.h:158
int channel
Definition AudioOutput.h:219
void setDelimiter(const char *del)
Defines an alternative (column) delimiter. The default is ,.
Definition AudioOutput.h:131
const char * delimiter()
Provides the current column delimiter.
Definition AudioOutput.h:134
Creates a Hex Dump.
Definition AudioOutput.h:243
virtual size_t write(const uint8_t *data, size_t len) override
Definition AudioOutput.h:268
void flush() override
Definition AudioOutput.h:263
int pos
Definition AudioOutput.h:294
AudioInfo defaultConfig(RxTxMode mode=TX_MODE)
Definition AudioOutput.h:287
HexDumpOutput(Print &out, int buffer_size=DEFAULT_BUFFER_SIZE, bool active=true)
Constructor.
Definition AudioOutput.h:250
Print * out_ptr
Definition AudioOutput.h:293
bool begin() override
Definition AudioOutput.h:256
HexDumpOutput(int buffer_size=DEFAULT_BUFFER_SIZE, bool active=true)
Definition AudioOutput.h:245
Writes to a preallocated memory.
Definition AudioOutput.h:742
int pos
Definition AudioOutput.h:779
uint8_t * p_start
Definition AudioOutput.h:780
uint8_t * p_next
Definition AudioOutput.h:781
MemoryOutput(uint8_t *start, int len)
Definition AudioOutput.h:744
size_t write(const uint8_t *data, size_t len) override
Definition AudioOutput.h:761
int availableForWrite() override
Definition AudioOutput.h:774
bool begin() override
Definition AudioOutput.h:754
size_t max_size
Definition AudioOutput.h:782
int size()
Definition AudioOutput.h:776
Abstract class: Objects can be put into a pipleline.
Definition AudioOutput.h:100
virtual void setOutput(Print &out)=0
Defines/Changes the output target.
Definition AudioOutput.h:411
void next()
Moves to the next mixing index.
Definition AudioOutput.h:631
size_t writeSilence(size_t bytes)
Writes silence to the current stream buffer.
Definition AudioOutput.h:609
bool flushMixer()
Force output to final destination.
Definition AudioOutput.h:562
void setIndex(int idx)
Sets the Output Stream index.
Definition AudioOutput.h:628
int size_bytes
Definition AudioOutput.h:652
void mixSamples(size_t samples)
Mixes the samples from all input streams into the output buffer.
Definition AudioOutput.h:665
bool is_active
Definition AudioOutput.h:650
int availableSamples()
Returns the minimum number of samples available across all buffers.
Definition AudioOutput.h:586
bool allocate_buffers(int sizeBytes)
Allocates ring buffers for all input streams.
Definition AudioOutput.h:712
OutputMixer(Print &finalOutput, int outputStreamCount, Allocator &allocator=DefaultAllocatorRAM)
Constructor with output stream, number of input streams, and allocator.
Definition AudioOutput.h:431
int stream_idx
Definition AudioOutput.h:651
Vector< T > output
Definition AudioOutput.h:647
size_t writeSilence(int idx, size_t bytes)
Writes silence to the specified stream buffer.
Definition AudioOutput.h:617
size_t write(int idx, const uint8_t *buffer_c, size_t bytes)
Write the data for an individual stream idx which will be mixed together.
Definition AudioOutput.h:515
bool is_auto_index
Definition AudioOutput.h:655
size_t write(const uint8_t *data, size_t len) override
Definition AudioOutput.h:502
int available(int idx)
Provides the available bytes in the buffer.
Definition AudioOutput.h:551
BaseBuffer< T > * getBuffer(int idx)
Provides the write buffer for the indicated index.
Definition AudioOutput.h:639
Vector< float > weights
Definition AudioOutput.h:644
void setCreateBufferCallback(BaseBuffer< T > *(*cb)(int size))
Define callback to allocate custum buffer types.
Definition AudioOutput.h:634
int availableForWrite() override
Provides the bytes available to write for the current stream buffer.
Definition AudioOutput.h:538
int availablePercent(int idx)
Provides the % fill level of the buffer for the indicated index.
Definition AudioOutput.h:559
Allocator & allocator
Definition AudioOutput.h:646
void update_total_weights()
Recalculates the total weights for normalization.
Definition AudioOutput.h:704
Print * p_final_output
Definition AudioOutput.h:648
void free_buffers()
Releases memory for all ring buffers.
Definition AudioOutput.h:727
~OutputMixer()
Definition AudioOutput.h:438
OutputMixer(Allocator &allocator=DefaultAllocatorRAM)
Default constructor. You must call setOutput() and setOutputCount() before use.
Definition AudioOutput.h:419
void end()
Remove all input streams.
Definition AudioOutput.h:487
void setOutput(Print &finalOutput)
Sets the final output destination for mixed audio.
Definition AudioOutput.h:441
void setWeight(int channel, float weight)
Definition AudioOutput.h:467
int output_count
Definition AudioOutput.h:653
BaseBuffer< T > *(* create_buffer_cb)(int size, Allocator &allocator)
Definition AudioOutput.h:656
Vector< BaseBuffer< T > * > buffers
Definition AudioOutput.h:645
int availableForWrite(int idx)
Provides the bytes available to write for the indicated stream index.
Definition AudioOutput.h:543
bool resize(size_t sizeBytes)
Resizes the buffer to the indicated number of bytes.
Definition AudioOutput.h:597
static BaseBuffer< T > * create_buffer(int sizeBytes, Allocator &allocator)
Creates a default ring buffer of the specified size.
Definition AudioOutput.h:660
void setAutoIndex(bool flag)
Automatically increment mixing index after each write.
Definition AudioOutput.h:625
bool begin(int copy_buffer_size_bytes=DEFAULT_BUFFER_SIZE)
Starts the processing.
Definition AudioOutput.h:477
void * p_memory
Definition AudioOutput.h:654
float total_weights
Definition AudioOutput.h:649
int size()
Number of stremams to which are mixed together.
Definition AudioOutput.h:495
void setOutputCount(int count)
Sets the number of streams to mix.
Definition AudioOutput.h:444
size_t write(uint8_t) override
Single byte write - not supported, returns 0.
Definition AudioOutput.h:498
Implements a typed Ringbuffer.
Definition Buffers.h:363
A simple Buffer implementation which just uses a (dynamically sized) array.
Definition Buffers.h:194
bool write(T sample) override
write add an entry to the buffer
Definition Buffers.h:228
int available() override
provides the number of entries that are available to read
Definition Buffers.h:255
T * address() override
Provides address to beginning of the buffer.
Definition Buffers.h:303
bool isFull() override
checks if the buffer is full
Definition Buffers.h:262
Vector implementation which provides the most important methods as defined by std::vector....
Definition Vector.h:21
bool resize(size_t newSize, T value)
Definition Vector.h:266
int size()
Definition Vector.h:178
RxTxMode
The Microcontroller is the Audio Source (TX_MODE) or Audio Sink (RX_MODE). RXTX_MODE is Source and Si...
Definition AudioTypes.h:26
@ TX_MODE
Definition AudioTypes.h:26
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition LMSEchoCancellationStream.h:6
int24_4bytes_t int24_t
Definition int24_t.h:12
static TAllocatorSTD DefaultAllocatorRAM
Definition Allocator.h:209
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
virtual void logInfo(const char *source="")
Definition AudioTypes.h:122
Mixing of multiple audio input streams into a single output stream.
Definition AudioOutput.h:379
float value
Definition AudioOutput.h:380
T scale(T sample) const
Definition AudioOutput.h:383
MixGain(float f)
Definition AudioOutput.h:382