/* Simple fixed-point linear resampler by BearOso*/ #ifndef __LINEAR_RESAMPLER_H #define __LINEAR_RESAMPLER_H #include "resampler.h" const int f_prec = 15; const uint32_t f__one = 1 << f_prec; class LinearResampler : public Resampler { protected: uint32_t f__r_step; uint32_t f__inv_r_step; uint32_t f__r_frac; int r_left, r_right; static short lerp(uint32_t t, int a, short b) { return (((b - a) * t) >> f_prec) + a; } public: LinearResampler(int num_samples) : Resampler(num_samples) { this->f__r_frac = 0; } void time_ratio(double ratio) { if (!ratio) ratio = 1.0; this->f__r_step = static_cast(ratio * f__one); this->f__inv_r_step = static_cast(f__one / ratio); this->clear(); } void clear() { ring_buffer::clear(); this->f__r_frac = 0; this->r_left = 0; this->r_right = 0; } void read(short *data, int num_samples) { int i_position = this->start >> 1; short *internal_buffer = reinterpret_cast(this->buffer); int o_position = 0; int consumed = 0; int max_samples = this->buffer_size >> 1; while (o_position < num_samples && consumed < this->buffer_size) { if (this->f__r_step == f__one) { data[o_position] = internal_buffer[i_position]; data[o_position + 1] = internal_buffer[i_position + 1]; o_position += 2; i_position += 2; if (i_position >= max_samples) i_position -= max_samples; consumed += 2; continue; } while (this->f__r_frac <= f__one && o_position < num_samples) { data[o_position] = lerp(this->f__r_frac, this->r_left, internal_buffer[i_position]); data[o_position + 1] = lerp(this->f__r_frac, this->r_right, internal_buffer[i_position + 1]); o_position += 2; this->f__r_frac += this->f__r_step; } if (this->f__r_frac > f__one) { this->f__r_frac -= f__one; this->r_left = internal_buffer[i_position]; this->r_right = internal_buffer[i_position + 1]; i_position += 2; if (i_position >= max_samples) i_position -= max_samples; consumed += 2; } } this->size -= consumed << 1; this->start += consumed << 1; if (this->start >= this->buffer_size) this->start -= this->buffer_size; } int avail() { return (((this->size >> 2) * this->f__inv_r_step) - ((this->f__r_frac * this->f__inv_r_step) >> f_prec)) >> (f_prec - 1); } }; #endif /* __LINEAR_RESAMPLER_H */