arduino-audio-tools
Loading...
Searching...
No Matches
CodecBase64.h
Go to the documentation of this file.
1
2#pragma once
3
5
6namespace audio_tools {
7
8
10static char encoding_table[] = {
11 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
12 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
13 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
14 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
15 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'};
16static int mod_table[] = {0, 2, 1};
17
18static const int B64index[256] = {
19 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
20 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
21 0, 0, 0, 0, 0, 0, 0, 62, 63, 62, 62, 63, 52, 53, 54, 55, 56, 57,
22 58, 59, 60, 61, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6,
23 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
24 25, 0, 0, 0, 0, 63, 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
25 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51};
26
38 public:
44
51 TRACED();
52 setOutput(out);
53 }
54
55 const char *mime() override { return "text/base64"; }
56
58 void setOutput(Print &out) override { p_print = &out; }
59
61 void setNewLine(Base46Logic logic) { newline_logic = logic; }
62
63 bool begin() override {
64 TRACED();
66 active = true;
67 return true;
68 }
69
70 void end() override {
71 TRACED();
72 // deconde ramaining bytes
73 int len = buffer.available();
74 uint8_t tmp[len];
75 buffer.readArray(tmp, len);
76 decodeLine(tmp, len);
77
78 active = false;
79 buffer.resize(0);
80 }
81
82 size_t write(const uint8_t *data, size_t len) override {
83 if (p_print == nullptr) return 0;
84 TRACED();
85 addToBuffer((uint8_t *)data, len);
86 int decode_size = 4; // maybe we should increase this ?
87 while (buffer.available() >= decode_size) {
88 uint8_t tmp[decode_size];
89 buffer.readArray(tmp, decode_size);
90 decodeLine(tmp, decode_size);
91 }
92
93 return len;
94 }
95
96 operator bool() override { return active; }
97
98 protected:
99 bool active = false;
100 bool is_valid = false;
105
106 void decodeLine(uint8_t *data, size_t byteCount) {
107 LOGD("decode: %d", (int)byteCount);
108 int len = byteCount;
109
110 unsigned char *p = (unsigned char *)data;
111 int pad = len > 0 && (len % 4 || p[len - 1] == '=');
112 const size_t L = ((len + 3) / 4 - pad) * 4;
113 result.resize(L / 4 * 3 + pad);
114 memset(result.data(), 0, result.size());
115
116 for (size_t i = 0, j = 0; i < L; i += 4) {
117 int32_t n = static_cast<int32_t>(B64index[p[i]]) << 18 | B64index[p[i + 1]] << 12 |
118 B64index[p[i + 2]] << 6 | B64index[p[i + 3]];
119 result[j++] = n >> 16;
120 result[j++] = n >> 8 & 0xFF;
121 result[j++] = n & 0xFF;
122 }
123 if (pad) {
124 int32_t n = static_cast<int32_t>(B64index[p[L]]) << 18 | B64index[p[L + 1]] << 12;
125 result[result.size() - 1] = n >> 16;
126
127 if (len > L + 2 && p[L + 2] != '=') {
128 n |= B64index[p[L + 2]] << 6;
129 result.push_back(n >> 8 & 0xFF);
130 }
131 }
133 }
134
135 void addToBuffer(uint8_t *data, size_t len) {
136 TRACED();
137 if (buffer.size() < len) {
138 buffer.resize(len);
139 }
140 // syncronize to find a valid start position
141 int start = 0;
142 if (!is_valid) {
143 for (int j = 0; j < len; j++) {
144 if (data[j] == '\n') {
145 start = j;
146 is_valid = true;
147 break;
148 }
149 }
150 }
151
152 if (is_valid) {
153 // remove white space
154 for (int j = start; j < len; j++) {
155 if (!isspace(data[j])) {
156 buffer.write(data[j]);
157 } else if (data[j] == '\n') {
158 int offset = buffer.available() % 4;
159 if (offset > 0) {
160 LOGW("Resync %d (-%d)...", buffer.available(), offset);
161 uint8_t tmp[4];
162 buffer.readArray(tmp, offset);
163 }
164 }
165 }
166 }
167 LOGD("buffer: %d, is_valid: %s", buffer.available(),
168 is_valid ? "true" : "false");
169 }
170};
171
172
184 public:
185 // Empty Conbuffeructor - the output buffeream must be provided with begin()
187
188 // Conbuffeructor providing the output buffeream
189 EncoderBase64(Print &out) { p_print = &out; }
190
192 void setOutput(Print &out_buffeream) override {
193 p_print = &out_buffeream;
194 }
195
197 const char *mime() override { return "text/base64"; }
198
200 void setNewLine(Base46Logic flag) { newline_logic = flag; }
201
203 virtual bool begin() override {
204 is_open = true;
206 if (newline_logic != NoCR) {
207 if (frame_size==0){
208 LOGW("AudioInfo not defined");
209 // assume frame size
210 frame_size = 4;
211 }
212 p_print->write('\n');
213 flush();
214 }
215 return true;
216 }
217
219 void end() override { is_open = false; }
220
222 virtual size_t write(const uint8_t *data, size_t len) override {
223 LOGD("EncoderBase64::write: %d", (int)len);
224
225 switch (newline_logic) {
226 case NoCR:
227 case CRforWrite:
228 encodeLine(data, len);
229 break;
230 case CRforFrame: {
231 int frames = len / frame_size;
232 int open = len;
233 int offset = 0;
234 while (open > 0) {
235 int write_size = min(frame_size, open);
236 encodeLine(data + offset, write_size);
237 open -= write_size;
238 offset += write_size;
239 }
240 break;
241 }
242 }
243
244 return len;
245 }
246
247 operator bool() override { return is_open; }
248
249 bool isOpen() { return is_open; }
250
251 protected:
252 Print *p_print = nullptr;
258
259 void flush() {
260#if defined(ESP32)
261# if ESP_IDF_VERSION > ESP_IDF_VERSION_VAL(3, 3, 5)
262 p_print->flush();
263# endif
264#else
265 p_print->flush();
266#endif
267 }
268
269 void encodeLine(const uint8_t *data, size_t input_length) {
270 LOGD("EncoderBase64::encodeLine: %d", (int)input_length);
271 int output_length = 4 * ((input_length + 2) / 3);
272 if (ret.size() < output_length + 1) {
273 ret.resize(output_length + 1);
274 }
275
276 for (int i = 0, j = 0; i < input_length;) {
277 uint32_t octet_a = i < input_length ? (unsigned char)data[i++] : 0;
278 uint32_t octet_b = i < input_length ? (unsigned char)data[i++] : 0;
279 uint32_t octet_c = i < input_length ? (unsigned char)data[i++] : 0;
280
281 uint32_t triple = (octet_a << 0x10) + (octet_b << 0x08) + octet_c;
282
283 ret[j++] = encoding_table[(triple >> 3 * 6) & 0x3F];
284 ret[j++] = encoding_table[(triple >> 2 * 6) & 0x3F];
285 ret[j++] = encoding_table[(triple >> 1 * 6) & 0x3F];
286 ret[j++] = encoding_table[(triple >> 0 * 6) & 0x3F];
287 }
288
289 for (int i = 0; i < mod_table[input_length % 3]; i++)
290 ret[output_length - 1 - i] = '=';
291
292 // add a new line to the end
293 if (newline_logic != NoCR) {
294 ret[output_length] = '\n';
295 output_length++;
296 }
297
298 writeBlocking(p_print, ret.data(), output_length);
299 flush();
300 }
301};
302
303} // namespace audio_tools
#define LOGW(...)
Definition AudioLoggerIDF.h:29
#define TRACED()
Definition AudioLoggerIDF.h:31
#define LOGD(...)
Definition AudioLoggerIDF.h:27
Definition Arduino.h:56
virtual size_t write(const uint8_t *data, size_t len)
Definition Arduino.h:120
virtual void flush()
Definition Arduino.h:130
Decoding of encoded audio into PCM data.
Definition AudioCodecsBase.h:19
Print * p_print
Definition AudioCodecsBase.h:79
Encoding of PCM data.
Definition AudioCodecsBase.h:101
void writeBlocking(Print *out, uint8_t *data, size_t len)
Definition AudioTypes.h:220
DecoderBase64 - Converts a Base64 encoded Stream into the original data stream. Decoding only gives a...
Definition CodecBase64.h:37
bool active
Definition CodecBase64.h:99
void setOutput(Print &out) override
Defines the output Stream.
Definition CodecBase64.h:58
AudioInfo info
Definition CodecBase64.h:104
void end() override
Definition CodecBase64.h:70
size_t write(const uint8_t *data, size_t len) override
Definition CodecBase64.h:82
void addToBuffer(uint8_t *data, size_t len)
Definition CodecBase64.h:135
bool is_valid
Definition CodecBase64.h:100
DecoderBase64()
Constructor for a new DecoderBase64 object.
Definition CodecBase64.h:43
void decodeLine(uint8_t *data, size_t byteCount)
Definition CodecBase64.h:106
const char * mime() override
Provides the mime type of the data that is expected by this decoder.
Definition CodecBase64.h:55
DecoderBase64(Print &out)
Constructor for a new DecoderBase64 object.
Definition CodecBase64.h:50
Vector< uint8_t > result
Definition CodecBase64.h:102
bool begin() override
Definition CodecBase64.h:63
Base46Logic newline_logic
Definition CodecBase64.h:101
RingBuffer< uint8_t > buffer
Definition CodecBase64.h:103
void setNewLine(Base46Logic logic)
We expect new lines to delimit the individual lines.
Definition CodecBase64.h:61
EncoderBase64s - Encodes the input data into a Base64 string. By default each audio frame is followed...
Definition CodecBase64.h:183
virtual size_t write(const uint8_t *data, size_t len) override
Writes PCM data to be encoded as RAW.
Definition CodecBase64.h:222
bool is_open
Definition CodecBase64.h:253
void setOutput(Print &out_buffeream) override
Defines the output Stream.
Definition CodecBase64.h:192
bool isOpen()
Definition CodecBase64.h:249
AudioInfo info
Definition CodecBase64.h:256
virtual bool begin() override
starts the processing using the actual RAWAudioInfo
Definition CodecBase64.h:203
void end() override
stops the processing
Definition CodecBase64.h:219
Vector< uint8_t > ret
Definition CodecBase64.h:255
EncoderBase64()
Definition CodecBase64.h:186
const char * mime() override
Provides "text/base64".
Definition CodecBase64.h:197
Print * p_print
Definition CodecBase64.h:252
Base46Logic newline_logic
Definition CodecBase64.h:254
int frame_size
Definition CodecBase64.h:257
EncoderBase64(Print &out)
Definition CodecBase64.h:189
void flush()
Definition CodecBase64.h:259
void encodeLine(const uint8_t *data, size_t input_length)
Definition CodecBase64.h:269
void setNewLine(Base46Logic flag)
We add a new line after each write.
Definition CodecBase64.h:200
Implements a typed Ringbuffer.
Definition Buffers.h:358
virtual int readArray(T data[], int len) override
reads multiple values
Definition Buffers.h:407
virtual bool write(T data) override
write add an entry to the buffer
Definition Buffers.h:451
virtual size_t size() override
Returns the maximum capacity of the buffer.
Definition Buffers.h:488
virtual bool resize(size_t len)
Resizes the buffer if supported: returns false if not supported.
Definition Buffers.h:478
virtual int available() override
provides the number of entries that are available to read
Definition Buffers.h:470
Vector implementation which provides the most important methods as defined by std::vector....
Definition Vector.h:21
void push_back(T &&value)
Definition Vector.h:182
bool resize(size_t newSize, T value)
Definition Vector.h:266
T * data()
Definition Vector.h:316
int size()
Definition Vector.h:178
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition LMSEchoCancellationStream.h:6
static int mod_table[]
Definition CodecBase64.h:16
static char encoding_table[]
Definition CodecBase64.h:10
static const int B64index[256]
Definition CodecBase64.h:18
Base46Logic
Definition CodecBase64.h:9
@ CRforWrite
Definition CodecBase64.h:9
@ NoCR
Definition CodecBase64.h:9
@ CRforFrame
Definition CodecBase64.h:9
Basic Audio information which drives e.g. I2S.
Definition AudioTypes.h:51
uint16_t channels
Number of channels: 2=stereo, 1=mono.
Definition AudioTypes.h:55
uint8_t bits_per_sample
Number of bits per sample (int16_t = 16 bits)
Definition AudioTypes.h:57