2 #include "AudioTools/AudioCodecs/AudioCodecsBase.h"
5 #define DEFAULT_NOISE_SHAPING NOISE_SHAPING_OFF
6 #define DEFAULT_LOOKAHEAD 0
7 #define DEFAULT_BLOCKSIZE_POW2 0
11 enum class ADPCMNoiseShaping {
12 AD_NOISE_SHAPING_OFF = 0,
13 AD_NOISE_SHAPING_STATIC = 1,
14 AD_NOISE_SHAPING_DYNAMIC = 2
35 if (pow >= 8 && pow >= 15) {
36 block_size_pow2 = pow;
50 bool begin()
override {
53 if (adpcm_cnxt ==
nullptr) {
54 adpcm_cnxt = adpcm_create_context(info.
channels, lookahead, noise_shaping,
58 block_size = 1 << block_size_pow2;
66 pcm_block.resize(samples_per_block * info.
channels);
67 adpcm_block.resize(block_size);
70 notifyAudioChange(info);
76 if (adpcm_cnxt !=
nullptr) {
77 adpcm_free_context(adpcm_cnxt);
81 adpcm_block.resize(0);
86 operator bool()
override {
return adpcm_cnxt !=
nullptr; }
88 virtual size_t write(
const uint8_t *data,
size_t len) {
89 uint8_t *input_buffer8 = (uint8_t *)data;
90 LOGD(
"write: %d", (
int)len);
91 for (
int j = 0; j < len; j++) {
92 adpcm_block[current_byte++] = input_buffer8[j];
93 if (current_byte == block_size) {
102 int current_byte = 0;
103 void *adpcm_cnxt =
nullptr;
104 Vector<int16_t> pcm_block;
105 Vector<uint8_t> adpcm_block;
106 int32_t initial_deltas[2] = {0};
107 Print *p_print =
nullptr;
108 int samples_per_block = 0, lookahead = DEFAULT_LOOKAHEAD,
109 noise_shaping = (int)DEFAULT_NOISE_SHAPING,
110 block_size_pow2 = DEFAULT_BLOCKSIZE_POW2, block_size = 0;
112 bool decode(
int this_block_adpcm_samples) {
113 int result = adpcm_decode_block(pcm_block.data(), adpcm_block.data(),
115 if (result != samples_per_block) {
116 LOGE(
"adpcm_decode_block: %d instead %d", result,
117 this_block_adpcm_samples);
120 int write_size = samples_per_block * info.
channels * 2;
121 p_print->write((uint8_t *)pcm_block.data(), write_size);
144 if (pow >= 8 && pow >= 15) {
145 block_size_pow2 = pow;
159 bool begin()
override {
163 block_size = 1 << block_size_pow2;
171 pcm_block.resize(samples_per_block * info.
channels);
172 adpcm_block.resize(block_size);
177 void end()
override {
179 if (adpcm_cnxt !=
nullptr) {
180 adpcm_free_context(adpcm_cnxt);
181 adpcm_cnxt =
nullptr;
184 adpcm_block.resize(0);
187 const char *
mime()
override {
return "audio/adpcm"; }
189 void setOutput(
Print &out_stream)
override { p_print = &out_stream; }
191 operator bool()
override {
return adpcm_cnxt !=
nullptr; }
193 size_t write(
const uint8_t *data,
size_t len)
override {
194 LOGD(
"write: %d", (
int)len);
195 int16_t *input_buffer = (int16_t *)data;
196 pcm_block_size = samples_per_block * info.
channels;
197 for (
int j = 0; j < len / 2; j++) {
198 pcm_block[current_sample++] = input_buffer[j];
199 if (current_sample == samples_per_block * info.
channels) {
208 int current_sample = 0;
209 void *adpcm_cnxt =
nullptr;
210 Vector<int16_t> pcm_block;
211 Vector<uint8_t> adpcm_block;
212 Print *p_print =
nullptr;
213 int samples_per_block = 0, lookahead = DEFAULT_LOOKAHEAD,
214 noise_shaping = (int)DEFAULT_NOISE_SHAPING,
215 block_size_pow2 = DEFAULT_BLOCKSIZE_POW2, block_size = 0, pcm_block_size;
216 bool is_first =
true;
223 if (adpcm_cnxt ==
nullptr) {
225 int32_t average_deltas[2];
227 average_deltas[0] = average_deltas[1] = 0;
230 average_deltas[0] -= average_deltas[0] >> 3;
232 abs((int32_t)pcm_block[i] - pcm_block[i - info.
channels]);
235 average_deltas[1] -= average_deltas[1] >> 3;
237 abs((int32_t)pcm_block[i - 1] - pcm_block[i + 1]);
241 average_deltas[0] >>= 3;
242 average_deltas[1] >>= 3;
244 adpcm_cnxt = adpcm_create_context(info.
channels, lookahead, noise_shaping,
249 adpcm_encode_block(adpcm_cnxt, adpcm_block.data(), &num_bytes,
250 pcm_block.data(), samples_per_block);
252 if (num_bytes != block_size) {
254 "adpcm_encode_block() did not return expected value "
255 "(expected %d, got %d)!\n",
256 block_size, (
int)num_bytes);
260 p_print->write(adpcm_block.data(), block_size);