arduino-audio-tools
Loading...
Searching...
No Matches
CodecSBC.h
Go to the documentation of this file.
1
9#pragma once
10
12#include "sbc.h"
13#include "sbc/formats.h"
14
15
16namespace audio_tools {
17
27class SBCDecoder : public AudioDecoder {
28public:
29 SBCDecoder(int bufferSize = 8192) {
30 result_buffer = new uint8_t[bufferSize];
31 result_buffer_size = bufferSize;
32 }
33
35 if (result_buffer != nullptr)
36 delete[] result_buffer;
37 if (input_buffer != nullptr)
38 delete[] input_buffer;
39 }
40
41 virtual bool begin() {
42 TRACEI();
43 is_first = true;
44 is_active = true;
45 sbc_init(&sbc, 0L);
46 return true;
47 }
48
49 virtual void end() {
50 TRACEI();
52 is_active = false;
53 }
54
56
57 operator bool() { return is_active; }
58
59 virtual size_t write(const uint8_t *data, size_t len) {
60 LOGD("write: %d", len);
61 if (!is_active) {
62 LOGE("inactive");
63 return 0;
64 }
65
66 uint8_t *start = (uint8_t *)data;
67 int count = len;
68 if (is_first) {
69 framelen = firstWrite(data, len);
70 LOGI("framelen: %d", framelen);
71 // check if we have a valid frame length
73 start = start + framelen;
74 count = len - framelen;
75 is_first = false;
76 }
77 }
78
79 if (!is_first) {
80 for (int j = 0; j < count; j++) {
81 processByte(start[j]);
82 }
83 }
84
85 return len;
86 }
87
88
89 // Provides the uncompressed length (of the PCM data) in bytes
91 return codeSize();
92 }
95 return frameLength();
96 }
97
98protected:
99 Print *p_print = nullptr;
101 bool is_first = true;
102 bool is_active = false;
107 int input_pos = 0;
108
111
112 // Provides the uncompressed length (of the PCM data) in bytes
113 int codeSize() { return sbc_get_codesize(&sbc); }
114
118 info.channels = sbc.mode == SBC_MODE_MONO ? 1 : 2;
119 LOGI("channels: %d", info.channels);
120 switch (sbc.frequency) {
121 case SBC_FREQ_16000:
122 info.sample_rate = 16000;
123 break;
124 case SBC_FREQ_32000:
125 info.sample_rate = 32000;
126 break;
127 case SBC_FREQ_44100:
128 info.sample_rate = 44100;
129 break;
130 case SBC_FREQ_48000:
131 info.sample_rate = 48000;
132 break;
133 default:
134 LOGE("Unsupported sample rate");
135 info.sample_rate = 0;
136 break;
137 }
138 LOGI("sample_rate: %d", info.sample_rate);
140 }
141
142 bool isValidFrameLen(int len) { return len > 0 && len < 256; }
143
145 int firstWrite(const void *data, size_t length) {
146 size_t result_len = 0;
147 int frame_len = sbc_parse(&sbc, data, length);
149
150 // setup audio info
152
153 // setup input buffer for subsequent decoding stpes
155 }
156
157 return frame_len;
158 }
159
160 void setupInputBuffer(int len) {
161 LOGI("input_buffer: %d", len);
162 if (input_buffer != nullptr)
163 delete[] input_buffer;
164 input_buffer = new uint8_t[len];
165 }
166
168 void processByte(uint8_t byte) {
169 // add byte to buffer
171
172 // decode if buffer is full
173 if (input_pos >= framelen) {
174 size_t result_len = 0;
177 if (result_len > 0) {
179 }
180 input_pos = 0;
181 }
182 }
183};
184
194class SBCEncoder : public AudioEncoder {
195public:
203
206 if (subbands == 8 || subbands == 4) {
207 this->subbands = subbands;
208 } else {
209 LOGE("Invalid subbands: %d - using 8", subbands);
210 this->subbands = 8;
211 }
212 }
213
215 void setBlocks(int blocks) {
216 if (blocks == 16 || blocks == 12 || blocks == 8 || blocks == 4) {
217 this->blocks = blocks;
218 } else {
219 LOGE("Invalid blocks: %d - using 16", blocks);
220 this->blocks = 16;
221 }
222 }
223
225 void setBitpool(int bitpool) { this->bitpool = bitpool; }
226
230 this->allocation_method = allocation_method;
231 } else {
232 LOGE("Invalid allocation Method: %d - using SBC_AM_LOUDNESS", allocation_method);
233 this->allocation_method = SBC_AM_LOUDNESS;
234 }
235 }
236
238 bool begin() {
239 TRACEI();
240 is_first = true;
241 is_active = setup();
245 return true;
246 }
247
249 virtual void end() {
250 TRACEI();
251 sbc_finish(&sbc);
252 is_active = false;
253 }
254
255 virtual const char *mime() { return "audio/sbc"; }
256
258
259 operator bool() { return is_active; }
260
261 virtual size_t write(const uint8_t *data, size_t len) {
262 LOGD("write: %d", len);
263 if (!is_active) {
264 LOGE("inactive");
265 return 0;
266 }
267 if (p_print==nullptr){
268 LOGE("output not defined");
269 return 0;
270 }
271
272 // encode bytes
273 for (int j = 0; j < len; j++) {
274 processByte(data[j]);
275 }
276
277 return len;
278 }
279
280
282 return codeSize();
283 }
285 return frameLength();
286 }
287
288protected:
289 Print *p_print = nullptr;
291 bool is_first = true;
292 bool is_active = false;
294 int buffer_pos = 0;
297 int subbands = 4;
298 int blocks = 4;
299 int bitpool = 32;
301
304
306 int codeSize() { return sbc_get_codesize(&sbc); }
307
309 bool setup() {
310 sbc_init(&sbc, 0L);
311
312 if (info.bits_per_sample!=16){
313 LOGE("Invalid bits_per_sample: %d", info.bits_per_sample);
314 return false;
315 }
316
317 switch (info.sample_rate) {
318 case 16000:
319 sbc.frequency = SBC_FREQ_16000;
320 break;
321 case 32000:
322 sbc.frequency = SBC_FREQ_32000;
323 break;
324 case 44100:
325 sbc.frequency = SBC_FREQ_44100;
326 break;
327 case 48000:
328 sbc.frequency = SBC_FREQ_48000;
329 break;
330 default:
331 LOGE("Invalid sample_rate: %d", info.sample_rate);
332 return false;
333 }
334
335 switch (info.channels) {
336 case 1:
337 sbc.mode = SBC_MODE_MONO;
338 break;
339 case 2:
340 sbc.mode = SBC_MODE_STEREO;
341 break;
342 default:
343 LOGE("Invalid channels: %d", info.channels);
344 return false;
345 }
346
347 switch (subbands) {
348 case 4:
349 sbc.subbands = SBC_SB_4;
350 break;
351 case 8:
352 sbc.subbands = SBC_SB_8;
353 break;
354 default:
355 LOGE("Invalid subbands: %d", subbands);
356 return false;
357 }
358
359 switch (blocks) {
360 case 4:
361 sbc.blocks = SBC_BLK_4;
362 break;
363 case 8:
364 sbc.blocks = SBC_BLK_8;
365 break;
366 case 12:
367 sbc.blocks = SBC_BLK_12;
368 break;
369 case 16:
370 sbc.blocks = SBC_BLK_16;
371 break;
372 default:
373 LOGE("Invalid blocks: %d", blocks);
374 return false;
375 }
376
377 sbc.bitpool = bitpool;
378 sbc.allocation = allocation_method;
379 return true;
380 }
381
382 // add byte to decoding buffer and decode if buffer is full
383 void processByte(uint8_t byte) {
386 ssize_t written;
387 // Encodes ONE input block into ONE output block */
388 // ssize_t sbc_encode(sbc_t *sbc, const void *input, size_t input_len,
389 // void *output, size_t output_len, ssize_t *written);
391 result_buffer.size(), &written);
392 LOGD("sbc_encode: %d -> %d (buffer: %d))", current_codesize, written,
394 p_print->write(&result_buffer[0], written);
395 buffer_pos = 0;
396 }
397 }
398};
399
400} // namespace audio_tools
#define TRACEI()
Definition AudioLoggerIDF.h:32
#define LOGI(...)
Definition AudioLoggerIDF.h:28
#define LOGD(...)
Definition AudioLoggerIDF.h:27
#define LOGE(...)
Definition AudioLoggerIDF.h:30
Decoding of encoded audio into PCM data.
Definition AudioCodecsBase.h:18
AudioInfo info
Definition AudioCodecsBase.h:76
Encoding of PCM data.
Definition AudioCodecsBase.h:97
AudioInfo info
Definition AudioCodecsBase.h:116
void notifyAudioChange(AudioInfo info)
Definition AudioTypes.h:178
Definition NoArduino.h:62
virtual size_t write(const uint8_t *data, size_t len)
Definition NoArduino.h:126
Decoder for SBC. Depends on https://github.com/pschatzmann/arduino-libsbc. Inspired by sbcdec....
Definition CodecSBC.h:27
int bytesUncompressed()
Definition CodecSBC.h:90
int input_pos
Definition CodecSBC.h:107
bool isValidFrameLen(int len)
Definition CodecSBC.h:142
virtual void setOutput(Print &out_stream)
Defines where the decoded result is written to.
Definition CodecSBC.h:55
int bytesCompressed()
Provides the compressed length in bytes (after encoding)
Definition CodecSBC.h:94
void setupAudioInfo()
Process audio info.
Definition CodecSBC.h:116
bool is_active
Definition CodecSBC.h:102
~SBCDecoder()
Definition CodecSBC.h:34
int codeSize()
Definition CodecSBC.h:113
bool is_first
Definition CodecSBC.h:101
virtual bool begin()
Definition CodecSBC.h:41
int result_buffer_size
Definition CodecSBC.h:104
int frameLength()
Provides the compressed length in bytes (after encoding)
Definition CodecSBC.h:110
virtual size_t write(const uint8_t *data, size_t len)
Definition CodecSBC.h:59
SBCDecoder(int bufferSize=8192)
Definition CodecSBC.h:29
int framelen
Definition CodecSBC.h:105
uint8_t * result_buffer
Definition CodecSBC.h:103
void processByte(uint8_t byte)
Build decoding buffer and decode when frame is full.
Definition CodecSBC.h:168
sbc_t sbc
Definition CodecSBC.h:100
Print * p_print
Definition CodecSBC.h:99
void setupInputBuffer(int len)
Definition CodecSBC.h:160
virtual void end()
Definition CodecSBC.h:49
uint8_t * input_buffer
Definition CodecSBC.h:106
int firstWrite(const void *data, size_t length)
Determines the framelen.
Definition CodecSBC.h:145
Encoder for SBC - Depends on https://github.com/pschatzmann/arduino-libsbc. Inspired by sbcenc....
Definition CodecSBC.h:194
int bytesUncompressed()
Definition CodecSBC.h:281
int allocation_method
Definition CodecSBC.h:300
SBCEncoder(int subbands=8, int blocks=16, int bitpool=32, int allocation_method=SBC_AM_LOUDNESS)
Definition CodecSBC.h:196
virtual void setOutput(Print &out_stream)
Default output assignment (encoders may override to store Print reference)
Definition CodecSBC.h:257
int bytesCompressed()
Definition CodecSBC.h:284
bool is_active
Definition CodecSBC.h:292
int current_codesize
Definition CodecSBC.h:293
int codeSize()
Provides the uncompressed length (of the PCM data) in bytes.
Definition CodecSBC.h:306
bool is_first
Definition CodecSBC.h:291
void setSubbands(int subbands)
Defines the subbands: Use 4 or 8.
Definition CodecSBC.h:205
Vector< uint8_t > result_buffer
Definition CodecSBC.h:296
void setBlocks(int blocks)
Defines the number of blocks: valid values (4,8,12,16)
Definition CodecSBC.h:215
bool begin()
Restarts the processing.
Definition CodecSBC.h:238
int bitpool
Definition CodecSBC.h:299
virtual const char * mime()
Provides the mime type of the encoded result.
Definition CodecSBC.h:255
int frameLength()
Provides the compressed length in bytes (after encoding)
Definition CodecSBC.h:303
int buffer_pos
Definition CodecSBC.h:294
virtual size_t write(const uint8_t *data, size_t len)
Definition CodecSBC.h:261
void processByte(uint8_t byte)
Definition CodecSBC.h:383
int subbands
Definition CodecSBC.h:297
sbc_t sbc
Definition CodecSBC.h:290
int blocks
Definition CodecSBC.h:298
void setBitpool(int bitpool)
Defines the bitpool (2-86?)
Definition CodecSBC.h:225
Print * p_print
Definition CodecSBC.h:289
virtual void end()
Ends the processing.
Definition CodecSBC.h:249
bool setup()
Determines audio information and calls sbc_init;.
Definition CodecSBC.h:309
Vector< uint8_t > buffer
Definition CodecSBC.h:295
void setAllocationMethod(int allocation_method)
Defines the allocation method: Use SBC_AM_LOUDNESS, SBC_AM_SNR.
Definition CodecSBC.h:228
Vector implementation which provides the most important methods as defined by std::vector....
Definition Vector.h:21
bool resize(int newSize, T value)
Definition Vector.h:266
int size()
Definition Vector.h:178
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition AudioCodecsBase.h:10
size_t writeData(Print *p_out, T *data, int samples, int maxSamples=512)
Definition AudioTypes.h:512
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