17#include "AudioTools/AudioCodecs/AudioCodecsBase.h"
18#include "AudioTools/AudioCodecs/MultiDecoder.h"
19#include "AudioTools/Communication/OSCData.h"
20#include "AudioTools/CoreAudio/AudioBasic/StrView.h"
37 void setEncoder(
AudioEncoder *encoder) { p_codec = encoder; }
39 void setOutput(
Print &outStream) { p_out = &outStream; }
41 bool begin()
override {
43 if (p_codec ==
nullptr)
return false;
44 osc_out.setOutput(*p_out);
46 p_codec->setOutput(osc_out);
48 is_active = p_codec->begin();
60 size_t write(
const uint8_t *data,
size_t len) {
61 LOGD(
"OSCContainerEncoder::write: %d", (
int)len);
62 if ((repeat_info > 0) && (packet_count % repeat_info == 0)) {
65 p_codec->write(data, len);
60 size_t write(
const uint8_t *data,
size_t len) {
…}
75 operator bool() {
return is_active; };
77 virtual const char *
mime() {
return "audio/OSC"; };
83 this->repeat_info = packet_count;
96 osc_out.setEncodedWriteCallback(write_callback);
101 return osc_out.write(data, len, seq);
105 uint64_t packet_count = 0;
107 bool is_active =
false;
108 bool is_send_info_active =
true;
110 Print *p_out =
nullptr;
115 void setReference(
void *ref) { this->ref = ref; }
116 void setOutput(
Print &outStream) { p_out = &outStream; }
117 void setEncodedWriteCallback(
void (*write_callback)(
118 uint8_t *data,
size_t len, uint64_t seq,
void *ref)) {
119 this->encoded_write_callback = write_callback;
121 uint64_t getSequenceNumber() {
return sequence_number; }
126 size_t write(
const uint8_t *data,
size_t len)
override {
127 size_t result = write(data, len);
131 size_t write(
const uint8_t *data,
size_t len, uint64_t seq) {
132 LOGD(
"writeAudio: %d", (
int)len);
133 if (encoded_write_callback !=
nullptr) {
134 encoded_write_callback((uint8_t *)data, len, sequence_number, ref);
136 uint8_t osc_data[len + 20];
137 OSCData osc{osc_data,
sizeof(osc_data)};
139 osc.setFormat(
"ttb");
140 osc.write((uint64_t)
millis());
142 osc.write(sequence_number);
143 osc.write(data, len);
144 p_out->write(osc_data, osc.size());
149 void (*encoded_write_callback)(uint8_t *data,
size_t len, uint64_t seq,
150 void *ref) =
nullptr;
151 Print *p_out =
nullptr;
152 uint64_t sequence_number = 0;
158 if (is_send_info_active) {
159 LOGD(
"writeAudioInfo");
160 uint8_t osc_data[100];
161 OSCData osc{osc_data,
sizeof(osc_data)};
163 osc.setFormat(
"iiis");
168 p_out->write(osc_data, osc.size());
197 is_multi_decoder =
true;
204 LOGD(
"OSCContainerDecoder::setOutput")
210 if (p_codec ==
nullptr || p_osc ==
nullptr)
return false;
212 p_osc->
addCallback(
"/audio/info", parseInfo, OSCCompare::StartsWith);
213 p_osc->
addCallback(
"/audio/data", parseData, OSCCompare::StartsWith);
218 void end() { is_active =
false; }
220 size_t write(
const uint8_t *data,
size_t len) {
221 if (!is_active)
return 0;
222 LOGD(
"write: %d", (
int)len);
223 if (!p_osc->
parse((uint8_t *)data, len)) {
229 operator bool() {
return is_active; };
239 bool (*callback)(
OSCData &data,
void *ref),
240 OSCCompare compare = OSCCompare::Matches) {
241 if (p_osc ==
nullptr)
return false;
248 uint8_t *data,
size_t len,
257 this->missing_data_callback = missing_data_callback;
264 bool is_active =
false;
265 bool is_multi_decoder =
false;
268 Print *p_out =
nullptr;
270 OSCData *p_osc = &osc_default;
275 void *ref) =
nullptr;
276 void (*missing_data_callback)(uint64_t from_seq, uint64_t to_seq,
283 LOGW(
"Missing sequence numbers %d - %d", from_seq, to_seq);
286 static bool parseData(
OSCData &osc,
void *ref) {
292 if (self->seq_no + 1 != seq) {
293 self->missing_data_callback(self->seq_no + 1, seq - 1, self->ref);
299 bool ok = self->
write_callback(time, seq, data.data, data.len, ref);
300 if (!ok)
return true;
303 if (self->p_codec !=
nullptr) {
304 self->p_codec->write(data.data, data.len);
310 static bool parseInfo(OSCData &osc,
void *ref) {
313 info.channels = osc.readInt32();
314 info.bits_per_sample = osc.readInt32();
315 const char *
mime = osc.readString();
317 OSCContainerDecoder *self =
static_cast<OSCContainerDecoder *
>(ref);
318 if (self !=
nullptr) {
319 self->setAudioInfo(info);
320 self->mime_str =
mime;
321 LOGI(
"mime: %s",
mime);
323 if (self->is_multi_decoder)
324 static_cast<MultiDecoder*
>(self->p_codec)->selectDecoder(
mime);