arduino-audio-tools
Loading...
Searching...
No Matches
ContainerBinary.h
Go to the documentation of this file.
1
16#pragma once
17#include <string.h>
18
21
22namespace audio_tools {
23
24enum class ContainerType : uint8_t {
25 Header = 1,
26 Audio = 2,
27 Meta = 3,
28 Undefined = 0
29};
30
32 CommonHeader() = default;
34 this->type = type;
35 this->len = len;
36 }
37 char header[2] = {'\r','\n'};
41};
42
48
52
56
57// struct ProcessedResult {
58// ContainerType type = ContainerType::Undefined;
59// // total length incl header
60// int total_len = 0;
61// // processed bytes incl header of last step
62// int processed = 0;
63// // still (total) open
64// int open = 0;
65// };
66
68static uint8_t checkSum(const uint8_t *data, size_t len) {
69 uint8_t result = 0;
70 for (int j = 0; j < len; j++) {
71 result ^= data[j];
72 }
73 return result;
74}
77
89public:
93
94 void setEncoder(AudioEncoder *encoder) { p_codec = encoder; }
95
97 LOGD("BinaryContainerEncoder::setOutput");
99 }
100
101 bool begin() override {
102 TRACED();
103 // target.begin();
104 bool rc = p_codec->begin();
106 is_beginning = true;
107 return rc;
108 }
109
110 void setAudioInfo(AudioInfo info) override {
111 TRACED();
112 if (info != audioInfo()) {
113 cfg.info = info;
114 }
115 }
116
117 AudioInfo audioInfo() override { return cfg.info; }
118
120 size_t writeMeta(const uint8_t *data, size_t len) {
121 LOGD("BinaryContainerEncoder::writeMeta: %d", (int)len);
124 memcpy(tmp_array, &meta, sizeof(meta));
125 memcpy(tmp_array + sizeof(meta), data, len);
127 return len;
128 }
129
131 size_t write(const uint8_t *data, size_t len) {
132 LOGD("BinaryContainerEncoder::write: %d", (int)len);
133 if (is_beginning) {
134 writeHeader();
135 is_beginning = false;
136 }
137 writeAudio((uint8_t *)data, len);
138 return len;
139 }
140
141 void end() { p_codec->end(); }
142
143 operator bool() { return true; };
144
145 virtual const char *mime() { return "audio/binary"; };
146
147protected:
149 bool is_beginning = true;
155 Print *p_out = nullptr;
156
157 void writeAudio(const uint8_t *data, size_t len) {
158 LOGD("writeAudio: %d", (int)len);
159 // encode data
162 tmp.begin();
163 p_codec->setOutput(tmp);
164 p_codec->write(data, len);
165
166 // output of audio data header
167 dh.common.len = tmp.available() + sizeof(CommonHeader);
168 dh.common.checksum = checkSum(tmp_buffer.data(), tmp_buffer.available());
169 output((uint8_t *)&dh, sizeof(dh));
170
171 // output of data
172 output(tmp_buffer.data(), tmp_buffer.available());
173 }
174
175 void writeHeader() {
176 LOGD("writeHeader");
177 output((uint8_t *)&cfg, sizeof(cfg));
178 }
179
180 size_t output(const uint8_t *data, size_t len) {
181 if (p_out != nullptr) {
182 int written = p_out->write((uint8_t *)data, len);
183 LOGD("output: %d -> %d", (int)len, written);
184 } else
185 LOGW("output not defined");
186 return len;
187 }
188};
189
198public:
202
203 void setDecoder(AudioDecoder *decoder){
204 p_codec = decoder;
205 }
206
207 // Defines the output: this method is called 2 times: first to define
208 // output defined in the EnocdedAudioStream and then to define the
209 // real output in the output chain.
211 LOGD("BinaryContainerDecoder::setOutput")
212 p_out = &outStream;
213 }
214
215 void setMetaCallback(void (*callback)(uint8_t*, int, void*)) {
216 meta_callback = callback;
217 }
218
219 bool begin() {
220 TRACED();
221 is_first = true;
222 return true;
223 }
224
225 void end() { TRACED(); }
226
227 size_t write(const uint8_t *data, size_t len) {
228 LOGD("write: %d", (int)len);
229 uint8_t *data8 = (uint8_t *)data;
230 if (buffer.size() < len) {
232 std::max(static_cast<int>(DEFAULT_BUFFER_SIZE + header_size),
233 static_cast<int>(len * 4 + header_size)));
234 }
235
236 size_t result = buffer.writeArray(data8, len);
237 while (parseBuffer())
238 ;
239 return ignore_write_errors ? len : result;
240 }
241
242 operator bool() { return true; };
243
247
252
254 void setReference(void* ref){
255 reference = ref;
256 }
257
258protected:
259 bool is_first = true;
261 const size_t header_size = sizeof(header);
264 Print *p_out = nullptr;
265 void (*meta_callback)(uint8_t* data, int len, void* ref) = nullptr;
268 void * reference = nullptr;
269
270
271 bool parseBuffer() {
272 LOGD("parseBuffer");
273 bool result = false;
274
275 StrView str{(const char *)buffer.data()};
276 int start = str.indexOf("\r\n");
277 LOGD("start: %d", start);
278 if (start < 0) {
279 return false;
280 }
281 // get next record
282 if (buffer.available() - start > sizeof(header)) {
283 // determine header
284 memmove((uint8_t *)&header, buffer.data() + start, sizeof(header));
285
286 // check header
287 if (!isValidHeader()) {
288 LOGW("invalid header: %d", header.type);
290 nextRecord();
291 return false;
292 };
293
294 if (buffer.available() - start >= header.len) {
295 // move to start of frame
296 buffer.clearArray(start);
297 // process frame
298 result = processData();
299 } else {
300 LOGD("not enough data - available %d / req: %d", buffer.available(),
301 header.len);
303
304 }
305 } else {
306 LOGD("not enough data for header: %d", buffer.available());
308 }
309 return result;
310 }
311
312 // processes the completed data from the buffer: e.g. writes it
313 bool processData() {
314 LOGD("processData");
315 bool rc = false;
316 switch (header.type) {
318 LOGD("Header");
320 buffer.readArray((uint8_t *)&config, sizeof(config));
321 info = config.info;
323 info.logInfo();
325 p_codec->begin();
326 rc = true;
327 } break;
328
330 LOGD("Audio");
331 buffer.clearArray(sizeof(header));
334 if (header.checksum == crc) {
335 // decode
338 tmp.begin();
339 p_codec->setOutput(tmp);
341
342 // output decoded data
343 output(tmp_buffer.data(), tmp_buffer.available());
345 } else {
346 LOGW("invalid checksum");
348 // move to next record
349 nextRecord();
350 return false;
351 }
352 rc = true;
353 } break;
354
355 case ContainerType::Meta: {
356 LOGD("Meta");
357 buffer.clearArray(sizeof(header));
359 if (meta_callback != nullptr) {
361 }
363 rc = true;
364 } break;
365 }
366 return rc;
367 }
368
370 switch (header.type) {
372 return header.checksum == 0;
374 return true;
376 return header.checksum == 0;
377 }
378 return false;
379 }
380
386
387 void nextRecord() {
388 TRACED();
390 while (buffer.available() && peekBufferValue() != '\n')
392 }
393
394 // writes the data to the decoder which forwards it to the output; if there
395 // is no coded we write to the output instead
396 size_t output(uint8_t *data, size_t len) {
397 LOGD("output: %d", (int)len);
398 if (p_out != nullptr)
399 p_out->write((uint8_t *)data, len);
400 else
401 LOGW("output not defined");
402
403 return len;
404 }
405};
406
407} // namespace audio_tools
#define LOGW(...)
Definition AudioLoggerIDF.h:29
#define TRACED()
Definition AudioLoggerIDF.h:31
#define LOGD(...)
Definition AudioLoggerIDF.h:27
#define DEFAULT_BUFFER_SIZE
Definition avr.h:20
minimial implementtion of Meta which just ignores the data
Definition AudioFaustDSP.h:40
Decoding of encoded audio into PCM data.
Definition AudioCodecsBase.h:18
AudioInfo info
Definition AudioCodecsBase.h:76
virtual bool begin(AudioInfo info) override
Definition AudioCodecsBase.h:54
void setAudioInfo(AudioInfo from) override
for most decoders this is not needed
Definition AudioCodecsBase.h:28
virtual void setOutput(AudioStream &out_stream)
Defines where the decoded result is written to.
Definition AudioCodecsBase.h:36
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
void notifyAudioChange(AudioInfo info)
Definition AudioTypes.h:178
virtual size_t write(const uint8_t *data, size_t len)=0
virtual void end()=0
virtual bool begin()=0
virtual int readArray(T data[], int len)
reads multiple values
Definition Buffers.h:33
Decodes the provided data from the DAT and CFG segments.
Definition ContainerBinary.h:197
void(* error_handler)(BinaryContainerEncoderError error, BinaryContainerDecoder *source, void *ref)
Definition ContainerBinary.h:266
bool ignore_write_errors
Definition ContainerBinary.h:267
void setIgnoreWriteErrors(bool flag)
If set to true we do not expect a retry to write the missing data but continue just with the next....
Definition ContainerBinary.h:249
void setOutput(Print &outStream)
Defines where the decoded result is written to.
Definition ContainerBinary.h:210
bool is_first
Definition ContainerBinary.h:259
CommonHeader header
Definition ContainerBinary.h:260
void addErrorHandler(void(*error_handler)(BinaryContainerEncoderError error, BinaryContainerDecoder *source, void *ref))
Definition ContainerBinary.h:244
bool begin()
Definition ContainerBinary.h:219
void(* meta_callback)(uint8_t *data, int len, void *ref)
Definition ContainerBinary.h:265
AudioDecoder * p_codec
Definition ContainerBinary.h:262
size_t output(uint8_t *data, size_t len)
Definition ContainerBinary.h:396
void setReference(void *ref)
Provide additional information for callback.
Definition ContainerBinary.h:254
BinaryContainerDecoder(AudioDecoder *decoder)
Definition ContainerBinary.h:201
void setMetaCallback(void(*callback)(uint8_t *, int, void *))
Definition ContainerBinary.h:215
Print * p_out
Definition ContainerBinary.h:264
bool isValidHeader()
Definition ContainerBinary.h:369
bool parseBuffer()
Definition ContainerBinary.h:271
SingleBuffer< uint8_t > buffer
Definition ContainerBinary.h:263
void end()
Definition ContainerBinary.h:225
bool processData()
Definition ContainerBinary.h:313
const size_t header_size
Definition ContainerBinary.h:261
void setDecoder(AudioDecoder *decoder)
Definition ContainerBinary.h:203
void nextRecord()
Definition ContainerBinary.h:387
void * reference
Definition ContainerBinary.h:268
uint8_t peekBufferValue()
Definition ContainerBinary.h:381
size_t write(const uint8_t *data, size_t len)
Definition ContainerBinary.h:227
BinaryContainerDecoder(AudioDecoder &decoder)
Definition ContainerBinary.h:200
Wraps the encoded data into Config, Data, and Meta segments so that we can recover the audio configur...
Definition ContainerBinary.h:88
AudioEncoder * p_codec
Definition ContainerBinary.h:154
SimpleContainerMetaDataHeader meta
Definition ContainerBinary.h:153
void writeHeader()
Definition ContainerBinary.h:175
size_t writeMeta(const uint8_t *data, size_t len)
Adds meta data segment.
Definition ContainerBinary.h:120
void setOutput(Print &outStream)
Default output assignment (encoders may override to store Print reference)
Definition ContainerBinary.h:96
void setEncoder(AudioEncoder *encoder)
Definition ContainerBinary.h:94
int repeat_header
Definition ContainerBinary.h:150
virtual const char * mime()
Provides the mime type of the encoded result.
Definition ContainerBinary.h:145
void writeAudio(const uint8_t *data, size_t len)
Definition ContainerBinary.h:157
BinaryContainerEncoder(AudioEncoder &encoder)
Definition ContainerBinary.h:91
size_t output(const uint8_t *data, size_t len)
Definition ContainerBinary.h:180
bool is_beginning
Definition ContainerBinary.h:149
Print * p_out
Definition ContainerBinary.h:155
void end()
Definition ContainerBinary.h:141
SimpleContainerDataHeader dh
Definition ContainerBinary.h:152
uint64_t packet_count
Definition ContainerBinary.h:148
bool begin() override
Definition ContainerBinary.h:101
BinaryContainerEncoder(AudioEncoder *encoder)
Definition ContainerBinary.h:92
void setAudioInfo(AudioInfo info) override
Defines the sample rate, number of channels and bits per sample.
Definition ContainerBinary.h:110
SimpleContainerConfig cfg
Definition ContainerBinary.h:151
AudioInfo audioInfo() override
provides the actual input AudioInfo
Definition ContainerBinary.h:117
size_t write(const uint8_t *data, size_t len)
Add data segment. On first write we also add a AudioInfo header.
Definition ContainerBinary.h:131
Parent class for all container formats.
Definition AudioCodecsBase.h:86
Definition NoArduino.h:62
virtual size_t write(const uint8_t *data, size_t len)
Definition NoArduino.h:126
Stream class which stores the data in a temporary queue buffer. The queue can be consumed e....
Definition BaseStream.h:311
virtual bool begin() override
Activates the output.
Definition BaseStream.h:339
A simple Buffer implementation which just uses a (dynamically sized) array.
Definition Buffers.h:172
size_t size() override
Definition Buffers.h:303
bool peek(T &result) override
peeks the actual entry from the buffer
Definition Buffers.h:224
bool read(T &result) override
reads a single value
Definition Buffers.h:215
int available() override
provides the number of entries that are available to read
Definition Buffers.h:233
bool resize(int size)
Resizes the buffer if supported: returns false if not supported.
Definition Buffers.h:305
int writeArray(const T data[], int len) override
Fills the buffer data.
Definition Buffers.h:201
T * data()
Provides address of actual data.
Definition Buffers.h:284
int clearArray(int len) override
consumes len bytes and moves current data to the beginning
Definition Buffers.h:252
A simple wrapper to provide string functions on existing allocated char*. If the underlying char* is ...
Definition StrView.h:28
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition AudioCodecsBase.h:10
@ Audio
Definition ContainerAVI.h:135
static uint8_t checkSum(const uint8_t *data, size_t len)
Calculates the checksum.
Definition ContainerBinary.h:68
ContainerType
Definition ContainerBinary.h:24
BinaryContainerEncoderError
Error types.
Definition ContainerBinary.h:76
@ InvalidChecksum
Definition ContainerBinary.h:76
@ InvalidHeader
Definition ContainerBinary.h:76
@ DataMissing
Definition ContainerBinary.h:76
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
virtual void logInfo(const char *source="")
Definition AudioTypes.h:125
Definition ContainerBinary.h:31
uint8_t checksum
Definition ContainerBinary.h:40
uint16_t len
Definition ContainerBinary.h:39
char header[2]
Definition ContainerBinary.h:37
CommonHeader(ContainerType type, uint16_t len)
Definition ContainerBinary.h:33
ContainerType type
Definition ContainerBinary.h:38
Definition ContainerBinary.h:43
CommonHeader common
Definition ContainerBinary.h:45
AudioInfo info
Definition ContainerBinary.h:46
Definition ContainerBinary.h:49
CommonHeader common
Definition ContainerBinary.h:50
Definition ContainerBinary.h:53
CommonHeader common
Definition ContainerBinary.h:54