#pragma once #include #include class QCborMap; class QCborValue; namespace Xybrid::NodeLib { // more precision than probably fits in a double, but it certainly shouldn't hurt const inline constexpr double PI = 3.141592653589793238462643383279502884197169399375105820974; const inline constexpr double SEMI = 1.059463094359295264561825294946341700779204317494185628559; /// Multiplier to compensate for the balance equation /// (1.0 / cos(PI*0.25)) const inline constexpr double PAN_MULT = 1.414213562373095048801688724209698078569671875376948073176; /// Sane mimimum transition time to avoid clip artifacts const inline constexpr double shortStep = 0.0025; struct ADSR { double a = 0.0, d = 0.0, s = 1.0, r = 0.0; ADSR normalized(); ADSR() = default; inline ADSR(double a, double d, double s, double r) : a(a), d(d), s(s), r(r) { } ADSR(const QCborMap&); ADSR(const QCborValue&); operator QCborMap() const; operator QCborValue() const; }; inline std::pair panSignal(double in, double pan) { if (pan == 0.0) return { in, in }; double s = (pan+1.0) * PI * 0.25; return { in * (std::cos(s) * PAN_MULT), in * (std::sin(s) * PAN_MULT) }; } }