#include #include #include class Param { std::string m_name; std::string m_unit; public: typedef struct _sparam_info_t { double pmin, pmax, pvalue, pinterval, pcenter, scenter, base, kexp; } param_info_t; param_info_t m_param_info; Param( std::string name, std::string unit, param_info_t param ) : m_name(name) , m_param_info(param) { } Param( std::string name, std::string unit, double pmin, double pmax, double pvalue, double base=1.0, double kexp=1.0, double pinterval=1.0, double pcenter=-1.0, double scenter=0.0 ) : Param(name, unit, {pmin, pmax, pvalue, pinterval, pcenter, scenter, base, kexp}) { } std::string name() { return m_name; } std::string unit() { return m_unit; } double getParameter() { return m_param_info.pvalue; } void setParameter(double p) { m_param_info.pvalue = p; } double getSlider() { return toSlider(); } // -------------------------------------------------------------- // Exported functions // -------------------------------------------------------------- double quantizeParam(double p) { double k, pq; if (m_param_info.pinterval == 0) { return p; } k = (double)1/(m_param_info.pinterval - 0); if (p < 0) { pq = ((int)(p*k - 0.5))*m_param_info.pinterval; } else { pq = ((int)(p*k + 0.5))*m_param_info.pinterval; } return pq; } double clampParam(double p) { return (double)std::min(m_param_info.pmax, std::max(m_param_info.pmin, quantizeParam(p))); } double fromSlider(double s) { double p, pcenter; double pmax, pmin, base, kexp, scenter; pmax = m_param_info.pmax; pmin = m_param_info.pmin; if (pmin == pmax) { pmax += 1E-9; } base = m_param_info.base; kexp = m_param_info.kexp; if (kexp == 0) { kexp = 1E-9; } scenter = m_param_info.scenter; pcenter = m_param_info.pcenter; if ((pcenter < pmin) || (pcenter > pmax)) pcenter = pmax*scenter + pmin*(1-scenter); s = (double)std::min(1.0, std::max(0.0, s)); if (s < scenter) { if (base == 1) { // pcenter-(pcenter-pmin)*(scenter-s)/scenter; p = pcenter-(pcenter-pmin)*(scenter-s)/scenter; } else { // pcenter-(pcenter-pmin)*(B^(k*(scenter-s)/scenter)-1)/(B^k-1); p = pcenter-(pcenter-pmin)*(pow(base,kexp*(scenter-s)/scenter)-1)/(pow(base,kexp)-1); } } else { if (base == 1) { // pcenter+(pmax-pcenter)*(-scenter+s)/(1-scenter); p = pcenter+(pmax-pcenter)*(-scenter+s)/(1-scenter); } else { // pcenter+(pmax-pcenter)*(B^(k*(-scenter+s)/(1-scenter))-1)/(B^k-1); p = pcenter+(pmax-pcenter)*(pow(base,kexp*(-scenter+s)/(1-scenter))-1)/(pow(base,kexp)-1); } } m_param_info.pvalue = p; return quantizeParam(p); } double toSlider() { double p = m_param_info.pvalue; double s, pcenter; double pmax, pmin, base, kexp, scenter; pmax = m_param_info.pmax; pmin = m_param_info.pmin; if (pmin == pmax) { pmax += 1E-9; } base = m_param_info.base; kexp = m_param_info.kexp; if (kexp == 0) { kexp = 1E-9; } scenter = m_param_info.scenter; pcenter = m_param_info.pcenter; if ((pcenter < pmin) || (pcenter > pmax)) { pcenter = pmax*scenter + pmin*(1-scenter); } p = clampParam(p); if (p < pcenter) { if (base == 1) { // (-pmin+p)*scenter/(pcenter-pmin); s = (-pmin+p)*scenter/(pcenter-pmin); } else { // scenter*(log(B)*k-log(-(-pcenter*B^k+pmin+p*B^k-p)/(pcenter-pmin)))/log(B)/k; s = scenter*(log(base)*kexp-log(-(-pcenter*pow(base,kexp)+pmin+p*pow(base,kexp)-p)/(pcenter-pmin)))/log(base)/kexp; } } else { if (base == 1) { // (pcenter-scenter*pmax-p+scenter*p)/(-pmax+pcenter); s = (pcenter-scenter*pmax-p+scenter*p)/(-pmax+pcenter); } else { // (k*log(B)*scenter+log(-(-pcenter*B^k+pmax+p*B^k-p)/(-pmax+pcenter))-log(-(-pcenter*B^k+pmax+p*B^k-p)/(-pmax+pcenter))*scenter)/log(B)/k; s = (kexp*log(base)*scenter+log(-(-pcenter*pow(base,kexp)+pmax+p*pow(base,kexp)-p)/(-pmax+pcenter))-log(-(-pcenter*pow(base,kexp)+pmax+p*pow(base,kexp)-p)/(-pmax+pcenter))*scenter)/log(base)/kexp; } } return s; } };