21    return (x * (27.0f + x * x) / (27.0f + 9.0f * x * x));
 
   28  tanh_restricted (
double x)
 
   37      return sign * 
tanh (x);
 
   46    double th3 = 
tanh (3);
 
   47    double delta = 1 - th3;
 
   48    double deriv = 1 - th3 * th3;
 
   49    double b = 3 * delta - deriv;
 
   52    return sign * (1 - (a * x4 + b) * x4 * x4);
 
   55  static constexpr int table_size = 512;
 
   56  static constexpr int oversample = 8;
 
   58  float current_drive = 0;
 
   60  float drive_max_step = 0;
 
   61  float current_mix = 1;
 
   63  float mix_max_step = 0;
 
   68   for (
size_t x = 0; x < table_size - 2; x++)
 
   70        double d = (x / 
double (table_size - 3)) * 8 - 4;
 
   71        table[x + 1] = tanh_restricted (d);
 
   74    table[table_size - 1] = table[table_size - 2];
 
   87  Mode mode = Mode::TANH_TABLE;
 
   92    using PandaResampler::Resampler2;
 
   99  reset (
unsigned int sample_rate)
 
  101    mix_max_step = 1 / (0.050 * sample_rate * oversample);    
 
  102    drive_max_step = 6 / (0.020 * sample_rate * oversample);  
 
  104    res_up_left->reset();
 
  105    res_up_right->reset();
 
  108  lookup_table (
float f)
 
  110    float tbl_index = 
std::clamp ((f + 4) / 8 * (table_size - 3) + 1, 0.5f, table_size - 1.5f);
 
  111    int   itbl_index = tbl_index;
 
  112    float frac = tbl_index - itbl_index;
 
  113    return table[itbl_index] + frac * (table[itbl_index + 1] - table[itbl_index]);
 
  116  set_drive (
float d, 
bool now)
 
  120      current_drive = dest_drive;
 
  123  set_mix (
float percent, 
bool now)
 
  125    dest_mix = 
std::clamp (percent * 0.01, 0.0, 1.0);
 
  127      current_mix = dest_mix;
 
  130  set_mode (Mode new_mode)
 
  134  template<
bool STEREO, 
bool INCREMENT>
 
  136  process_sub_block (
float *left_over, 
float *right_over, 
int n_samples)
 
  138    float mix_step = 
std::clamp ((dest_mix - current_mix) / (n_samples * oversample), -mix_max_step, mix_max_step);
 
  139    float drive_step = 
std::clamp ((dest_drive - current_drive) / (n_samples * oversample), -drive_max_step, drive_max_step);
 
  141    float current_factor = 
exp2f (current_drive / 6);
 
  142    current_drive += drive_step * n_samples * oversample;
 
  144    float end_factor = 
exp2f (current_drive / 6);
 
  145    float factor_step = (end_factor - current_factor) / (n_samples * oversample);
 
  147    if (mode == Mode::TANH_TABLE)
 
  149        for (
int i = 0; i < n_samples * oversample; i++)
 
  151            left_over[i] = lookup_table (left_over[i] * current_factor) * current_mix + left_over[i] * (1 - current_mix);
 
  153              right_over[i] = lookup_table (right_over[i] * current_factor) * current_mix + right_over[i] * (1 - current_mix);
 
  156                current_mix += mix_step;
 
  157                current_factor += factor_step;
 
  161    if (mode == Mode::TANH_TRUE)
 
  163        for (
int i = 0; i < n_samples * oversample; i++)
 
  165            left_over[i] = 
std::tanh (left_over[i] * current_factor) * current_mix + left_over[i] * (1 - current_mix);
 
  167              right_over[i] = 
std::tanh (right_over[i] * current_factor) * current_mix + right_over[i] * (1 - current_mix);
 
  170                current_mix += mix_step;
 
  171                current_factor += factor_step;
 
  175    if (mode == Mode::TANH_CHEAP)
 
  177        for (
int i = 0; i < n_samples * oversample; i++)
 
  179            left_over[i] = cheap_tanh (left_over[i] * current_factor) * current_mix + left_over[i] * (1 - current_mix);
 
  181              right_over[i] = cheap_tanh (right_over[i] * current_factor) * current_mix + right_over[i] * (1 - current_mix);
 
  184                current_mix += mix_step;
 
  185                current_factor += factor_step;
 
  189    if (mode == Mode::HARD_CLIP)
 
  191        for (
int i = 0; i < n_samples * oversample; i++)
 
  193            left_over[i] = 
std::clamp (left_over[i] * current_factor, -1.f, 1.f) * current_mix + left_over[i] * (1 - current_mix);
 
  195              right_over[i] = 
std::clamp (right_over[i] * current_factor, -1.f, 1.f) * current_mix + right_over[i] * (1 - current_mix);
 
  198                current_mix += mix_step;
 
  199                current_factor += factor_step;
 
  204  template<
bool STEREO>
 
  206  process (
float *left_in, 
float *right_in, 
float *left_out, 
float *right_out, 
int n_samples)
 
  208    float left_over[oversample * n_samples];
 
  209    float right_over[oversample * n_samples];
 
  211    res_up_left->process_block (left_in, n_samples, left_over);
 
  213      res_up_right->process_block (right_in, n_samples, right_over);
 
  216    while (pos < n_samples)
 
  218        if (std::abs (dest_drive - current_drive) > 0.001 || std::abs (dest_mix - current_mix) > 0.001)
 
  221            int todo = 
std::min (n_samples - pos, 64);
 
  222            process_sub_block<STEREO, true> (left_over + pos * oversample, right_over + pos * oversample, todo);
 
  228            process_sub_block<STEREO, false> (left_over + pos * oversample, right_over + pos * oversample, n_samples - pos);
 
  233    res_down_left->process_block (left_over, oversample * n_samples, left_out);
 
  235      res_down_right->process_block (right_over, oversample * n_samples, right_out);