2#include "AudioTools/CoreAudio/AudioOutput.h"
3#include "AudioTools/CoreAudio/AudioStreams.h"
5#ifndef MAX_ZERO_READ_COUNT
6# define MAX_ZERO_READ_COUNT 3
9#ifndef CHANNEL_SELECT_BUFFER_SIZE
10# define CHANNEL_SELECT_BUFFER_SIZE 256
33 p_transform = transform;
34 if (transform ==
nullptr) {
35 LOGE(
"transform is NULL");
38 if (p_stream ==
nullptr) {
39 LOGE(
"p_stream is NULL");
50 result_queue_buffer.
resize(size);
55 size_t readBytes(uint8_t *data,
size_t len) {
56 LOGD(
"TransformationReader::readBytes: %d", (
int)len);
61 if (p_stream ==
nullptr) {
62 LOGE(
"p_stream is NULL");
67 if (buffer.size() == 0) {
68 int size = (0.5f / p_transform->getByteFactor() * len);
71 LOGI(
"read size: %d", size);
75 if (result_queue_buffer.
size() == 0) {
77 int rb_size = len * result_queue_factor;
78 LOGI(
"buffer size: %d", rb_size);
79 result_queue_buffer.
resize(rb_size);
83 if (result_queue.available() < len) {
86 while (result_queue.available() < len) {
87 int read_eff = p_stream->readBytes(buffer.data(), buffer.size());
90 if (read_eff != buffer.size()){
91 LOGD(
"readBytes %d -> %d", buffer.size(), read_eff);
93 int write_eff = p_transform->write(buffer.data(), read_eff);
94 if (write_eff != read_eff){
95 LOGE(
"TransformationReader::write %d -> %d", read_eff, write_eff);
99 if (++zero_count > MAX_ZERO_READ_COUNT){
109 int result_len = min((
int)len, result_queue.available());
110 result_len = result_queue.readBytes(data, result_len);
111 LOGD(
"TransformationReader::readBytes: %d -> %d", (
int)len,
118 result_queue_buffer.
resize(0);
127 QueueStream<uint8_t> result_queue{result_queue_buffer};
128 Stream *p_stream =
nullptr;
129 Vector<uint8_t> buffer{0};
130 T *p_transform =
nullptr;
132 int result_queue_factor = 5;
138 Print *result = p_transform->getPrint();
139 p_transform->setOutput((
Print &)result_queue);
146 if (out) p_transform->setOutput(*out);
172 virtual void setOutput(AudioOutput &print) {
183 virtual Print *getPrint() {
return p_print; }
185 virtual Stream *getStream() {
return p_stream; }
187 size_t readBytes(uint8_t *data,
size_t len)
override {
188 LOGD(
"ReformatBaseStream::readBytes: %d", (
int)len);
189 return reader.readBytes(data, len);
192 int available()
override {
193 return DEFAULT_BUFFER_SIZE;
196 int availableForWrite()
override {
197 return DEFAULT_BUFFER_SIZE;
200 virtual float getByteFactor() = 0;
202 void end()
override {
217 Stream *p_stream =
nullptr;
218 Print *p_print =
nullptr;
221 if (getStream() !=
nullptr) {
222 reader.
begin(
this, getStream());
241 void setStream(
Print& out) { p_print = &out; }
243 size_t write(
const uint8_t *data,
size_t len) {
244 return p_print->write(data, len);
252 Print *p_print =
nullptr;
266 void setStream(
AudioStream &stream) { p_stream = &stream; }
272 size_t write(
const uint8_t *data,
size_t len)
override {
273 return p_stream->write(data, len);
276 int availableForWrite()
override {
return p_stream->availableForWrite(); }
278 bool begin()
override {
return p_stream->begin(); }
280 void end()
override { p_stream->end(); }
285 operator bool()
override {
return *p_stream; }
288 AudioStream *p_stream =
nullptr;
301 void setOutput(
AudioOutput &stream) { p_stream = &stream; }
307 size_t write(
const uint8_t *data,
size_t len)
override {
308 return p_stream->write(data, len);
311 bool begin()
override {
return p_stream->begin(); }
313 void end()
override { p_stream->end(); }
318 operator bool()
override {
return *p_stream; }
321 AudioOutput *p_stream =
nullptr;
362 for (
int j = 0; j < vector.size(); j++) {
376 vector.push_back(out);
381 vector.push_back(out);
385 for (
int j = 0; j < vector.size(); j++) {
391 for (
int j = 0; j < vector.size(); j++) {
392 vector[j]->setAudioInfo(info);
396 size_t write(
const uint8_t *data,
size_t len) {
397 for (
int j = 0; j < vector.size(); j++) {
401 int written = vector[j]->write(data + start, open);
409 size_t write(uint8_t ch) {
410 for (
int j = 0; j < vector.size(); j++) {
413 open -= vector[j]->write(ch);
420 Vector<AudioOutput *> vector;
469 start_ms = startSeconds * 1000;
470 calculateByteLimits();
476 calculateByteLimits();
482 end_ms = endSeconds * 1000;
483 calculateByteLimits();
489 calculateByteLimits();
494 if (current_bytes < start_bytes)
return false;
495 if (end_bytes > 0 && current_bytes > end_bytes)
return false;
501 return (current_bytes < end_bytes && current_bytes >= start_bytes);
509 bool begin()
override {
510 calculateByteLimits();
512 LOGI(
"byte range %u - %u",(
unsigned) start_bytes,(
unsigned) end_bytes);
516 operator bool()
override {
return isActive(); }
523 if (p_stream ==
nullptr)
return 0;
525 if (start_bytes > current_bytes){
526 consumeBytes(start_bytes - current_bytes);
533 result = p_stream->readBytes(data, len);
534 current_bytes += len;
536 }
while (result > 0 && current_bytes < start_bytes);
541 size_t write(
const uint8_t *data,
size_t len)
override {
542 if (current_bytes >= end_bytes)
return 0;
543 current_bytes += len;
544 if (current_bytes < start_bytes)
return len;
545 return p_print->write(data, len);
550 if (p_stream ==
nullptr)
return 0;
551 return current_bytes < end_bytes ? p_stream->available() : 0;
558 calculateByteLimits();
561 int availableForWrite()
override {
562 return current_bytes < end_bytes ? p_print->availableForWrite() : 0;
598 return end_bytes - start_bytes;
602 Stream *p_stream =
nullptr;
603 Print *p_print =
nullptr;
604 AudioInfoSupport *p_info =
nullptr;
605 uint32_t start_ms = 0;
606 uint32_t end_ms = UINT32_MAX;
607 uint32_t start_bytes = 0;
608 uint32_t end_bytes = UINT32_MAX;
609 uint32_t current_bytes = 0;
610 float compression_ratio = 1.0;
612 void consumeBytes(uint32_t len){
614 uint8_t buffer[1024];
616 int toread = min(1024, open);
617 p_stream->readBytes(buffer, toread);
620 current_bytes += len;
621 LOGD(
"consumed %u -> %u",(
unsigned) len, (
unsigned)current_bytes);
624 void calculateByteLimits() {
626 if (bytes_per_second > 0) {
627 start_bytes = bytes_per_second * start_ms / compression_ratio / 1000;
628 end_bytes = bytes_per_second * end_ms / compression_ratio / 1000;
630 LOGE(
"AudioInfo not defined");
653 bool begin()
override {
654 AudioOutput::begin();
656 for (
auto &out : out_channels) {
657 for (
auto &ch : out.channels) {
659 LOGE(
"Channel '%d' not valid for max %d channels", ch, cfg.
channels);
671 channels.push_back(channel);
673 def.channels = channels;
675 def.p_audio_info = &out;
676 out_channels.push_back(def);
683 channels.push_back(channel);
685 def.channels = channels;
687 def.p_audio_info = &out;
688 out_channels.push_back(def);
695 channels.push_back(channel);
697 def.channels = channels;
699 out_channels.push_back(def);
706 channels.push_back(left);
707 channels.push_back(right);
709 def.channels = channels;
711 out_channels.push_back(def);
718 channels.push_back(left);
719 channels.push_back(right);
721 def.channels = channels;
723 def.p_audio_info = &out;
724 out_channels.push_back(def);
731 channels.push_back(left);
732 channels.push_back(right);
734 def.channels = channels;
736 def.p_audio_info = &out;
737 out_channels.push_back(def);
740 size_t write(
const uint8_t *data,
size_t len)
override {
741 if (!is_active)
return false;
742 LOGD(
"write %d", (
int)len);
745 return writeT<int16_t>(data, len);
747 return writeT<int24_t>(data, len);
749 return writeT<int32_t>(data, len);
758 for (
auto &info : out_channels) {
759 auto p_notify = info.p_audio_info;
760 if (p_notify !=
nullptr) {
763 p_notify->setAudioInfo(result);
770 Print *p_out =
nullptr;
777 template <
typename T>
778 size_t writeT(
const uint8_t *buffer,
size_t size) {
779 if (!is_active)
return 0;
780 int sample_count = size /
sizeof(T);
782 T *data = (T *)buffer;
784 for (
int i = 0; i < sample_count; i += cfg.
channels) {
786 for (
auto &out : out_channels) {
787 T out_frame[out.channels.size()];
789 for (
auto &ch : out.channels) {
791 int channel = (ch < cfg.
channels) ? ch : cfg.channels - 1;
792 out_frame[ch_out++] = frame[channel];
795 size_t written = out.buffer.writeArray((
const uint8_t *)&out_frame,
sizeof(out_frame));
797 if (out.buffer.availableForWrite()<
sizeof(out_frame)){
798 out.p_out->write(out.buffer.data(), out.buffer.available());
811 for (
auto &channels_select : out_channels) {
812 if (channels_select.p_out == out)
return channels_select.channels.size();
814 return defaultChannels;