3 #include "AudioTools/AudioIO.h"
13 float step_size = 1.0f;
16 int buffer_size = DEFAULT_BUFFER_SIZE;
58 LOGI(
"begin step_size: %f", cfg.step_size);
60 out_buffer.resize(cfg.buffer_size);
76 bool begin(AudioInfo from,
int toRate) {
77 return begin(from, (sample_rate_t)toRate);
80 bool begin(AudioInfo from, sample_rate_t toRate) {
83 rcfg.to_sample_rate = toRate;
84 rcfg.step_size =
getStepSize(from.sample_rate, toRate);
88 virtual bool begin(AudioInfo info) {
89 if (to_sample_rate != 0)
return begin(info, to_sample_rate);
90 return begin(info, step_size);
93 bool begin()
override {
97 bool begin(AudioInfo info,
float step) {
106 if (to_sample_rate != 0) {
110 LOGI(
"-> ResampleStream:")
116 if (to_sample_rate != 0) {
126 LOGI(
"setStepSize: %f", step);
130 void setTargetSampleRate(
int rate) { to_sample_rate = rate; }
135 return sampleRateFrom / sampleRateTo;
143 size_t write(
const uint8_t *buffer,
size_t bytes)
override {
144 LOGD(
"ResampleStream::write: %d", (
int)bytes);
146 switch (info.bits_per_sample) {
148 return write<int16_t>(p_print, buffer, bytes, written);
150 return write<int24_t>(p_print, buffer, bytes, written);
152 return write<int32_t>(p_print, buffer, bytes, written);
164 if (p_out !=
nullptr && !out_buffer.isEmpty()) {
167 int rc = p_out->write(out_buffer.
data(), out_buffer.
available());
169 LOGE(
"write error %d vs %d", rc, out_buffer.
available());
175 float getByteFactor() {
return 1.0 / step_size; }
178 Vector<uint8_t> last_samples{0};
180 bool is_first =
true;
181 float step_size = 1.0;
182 int to_sample_rate = 0;
183 int bytes_per_frame = 0;
185 bool is_buffer_active = USE_RESAMPLE_BUFFER;
186 SingleBuffer<uint8_t> out_buffer{0};
187 Print *p_out =
nullptr;
192 int last_samples_size = cfg.
channels * bytes_per_sample;
193 last_samples.resize(last_samples_size);
194 memset(last_samples.data(), 0, last_samples_size);
198 template <
typename T>
199 size_t write(
Print *p_out,
const uint8_t *buffer,
size_t bytes,
202 if (step_size == 1.0) {
203 written = p_out->write(buffer, bytes);
207 if (info.channels == 0) {
208 LOGE(
"channels is 0");
211 T *data = (T *)buffer;
212 int samples = bytes /
sizeof(T);
213 size_t frames = samples / info.channels;
219 setupLastSamples<T>(data, 0);
222 T frame[info.channels];
223 size_t frame_size =
sizeof(frame);
226 while (idx < frames - 1) {
227 for (
int ch = 0; ch < info.channels; ch++) {
228 T result = getValue<T>(data, idx, ch);
232 if (is_buffer_active) {
240 out_buffer.
writeArray((
const uint8_t *)&frame, frame_size);
241 written += tmp_written;
242 if (frame_size != tmp_written) {
246 int tmp = p_out->write((
const uint8_t *)&frame, frame_size);
248 if (tmp != frame_size) {
249 LOGE(
"Failed to write %d bytes: %d", (
int)frame_size, tmp);
259 setupLastSamples<T>(data, frames - 1);
262 if (bytes != (written * step_size)) {
263 LOGD(
"write: %d vs %d", (
int)bytes, (
int)written);
267 return frames * info.channels *
sizeof(T);
271 template <
typename T>
272 T
getValue(T *data,
float frame_idx,
int channel) {
274 int frame_idx0 = frame_idx;
276 if (frame_idx0 == 0 && frame_idx < 0) frame_idx0 = -1;
277 int frame_idx1 = frame_idx0 + 1;
278 T val0 = lookup<T>(data, frame_idx0, channel);
279 T val1 = lookup<T>(data, frame_idx1, channel);
281 float result =
mapFloat(frame_idx, frame_idx0, frame_idx1, val0, val1);
282 LOGD(
"getValue idx: %d:%d / val: %d:%d / %f -> %f", frame_idx0, frame_idx1,
283 (
int)val0, (
int)val1, frame_idx, result)
284 return (
float)round(result);
288 template <
typename T>
289 T
lookup(T *data,
int frame,
int channel) {
291 return data[frame * info.channels + channel];
294 T *pt_last_samples = (T *)last_samples.data();
295 return pt_last_samples[channel];
299 template <
typename T>
301 for (
int ch = 0; ch < info.channels; ch++) {
302 T *pt_last_samples = (T *)last_samples.data();
303 pt_last_samples[ch] = data[(frame * info.channels) + ch];
304 LOGD(
"setupLastSamples ch:%d - %d", ch, (
int)pt_last_samples[ch])