42#include "AudioTools/CoreAudio/AudioOutput.h"
43#include "AudioTools/CoreAudio/AudioTypes.h"
44#include "AudioToolsConfig.h"
97 if (size > 0)
resize(size);
113 return buffer.resize(size);
128 read_pos_float += read_increment;
130 if (read_pos_float > buffer_size) {
131 read_pos_float -= buffer_size;
142 if (buffer.size() == 0) {
143 LOGE(
"buffer has no memory");
146 result = buffer[(int)read_pos_float];
157 if (buffer.size() == 0) {
158 LOGE(
"buffer has no memory");
161 buffer[write_pos++] = sample;
163 if (write_pos >= buffer_size) {
173 memset(buffer.data(), 0,
sizeof(T) * buffer_size);
180 size_t size() {
return buffer_size; }
185 float read_pos_float = 0.0;
186 float read_increment = 1.0;
214 if (size > 0)
resize(size);
230 overlap = buffer_size / 10;
231 return buffer.resize(size);
249 bool peek(T &result) {
return false; }
257 if (buffer.size() == 0) {
258 LOGE(
"buffer has no memory");
262 write_pointer = write_pos;
263 buffer[write_pos++] = sample;
265 if (write_pos >= buffer_size) {
276 overlap = buffer_size / 10;
277 memset(buffer.data(), 0,
sizeof(T) * buffer_size);
284 size_t size() {
return buffer_size; }
288 float read_pos_float = 0.0;
289 float cross_fade = 1.0;
291 int write_pointer = 0;
294 float pitch_shift = 0;
313 assert(pitch_shift > 0);
314 assert(buffer_size > 0);
318 int read_pointer_int = roundf(read_pos_float);
319 int read_pointer_int180 = 0;
320 if (read_pointer_int >= buffer_size / 2)
321 read_pointer_int180 = read_pointer_int - (buffer_size / 2);
323 read_pointer_int180 = read_pointer_int + (buffer_size / 2);
326 float read_sample = (float)buffer[read_pointer_int];
327 float read_sample_180 = (float)buffer[read_pointer_int180];
331 if (overlap >= (write_pointer - read_pointer_int) &&
332 (write_pointer - read_pointer_int) >= 0 && pitch_shift != 1.0f) {
333 int rel = write_pointer - read_pointer_int;
334 cross_fade = ((float)rel) / (float)overlap;
335 }
else if (write_pointer - read_pointer_int == 0)
340 if (overlap >= (write_pointer - read_pointer_int180) &&
341 (write_pointer - read_pointer_int180) >= 0 && pitch_shift != 1.0f) {
342 int rel = write_pointer - read_pointer_int180;
343 cross_fade = 1.0f - ((float)rel) / (float)overlap;
344 }
else if (write_pointer - read_pointer_int180 == 0)
348 T sum = (read_sample * cross_fade + read_sample_180 * (1.0f - cross_fade));
351 read_pos_float += pitch_shift;
352 if (roundf(read_pos_float) >= buffer_size) read_pos_float = 0.0f;
384 if (size > 0)
resize(size);
401 read_pos_float = size / 2;
402 return buffer.resize(size);
406 assert(read_increment != 0.0f);
408 read_pos_float += read_increment;
410 if (read_pos_float > buffer_size) {
411 read_pos_float -= buffer_size;
417 if (buffer.size() == 0) {
426 if (buffer.size() == 0)
return false;
428 buffer[write_pos++] = sample;
430 if (write_pos >= buffer_size) {
440 memset(buffer.data(), 0,
sizeof(T) * buffer_size);
447 size_t size() {
return buffer_size; }
452 float read_pos_float = 0.0f;
453 float read_increment = 0.0f;
470 int read_pos_int = read_pos;
472 T value2 =
getValue(read_pos_int + 1);
476 if (value2 < value1) {
482 float offset_in = read_pos - read_pos_int;
483 LOGD(
"read_pos=%f read_pos_int=%d, offset_in=%f", read_pos, read_pos_int,
486 abs(value2 - value1);
487 float offset_result = offset_in * diff_result;
488 float result = offset_result + value1;
489 LOGD(
"interpolate %d %d -> %f -> %f", value1, value2, offset_result,
502 T
getValue(
int pos) {
return buffer[pos % buffer_size]; }
518 bool v_incrementing = v2 - v1 >= 0;
520 if (
incrementing && v_incrementing && value1 >= v1 && value1 <= v2) {
524 if (!
incrementing && !v_incrementing && value1 <= v1 && value1 >= v2) {
548 int read_pos_int = read_pos_float;
549 if (write_pos == read_pos_int ||
550 write_pos == (buffer_size % (read_pos_int + 1))) {
551 LOGD(
"handleReadWriteOverrun write_pos=%d read_pos_int=%d", write_pos,
556 for (
int j = read_increment * 2; j < buffer_size; j++) {
557 int pos = read_pos_int + j;
563 float diff_value = abs(v1 - v2);
566 if (diff_value > 0) {
567 fraction = diff_last_value / diff_value;
570 read_pos_float = fraction + pos;
572 read_pos_float += read_increment;
574 if (read_pos_float > buffer_size) {
575 read_pos_float -= buffer_size;
577 LOGD(
"handleReadWriteOverrun -> read_pos pos=%d pos_float=%f", pos,
584 LOGW(
"phase allign failed: maybe the buffer is too small")
614template <
typename T,
class BufferT>
669 size_t write(
const uint8_t *data,
size_t len)
override {
670 LOGD(
"PitchShiftOutput::write %d bytes", (
int)len);
676 int sample_count = len /
sizeof(T);
678 for (
int j = 0; j < sample_count; j += channels) {
680 for (
int ch = 0; ch < channels; ch++) {
681 value += p_in[j + ch];
688 LOGD(
"PitchShiftOutput %f -> %d", value, (
int)out_value);
689 T out_array[channels];
690 for (
int ch = 0; ch < channels; ch++) {
691 out_array[ch] = out_value;
693 result +=
p_out->write((uint8_t *)out_array,
sizeof(T) * channels);