arduino-audio-tools
Loading...
Searching...
No Matches
CodecBase64.h
1
2#pragma once
3
4#include "AudioTools/AudioCodecs/AudioCodecsBase.h"
5
6namespace audio_tools {
7
8
9enum Base46Logic { NoCR, CRforFrame, CRforWrite };
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:
43 DecoderBase64() { TRACED(); }
44
51 TRACED();
52 setOutput(out);
53 }
54
56 void setOutput(Print &out) override { p_print = &out; }
57
59 void setNewLine(Base46Logic logic) { newline_logic = logic; }
60
61 bool begin() override {
62 TRACED();
63 is_valid = newline_logic == NoCR;
64 active = true;
65 return true;
66 }
67
68 void end() override {
69 TRACED();
70 // deconde ramaining bytes
71 int len = buffer.available();
72 uint8_t tmp[len];
73 buffer.readArray(tmp, len);
74 decodeLine(tmp, len);
75
76 active = false;
77 buffer.resize(0);
78 }
79
80 size_t write(const uint8_t *data, size_t len) override {
81 if (p_print == nullptr) return 0;
82 TRACED();
83 addToBuffer((uint8_t *)data, len);
84 int decode_size = 4; // maybe we should increase this ?
85 while (buffer.available() >= decode_size) {
86 uint8_t tmp[decode_size];
87 buffer.readArray(tmp, decode_size);
88 decodeLine(tmp, decode_size);
89 }
90
91 return len;
92 }
93
94 operator bool() override { return active; }
95
96 protected:
97 bool active = false;
98 bool is_valid = false;
99 Base46Logic newline_logic = CRforFrame;
100 Vector<uint8_t> result;
101 RingBuffer<uint8_t> buffer{1500};
102 AudioInfo info;
103
104 void decodeLine(uint8_t *data, size_t byteCount) {
105 LOGD("decode: %d", (int)byteCount);
106 int len = byteCount;
107
108 unsigned char *p = (unsigned char *)data;
109 int pad = len > 0 && (len % 4 || p[len - 1] == '=');
110 const size_t L = ((len + 3) / 4 - pad) * 4;
111 result.resize(L / 4 * 3 + pad);
112 memset(result.data(), 0, result.size());
113
114 for (size_t i = 0, j = 0; i < L; i += 4) {
115 int32_t n = static_cast<int32_t>(B64index[p[i]]) << 18 | B64index[p[i + 1]] << 12 |
116 B64index[p[i + 2]] << 6 | B64index[p[i + 3]];
117 result[j++] = n >> 16;
118 result[j++] = n >> 8 & 0xFF;
119 result[j++] = n & 0xFF;
120 }
121 if (pad) {
122 int32_t n = static_cast<int32_t>(B64index[p[L]]) << 18 | B64index[p[L + 1]] << 12;
123 result[result.size() - 1] = n >> 16;
124
125 if (len > L + 2 && p[L + 2] != '=') {
126 n |= B64index[p[L + 2]] << 6;
127 result.push_back(n >> 8 & 0xFF);
128 }
129 }
130 writeBlocking(p_print, result.data(), result.size());
131 }
132
133 void addToBuffer(uint8_t *data, size_t len) {
134 TRACED();
135 if (buffer.size() < len) {
136 buffer.resize(len);
137 }
138 // syncronize to find a valid start position
139 int start = 0;
140 if (!is_valid) {
141 for (int j = 0; j < len; j++) {
142 if (data[j] == '\n') {
143 start = j;
144 is_valid = true;
145 break;
146 }
147 }
148 }
149
150 if (is_valid) {
151 // remove white space
152 for (int j = start; j < len; j++) {
153 if (!isspace(data[j])) {
154 buffer.write(data[j]);
155 } else if (data[j] == '\n') {
156 int offset = buffer.available() % 4;
157 if (offset > 0) {
158 LOGW("Resync %d (-%d)...", buffer.available(), offset);
159 uint8_t tmp[4];
160 buffer.readArray(tmp, offset);
161 }
162 }
163 }
164 }
165 LOGD("buffer: %d, is_valid: %s", buffer.available(),
166 is_valid ? "true" : "false");
167 }
168};
169
170
182 public:
183 // Empty Conbuffeructor - the output buffeream must be provided with begin()
184 EncoderBase64() {}
185
186 // Conbuffeructor providing the output buffeream
187 EncoderBase64(Print &out) { p_print = &out; }
188
190 void setOutput(Print &out_buffeream) override {
191 p_print = &out_buffeream;
192 }
193
195 const char *mime() override { return "text/base64"; }
196
198 void setNewLine(Base46Logic flag) { newline_logic = flag; }
199
201 virtual bool begin() override {
202 is_open = true;
203 frame_size = info.bits_per_sample * info.channels / 8;
204 if (newline_logic != NoCR) {
205 if (frame_size==0){
206 LOGW("AudioInfo not defined");
207 // assume frame size
208 frame_size = 4;
209 }
210 p_print->write('\n');
211 flush();
212 }
213 return true;
214 }
215
217 void end() override { is_open = false; }
218
220 virtual size_t write(const uint8_t *data, size_t len) override {
221 LOGD("EncoderBase64::write: %d", (int)len);
222
223 switch (newline_logic) {
224 case NoCR:
225 case CRforWrite:
226 encodeLine(data, len);
227 break;
228 case CRforFrame: {
229 int frames = len / frame_size;
230 int open = len;
231 int offset = 0;
232 while (open > 0) {
233 int write_size = min(frame_size, open);
234 encodeLine(data + offset, write_size);
235 open -= write_size;
236 offset += write_size;
237 }
238 break;
239 }
240 }
241
242 return len;
243 }
244
245 operator bool() override { return is_open; }
246
247 bool isOpen() { return is_open; }
248
249 protected:
250 Print *p_print = nullptr;
251 bool is_open;
252 Base46Logic newline_logic = CRforFrame;
253 Vector<uint8_t> ret;
254 AudioInfo info;
255 int frame_size;
256
257 void flush() {
258#if defined(ESP32)
259# if ESP_IDF_VERSION > ESP_IDF_VERSION_VAL(3, 3, 5)
260 p_print->flush();
261# endif
262#else
263 p_print->flush();
264#endif
265 }
266
267 void encodeLine(const uint8_t *data, size_t input_length) {
268 LOGD("EncoderBase64::encodeLine: %d", (int)input_length);
269 int output_length = 4 * ((input_length + 2) / 3);
270 if (ret.size() < output_length + 1) {
271 ret.resize(output_length + 1);
272 }
273
274 for (int i = 0, j = 0; i < input_length;) {
275 uint32_t octet_a = i < input_length ? (unsigned char)data[i++] : 0;
276 uint32_t octet_b = i < input_length ? (unsigned char)data[i++] : 0;
277 uint32_t octet_c = i < input_length ? (unsigned char)data[i++] : 0;
278
279 uint32_t triple = (octet_a << 0x10) + (octet_b << 0x08) + octet_c;
280
281 ret[j++] = encoding_table[(triple >> 3 * 6) & 0x3F];
282 ret[j++] = encoding_table[(triple >> 2 * 6) & 0x3F];
283 ret[j++] = encoding_table[(triple >> 1 * 6) & 0x3F];
284 ret[j++] = encoding_table[(triple >> 0 * 6) & 0x3F];
285 }
286
287 for (int i = 0; i < mod_table[input_length % 3]; i++)
288 ret[output_length - 1 - i] = '=';
289
290 // add a new line to the end
291 if (newline_logic != NoCR) {
292 ret[output_length] = '\n';
293 output_length++;
294 }
295
296 writeBlocking(p_print, ret.data(), output_length);
297 flush();
298 }
299};
300
301} // namespace audio_tools
Decoding of encoded audio into PCM data.
Definition AudioCodecsBase.h:18
Encoding of PCM data.
Definition AudioCodecsBase.h:96
virtual int readArray(T data[], int len)
reads multiple values
Definition Buffers.h:33
DecoderBase64 - Converts a Base64 encoded Stream into the original data stream. Decoding only gives a...
Definition CodecBase64.h:37
void setOutput(Print &out) override
Defines the output Stream.
Definition CodecBase64.h:56
DecoderBase64()
Constructor for a new DecoderBase64 object.
Definition CodecBase64.h:43
DecoderBase64(Print &out)
Constructor for a new DecoderBase64 object.
Definition CodecBase64.h:50
void setNewLine(Base46Logic logic)
We expect new lines to delimit the individual lines.
Definition CodecBase64.h:59
EncoderBase64s - Encodes the input data into a Base64 string. By default each audio frame is followed...
Definition CodecBase64.h:181
virtual size_t write(const uint8_t *data, size_t len) override
Writes PCM data to be encoded as RAW.
Definition CodecBase64.h:220
void setOutput(Print &out_buffeream) override
Defines the output Stream.
Definition CodecBase64.h:190
virtual bool begin() override
starts the processing using the actual RAWAudioInfo
Definition CodecBase64.h:201
void end() override
stops the processing
Definition CodecBase64.h:217
const char * mime() override
Provides "text/base64".
Definition CodecBase64.h:195
void setNewLine(Base46Logic flag)
We add a new line after each write.
Definition CodecBase64.h:198
Definition NoArduino.h:62
virtual bool write(T data) override
write add an entry to the buffer
Definition Buffers.h:377
virtual size_t size() override
Returns the maximum capacity of the buffer.
Definition Buffers.h:414
virtual bool resize(int len)
Resizes the buffer if supported: returns false if not supported.
Definition Buffers.h:404
virtual int available() override
provides the number of entries that are available to read
Definition Buffers.h:396
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition AudioCodecsBase.h:10
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy