15 LP1, LP2, LP3, LP4, LP6, LP8,
17 HP1, HP2, HP3, HP4, HP6, HP8
20 static constexpr size_t LAST_MODE = HP8;
21 Mode mode_ = Mode::LP2;
25 float global_volume_ = 1;
26 bool test_linear_ =
false;
28 float freq_warp_factor_ = 0;
29 float frequency_range_min_ = 0;
30 float frequency_range_max_ = 0;
31 float clamp_freq_min_ = 0;
32 float clamp_freq_max_ = 0;
35 static constexpr int MAX_STAGES = 4;
36 static constexpr uint MAX_BLOCK_SIZE = 1024;
53 mode2stages (Mode mode)
74 bool fparams_valid_ =
false;
80 static constexpr int TSIZE = 16;
83 for (
int order = 4; order <= 8; order += 2)
85 for (
int t = 0; t <= TSIZE + 1; t++)
87 double res =
std::clamp (
double (t) / TSIZE, 0.0, 1.0);
90 const double R = 1 - res;
91 const double r_alpha =
std::acos (R) / (order / 2);
94 for (
int i = 0; i < order / 2; i++)
97 const double bw_s_alpha = M_PI * (4 * i + order + 2) / (2 * order);
99 Rn.push_back (-
cos (bw_s_alpha + r_alpha));
107 res2_k.push_back ((1 - xr) * 2);
109 res3_k.push_back ((1 - xr) * 2);
111 res4_k.push_back ((1 - xr) * 2);
120 static RTable rtable;
124 interpolate_resonance (
float res,
int stages,
float *k,
const std::vector<float>& res_k)
const
126 auto lerp = [] (
float a,
float b,
float frac) {
127 return a + frac * (b - a);
130 float fidx =
std::clamp (res, 0.f, 1.f) * TSIZE;
132 float frac = fidx - idx;
134 for (
int s = 0; s < stages; s++)
136 k[s] = lerp (res_k[idx * stages + s], res_k[idx * stages + stages + s], frac);
140 lookup_resonance (
float res,
int stages,
float *k)
const
143 interpolate_resonance (res, stages, k, res2_k);
146 interpolate_resonance (res, stages, k, res3_k);
149 interpolate_resonance (res, stages, k, res4_k);
152 k[stages - 1] = res * 2;
155 const RTable& rtable_;
159 rtable_ (RTable::the())
161 for (
auto& channel : channels_)
167 set_frequency_range (10, 24000);
172 setup_reso_drive (FParams& fparams,
float reso,
float drive)
176 const float scale = 1e-5;
177 fparams.pre_scale = scale;
178 fparams.post_scale = 1 / scale;
179 setup_k (fparams, reso);
183 const float db_x2_factor = 0.166096404744368;
184 const float sqrt2 = M_SQRT2;
187 float negative_drive_vol = 1;
190 negative_drive_vol =
exp2f (drive * db_x2_factor);
195 reso += drive * 0.015f;
197 float vol =
exp2f ((drive + -18 * reso) * db_x2_factor);
201 reso = 1 - (1-reso)*(1-reso)*(1-sqrt2/4);
205 reso = 1 - (1-0.9f)*(1-0.9f)*(1-sqrt2/4) + (reso-0.9f)*0.1f;
208 fparams.pre_scale = negative_drive_vol * vol * global_volume_;
209 fparams.post_scale =
std::max (1 / vol, 1.0f) / global_volume_;
210 setup_k (fparams, reso);
213 setup_k (FParams& fparams,
float res)
215 if (mode2stages (mode_) == 1)
218 fparams.k[0] = res * 2;
222 rtable_.lookup_resonance (res, mode2stages (mode_), fparams.k.data());
228 for (
auto& channel : channels_)
230 std::fill (channel.s1.begin(), channel.s1.end(), 0.0);
231 std::fill (channel.s2.begin(), channel.s2.end(), 0.0);
243 fparams_valid_ =
false;
247 set_freq (
float freq)
252 set_reso (
float reso)
255 fparams_valid_ =
false;
258 set_drive (
float drive)
261 fparams_valid_ =
false;
264 set_global_volume (
float global_volume)
271 global_volume_ = global_volume;
272 fparams_valid_ =
false;
275 set_test_linear (
bool test_linear)
277 test_linear_ = test_linear;
278 fparams_valid_ =
false;
283 for (
auto& channel : channels_)
285 channel.res_up->reset();
286 channel.res_down->reset();
289 fparams_valid_ =
false;
292 set_rate (
float rate)
294 freq_warp_factor_ = 4 / (rate * over_);
297 update_frequency_range();
300 set_frequency_range (
float min_freq,
float max_freq)
302 frequency_range_min_ = min_freq;
303 frequency_range_max_ = max_freq;
305 update_frequency_range();
310 return channels_[0].res_up->delay() / over_ + channels_[0].res_down->delay();
314 update_frequency_range()
319 clamp_freq_min_ = frequency_range_min_;
320 clamp_freq_max_ =
std::min (frequency_range_max_, rate_ * over_ * 0.49f);
323 cutoff_warp (
float freq)
325 float x = freq * freq_warp_factor_;
328 const float c1 = -3.16783027;
329 const float c2 = 0.134516124;
330 const float c3 = -4.033321984;
334 return x * (c1 + c2 * x2) / (c3 + x2);
337 tanh_approx (
float x)
342 return x * (27.0f + x * x) / (27.0f + 9.0f * x * x);
344 template<Mode MODE,
bool STEREO>
347 process (
float *left,
float *right,
float freq, uint n_samples)
349 float g = cutoff_warp (
std::clamp (freq, clamp_freq_min_, clamp_freq_max_));
350 float G = g / (1 + g);
352 for (
int stage = 0; stage < mode2stages (MODE); stage++)
354 const float k = fparams_.k[stage];
356 float xnorm = 1.f / (1 - k * G + k * G * G);
357 float s1feedback = -xnorm * k * (G - 1) / (1 + g);
358 float s2feedback = -xnorm * k / (1 + g);
360 auto lowpass = [G] (
float in,
float& state)
362 float v = G * (in - state);
368 auto mode_out = [] (
float y0,
float y1,
float y2,
bool last_stage) ->
float
370 float y1hp =
y0 -
y1;
371 float y2hp =
y1 - y2;
382 case BP8:
return y2hp;
386 case HP8:
return (y1hp - y2hp);
388 case LP3:
return last_stage ?
y1 : y2;
390 case HP3:
return last_stage ? y1hp : (y1hp - y2hp);
394 float s1l, s1r, s2l, s2r;
396 s1l = channels_[0].s1[stage];
397 s2l = channels_[0].s2[stage];
401 s1r = channels_[1].s1[stage];
402 s2r = channels_[1].s2[stage];
405 auto tick = [&] (uint i,
bool last_stage,
float pre_scale,
float post_scale)
407 float xl, xr, y0l, y0r, y1l, y1r, y2l, y2r;
414 { xl = left[i] * pre_scale; }
415 if (STEREO) { xr = right[i] * pre_scale; }
417 { y0l = xl * xnorm + s1l * s1feedback + s2l * s2feedback; }
418 if (STEREO) { y0r = xr * xnorm + s1r * s1feedback + s2r * s2feedback; }
422 { y0l = tanh_approx (y0l); }
423 if (STEREO) { y0r = tanh_approx (y0r); }
425 { y1l = lowpass (y0l, s1l); }
426 if (STEREO) { y1r = lowpass (y0r, s1r); }
428 { y2l = lowpass (y1l, s2l); }
429 if (STEREO) { y2r = lowpass (y1r, s2r); }
431 { left[i] = mode_out (y0l, y1l, y2l, last_stage) * post_scale; }
432 if (STEREO) { right[i] = mode_out (y0r, y1r, y2r, last_stage) * post_scale; }
435 const bool last_stage = mode2stages (MODE) == (stage + 1);
439 for (uint i = 0; i < n_samples; i++)
440 tick (i,
true, fparams_.pre_scale, fparams_.post_scale);
444 for (uint i = 0; i < n_samples; i++)
445 tick (i,
false, 1, 1);
448 channels_[0].s1[stage] = s1l;
449 channels_[0].s2[stage] = s2l;
453 channels_[1].s1[stage] = s1r;
454 channels_[1].s2[stage] = s2r;
460 process_block_mode (uint n_samples,
float *left,
float *right,
const float *freq_in,
const float *reso_in,
const float *drive_in)
462 float over_samples_left[n_samples * over_];
463 float over_samples_right[n_samples * over_];
466 bool stereo = left && right;
468 channels_[0].res_up->process_block (left, n_samples, over_samples_left);
470 channels_[1].res_up->process_block (right, n_samples, over_samples_right);
474 setup_reso_drive (fparams_, reso_in ? reso_in[0] : reso_, drive_in ? drive_in[0] : drive_);
475 fparams_valid_ =
true;
478 if (reso_in || drive_in)
483 float *left_blk = over_samples_left;
484 float *right_blk = over_samples_right;
486 uint n_remaining_samples = n_samples;
487 while (n_remaining_samples)
492 setup_reso_drive (fparams_end, reso_in ? reso_in[todo - 1] : reso_, drive_in ? drive_in[todo - 1] : drive_);
494 constexpr static int STAGES = mode2stages (MODE);
495 float todo_inv = 1.f / todo;
496 float delta_pre_scale = (fparams_end.pre_scale - fparams_.pre_scale) * todo_inv;
497 float delta_post_scale = (fparams_end.post_scale - fparams_.post_scale) * todo_inv;
498 float delta_k[STAGES];
499 for (
int stage = 0; stage < STAGES; stage++)
500 delta_k[stage] = (fparams_end.k[stage] - fparams_.k[stage]) * todo_inv;
503 for (uint i = 0; i < todo * over_; i += over_)
505 fparams_.pre_scale += delta_pre_scale;
506 fparams_.post_scale += delta_post_scale;
508 for (
int stage = 0; stage < STAGES; stage++)
509 fparams_.k[stage] += delta_k[stage];
511 float freq = freq_in ? freq_in[j++] : freq_;
515 process<MODE, true> (left_blk + i, right_blk + i, freq, over_);
519 process<MODE, false> (left_blk + i,
nullptr, freq, over_);
523 n_remaining_samples -= todo;
524 left_blk += todo * over_;
525 right_blk += todo * over_;
538 for (uint i = 0; i < n_samples * over_; i += over_)
540 float freq = freq_in[j++];
544 process<MODE, true> (over_samples_left + i, over_samples_right + i, freq, over_);
548 process<MODE, false> (over_samples_left + i,
nullptr, freq, over_);
556 process<MODE, true> (over_samples_left, over_samples_right, freq_, n_samples * over_);
560 process<MODE, false> (over_samples_left,
nullptr, freq_, n_samples * over_);
564 channels_[0].res_down->process_block (over_samples_left, n_samples * over_, left);
566 channels_[1].res_down->process_block (over_samples_right, n_samples * over_, right);
569 using ProcessBlockFunc =
decltype (&SKFilter::process_block_mode<LP2>);
571 template<
size_t... INDICES>
575 auto mk_func = [] (
auto I) {
return &SKFilter::process_block_mode<Mode (I.value)>; };
581 process_block (uint n_samples,
float *left,
float *right =
nullptr,
const float *freq_in =
nullptr,
const float *reso_in =
nullptr,
const float *drive_in =
nullptr)
587 const uint todo =
std::min (n_samples, MAX_BLOCK_SIZE);
589 (this->*jump_table[mode_]) (todo, left, right, freq_in, reso_in, drive_in);