arduino-audio-tools
Loading...
Searching...
No Matches
MetaDataFilter.h
Go to the documentation of this file.
1#pragma once
2#include "AudioLogger.h"
6
7namespace audio_tools {
8
17 public:
19 MetaDataFilter() = default;
20
25
27 void setOutput(Print &out) { p_out = &out; }
29 void setOutput(AudioWriter &out) { p_writer = &out; }
30
32 bool begin() override {
33 TRACED();
34 total_pos = 0;
36 tail.reset();
37 out_buf.reset();
38 if (p_writer) p_writer->begin();
39 return true;
40 }
41
42 void end() override {
43 // the last bytes are still held back in case they are a trailing
44 // ID3v1/TAG+ tag: decide now and flush whatever is real audio
45 flushTail();
46 if (p_writer) p_writer->end();
47 }
48
50 size_t write(const uint8_t *data, size_t len) override {
51 LOGI("write: %u", (unsigned)len);
52 // prevent npe
53 if ((p_out == nullptr && p_writer == nullptr) || (data == nullptr) ||
54 (len == 0))
55 return 0;
56
57 // an ID3v2 header can only ever be located at the very start of the
58 // stream, so it is only ever checked once, on the first bytes seen
59 if (total_pos == 0) checkID3v2Header(data, len);
60
61 // Bytes that turn out not to belong to the leading ID3v2 tag are held
62 // back in a small trailing ring buffer: this way a byte is only ever
63 // forwarded once we know it is not part of a trailing ID3v1/TAG+ tag
64 // (which is only recognizable once we reach the real end of stream).
65 // This avoids treating a coincidental "TAG"/"ID3" byte sequence inside
66 // the actual audio data as metadata.
67 out_buf.resize(len);
68 out_buf.reset();
69 for (size_t j = 0; j < len; j++) {
70 total_pos++;
71 if (id3v2_skip_remaining > 0) {
73 continue;
74 }
75 if (tail.isFull()) {
76 uint8_t old = 0;
77 tail.read(old);
78 out_buf.write(old);
79 }
80 tail.write(data[j]);
81 }
82
83 size_t to_write = out_buf.available();
84 if (to_write > 0) {
85 LOGI("output: %u", (unsigned)to_write);
86 writeOut(out_buf.data(), to_write);
87 } else {
88 LOGI("output ignored");
89 }
90
91 return len;
92 }
93
94 protected:
95 Print *p_out = nullptr;
98 uint64_t total_pos = 0;
101
102 static const int kID3v1Len = 128;
103 static const int kID3v1EnhancedLen = 227;
111
113 struct ID3v2Header {
114 uint8_t header[3]; // ID3
115 uint8_t version[2];
116 uint8_t flags;
117 uint8_t size[4];
118 };
119
120 size_t writeOut(const uint8_t *data, size_t len) {
121 if (p_out) return p_out->write(data, len);
122 if (p_writer) return p_writer->write(data, len);
123 return 0;
124 }
125
128 void checkID3v2Header(const uint8_t *data, size_t len) {
129 if (len < sizeof(ID3v2Header)) return;
130 if (data[0] == 'I' && data[1] == 'D' && data[2] == '3') {
131 ID3v2Header hdr;
132 memcpy(&hdr, data, sizeof(hdr));
134 (int)sizeof(ID3v2Header) + (int)calcSizeID3v2(hdr.size);
135 LOGI("ignoring ID3v2 header at stream start, len: %d",
137 }
138 }
139
143 void flushTail() {
144 int n = tail.available();
145 if (n <= 0) return;
146 uint8_t buf[kMaxTailLen];
147 tail.readArray(buf, n);
148
149 int drop_from = n;
150 if (n >= kID3v1Len && buf[n - kID3v1Len] == 'T' &&
151 buf[n - kID3v1Len + 1] == 'A' && buf[n - kID3v1Len + 2] == 'G') {
152 drop_from = n - kID3v1Len;
153 if (drop_from >= kID3v1EnhancedLen) {
154 int e = drop_from - kID3v1EnhancedLen;
155 if (buf[e] == 'T' && buf[e + 1] == 'A' && buf[e + 2] == 'G' &&
156 buf[e + 3] == '+') {
157 drop_from = e;
158 }
159 }
160 }
161
162 if (drop_from > 0) {
163 LOGI("output: %d", drop_from);
164 writeOut(buf, drop_from);
165 }
166 if (drop_from < n) {
167 LOGI("ignoring trailing tag, len: %d", n - drop_from);
168 }
169 }
170
171 // calculate the synch save size for ID3v2
172 uint32_t calcSizeID3v2(uint8_t chars[4]) {
173 uint32_t byte0 = chars[0];
174 uint32_t byte1 = chars[1];
175 uint32_t byte2 = chars[2];
176 uint32_t byte3 = chars[3];
177 return byte0 << 21 | byte1 << 14 | byte2 << 7 | byte3;
178 }
179};
180
190 public:
192 p_decoder = &decoder;
193 filter.setOutput(decoder);
194 }
195
196 bool begin() override {
197 is_active = true;
198 filter.begin();
199 p_decoder->begin();
200 return AudioDecoder::begin();
201 }
202
203 void end() override {
204 is_active = false;
205 filter.end();
207 }
208
209 size_t write(const uint8_t *data, size_t len) override {
210 return filter.write(data, len);
211 }
212
213 void setOutput(AudioStream &out_stream) override {
214 p_decoder->setOutput(out_stream);
215 addNotifyAudioChange(out_stream);
216 }
217
218 virtual void setOutput(AudioOutput &out_stream) override {
219 p_decoder->setOutput(out_stream);
220 addNotifyAudioChange(out_stream);
221 }
222
224 virtual void setOutput(Print &out_stream) override {
225 p_decoder->setOutput(out_stream);
226 }
227
228 operator bool() override { return p_print != nullptr && is_active; }
229
230 protected:
233 bool is_active = false;
234};
235
244 public:
246 p_encoder = &encoder;
247 filter.setOutput(encoder);
248 }
249
250 bool begin(AudioInfo info) override {
252 return begin();
253 }
254
255 bool begin() override { return p_encoder->begin() && filter.begin(); }
256
257 void end() override {
258 p_encoder->end();
259 filter.end();
260 }
261
263
264 void setOutput(Print &out_stream) override {
265 p_encoder->setOutput(out_stream);
266 }
267
268 size_t write(const uint8_t *data, size_t len) override {
269 return filter.write(data, len);
270 }
271
272 operator bool() override { return (bool)(*p_encoder); }
273
274 const char *mime() override { return p_encoder->mime(); }
275
276 uint32_t frameDurationUs() override { return p_encoder->frameDurationUs(); }
277
278 uint16_t samplesPerFrame() override { return p_encoder->samplesPerFrame(); }
279
280 protected:
283 bool is_initialized = false;
284};
285
286} // namespace audio_tools
#define TRACED()
Definition AudioLoggerIDF.h:31
#define LOGI(...)
Definition AudioLoggerIDF.h:28
Definition Arduino.h:56
virtual size_t write(const uint8_t *data, size_t len)
Definition Arduino.h:120
Decoding of encoded audio into PCM data.
Definition AudioCodecsBase.h:18
virtual bool begin(AudioInfo info) override
Definition AudioCodecsBase.h:54
void end() override
Definition AudioCodecsBase.h:59
virtual void setOutput(AudioStream &out_stream)
Defines where the decoded result is written to.
Definition AudioCodecsBase.h:36
bool begin() override
Definition AudioCodecsBase.h:58
Print * p_print
Definition AudioCodecsBase.h:75
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 uint16_t samplesPerFrame()
Optional rtsp function: provide samples per the frame.
Definition AudioCodecsBase.h:113
virtual void setOutput(Print &out_stream) override
Default output assignment (encoders may override to store Print reference)
Definition AudioCodecsBase.h:109
virtual uint32_t frameDurationUs()
Optional rtsp function: provide the frame duration in microseconds.
Definition AudioCodecsBase.h:111
virtual const char * mime()=0
Provides the mime type of the encoded result.
virtual void addNotifyAudioChange(AudioInfoSupport &bi)
Adds target to be notified about audio changes.
Definition AudioTypes.h:149
Abstract Audio Ouptut class.
Definition AudioOutput.h:25
Base class for all Audio Streams. It support the boolean operator to test if the object is ready with...
Definition BaseStream.h:120
E.g. used by Encoders and Decoders.
Definition AudioTypes.h:205
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:34
MetaDataFiler applied to the indicated decoder: Class which filters out ID3v1 and ID3v2 Metadata and ...
Definition MetaDataFilter.h:189
virtual void setOutput(AudioOutput &out_stream) override
Defines where the decoded result is written to.
Definition MetaDataFilter.h:218
bool is_active
Definition MetaDataFilter.h:233
MetaDataFilter filter
Definition MetaDataFilter.h:232
void end() override
Definition MetaDataFilter.h:203
size_t write(const uint8_t *data, size_t len) override
Definition MetaDataFilter.h:209
AudioDecoder * p_decoder
Definition MetaDataFilter.h:231
MetaDataFilterDecoder(AudioDecoder &decoder)
Definition MetaDataFilter.h:191
void setOutput(AudioStream &out_stream) override
Defines where the decoded result is written to.
Definition MetaDataFilter.h:213
bool begin() override
Definition MetaDataFilter.h:196
virtual void setOutput(Print &out_stream) override
Defines where the decoded result is written to.
Definition MetaDataFilter.h:224
MetaDataFilter applied to an encoder: filters out ID3v1 / ID3v2 metadata from the mp3 input stream be...
Definition MetaDataFilter.h:243
void setOutput(Print &out_stream) override
Default output assignment (encoders may override to store Print reference)
Definition MetaDataFilter.h:264
bool is_initialized
Definition MetaDataFilter.h:283
MetaDataFilter filter
Definition MetaDataFilter.h:282
void end() override
Definition MetaDataFilter.h:257
uint16_t samplesPerFrame() override
Optional rtsp function: provide samples per the frame.
Definition MetaDataFilter.h:278
size_t write(const uint8_t *data, size_t len) override
Definition MetaDataFilter.h:268
const char * mime() override
Provides the mime type of the encoded result.
Definition MetaDataFilter.h:274
MetaDataFilterEncoder(AudioEncoder &encoder)
Definition MetaDataFilter.h:245
uint32_t frameDurationUs() override
Optional rtsp function: provide the frame duration in microseconds.
Definition MetaDataFilter.h:276
bool begin(AudioInfo info) override
Definition MetaDataFilter.h:250
bool begin() override
Definition MetaDataFilter.h:255
void setAudioInfo(AudioInfo info) override
Defines the sample rate, number of channels and bits per sample.
Definition MetaDataFilter.h:262
AudioEncoder * p_encoder
Definition MetaDataFilter.h:281
Class which filters out ID3v1 and ID3v2 Metadata and provides only the audio data to the decoder.
Definition MetaDataFilter.h:16
static const int kID3v1Len
Definition MetaDataFilter.h:102
void flushTail()
Definition MetaDataFilter.h:143
MetaDataFilter(Print &out)
Constructor which assigns the decoder.
Definition MetaDataFilter.h:22
int id3v2_skip_remaining
remaining bytes of a leading ID3v2 tag still to be dropped
Definition MetaDataFilter.h:100
uint32_t calcSizeID3v2(uint8_t chars[4])
Definition MetaDataFilter.h:172
void end() override
Definition MetaDataFilter.h:42
void setOutput(AudioWriter &out)
Defines the decoder to which we write the data.
Definition MetaDataFilter.h:29
AudioWriter * p_writer
Definition MetaDataFilter.h:96
size_t write(const uint8_t *data, size_t len) override
Writes the data to the decoder.
Definition MetaDataFilter.h:50
static const int kID3v1EnhancedLen
Definition MetaDataFilter.h:103
uint64_t total_pos
total number of input bytes seen so far (absolute stream position)
Definition MetaDataFilter.h:98
Print * p_out
Definition MetaDataFilter.h:95
void checkID3v2Header(const uint8_t *data, size_t len)
Definition MetaDataFilter.h:128
size_t writeOut(const uint8_t *data, size_t len)
Definition MetaDataFilter.h:120
static const int kMaxTailLen
Definition MetaDataFilter.h:104
MetaDataFilter(AudioWriter &out)
Constructor which assigns the decoder.
Definition MetaDataFilter.h:24
MetaDataFilter()=default
Default Constructor.
bool begin() override
(Re)starts the processing
Definition MetaDataFilter.h:32
SingleBuffer< uint8_t > out_buf
reused scratch buffer for the bytes flushed out of the tail per write()
Definition MetaDataFilter.h:110
void setOutput(Print &out)
Defines the decoder to which we write the data.
Definition MetaDataFilter.h:27
RingBuffer< uint8_t > tail
Definition MetaDataFilter.h:108
Implements a typed Ringbuffer.
Definition Buffers.h:353
bool read(T &result) override
reads a single value
Definition Buffers.h:360
virtual bool write(T data) override
write add an entry to the buffer
Definition Buffers.h:403
virtual void reset() override
clears the buffer
Definition Buffers.h:415
virtual bool isFull() override
checks if the buffer is full
Definition Buffers.h:398
virtual int available() override
provides the number of entries that are available to read
Definition Buffers.h:422
A simple Buffer implementation which just uses a (dynamically sized) array.
Definition Buffers.h:184
bool write(T sample) override
write add an entry to the buffer
Definition Buffers.h:218
int available() override
provides the number of entries that are available to read
Definition Buffers.h:245
T * data()
Provides address of actual data.
Definition Buffers.h:296
bool resize(size_t size)
Resizes the buffer if supported: returns false if not supported.
Definition Buffers.h:317
void reset() override
clears the buffer
Definition Buffers.h:298
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition LMSEchoCancellationStream.h:6
Basic Audio information which drives e.g. I2S.
Definition AudioTypes.h:51
ID3 verion 2 TAG Header (10 bytes)
Definition MetaDataFilter.h:113
uint8_t header[3]
Definition MetaDataFilter.h:114
uint8_t flags
Definition MetaDataFilter.h:116
uint8_t size[4]
Definition MetaDataFilter.h:117
uint8_t version[2]
Definition MetaDataFilter.h:115