5 #include "smpandaresampler.hh"
17 LP1, LP2, LP3, LP4, LP6, LP8,
19 HP1, HP2, HP3, HP4, HP6, HP8
22 static constexpr
size_t LAST_MODE = HP8;
23 Mode mode_ = Mode::LP2;
27 float global_volume_ = 1;
28 bool test_linear_ =
false;
30 float freq_warp_factor_ = 0;
31 float frequency_range_min_ = 0;
32 float frequency_range_max_ = 0;
33 float clamp_freq_min_ = 0;
34 float clamp_freq_max_ = 0;
37 static constexpr
int MAX_STAGES = 4;
38 static constexpr uint MAX_BLOCK_SIZE = 1024;
42 std::unique_ptr<Resampler2> res_up;
43 std::unique_ptr<Resampler2> res_down;
45 std::array<float, MAX_STAGES> s1;
46 std::array<float, MAX_STAGES> s2;
50 std::array<float, MAX_STAGES> k;
55 mode2stages (Mode mode)
74 std::array<Channel, 2> channels_;
76 bool fparams_valid_ =
false;
79 std::vector<float> res2_k;
80 std::vector<float> res3_k;
81 std::vector<float> res4_k;
82 static constexpr
int TSIZE = 16;
85 for (
int order = 4; order <= 8; order += 2)
87 for (
int t = 0; t <= TSIZE + 1; t++)
89 double res = std::clamp (
double (t) / TSIZE, 0.0, 1.0);
92 const double R = 1 - res;
93 const double r_alpha = std::acos (R) / (order / 2);
95 std::vector<double> Rn;
96 for (
int i = 0; i < order / 2; i++)
99 const double bw_s_alpha = M_PI * (4 * i + order + 2) / (2 * order);
101 Rn.push_back (-cos (bw_s_alpha + r_alpha));
104 std::sort (Rn.begin(), Rn.end(), std::greater<double>());
109 res2_k.push_back ((1 - xr) * 2);
111 res3_k.push_back ((1 - xr) * 2);
113 res4_k.push_back ((1 - xr) * 2);
122 static RTable rtable;
126 interpolate_resonance (
float res,
int stages,
float *k,
const std::vector<float>& res_k)
const
128 auto lerp = [] (
float a,
float b,
float frac) {
129 return a + frac * (b - a);
132 float fidx = std::clamp (res, 0.f, 1.f) * TSIZE;
134 float frac = fidx - idx;
136 for (
int s = 0; s < stages; s++)
138 k[s] = lerp (res_k[idx * stages + s], res_k[idx * stages + stages + s], frac);
142 lookup_resonance (
float res,
int stages,
float *k)
const
145 interpolate_resonance (res, stages, k, res2_k);
148 interpolate_resonance (res, stages, k, res3_k);
151 interpolate_resonance (res, stages, k, res4_k);
154 k[stages - 1] = res * 2;
157 const RTable& rtable_;
161 rtable_ (RTable::the())
163 for (
auto& channel : channels_)
165 channel.res_up = std::make_unique<Resampler2> (Resampler2::UP, over_, Resampler2::PREC_72DB);
166 channel.res_down = std::make_unique<Resampler2> (Resampler2::DOWN, over_, Resampler2::PREC_72DB);
169 set_frequency_range (10, 24000);
174 setup_reso_drive (FParams& fparams,
float reso,
float drive)
178 const float scale = 1e-5;
179 fparams.pre_scale = scale;
180 fparams.post_scale = 1 / scale;
181 setup_k (fparams, reso);
185 const float db_x2_factor = 0.166096404744368;
186 const float sqrt2 = M_SQRT2;
189 float negative_drive_vol = 1;
192 negative_drive_vol = exp2f (drive * db_x2_factor);
197 reso += drive * 0.015f;
199 float vol = exp2f ((drive + -18 * reso) * db_x2_factor);
203 reso = 1 - (1-reso)*(1-reso)*(1-sqrt2/4);
207 reso = 1 - (1-0.9f)*(1-0.9f)*(1-sqrt2/4) + (reso-0.9f)*0.1f;
210 fparams.pre_scale = negative_drive_vol * vol * global_volume_;
211 fparams.post_scale = std::max (1 / vol, 1.0f) / global_volume_;
212 setup_k (fparams, reso);
215 setup_k (FParams& fparams,
float res)
217 if (mode2stages (mode_) == 1)
220 fparams.k[0] = res * 2;
224 rtable_.lookup_resonance (res, mode2stages (mode_), fparams.k.data());
230 for (
auto& channel : channels_)
232 std::fill (channel.s1.begin(), channel.s1.end(), 0.0);
233 std::fill (channel.s2.begin(), channel.s2.end(), 0.0);
245 fparams_valid_ =
false;
249 set_freq (
float freq)
254 set_reso (
float reso)
257 fparams_valid_ =
false;
260 set_drive (
float drive)
263 fparams_valid_ =
false;
266 set_global_volume (
float global_volume)
273 global_volume_ = global_volume;
274 fparams_valid_ =
false;
277 set_test_linear (
bool test_linear)
279 test_linear_ = test_linear;
280 fparams_valid_ =
false;
285 for (
auto& channel : channels_)
287 channel.res_up->reset();
288 channel.res_down->reset();
291 fparams_valid_ =
false;
294 set_rate (
float rate)
296 freq_warp_factor_ = 4 / (rate * over_);
299 update_frequency_range();
302 set_frequency_range (
float min_freq,
float max_freq)
304 frequency_range_min_ = min_freq;
305 frequency_range_max_ = max_freq;
307 update_frequency_range();
312 return channels_[0].res_up->delay() / over_ + channels_[0].res_down->delay();
316 update_frequency_range()
321 clamp_freq_min_ = frequency_range_min_;
322 clamp_freq_max_ = std::min (frequency_range_max_, rate_ * over_ * 0.49f);
325 cutoff_warp (
float freq)
327 float x = freq * freq_warp_factor_;
330 const float c1 = -3.16783027;
331 const float c2 = 0.134516124;
332 const float c3 = -4.033321984;
336 return x * (c1 + c2 * x2) / (c3 + x2);
339 tanh_approx (
float x)
342 x = std::clamp (x, -3.0f, 3.0f);
344 return x * (27.0f + x * x) / (27.0f + 9.0f * x * x);
346 template<Mode MODE,
bool STEREO>
349 process (
float *left,
float *right,
float freq, uint n_samples)
351 float g = cutoff_warp (std::clamp (freq, clamp_freq_min_, clamp_freq_max_));
352 float G = g / (1 + g);
354 for (
int stage = 0; stage < mode2stages (MODE); stage++)
356 const float k = fparams_.k[stage];
358 float xnorm = 1.f / (1 - k * G + k * G * G);
359 float s1feedback = -xnorm * k * (G - 1) / (1 + g);
360 float s2feedback = -xnorm * k / (1 + g);
362 auto lowpass = [G] (
float in,
float& state)
364 float v = G * (in - state);
370 auto mode_out = [] (
float y0,
float y1,
float y2,
bool last_stage) ->
float
372 float y1hp = y0 - y1;
373 float y2hp = y1 - y2;
384 case BP8:
return y2hp;
388 case HP8:
return (y1hp - y2hp);
390 case LP3:
return last_stage ? y1 : y2;
392 case HP3:
return last_stage ? y1hp : (y1hp - y2hp);
396 float s1l, s1r, s2l, s2r;
398 s1l = channels_[0].s1[stage];
399 s2l = channels_[0].s2[stage];
403 s1r = channels_[1].s1[stage];
404 s2r = channels_[1].s2[stage];
407 auto tick = [&] (uint i,
bool last_stage,
float pre_scale,
float post_scale)
409 float xl, xr, y0l, y0r, y1l, y1r, y2l, y2r;
416 { xl = left[i] * pre_scale; }
417 if (STEREO) { xr = right[i] * pre_scale; }
419 { y0l = xl * xnorm + s1l * s1feedback + s2l * s2feedback; }
420 if (STEREO) { y0r = xr * xnorm + s1r * s1feedback + s2r * s2feedback; }
424 { y0l = tanh_approx (y0l); }
425 if (STEREO) { y0r = tanh_approx (y0r); }
427 { y1l = lowpass (y0l, s1l); }
428 if (STEREO) { y1r = lowpass (y0r, s1r); }
430 { y2l = lowpass (y1l, s2l); }
431 if (STEREO) { y2r = lowpass (y1r, s2r); }
433 { left[i] = mode_out (y0l, y1l, y2l, last_stage) * post_scale; }
434 if (STEREO) { right[i] = mode_out (y0r, y1r, y2r, last_stage) * post_scale; }
437 const bool last_stage = mode2stages (MODE) == (stage + 1);
441 for (uint i = 0; i < n_samples; i++)
442 tick (i,
true, fparams_.pre_scale, fparams_.post_scale);
446 for (uint i = 0; i < n_samples; i++)
447 tick (i,
false, 1, 1);
450 channels_[0].s1[stage] = s1l;
451 channels_[0].s2[stage] = s2l;
455 channels_[1].s1[stage] = s1r;
456 channels_[1].s2[stage] = s2r;
462 process_block_mode (uint n_samples,
float *left,
float *right,
const float *freq_in,
const float *reso_in,
const float *drive_in)
464 float over_samples_left[n_samples * over_];
465 float over_samples_right[n_samples * over_];
468 bool stereo = left && right;
470 channels_[0].res_up->process_block (left, n_samples, over_samples_left);
472 channels_[1].res_up->process_block (right, n_samples, over_samples_right);
476 setup_reso_drive (fparams_, reso_in ? reso_in[0] : reso_, drive_in ? drive_in[0] : drive_);
477 fparams_valid_ =
true;
480 if (reso_in || drive_in)
485 float *left_blk = over_samples_left;
486 float *right_blk = over_samples_right;
488 uint n_remaining_samples = n_samples;
489 while (n_remaining_samples)
491 const uint todo = std::min<uint> (n_remaining_samples, 64);
494 setup_reso_drive (fparams_end, reso_in ? reso_in[todo - 1] : reso_, drive_in ? drive_in[todo - 1] : drive_);
496 constexpr
static int STAGES = mode2stages (MODE);
497 float todo_inv = 1.f / todo;
498 float delta_pre_scale = (fparams_end.pre_scale - fparams_.pre_scale) * todo_inv;
499 float delta_post_scale = (fparams_end.post_scale - fparams_.post_scale) * todo_inv;
500 float delta_k[STAGES];
501 for (
int stage = 0; stage < STAGES; stage++)
502 delta_k[stage] = (fparams_end.k[stage] - fparams_.k[stage]) * todo_inv;
505 for (uint i = 0; i < todo * over_; i += over_)
507 fparams_.pre_scale += delta_pre_scale;
508 fparams_.post_scale += delta_post_scale;
510 for (
int stage = 0; stage < STAGES; stage++)
511 fparams_.k[stage] += delta_k[stage];
513 float freq = freq_in ? freq_in[j++] : freq_;
517 process<MODE, true> (left_blk + i, right_blk + i, freq, over_);
521 process<MODE, false> (left_blk + i,
nullptr, freq, over_);
525 n_remaining_samples -= todo;
526 left_blk += todo * over_;
527 right_blk += todo * over_;
540 for (uint i = 0; i < n_samples * over_; i += over_)
542 float freq = freq_in[j++];
546 process<MODE, true> (over_samples_left + i, over_samples_right + i, freq, over_);
550 process<MODE, false> (over_samples_left + i,
nullptr, freq, over_);
558 process<MODE, true> (over_samples_left, over_samples_right, freq_, n_samples * over_);
562 process<MODE, false> (over_samples_left,
nullptr, freq_, n_samples * over_);
566 channels_[0].res_down->process_block (over_samples_left, n_samples * over_, left);
568 channels_[1].res_down->process_block (over_samples_right, n_samples * over_, right);
571 using ProcessBlockFunc = decltype (&SKFilter::process_block_mode<LP2>);
573 template<
size_t... INDICES>
574 static constexpr std::array<ProcessBlockFunc, LAST_MODE + 1>
575 make_jump_table (std::integer_sequence<size_t, INDICES...>)
577 auto mk_func = [] (
auto I) {
return &SKFilter::process_block_mode<Mode (I.value)>; };
579 return { mk_func (std::integral_constant<int, INDICES>{})... };
583 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)
585 static constexpr
auto jump_table { make_jump_table (std::make_index_sequence<LAST_MODE + 1>()) };
589 const uint todo = std::min (n_samples, MAX_BLOCK_SIZE);
591 (this->*jump_table[mode_]) (todo, left, right, freq_in, reso_in, drive_in);
Definition: smpandaresampler.hh:99
Definition: smskfilter.hh:14