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