3 #include "AudioTools/CoreAudio/AudioIO.h"
6 # define PRINT_FLUSH_OVERRIDE override
8 # define PRINT_FLUSH_OVERRIDE
19 float step_size = 1.0f;
22 int buffer_size = DEFAULT_BUFFER_SIZE;
64 LOGI(
"begin step_size: %f", cfg.step_size);
67 out_buffer.resize(cfg.buffer_size);
83 bool begin(AudioInfo from, AudioInfo to) {
84 if (from.bits_per_sample != to.bits_per_sample){
85 LOGE(
"invalid bits_per_sample: %d", (
int) to.bits_per_sample);
88 if (from.channels != to.channels){
89 LOGE(
"invalid channels: %d", (
int) to.channels);
92 return begin(from, (sample_rate_t)to.sample_rate);
95 bool begin(AudioInfo from,
int toRate) {
96 return begin(from, (sample_rate_t)toRate);
99 bool begin(AudioInfo from, sample_rate_t toRate) {
102 rcfg.to_sample_rate = toRate;
103 rcfg.step_size =
getStepSize(from.sample_rate, toRate);
107 virtual bool begin(AudioInfo info) {
108 if (to_sample_rate != 0)
return begin(info, to_sample_rate);
109 return begin(info, step_size);
112 bool begin()
override {
116 bool begin(AudioInfo info,
float step) {
125 if (to_sample_rate != 0) {
129 LOGI(
"-> ResampleStream:")
135 if (to_sample_rate != 0) {
145 LOGI(
"setStepSize: %f", step);
149 void setTargetSampleRate(
int rate) { to_sample_rate = rate; }
154 return sampleRateFrom / sampleRateTo;
162 size_t write(
const uint8_t *data,
size_t len)
override {
163 LOGD(
"ResampleStream::write: %d", (
int)len);
166 switch (info.bits_per_sample) {
168 return write<int16_t>(p_print, data, len, written);
170 return write<int24_t>(p_print, data, len, written);
172 return write<int32_t>(p_print, data, len, written);
184 if (p_out !=
nullptr && !out_buffer.isEmpty()) {
189 int rc = p_out->write(out_buffer.
data(), out_buffer.
available());
191 LOGE(
"write error %d vs %d", rc, out_buffer.
available());
197 float getByteFactor() {
return 1.0 / step_size; }
200 Vector<uint8_t> last_samples{0};
202 bool is_first =
true;
203 float step_size = 1.0;
204 int to_sample_rate = 0;
205 int bytes_per_frame = 0;
207 bool is_buffer_active = USE_RESAMPLE_BUFFER;
208 SingleBuffer<uint8_t> out_buffer{0};
209 Print *p_out =
nullptr;
214 int last_samples_size = cfg.
channels * bytes_per_sample;
215 last_samples.resize(last_samples_size);
216 memset(last_samples.data(), 0, last_samples_size);
220 template <
typename T>
221 size_t write(
Print *p_out,
const uint8_t *buffer,
size_t bytes,
224 if (step_size == 1.0) {
225 written = p_out->write(buffer, bytes);
229 if (info.channels == 0) {
230 LOGE(
"channels is 0");
233 T *data = (T *)buffer;
234 int samples = bytes /
sizeof(T);
235 size_t frames = samples / info.channels;
241 setupLastSamples<T>(data, 0);
244 T frame[info.channels];
245 size_t frame_size =
sizeof(frame);
248 while (idx < frames - 1) {
249 for (
int ch = 0; ch < info.channels; ch++) {
250 T result = getValue<T>(data, idx, ch);
254 if (is_buffer_active) {
262 out_buffer.
writeArray((
const uint8_t *)&frame, frame_size);
263 written += tmp_written;
264 if (frame_size != tmp_written) {
268 int tmp = p_out->write((
const uint8_t *)&frame, frame_size);
270 if (tmp != frame_size) {
271 LOGE(
"Failed to write %d bytes: %d", (
int)frame_size, tmp);
281 setupLastSamples<T>(data, frames - 1);
284 if (bytes != (written * step_size)) {
285 LOGD(
"write: %d vs %d", (
int)bytes, (
int)written);
289 return frames * info.channels *
sizeof(T);
293 template <
typename T>
294 T
getValue(T *data,
float frame_idx,
int channel) {
296 int frame_idx0 = frame_idx;
298 if (frame_idx0 == 0 && frame_idx < 0) frame_idx0 = -1;
299 int frame_idx1 = frame_idx0 + 1;
300 T val0 = lookup<T>(data, frame_idx0, channel);
301 T val1 = lookup<T>(data, frame_idx1, channel);
303 float result = mapT<float>(frame_idx, frame_idx0, frame_idx1, val0, val1);
304 LOGD(
"getValue idx: %d:%d / val: %d:%d / %f -> %f", frame_idx0, frame_idx1,
305 (
int)val0, (
int)val1, frame_idx, result)
306 return (
float)round(result);
310 template <
typename T>
311 T
lookup(T *data,
int frame,
int channel) {
313 return data[frame * info.channels + channel];
316 T *pt_last_samples = (T *)last_samples.data();
317 return pt_last_samples[channel];
321 template <
typename T>
323 for (
int ch = 0; ch < info.channels; ch++) {
324 T *pt_last_samples = (T *)last_samples.data();
325 pt_last_samples[ch] = data[(frame * info.channels) + ch];
326 LOGD(
"setupLastSamples ch:%d - %d", ch, (
int)pt_last_samples[ch])