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);