Path: blob/main/misc/emulator/xnes/snes9x/apu/hermite_resampler.h
28798 views
/* Simple resampler based on bsnes's ruby audio library */12#ifndef __HERMITE_RESAMPLER_H3#define __HERMITE_RESAMPLER_H45#include "resampler.h"67#undef CLAMP8#undef SHORT_CLAMP9#define CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x)))10#define SHORT_CLAMP(n) ((short) CLAMP((n), -32768, 32767))1112class HermiteResampler : public Resampler13{14protected:1516double r_step;17double r_frac;18int r_left[4], r_right[4];1920double21hermite (double mu1, double a, double b, double c, double d)22{23const double tension = 0.0; //-1 = low, 0 = normal, 1 = high24const double bias = 0.0; //-1 = left, 0 = even, 1 = right2526double mu2, mu3, m0, m1, a0, a1, a2, a3;2728mu2 = mu1 * mu1;29mu3 = mu2 * mu1;3031m0 = (b - a) * (1 + bias) * (1 - tension) / 2;32m0 += (c - b) * (1 - bias) * (1 - tension) / 2;33m1 = (c - b) * (1 + bias) * (1 - tension) / 2;34m1 += (d - c) * (1 - bias) * (1 - tension) / 2;3536a0 = +2 * mu3 - 3 * mu2 + 1;37a1 = mu3 - 2 * mu2 + mu1;38a2 = mu3 - mu2;39a3 = -2 * mu3 + 3 * mu2;4041return (a0 * b) + (a1 * m0) + (a2 * m1) + (a3 * c);42}4344public:45HermiteResampler (int num_samples) : Resampler (num_samples)46{47clear ();48}4950~HermiteResampler ()51{52}5354void55time_ratio (double ratio)56{57r_step = ratio;58clear ();59}6061void62clear (void)63{64ring_buffer::clear ();65r_frac = 1.0;66r_left [0] = r_left [1] = r_left [2] = r_left [3] = 0;67r_right[0] = r_right[1] = r_right[2] = r_right[3] = 0;68}6970void71read (short *data, int num_samples)72{73int i_position = start >> 1;74short *internal_buffer = (short *) buffer;75int o_position = 0;76int consumed = 0;7778while (o_position < num_samples && consumed < buffer_size)79{80int s_left = internal_buffer[i_position];81int s_right = internal_buffer[i_position + 1];82int max_samples = buffer_size >> 1;83const double margin_of_error = 1.0e-10;8485if (fabs(r_step - 1.0) < margin_of_error)86{87data[o_position] = (short) s_left;88data[o_position + 1] = (short) s_right;8990o_position += 2;91i_position += 2;92if (i_position >= max_samples)93i_position -= max_samples;94consumed += 2;9596continue;97}9899while (r_frac <= 1.0 && o_position < num_samples)100{101data[o_position] = SHORT_CLAMP (hermite (r_frac, r_left [0], r_left [1], r_left [2], r_left [3]));102data[o_position + 1] = SHORT_CLAMP (hermite (r_frac, r_right[0], r_right[1], r_right[2], r_right[3]));103104o_position += 2;105106r_frac += r_step;107}108109if (r_frac > 1.0)110{111r_left [0] = r_left [1];112r_left [1] = r_left [2];113r_left [2] = r_left [3];114r_left [3] = s_left;115116r_right[0] = r_right[1];117r_right[1] = r_right[2];118r_right[2] = r_right[3];119r_right[3] = s_right;120121r_frac -= 1.0;122123i_position += 2;124if (i_position >= max_samples)125i_position -= max_samples;126consumed += 2;127}128}129130size -= consumed << 1;131start += consumed << 1;132if (start >= buffer_size)133start -= buffer_size;134}135136inline int137avail (void)138{139return (int) floor (((size >> 2) - r_frac) / r_step) * 2;140}141};142143#endif /* __HERMITE_RESAMPLER_H */144145146