VIANC/pw_plugin_II/pickup_cancel.cc

53 lines
1.4 KiB
C++
Raw Normal View History

#include "pickup_cancel.h"
#include <numbers>
#include <algorithm>
#include <cstdio>
static constexpr float twopi = 2.0f*std::numbers::pi_v<float>;
pickup_cancel::pickup_cancel(float fst_f, float eps_u, int nharm) :
act_f(fst_f), act_phi(0.0f),
max_f(fst_f+eps_u),min_f(fst_f-eps_u), decay_cst(fst_f/50.0f), error_filter(0.0f),
size(nharm), cosine_coeffs(nharm, 0.0f), sine_coeffs(nharm, 0.0f)
{}
bool pickup_cancel::is_in_sync() {
return cosine_coeffs[0]*cosine_coeffs[0]
<= 0.5f * sine_coeffs[0] * sine_coeffs[0];
}
float pickup_cancel::do_sample(float s) {
act_phi += act_f;
if(act_phi >= twopi) {
act_phi -= twopi;
}
float cosphi = std::cos(act_phi);
float sinphi = std::sin(act_phi);
// Always between -1 and 1
error_filter += decay_cst * (s * cosphi - error_filter);
// Sensitivity setting to tune?
float scaled_err = 10.0f * error_filter;
scaled_err = std::clamp(scaled_err, -1.0f, 1.0f);
act_f = (min_f + max_f)/2 + (max_f - min_f)/2 * scaled_err;
float corr = 0.0f;
float cos = 1.0f;
float sin = 0.0f;
for(int i = 0; i < size; ++i) {
sin = std::sin((i+1)*act_phi);
cos = std::cos((i+1)*act_phi);
corr += cos*cosine_coeffs[i] + sin*sine_coeffs[i];
cosine_coeffs[i] += (i+1) * decay_cst * (2 * s * cos - cosine_coeffs[i]);
sine_coeffs[i] += (i+1) * decay_cst * (2 * s * sin - sine_coeffs[i]);
}
if(!this->is_in_sync()) {return 0.0f;} else {return corr;}
}