arduino-audio-tools
Loading...
Searching...
No Matches
ContainerOSC.h
Go to the documentation of this file.
1
14#pragma once
15#include <string.h>
16
21
22namespace audio_tools {
23
33 public:
35 OSCContainerEncoder(AudioEncoder &encoder) { p_codec = &encoder; }
36
37 void setEncoder(AudioEncoder *encoder) { p_codec = encoder; }
38
40
41 bool begin() override {
42 TRACED();
43 if (p_codec == nullptr) return false;
45 osc_out.begin();
50 return is_active;
51 }
52
58
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)) {
64 }
65 p_codec->write(data, len);
67 return len;
68 }
69
70 void end() {
71 p_codec->end();
72 is_active = false;
73 }
74
75 operator bool() { return is_active; };
76
77 virtual const char *mime() { return "audio/OSC"; };
78
85
88
90 void setReference(void *ref) { osc_out.setReference(ref); }
91
93 void setEncodedWriteCallback(void (*write_callback)(uint8_t *data, size_t len,
94 uint64_t seq,
95 void *ref)) {
96 osc_out.setEncodedWriteCallback(write_callback);
97 }
98
100 size_t resendEncodedData(uint8_t *data, size_t len, uint64_t seq) {
101 return osc_out.write(data, len, seq);
102 }
103
104 protected:
106 int repeat_info = 0;
107 bool is_active = false;
110 Print *p_out = nullptr;
111
113 class OSCOutput : public AudioOutput {
114 public:
115 void setReference(void *ref) { this->ref = ref; }
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;
120 }
122 bool begin() {
123 sequence_number = 0;
124 return true;
125 }
126 size_t write(const uint8_t *data, size_t len) override {
127 size_t result = write(data, len);
129 return result;
130 }
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) {
135 }
136 uint8_t osc_data[len + 20]; // 20 is guess to cover address & fmt
137 OSCData osc{osc_data, sizeof(osc_data)};
138 osc.setAddress("/audio/data");
139 osc.setFormat("ttb");
140 osc.write((uint64_t)millis());
141 // we use a uint64_t for a sequence number
142 osc.write(sequence_number);
143 osc.write(data, len);
144 p_out->write(osc_data, osc.size());
145 return len;
146 }
147
148 protected:
149 void (*encoded_write_callback)(uint8_t *data, size_t len, uint64_t seq,
150 void *ref) = nullptr;
151 Print *p_out = nullptr;
153 void *ref = nullptr;
155
157 void writeAudioInfo(AudioInfo info, const char *mime) {
159 LOGD("writeAudioInfo");
160 uint8_t osc_data[100];
161 OSCData osc{osc_data, sizeof(osc_data)};
162 osc.setAddress("/audio/info");
163 osc.setFormat("iiis");
164 osc.write((int32_t)info.sample_rate);
165 osc.write((int32_t)info.channels);
166 osc.write((int32_t)info.bits_per_sample);
167 osc.write(mime);
168 p_out->write(osc_data, osc.size());
169 }
170 }
171};
172
182 public:
185 setDecoder(decoder);
186 }
188 setDecoder(decoder);
189 }
190
192 void setDecoder(AudioDecoder &decoder) { p_codec = &decoder; }
193
195 void setDecoder(MultiDecoder &decoder) {
196 p_codec = &decoder;
197 is_multi_decoder = true;
198 }
199
201 void setOSCData(OSCData &osc) { p_osc = &osc; }
202
204 LOGD("OSCContainerDecoder::setOutput")
205 p_out = &outStream;
206 }
207
208 bool begin() {
209 TRACED();
210 if (p_codec == nullptr || p_osc == nullptr) return false;
211 p_osc->setReference(this);
214 is_active = true;
215 return true;
216 }
217
218 void end() { is_active = false; }
219
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)) {
224 return 0;
225 }
226 return len;
227 }
228
229 operator bool() { return is_active; };
230
232 const char *mime() { return mime_str.c_str(); };
233
236
238 bool addParserCallback(const char *address,
239 bool (*callback)(OSCData &data, void *ref),
241 if (p_osc == nullptr) return false;
242 p_osc->addCallback(address, callback, compare);
243 return true;
244 }
245
248 uint8_t *data, size_t len,
249 void *ref)) {
251 }
252
259
261 void setReference(void *ref) { this->ref = ref; }
262
263 protected:
264 bool is_active = false;
265 bool is_multi_decoder = false;
268 Print *p_out = nullptr;
274 bool (*write_callback)(uint64_t time, uint64_t seq, uint8_t *data, size_t len,
275 void *ref) = nullptr;
277 void *ref) = missingDataCallback;
278 void *ref = nullptr;
279
282 void *ref) {
283 LOGW("Missing sequence numbers %d - %d", from_seq, to_seq);
284 }
285
286 static bool parseData(OSCData &osc, void *ref) {
287 uint64_t time = osc.readTime();
288 uint64_t seq = osc.readTime();
289 OSCBinaryData data = osc.readData();
290 OSCContainerDecoder *self = static_cast<OSCContainerDecoder *>(ref);
291 // Check for missing sequence numbers
292 if (self->seq_no + 1 != seq) {
293 self->missing_data_callback(self->seq_no + 1, seq - 1, self->ref);
294 }
295 // store the actual sequence number
296 self->seq_no = seq;
297 // call write callbak if defined
298 if (self->write_callback != nullptr) {
299 bool ok = self->write_callback(time, seq, data.data, data.len, ref);
300 if (!ok) return true;
301 }
302 // output to decoder
303 if (self->p_codec != nullptr) {
304 self->p_codec->write(data.data, data.len);
305 }
306
307 return true;
308 }
309
310 static bool parseInfo(OSCData &osc, void *ref) {
312 info.sample_rate = osc.readInt32();
313 info.channels = osc.readInt32();
315 const char *mime = osc.readString();
316
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);
322 // select the right decoder based on the mime type
323 if (self->is_multi_decoder)
324 static_cast<MultiDecoder*>(self->p_codec)->selectDecoder(mime);
325 }
326
327 return true;
328 }
329};
330
331} // namespace audio_tools
#define LOGW(...)
Definition AudioLoggerIDF.h:29
#define TRACED()
Definition AudioLoggerIDF.h:31
#define LOGI(...)
Definition AudioLoggerIDF.h:28
#define LOGD(...)
Definition AudioLoggerIDF.h:27
Decoding of encoded audio into PCM data.
Definition AudioCodecsBase.h:18
AudioInfo info
Definition AudioCodecsBase.h:76
void setAudioInfo(AudioInfo from) override
for most decoders this is not needed
Definition AudioCodecsBase.h:28
Encoding of PCM data.
Definition AudioCodecsBase.h:97
AudioInfo info
Definition AudioCodecsBase.h:116
void setAudioInfo(AudioInfo from) override
Defines the sample rate, number of channels and bits per sample.
Definition AudioCodecsBase.h:106
virtual void setOutput(Print &out_stream) override
Default output assignment (encoders may override to store Print reference)
Definition AudioCodecsBase.h:109
virtual const char * mime()=0
Provides the mime type of the encoded result.
AudioInfo audioInfo() override
provides the actual input AudioInfo
Definition AudioCodecsBase.h:107
Abstract Audio Ouptut class.
Definition AudioOutput.h:25
virtual void setAudioInfo(AudioInfo from)=0
Defines the input AudioInfo.
virtual size_t write(const uint8_t *data, size_t len)=0
virtual void end()=0
virtual bool begin()=0
Parent class for all container formats.
Definition AudioCodecsBase.h:86
Manage multiple AudioDecoders with automatic format detection.
Definition MultiDecoder.h:42
Decodes the provided data from the OSC segments. I recommend to assign a MultiDecoder so that we can ...
Definition ContainerOSC.h:181
OSCData * p_osc
Definition ContainerOSC.h:270
void * ref
Definition ContainerOSC.h:278
static bool parseInfo(OSCData &osc, void *ref)
Definition ContainerOSC.h:310
static bool parseData(OSCData &osc, void *ref)
Definition ContainerOSC.h:286
void setDecoder(MultiDecoder &decoder)
Defines the decoder to be used: special logic for multidecoder.
Definition ContainerOSC.h:195
void setDecoder(AudioDecoder &decoder)
Defines the decoder to be used.
Definition ContainerOSC.h:192
bool is_active
Definition ContainerOSC.h:264
Str mime_str
Definition ContainerOSC.h:271
void setOutput(Print &outStream)
Defines where the decoded result is written to.
Definition ContainerOSC.h:203
bool(* write_callback)(uint64_t time, uint64_t seq, uint8_t *data, size_t len, void *ref)
Return false to complete the processing w/o writing to the decoder.
Definition ContainerOSC.h:274
bool begin()
Definition ContainerOSC.h:208
const char * mime()
Provides the mime type from the encoder.
Definition ContainerOSC.h:232
AudioDecoder * p_codec
Definition ContainerOSC.h:266
bool addParserCallback(const char *address, bool(*callback)(OSCData &data, void *ref), OSCCompare compare=OSCCompare::Matches)
Adds an new parser callback for a specific address matching string.
Definition ContainerOSC.h:238
void(* missing_data_callback)(uint64_t from_seq, uint64_t to_seq, void *ref)
Definition ContainerOSC.h:276
void setReference(void *ref)
Provide a reference object to the callback.
Definition ContainerOSC.h:261
OSCContainerDecoder(AudioDecoder &decoder)
Definition ContainerOSC.h:184
Print * p_out
Definition ContainerOSC.h:268
OSCData osc_default
Definition ContainerOSC.h:269
uint64_t getSequenceNumber()
Provides the sequence number of the last packet.
Definition ContainerOSC.h:235
SingleBuffer< uint8_t > buffer
Definition ContainerOSC.h:267
void end()
Definition ContainerOSC.h:218
void setMissingDataCallback(void(*missing_data_callback)(uint64_t from_seq, uint64_t to_seq, void *ref))
Callback to be called when data is missing.
Definition ContainerOSC.h:254
void setWriteCallback(bool(*write_callback)(uint64_t time, uint64_t seq, uint8_t *data, size_t len, void *ref))
Replace the write to the decoder with a callback:
Definition ContainerOSC.h:247
static void missingDataCallback(uint64_t from_seq, uint64_t to_seq, void *ref)
Default callback for missing data: just log the missing range.
Definition ContainerOSC.h:281
void setOSCData(OSCData &osc)
Optionally define you own OSCData object.
Definition ContainerOSC.h:201
uint64_t seq_no
Definition ContainerOSC.h:272
bool is_multi_decoder
Definition ContainerOSC.h:265
OSCContainerDecoder(MultiDecoder &decoder)
Definition ContainerOSC.h:187
size_t write(const uint8_t *data, size_t len)
Definition ContainerOSC.h:220
Output Encoded Audio via OSC.
Definition ContainerOSC.h:113
void * ref
Definition ContainerOSC.h:153
size_t write(const uint8_t *data, size_t len, uint64_t seq)
Definition ContainerOSC.h:131
void setOutput(Print &outStream)
Definition ContainerOSC.h:116
bool begin()
Definition ContainerOSC.h:122
size_t write(const uint8_t *data, size_t len) override
Definition ContainerOSC.h:126
void setEncodedWriteCallback(void(*write_callback)(uint8_t *data, size_t len, uint64_t seq, void *ref))
Definition ContainerOSC.h:117
void setReference(void *ref)
Definition ContainerOSC.h:115
void(* encoded_write_callback)(uint8_t *data, size_t len, uint64_t seq, void *ref)
Definition ContainerOSC.h:149
uint64_t sequence_number
Definition ContainerOSC.h:152
Print * p_out
Definition ContainerOSC.h:151
uint64_t getSequenceNumber()
Definition ContainerOSC.h:121
Wraps the encoded data into OSC info and data segments so that the receiver can recover the audio con...
Definition ContainerOSC.h:32
audio_tools::OSCContainerEncoder::OSCOutput osc_out
void setInfoActive(bool flag)
Activate/deactivate the sending of the audio info.
Definition ContainerOSC.h:80
AudioEncoder * p_codec
Definition ContainerOSC.h:109
void setRepeatInfoEvery(int packet_count)
Automatically resend audio info ever nth write.
Definition ContainerOSC.h:82
int repeat_info
Definition ContainerOSC.h:106
bool is_active
Definition ContainerOSC.h:107
void setOutput(Print &outStream)
Default output assignment (encoders may override to store Print reference)
Definition ContainerOSC.h:39
OSCContainerEncoder(AudioEncoder &encoder)
Definition ContainerOSC.h:35
void setEncoder(AudioEncoder *encoder)
Definition ContainerOSC.h:37
void setEncodedWriteCallback(void(*write_callback)(uint8_t *data, size_t len, uint64_t seq, void *ref))
Get informed about the encoded packages.
Definition ContainerOSC.h:93
virtual const char * mime()
Provides the mime type of the encoded result.
Definition ContainerOSC.h:77
void setReference(void *ref)
Define a reference object to be provided by the callback.
Definition ContainerOSC.h:90
Print * p_out
Definition ContainerOSC.h:110
uint64_t getSequenceNumber()
Returns the sequence number of the next packet.
Definition ContainerOSC.h:87
void end()
Definition ContainerOSC.h:70
uint64_t packet_count
Definition ContainerOSC.h:105
bool begin() override
Definition ContainerOSC.h:41
void setAudioInfo(AudioInfo info) override
Defines the sample rate, number of channels and bits per sample.
Definition ContainerOSC.h:53
void writeAudioInfo(AudioInfo info, const char *mime)
OUtput AudioInfo via OSC.
Definition ContainerOSC.h:157
size_t resendEncodedData(uint8_t *data, size_t len, uint64_t seq)
Resend the encoded data.
Definition ContainerOSC.h:100
bool is_send_info_active
Definition ContainerOSC.h:108
size_t write(const uint8_t *data, size_t len)
Add data segment. On first write we also add a AudioInfo header.
Definition ContainerOSC.h:60
A simple OSC Data composer and parser. A OSC data starts with an address string followed by a format ...
Definition OSCData.h:56
uint64_t readTime()
reads the next attribute as uint64_t
Definition OSCData.h:270
bool parse(uint8_t *data, size_t len)
parse the data to start for reading
Definition OSCData.h:175
const OSCBinaryData readData()
reads the next attribute as binary data blob.
Definition OSCData.h:287
bool addCallback(const char *address, bool(*callback)(OSCData &data, void *ref), OSCCompare compare=OSCCompare::Matches)
register a parsing callback for a specific address matching string
Definition OSCData.h:337
void setReference(void *ref)
store a reference object (for callback)
Definition OSCData.h:334
const char * readString()
reads the next string
Definition OSCData.h:279
void setAddress(const char *address)
Defines the address string (e.g. /test)
Definition OSCData.h:67
int32_t readInt32()
reads the next attribute as int32
Definition OSCData.h:254
Definition NoArduino.h:62
virtual size_t write(const uint8_t *data, size_t len)
Definition NoArduino.h:126
A simple Buffer implementation which just uses a (dynamically sized) array.
Definition Buffers.h:172
Str which keeps the data on the heap. We grow the allocated memory only if the copy source is not fit...
Definition Str.h:24
virtual const char * c_str()
provides the string value as const char*
Definition StrView.h:379
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition AudioCodecsBase.h:10
uint32_t millis()
Returns the milliseconds since the start.
Definition Time.h:12
OSCCompare
Definition OSCData.h:25
size_t writeData(Print *p_out, T *data, int samples, int maxSamples=512)
Definition AudioTypes.h:512
Basic Audio information which drives e.g. I2S.
Definition AudioTypes.h:55
sample_rate_t sample_rate
Sample Rate: e.g 44100.
Definition AudioTypes.h:57
uint16_t channels
Number of channels: 2=stereo, 1=mono.
Definition AudioTypes.h:59
uint8_t bits_per_sample
Number of bits per sample (int16_t = 16 bits)
Definition AudioTypes.h:61
Simple structure to hold binary data.
Definition OSCData.h:15
size_t len
Definition OSCData.h:17
uint8_t * data
Definition OSCData.h:16