3 #include "AudioConfig.h"
21 float pitch_shift = 1.4f;
22 int buffer_size = 1000;
36 setIncrement(increment);
41 void setIncrement(
float increment) { read_increment = increment; }
43 void resize(
int size) {
50 read_pos_float += read_increment;
52 if (read_pos_float > buffer_size) {
53 read_pos_float -= buffer_size;
59 if (buffer.size() == 0) {
60 LOGE(
"buffer has no memory");
63 return buffer[(int)read_pos_float];
67 if (buffer.size() == 0) {
68 LOGE(
"buffer has no memory");
71 buffer[write_pos++] = sample;
73 if (write_pos >= buffer_size) {
83 memset(buffer.data(), 0,
sizeof(T) * buffer_size);
86 virtual bool isFull() {
return false; }
90 size_t size() {
return buffer_size;}
95 float read_pos_float = 0.0;
96 float read_increment = 1.0;
110 setIncrement(increment);
115 void setIncrement(
float increment) { pitch_shift = increment; }
117 void resize(
int size) {
119 overlap = buffer_size / 10;
128 if (buffer.size() == 0) {
129 LOGE(
"buffer has no memory");
133 write_pointer = write_pos;
134 buffer[write_pos++] = sample;
136 if (write_pos >= buffer_size) {
147 overlap = buffer_size / 10;
148 memset(buffer.data(), 0,
sizeof(T) * buffer_size);
155 size_t size() {
return buffer_size;}
159 float read_pos_float = 0.0;
160 float cross_fade = 1.0;
162 int write_pointer = 0;
165 float pitch_shift = 0;
170 assert(pitch_shift > 0);
171 assert(buffer_size > 0);
175 int read_pointer_int = roundf(read_pos_float);
176 int read_pointer_int180 = 0;
177 if (read_pointer_int >= buffer_size / 2)
178 read_pointer_int180 = read_pointer_int - (buffer_size / 2);
180 read_pointer_int180 = read_pointer_int + (buffer_size / 2);
183 float read_sample = (float)buffer[read_pointer_int];
184 float read_sample_180 = (float)buffer[read_pointer_int180];
188 if (overlap >= (write_pointer - read_pointer_int) &&
189 (write_pointer - read_pointer_int) >= 0 && pitch_shift != 1.0f) {
190 int rel = write_pointer - read_pointer_int;
191 cross_fade = ((float)rel) / (float)overlap;
192 }
else if (write_pointer - read_pointer_int == 0)
197 if (overlap >= (write_pointer - read_pointer_int180) &&
198 (write_pointer - read_pointer_int180) >= 0 && pitch_shift != 1.0f) {
199 int rel = write_pointer - read_pointer_int180;
200 cross_fade = 1.0f - ((float)rel) / (float)overlap;
201 }
else if (write_pointer - read_pointer_int180 == 0)
205 T sum = (read_sample * cross_fade + read_sample_180 * (1.0f - cross_fade));
208 read_pos_float += pitch_shift;
209 if (roundf(read_pos_float) >= buffer_size)
210 read_pos_float = 0.0f;
226 setIncrement(increment);
231 void setIncrement(
float increment) { read_increment = increment; }
233 void resize(
int size) {
236 read_pos_float = size / 2;
241 assert(read_increment != 0.0f);
243 read_pos_float += read_increment;
245 if (read_pos_float > buffer_size) {
246 read_pos_float -= buffer_size;
252 if (buffer.size() == 0)
258 if (buffer.size() == 0)
261 buffer[write_pos++] = sample;
263 if (write_pos >= buffer_size) {
273 memset(buffer.data(), 0,
sizeof(T) * buffer_size);
280 size_t size() {
return buffer_size;}
286 float read_pos_float = 0.0f;
287 float read_increment = 0.0f;
295 int read_pos_int = read_pos;
297 T value2 =
getValue(read_pos_int + 1);
298 incrementing = value2 - value1 >= 0;
301 if (value2 < value1) {
307 float offset_in = read_pos - read_pos_int;
308 LOGD(
"read_pos=%f read_pos_int=%d, offset_in=%f", read_pos, read_pos_int, offset_in);
309 float diff_result = abs(value2 - value1);
310 float offset_result = offset_in * diff_result;
311 float result = offset_result + value1;
312 LOGD(
"interpolate %d %d -> %f -> %f", value1, value2, offset_result, result);
320 T
getValue(
int pos) {
return buffer[pos % buffer_size]; }
325 bool v_incrementing = v2 - v1 >= 0;
327 if (incrementing && v_incrementing && value1 >= v1 && value1 <= v2) {
331 if (!incrementing && !v_incrementing && value1 <= v1 && value1 >= v2) {
341 int read_pos_int = read_pos_float;
342 if (write_pos == read_pos_int ||
343 write_pos == (buffer_size % (read_pos_int + 1))) {
344 LOGD(
"handleReadWriteOverrun write_pos=%d read_pos_int=%d", write_pos,
349 for (
int j = read_increment * 2; j < buffer_size; j++) {
350 int pos = read_pos_int + j;
354 if (
isMatching(last_value, incrementing, v1, v2)) {
356 float diff_value = abs(v1 - v2);
357 float diff_last_value = abs(v1 - last_value);
360 fraction = diff_last_value / diff_value;
363 read_pos_float = fraction + pos;
365 read_pos_float += read_increment;
367 if (read_pos_float > buffer_size) {
368 read_pos_float -= buffer_size;
370 LOGD(
"handleReadWriteOverrun -> read_pos pos=%d pos_float=%f", pos, read_pos_float);
376 LOGW(
"phase allign failed: maybe the buffer is too small")
392 template <
typename T,
class BufferT>
407 buffer.resize(info.buffer_size);
409 buffer.setIncrement(info.pitch_shift);
414 size_t write(
const uint8_t *data,
size_t len)
override {
422 int sample_count = len /
sizeof(T);
424 for (
int j = 0; j < sample_count; j += channels) {
426 for (
int ch = 0; ch < channels; ch++) {
427 value += p_in[j + ch];
433 T out_value = pitchShift(value);
434 LOGD(
"PitchShiftOutput %f -> %d", value, (
int) out_value);
435 T out_array[channels];
436 for (
int ch = 0; ch < channels; ch++) {
437 out_array[ch] = out_value;
439 result += p_out->write((uint8_t *)out_array,
sizeof(T) * channels);
444 void end() { active =
false; }
450 Print *p_out =
nullptr;
454 T pitchShift(T value) {
459 T out_value = buffer.read();