12 #include "AudioConfig.h"
13 #include "AudioTools/AudioCodecs/AudioCodecsBase.h"
35 bool begin()
override {
37 ctx = aptx_init(is_hd);
38 is_first_write =
true;
39 notifyAudioChange(info);
40 return ctx !=
nullptr;
45 bool dropped = aptx_decode_sync_finish(ctx);
52 operator bool() {
return ctx !=
nullptr; }
54 virtual size_t write(
const uint8_t *data,
size_t len) {
55 LOGI(
"write: %d", len);
61 is_first_write =
false;
67 output_buffer.resize(len * 10);
68 memset(output_buffer.data(), 0, output_buffer.size());
69 processed = aptx_decode_sync(ctx, (
const uint8_t *)data, len,
70 output_buffer.data(), output_buffer.size(),
71 &written, &synced, &dropped);
77 if (processed != len) {
78 LOGE(
"aptX decoding reqested: %d eff: %d", len, processed);
84 return is_ok ? len : 0;
88 struct aptx_context *ctx =
nullptr;
89 Print *p_print =
nullptr;
90 bool is_first_write =
true;
91 Vector<uint8_t> output_buffer;
100 int samples = written / 3;
101 LOGI(
"written: %d", written);
102 LOGI(
"samples: %d", samples);
104 int16_t *p_int16 = (int16_t *)output_buffer.data();
105 for (
int j = 0; j < samples; j++) {
106 p_int16[j] = p_int24[j].getAndScale16();
109 if (p_print->write((uint8_t *)output_buffer.data(), samples * 2) !=
111 LOGE(
"aptX decoding failed to write decoded data");
118 void checkSync(
bool synced,
bool dropped,
bool &is_ok) {
122 LOGE(
"aptX decoding failed, synchronizing");
127 LOGE(
"aptX synchronization successful, dropped %lu byte%s",
128 (
unsigned long)dropped, (dropped != 1) ?
"s" :
"");
133 LOGE(
"aptX decoding failed, synchronizing");
139 if (!syncing) LOGE(
"aptX decoding failed, synchronizing");
140 LOGE(
"aptX synchronization successful, dropped %lu byte%s",
141 (
unsigned long)dropped, (dropped != 1) ?
"s" :
"");
144 }
else if (syncing) {
145 LOGI(
"aptX synchronization successful");
155 if (length >= 4 && memcmp(input_buffer,
"\x4b\xbf\x4b\xbf", 4) == 0) {
157 LOGE(
"aptX audio stream (not aptX HD)");
160 }
else if (length >= 6 &&
161 memcmp(input_buffer,
"\x73\xbe\xff\x73\xbe\xff", 6) == 0) {
163 LOGE(
"aptX HD audio stream");
167 if (length >= 4 && memcmp(input_buffer,
"\x6b\xbf\x6b\xbf", 4) == 0) {
168 LOGE(
"standard aptX audio stream - not supported");
171 LOGE(
"No aptX nor aptX HD audio stream");
198 input_buffer.resize(4 * 2);
199 output_buffer.resize(100 * (is_hd ? 6 : 4));
201 LOGI(
"input_buffer.size: %d", input_buffer.size());
202 LOGI(
"output_buffer.size: %d", output_buffer.size());
203 LOGI(
"is_hd: %s", is_hd ?
"true" :
"false");
204 ctx = aptx_init(is_hd);
210 if (ctx !=
nullptr) {
211 size_t output_written = 0;
212 aptx_encode_finish(ctx, output_buffer.data(), output_buffer.size(),
214 if (output_written > 0) {
216 int written = p_print->write((
const uint8_t *)output_buffer.data(),
218 if (written != output_written) {
219 LOGE(
"write requested: %d eff: %d", output_written, written);
227 virtual const char *
mime() {
return "audio/aptx"; }
243 virtual void setOutput(
Print &out_stream) { p_print = &out_stream; }
245 operator bool() {
return ctx !=
nullptr; }
247 virtual size_t write(
const uint8_t *data,
size_t len) {
248 LOGI(
"write: %d", len);
249 if (ctx ==
nullptr)
return 0;
250 size_t output_written = 0;
253 int16_t *in_ptr16 = (int16_t *)data;
254 int in_samples = len / 2;
255 for (
int j = 0; j < in_samples; j++) {
256 input_buffer[input_pos++].setAndScale16(in_ptr16[j]);
259 if (input_pos >= input_buffer.size()) {
260 size_t result = aptx_encode(
261 ctx, (
const uint8_t *)input_buffer.data(), input_buffer.size() * 3,
262 output_buffer.data() + output_pos,
263 output_buffer.size() - output_pos, &output_written);
265 output_pos += output_written;
267 if (result != input_buffer.size() * 3) {
268 LOGW(
"encode requested: %d, eff: %d", input_buffer.size() * 3,
273 if (output_pos + output_pos >= output_buffer.size()) {
275 p_print->write((
const uint8_t *)output_buffer.data(), output_pos);
276 if (written != output_pos) {
277 LOGE(
"write requested: %d eff: %d", output_pos, written);
292 Vector<int24_t> input_buffer{4 * 2};
293 Vector<uint8_t> output_buffer;
296 Print *p_print =
nullptr;
297 struct aptx_context *ctx =
nullptr;