68 std::complex<double> variance = std::complex<double>(0.0, 0.0);
69 for (
const std::complex<double> &pole : poles) {
70 const double magnitude = std::pow(std::abs(pole), 1.0 / scale_factor);
71 const double phase = std::arg(pole) / scale_factor;
72 const std::complex<double> multiplier1 = std::polar(magnitude, phase);
73 const std::complex<double> multiplier2 = std::pow(magnitude - std::polar(1.0, phase), -2.0);
74 variance += 2.0 * multiplier1 * multiplier2;
79 return variance.real();
102 const std::array<std::complex<double>, 4> &poles,
double scale_factor)
104 std::complex<double> variance_derivative = std::complex<double>(0.0, 0.0);
105 for (
const std::complex<double> &pole : poles) {
106 const double magnitude = std::pow(std::abs(pole), 1.0 / scale_factor);
107 const double phase = std::arg(pole) / scale_factor;
109 const std::complex<double> multiplier1 = std::polar(magnitude, phase);
110 const std::complex<double> multiplier2 = magnitude + std::polar(1.0, phase);
111 const std::complex<double> multiplier3 = std::log(std::abs(pole)) -
112 std::complex<double>(0.0, std::arg(pole));
114 const std::complex<double> divisor1 = std::pow(magnitude - std::polar(1.0, phase), 3.0);
115 const std::complex<double> divisor2 =
math::square(scale_factor);
117 variance_derivative += 2.0 * multiplier1 * multiplier2 * multiplier3 / (divisor1 * divisor2);
122 return variance_derivative.real();
168 const std::array<std::complex<double>, 4> &poles,
float sigma)
172 std::array<std::complex<double>, 4> scaled_poles;
173 for (
int i = 0;
i < poles.size();
i++) {
174 const std::complex<double> &pole = poles[
i];
175 const double magnitude = std::pow(std::abs(pole), 1.0 / scale_factor);
176 const double phase = std::arg(pole) / scale_factor;
177 scaled_poles[
i] = std::polar(magnitude, phase);
187 const std::array<std::complex<double>, 4> &non_causal_poles)
189 std::array<std::complex<double>, 4> causal_poles;
190 for (
int i = 0;
i < non_causal_poles.size();
i++) {
191 causal_poles[
i] = 1.0 / non_causal_poles[
i];
202 std::complex<double> gain = std::complex<double>(1.0, 0.0);
203 for (
const std::complex<double> &pole : poles) {
230 const std::complex<double> b4 = gain;
231 const std::complex<double> b3 = -gain * (poles[0] + poles[1] + poles[2] + poles[3]);
232 const std::complex<double> b2 = gain * (poles[1] * poles[0] + poles[2] * poles[0] +
233 poles[2] * poles[1] + poles[3] * poles[0] +
234 poles[3] * poles[1] + poles[3] * poles[2]);
235 const std::complex<double>
b1 = -gain * (poles[2] * poles[1] * poles[0] +
236 poles[3] * poles[1] * poles[0] +
237 poles[3] * poles[2] * poles[0] +
238 poles[3] * poles[2] * poles[1]);
242 const double4 coefficients =
double4(
b1.real(), b2.real(), b3.real(), b4.real());
291 const std::array<std::complex<double>, 4> &poles,
292 const std::complex<double> &target_pole,
299 std::complex<double> target_pole_inverse = 1.0 / target_pole;
300 std::complex<double> residue = std::complex<double>(1.0, 0.0);
301 for (
const std::complex<double> &pole : poles) {
302 if (pole != target_pole && pole != std::conj(target_pole)) {
303 residue *= 1.0 - pole * target_pole_inverse;
308 return gain / residue;
317 const std::array<std::complex<double>, 4> &poles,
318 const std::complex<double> &target_pole,
321 std::complex<double>
result = std::complex<double>(1.0, 0.0);
322 for (
const std::complex<double> &pole : poles) {
323 result *= 1.0 - pole * target_pole;
335 const std::complex<double> &residue,
336 const std::complex<double> &transfer_value,
337 double2 &r_feedback_coefficients,
338 double2 &r_causal_feedforward_coefficients,
339 double2 &r_non_causal_feedforward_coefficients)
341 const std::complex<double> parallel_residue = residue * transfer_value;
342 const std::complex<double> pole_inverse = 1.0 / pole;
344 r_feedback_coefficients =
double2(-2.0 * pole.real(), std::norm(pole));
346 const double causal_feedforward_1 = parallel_residue.imag() / pole_inverse.imag();
347 const double causal_feedforward_0 = parallel_residue.real() -
348 causal_feedforward_1 * pole_inverse.real();
349 r_causal_feedforward_coefficients =
double2(causal_feedforward_0, causal_feedforward_1);
351 const double non_causal_feedforward_1 = causal_feedforward_1 -
352 causal_feedforward_0 * r_feedback_coefficients[0];
353 const double non_causal_feedforward_2 = -causal_feedforward_0 * r_feedback_coefficients[1];
354 r_non_causal_feedforward_coefficients =
double2(non_causal_feedforward_1,
355 non_causal_feedforward_2);
412 const std::array<std::complex<double>, 4> poles = {
413 std::complex<double>(1.12075, 1.27788),
414 std::complex<double>(1.12075, -1.27788),
415 std::complex<double>(1.76952, 0.46611),
416 std::complex<double>(1.76952, -0.46611),
424 const std::array<std::complex<double>, 4> non_causal_poles = scaled_poles;
425 const std::array<std::complex<double>, 4> causal_poles =
compute_causal_poles(non_causal_poles);
437 causal_poles, causal_poles[0], feedforward_coefficient);
439 causal_poles, causal_poles[2], feedforward_coefficient);
445 const std::complex<double> first_transfer_value =
447 causal_poles, causal_poles[0], feedforward_coefficient);
448 const std::complex<double> second_transfer_value =
450 causal_poles, causal_poles[2], feedforward_coefficient);
456 first_transfer_value,
457 first_feedback_coefficients_,
458 first_causal_feedforward_coefficients_,
459 first_non_causal_feedforward_coefficients_);
462 second_transfer_value,
463 second_feedback_coefficients_,
464 second_causal_feedforward_coefficients_,
465 second_non_causal_feedforward_coefficients_);
469 first_feedback_coefficients_, first_causal_feedforward_coefficients_);
471 first_feedback_coefficients_, first_non_causal_feedforward_coefficients_);
473 second_feedback_coefficients_, second_causal_feedforward_coefficients_);
475 second_feedback_coefficients_, second_non_causal_feedforward_coefficients_);
static void compute_second_order_section(const std::complex< double > &pole, const std::complex< double > &residue, const std::complex< double > &transfer_value, double2 &r_feedback_coefficients, double2 &r_causal_feedforward_coefficients, double2 &r_non_causal_feedforward_coefficients)