2#include "AudioToolsConfig.h"
3#include "AudioTools/CoreAudio/AudioTypes.h"
4#include "AudioTools/CoreAudio/BaseConverter.h"
5#include "AudioTools/CoreAudio/Buffers.h"
10#define PRINT_FLUSH_OVERRIDE override
12#define PRINT_FLUSH_OVERRIDE
26 virtual size_t write(
const uint8_t *data,
size_t len)
override = 0;
28 virtual size_t write(uint8_t ch)
override {
35 virtual int availableForWrite()
override {
return DEFAULT_BUFFER_SIZE; }
39 virtual void flush() PRINT_FLUSH_OVERRIDE {
53 if (out) notifyAudioChange(out);
65 for (
int j = 0; j < len / 2; j++) {
66 write((uint8_t *)&zero, 2);
75 virtual bool begin() {
79 virtual void end() { is_active =
false; }
81 virtual operator bool() {
return is_active; }
86 SingleBuffer<uint8_t> tmp{MAX_SINGLE_CHARS};
87 bool is_active =
false;
115 CsvOutput(
int buffer_size = DEFAULT_BUFFER_SIZE,
bool active =
true) {
116 this->is_active = active;
121 bool active =
true) {
122 this->out_ptr = &out;
123 this->is_active = active;
156 this->is_active =
true;
166 this->is_active =
true;
172 virtual size_t write(
const uint8_t *data,
size_t len)
override {
173 LOGD(
"CsvOutput::write: %d", (
int)len);
175 LOGE(
"is not active");
184 LOGW(
"Channels not defined: using 2");
187 size_t lenChannels = len / (
sizeof(T) * cfg.
channels);
188 if (lenChannels > 0) {
189 writeFrames((T *)data, lenChannels);
190 }
else if (len ==
sizeof(T)) {
192 T *data_value = (T *)data;
193 out_ptr->print(data_value[0]);
199 out_ptr->print(delimiter_str);
202 LOGE(
"Unsupported size: %d for channels %d and bits: %d", (
int)len,
211 int availableForWrite()
override {
return 1024; }
215 Print *out_ptr = &Serial;
217 const char *delimiter_str =
",";
219 void writeFrames(T *data_ptr,
int frameCount) {
220 for (
size_t j = 0; j < frameCount; j++) {
221 for (
int ch = 0; ch < cfg.
channels; ch++) {
222 if (out_ptr !=
nullptr && data_ptr !=
nullptr) {
224 out_ptr->print(value);
228 this->out_ptr->print(delimiter_str);
230 this->out_ptr->println();
244 HexDumpOutput(
int buffer_size = DEFAULT_BUFFER_SIZE,
bool active =
true) {
245 this->is_active = active;
250 bool active =
true) {
251 this->out_ptr = &out;
252 this->is_active = active;
255 bool begin()
override {
257 this->is_active =
true;
262 void flush()
override {
267 virtual size_t write(
const uint8_t *data,
size_t len)
override {
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;
380 output_count = count;
381 buffers.resize(count);
382 for (
int i = 0; i < count; i++) {
383 buffers[i] =
nullptr;
385 weights.resize(count);
386 for (
int i = 0; i < count; i++) {
396 if (channel <
size()) {
397 weights[channel] = weight;
399 LOGE(
"Invalid channel %d - max is %d", channel,
size() - 1);
405 bool begin(
int copy_buffer_size_bytes = DEFAULT_BUFFER_SIZE) {
407 size_bytes = copy_buffer_size_bytes;
422 int size() {
return output_count; }
425 size_t write(uint8_t)
override {
return 0; }
429 size_t write(
const uint8_t *data,
size_t len)
override {
430 size_t result =
write(stream_idx, data, len);
434 if (stream_idx >= output_count) {
442 size_t write(
int idx,
const uint8_t *buffer_c,
size_t bytes) {
443 LOGD(
"write idx %d: %d", idx, (
int)bytes);
445 BaseBuffer<T> *p_buffer = idx < output_count ? buffers[idx] :
nullptr;
446 assert(p_buffer !=
nullptr);
447 size_t samples = bytes /
sizeof(T);
449 result = p_buffer->
writeArray((T *)buffer_c, samples) *
sizeof(T);
451 LOGW(
"Available Buffer %d too small %d: requested: %d -> increase the "
452 "buffer size", (
int) idx,
466 if (p_buffer ==
nullptr)
474 if (p_buffer ==
nullptr)
476 return p_buffer->
available() *
sizeof(T);
481 return 100.0 *
available(idx) / size_bytes;
495 output.resize(samples);
496 memset(output.data(), 0, samples *
sizeof(T));
497 for (
int j = 0; j < output_count; j++) {
498 float weight = weights[j];
500 for (
int i = 0; i < samples; i++) {
502 buffers[j]->read(sample);
503 output[i] += weight * sample / total_weights;
508 LOGD(
"write to final out: %d",
static_cast<int>(samples *
sizeof(T)));
509 p_final_output->write((uint8_t *)output.data(), samples *
sizeof(T));
518 for (
int j = 0; j < output_count; j++) {
519 int available_samples = buffers[j]->available();
520 if (available_samples > 0){
521 samples = MIN(size_bytes /
sizeof(T), (
size_t)available_samples);
529 if (
size != size_bytes) {
537 if (bytes == 0)
return 0;
538 uint8_t silence[bytes];
539 memset(silence, 0, bytes);
540 return write(stream_idx, silence, bytes);
545 if (bytes == 0)
return 0;
546 uint8_t silence[bytes];
547 memset(silence, 0, bytes);
548 return write(idx, silence, bytes);
553 is_auto_index = flag;
568 create_buffer_cb = cb;
573 return idx < output_count ? buffers[idx] :
nullptr;
579 Vector<float> weights{0};
580 Print *p_final_output =
nullptr;
581 float total_weights = 0.0;
582 bool is_active =
false;
585 int output_count = 0;
586 void *p_memory =
nullptr;
587 bool is_auto_index =
true;
598 for (
int j = 0; j < weights.size(); j++) {
599 total_weights += weights[j];
606 for (
int j = 0; j < output_count; j++) {
607 if (buffers[j] !=
nullptr) {
617 for (
int j = 0; j < output_count; j++) {
618 if (buffers[j] !=
nullptr) {
620 buffers[j] =
nullptr;
638 if (p_next ==
nullptr) {
639 LOGE(
"start must not be null");
643 bool begin()
override {
650 size_t write(
const uint8_t *data,
size_t len)
override {
651 if (p_next ==
nullptr)
653 if (pos + len <= max_size) {
654 memcpy(p_next, data, len);
659 LOGE(
"Buffer too small: pos:%d, size: %d ", pos, (
int)max_size);
664 int availableForWrite()
override {
return max_size - pos; }
666 int size() {
return max_size; }
670 uint8_t *p_start =
nullptr;
671 uint8_t *p_next =
nullptr;
694 def.channel = channel;
696 out_channels.push_back(def);
699 size_t write(
const uint8_t *data,
size_t len)
override {
702 return writeT<int16_t>(data, len);
704 return writeT<int24_t>(data, len);
706 return writeT<int32_t>(data, len);
714 Print *p_out =
nullptr;
719 template <
typename T>
720 size_t writeT(
const uint8_t *buffer,
size_t size) {
721 int sample_count = size /
sizeof(T);
722 int result_size = sample_count / cfg.
channels;
723 T *data = (T *)buffer;
724 T result[result_size];
726 for (
int ch = 0; ch < out_channels.size(); ch++) {
730 for (
int j = def.channel; j < sample_count; j += cfg.
channels) {
731 result[i++] = data[j];
735 def.p_out->write((uint8_t *)result, result_size *
sizeof(T));
736 if (written != result_size *
sizeof(T)) {
737 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:28