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;
372 vector.push_back(out);
377 vector.push_back(out);
381 for (
int j = 0; j < vector.size(); j++) {
387 for (
int j = 0; j < vector.size(); j++) {
388 vector[j]->setAudioInfo(info);
392 size_t write(
const uint8_t *data,
size_t len) {
393 for (
int j = 0; j < vector.size(); j++) {
397 int written = vector[j]->write(data + start, open);
405 size_t write(uint8_t ch) {
406 for (
int j = 0; j < vector.size(); j++) {
409 open -= vector[j]->write(ch);
417 for (
auto &tmp : vector) {
418 if (tmp !=
nullptr && tmp->isDeletable()) {
476 start_ms = startSeconds * 1000;
477 calculateByteLimits();
483 calculateByteLimits();
489 end_ms = endSeconds * 1000;
490 calculateByteLimits();
496 calculateByteLimits();
501 if (current_bytes < start_bytes)
return false;
502 if (end_bytes > 0 && current_bytes > end_bytes)
return false;
508 return (current_bytes < end_bytes && current_bytes >= start_bytes);
516 bool begin()
override {
517 calculateByteLimits();
519 LOGI(
"byte range %u - %u",(
unsigned) start_bytes,(
unsigned) end_bytes);
523 operator bool()
override {
return isActive(); }
530 if (p_stream ==
nullptr)
return 0;
532 if (start_bytes > current_bytes){
533 consumeBytes(start_bytes - current_bytes);
540 result = p_stream->readBytes(data, len);
541 current_bytes += len;
543 }
while (result > 0 && current_bytes < start_bytes);
548 size_t write(
const uint8_t *data,
size_t len)
override {
549 if (current_bytes >= end_bytes)
return 0;
550 current_bytes += len;
551 if (current_bytes < start_bytes)
return len;
552 return p_print->write(data, len);
557 if (p_stream ==
nullptr)
return 0;
558 return current_bytes < end_bytes ? p_stream->available() : 0;
565 calculateByteLimits();
568 int availableForWrite()
override {
569 return current_bytes < end_bytes ? p_print->availableForWrite() : 0;
605 return end_bytes - start_bytes;
609 Stream *p_stream =
nullptr;
610 Print *p_print =
nullptr;
611 AudioInfoSupport *p_info =
nullptr;
612 uint32_t start_ms = 0;
613 uint32_t end_ms = UINT32_MAX;
614 uint32_t start_bytes = 0;
615 uint32_t end_bytes = UINT32_MAX;
616 uint32_t current_bytes = 0;
617 float compression_ratio = 1.0;
619 void consumeBytes(uint32_t len){
621 uint8_t buffer[1024];
623 int toread = min(1024, open);
624 p_stream->readBytes(buffer, toread);
627 current_bytes += len;
628 LOGD(
"consumed %u -> %u",(
unsigned) len, (
unsigned)current_bytes);
631 void calculateByteLimits() {
633 if (bytes_per_second > 0) {
634 start_bytes = bytes_per_second * start_ms / compression_ratio / 1000;
635 end_bytes = bytes_per_second * end_ms / compression_ratio / 1000;
637 LOGE(
"AudioInfo not defined");
660 bool begin()
override {
661 AudioOutput::begin();
663 for (
auto &out : out_channels) {
664 for (
auto &ch : out.channels) {
666 LOGE(
"Channel '%d' not valid for max %d channels", ch, cfg.
channels);
678 channels.push_back(channel);
680 def.channels = channels;
682 def.p_audio_info = &out;
683 out_channels.push_back(def);
690 channels.push_back(channel);
692 def.channels = channels;
694 def.p_audio_info = &out;
695 out_channels.push_back(def);
702 channels.push_back(channel);
704 def.channels = channels;
706 out_channels.push_back(def);
713 channels.push_back(left);
714 channels.push_back(right);
716 def.channels = channels;
718 out_channels.push_back(def);
725 channels.push_back(left);
726 channels.push_back(right);
728 def.channels = channels;
730 def.p_audio_info = &out;
731 out_channels.push_back(def);
738 channels.push_back(left);
739 channels.push_back(right);
741 def.channels = channels;
743 def.p_audio_info = &out;
744 out_channels.push_back(def);
747 size_t write(
const uint8_t *data,
size_t len)
override {
748 if (!is_active)
return false;
749 LOGD(
"write %d", (
int)len);
752 return writeT<int16_t>(data, len);
754 return writeT<int24_t>(data, len);
756 return writeT<int32_t>(data, len);
765 for (
auto &info : out_channels) {
766 auto p_notify = info.p_audio_info;
767 if (p_notify !=
nullptr) {
770 p_notify->setAudioInfo(result);
777 Print *p_out =
nullptr;
784 template <
typename T>
785 size_t writeT(
const uint8_t *buffer,
size_t size) {
786 if (!is_active)
return 0;
787 int sample_count = size /
sizeof(T);
789 T *data = (T *)buffer;
791 for (
int i = 0; i < sample_count; i += cfg.
channels) {
793 for (
auto &out : out_channels) {
794 T out_frame[out.channels.size()];
796 for (
auto &ch : out.channels) {
798 int channel = (ch < cfg.
channels) ? ch : cfg.channels - 1;
799 out_frame[ch_out++] = frame[channel];
802 size_t written = out.buffer.writeArray((
const uint8_t *)&out_frame,
sizeof(out_frame));
804 if (out.buffer.availableForWrite()<
sizeof(out_frame)){
805 out.p_out->write(out.buffer.data(), out.buffer.available());
818 for (
auto &channels_select : out_channels) {
819 if (channels_select.p_out == out)
return channels_select.channels.size();
821 return defaultChannels;