2#include "AudioTools/CoreAudio/AudioTypes.h"
3#include "AudioTools/CoreAudio/BaseConverter.h"
4#include "AudioTools/CoreAudio/Buffers.h"
5#include "AudioToolsConfig.h"
6#if defined(USE_ESP32_DSP)
13#define PRINT_FLUSH_OVERRIDE override
15#define PRINT_FLUSH_OVERRIDE
29 virtual size_t write(
const uint8_t *data,
size_t len)
override = 0;
31 virtual size_t write(uint8_t ch)
override {
38 virtual int availableForWrite()
override {
return DEFAULT_BUFFER_SIZE; }
42 virtual void flush() PRINT_FLUSH_OVERRIDE {
56 if (out) notifyAudioChange(out);
68 for (
int j = 0; j < len / 2; j++) {
69 write((uint8_t *)&zero, 2);
78 virtual bool begin() {
82 virtual void end() { is_active =
false; }
84 virtual operator bool() {
return is_active; }
89 SingleBuffer<uint8_t> tmp{MAX_SINGLE_CHARS};
90 bool is_active =
false;
115template <
typename T =
int16_t>
118 CsvOutput(
int buffer_size = DEFAULT_BUFFER_SIZE,
bool active =
true) {
119 this->is_active = active;
124 bool active =
true) {
125 this->out_ptr = &out;
126 this->is_active = active;
159 this->is_active =
true;
169 this->is_active =
true;
175 virtual size_t write(
const uint8_t *data,
size_t len)
override {
176 LOGD(
"CsvOutput::write: %d", (
int)len);
178 LOGE(
"is not active");
187 LOGW(
"Channels not defined: using 2");
190 size_t lenChannels = len / (
sizeof(T) * cfg.
channels);
191 if (lenChannels > 0) {
192 writeFrames((T *)data, lenChannels);
193 }
else if (len ==
sizeof(T)) {
195 T *data_value = (T *)data;
196 out_ptr->print(data_value[0]);
202 out_ptr->print(delimiter_str);
205 LOGE(
"Unsupported size: %d for channels %d and bits: %d", (
int)len,
214 int availableForWrite()
override {
return 1024; }
218 Print *out_ptr = &Serial;
220 const char *delimiter_str =
",";
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) {
227 out_ptr->print(value);
230 if (ch < cfg.
channels - 1) this->out_ptr->print(delimiter_str);
232 this->out_ptr->println();
245 HexDumpOutput(
int buffer_size = DEFAULT_BUFFER_SIZE,
bool active =
true) {
246 this->is_active = active;
251 bool active =
true) {
252 this->out_ptr = &out;
253 this->is_active = active;
256 bool begin()
override {
258 this->is_active =
true;
263 void flush()
override {
268 virtual size_t write(
const uint8_t *data,
size_t len)
override {
269 if (!is_active)
return 0;
271 for (
size_t j = 0; j < len; j++) {
272 out_ptr->print(data[j], HEX);
276 out_ptr->print(
" - ");
287 AudioInfo defaultConfig(
RxTxMode mode = TX_MODE) {
293 Print *out_ptr = &Serial;
368template <
typename T =
int16_t>
378 : allocator(allocator) {}
390 Allocator &allocator = DefaultAllocatorRAM)
401 output_count = count;
402 buffers.resize(count);
403 for (
int i = 0; i < count; i++) {
404 buffers[i] =
nullptr;
406 weights.resize(count);
407 for (
int i = 0; i < count; i++) {
417 if (channel <
size()) {
418 weights[channel] = weight;
420 LOGE(
"Invalid channel %d - max is %d", channel,
size() - 1);
426 bool begin(
int copy_buffer_size_bytes = DEFAULT_BUFFER_SIZE) {
428 size_bytes = copy_buffer_size_bytes;
443 int size() {
return output_count; }
446 size_t write(uint8_t)
override {
return 0; }
450 size_t write(
const uint8_t *data,
size_t len)
override {
451 size_t result =
write(stream_idx, data, len);
455 if (stream_idx >= output_count) {
463 size_t write(
int idx,
const uint8_t *buffer_c,
size_t bytes) {
464 LOGD(
"write idx %d: %d", idx, (
int)bytes);
466 BaseBuffer<T> *p_buffer = idx < output_count ? buffers[idx] :
nullptr;
467 assert(p_buffer !=
nullptr);
468 size_t samples = bytes /
sizeof(T);
470 result = p_buffer->
writeArray((T *)buffer_c, samples) *
sizeof(T);
473 "Available Buffer %d too small %d: requested: %d -> increase the "
489 if (p_buffer ==
nullptr)
return 0;
496 if (p_buffer ==
nullptr)
return 0;
497 return p_buffer->
available() *
sizeof(T);
515 LOGD(
"write to final out: %d",
static_cast<int>(samples *
sizeof(T)));
516 p_final_output->write((uint8_t *)output.data(), samples *
sizeof(T));
527 for (
int j = 0; j < output_count; j++) {
528 int available_samples = buffers[j]->available();
529 if (available_samples > 0) {
530 samples = MIN(size_bytes /
sizeof(T), (
size_t)available_samples);
538 if (sizeBytes != size_bytes) {
541 size_bytes = sizeBytes;
546 if (bytes == 0)
return 0;
547 uint8_t silence[bytes];
548 memset(silence, 0, bytes);
549 return write(stream_idx, silence, bytes);
554 if (bytes == 0)
return 0;
555 uint8_t silence[bytes];
556 memset(silence, 0, bytes);
557 return write(idx, silence, bytes);
571 create_buffer_cb = cb;
576 return idx < output_count ? buffers[idx] :
nullptr;
581 Vector<BaseBuffer<T> *> buffers{0, DefaultAllocatorRAM};
582 Allocator &allocator;
583 Vector<T> output{0, allocator};
584 Print *p_final_output =
nullptr;
585 float total_weights = 0.0;
586 bool is_active =
false;
589 int output_count = 0;
590 void *p_memory =
nullptr;
591 bool is_auto_index =
true;
592 BaseBuffer<T> *(*create_buffer_cb)(
int size,
602#if defined(USE_ESP32_DSP)
604 float mix_out[samples] = {0.0f};
605 float temp[samples] = {0.0f};
607 for (uint8_t j = 0; j < output_count; j++) {
608 const float factor = weights[j] / total_weights;
610 for (uint16_t i = 0; i < samples; i++) {
613 temp[i] =
static_cast<float>(s) * factor;
616 dsps_add_f32(mix_out, temp, mix_out, samples, 1, 1, 1);
619 output.resize(samples);
620 for (
size_t i = 0; i < samples; i++) {
621 float v = mix_out[i];
622 output[i] =
static_cast<int16_t
>(v);
626 output.resize(samples);
627 memset(output.data(), 0, samples *
sizeof(T));
628 for (
int j = 0; j < output_count; j++) {
629 float factor = weights[j] / total_weights;
630 for (
int i = 0; i < samples; i++) {
632 buffers[j]->read(sample);
633 output[i] +=
static_cast<int16_t
>(factor * sample);
642 for (
int j = 0; j < weights.size(); j++) {
643 total_weights += weights[j];
650 for (
int j = 0; j < output_count; j++) {
651 if (buffers[j] !=
nullptr) {
661 for (
int j = 0; j < output_count; j++) {
662 if (buffers[j] !=
nullptr) {
664 buffers[j] =
nullptr;
681 if (p_next ==
nullptr) {
682 LOGE(
"start must not be null");
686 bool begin()
override {
693 size_t write(
const uint8_t *data,
size_t len)
override {
694 if (p_next ==
nullptr)
return 0;
695 if (pos + len <= max_size) {
696 memcpy(p_next, data, len);
701 LOGE(
"Buffer too small: pos:%d, size: %d ", pos, (
int)max_size);
706 int availableForWrite()
override {
return max_size - pos; }
708 int size() {
return max_size; }
712 uint8_t *p_start =
nullptr;
713 uint8_t *p_next =
nullptr;
735 def.channel = channel;
737 out_channels.push_back(def);
740 size_t write(
const uint8_t *data,
size_t len)
override {
743 return writeT<int16_t>(data, len);
745 return writeT<int24_t>(data, len);
747 return writeT<int32_t>(data, len);
755 Print *p_out =
nullptr;
760 template <
typename T =
int16_t>
761 size_t writeT(
const uint8_t *buffer,
size_t size) {
762 int sample_count = size /
sizeof(T);
763 int result_size = sample_count / cfg.
channels;
764 T *data = (T *)buffer;
765 T result[result_size];
767 for (
int ch = 0; ch < out_channels.size(); ch++) {
771 for (
int j = def.channel; j < sample_count; j += cfg.
channels) {
772 result[i++] = data[j];
776 def.p_out->write((uint8_t *)result, result_size *
sizeof(T));
777 if (written != result_size *
sizeof(T)) {
778 LOGW(
"Could not write all samples");
RxTxMode
The Microcontroller is the Audio Source (TX_MODE) or Audio Sink (RX_MODE). RXTX_MODE is Source and Si...
Definition AudioTypes.h:30