| @@ -51,6 +51,51 @@ void SVFilter::cleanup() | |||
| abovenq = false; | |||
| } | |||
| SVFilter::response::response(float b0, float b1, float b2, | |||
| float a0, float a1 ,float a2) | |||
| { | |||
| a[0] = a0; | |||
| a[1] = a1; | |||
| a[2] = a2; | |||
| b[0] = b0; | |||
| b[1] = b1; | |||
| b[2] = b2; | |||
| } | |||
| SVFilter::response SVFilter::computeResponse(int type, | |||
| float freq, float pq, int stages, float gain, float fs) | |||
| { | |||
| typedef SVFilter::response res; | |||
| float f = freq / fs * 4.0; | |||
| if(f > 0.99999f) | |||
| f = 0.99999f; | |||
| float q = 1.0f - atanf(sqrtf(pq)) * 2.0f / PI; | |||
| q = powf(q, 1.0f / (stages + 1)); | |||
| float qrt = sqrtf(q); | |||
| float g = powf(gain, 1.0 / (stages + 1)); | |||
| if(type == 0) { //Low | |||
| return res{0, g*f*f*qrt, 0, | |||
| 1, (q*f+f*f-2), (1-q*f)}; | |||
| } | |||
| if(type == 1) {//High | |||
| //g *= qrt/(1+f*q); | |||
| g *= qrt; | |||
| return res{g, -2*g, g, | |||
| //1, (f*f-2*f*q-2)/(1+f*q), 1}; | |||
| 1, (q*f+f*f-2), (1-q*f)}; | |||
| } | |||
| if(type == 2) {//Band | |||
| g *= f*qrt; | |||
| return res{g, -g, 0, | |||
| 1, (q*f+f*f-2), (1-q*f)}; | |||
| } | |||
| if(type == 3 || true) {//Notch | |||
| g *= qrt; | |||
| return res{g, -2*g+g*f*f, g, | |||
| 1, (q*f+f*f-2), (1-q*f)}; | |||
| } | |||
| } | |||
| void SVFilter::computefiltercoefs(void) | |||
| { | |||
| par.f = freq / samplerate_f * 4.0f; | |||
| @@ -136,7 +181,8 @@ void SVFilter::singlefilterout(float *smp, fstage &x, parameters &par) | |||
| out = &x.notch; | |||
| break; | |||
| default: | |||
| errx(1, "Impossible SVFilter type encountered [%d]", type); | |||
| out = &x.low; | |||
| warnx("Impossible SVFilter type encountered [%d]", type); | |||
| } | |||
| for(int i = 0; i < buffersize; ++i) { | |||
| @@ -148,6 +194,17 @@ void SVFilter::singlefilterout(float *smp, fstage &x, parameters &par) | |||
| } | |||
| } | |||
| // simplifying the responses | |||
| // xl = xl*z(-1) + pf*xb*z(-1) | |||
| // xh = pq1*x - xl - pq*xb*z(-1) | |||
| // xb = pf*xh + xb*z(-1) | |||
| // xn = xh + xl | |||
| // | |||
| // xl = pf*xb*z(-1)/(1-z(-1)) | |||
| // xb = pf*xh/(1-z(-1)) | |||
| // xl = pf*pfxh*z(-1)/(1-z(-1))^2 | |||
| void SVFilter::filterout(float *smp) | |||
| { | |||
| for(int i = 0; i < stages + 1; ++i) | |||
| @@ -36,6 +36,15 @@ class SVFilter:public Filter | |||
| void setstages(int stages_); | |||
| void cleanup(); | |||
| struct response { | |||
| response(float b0, float b1, float b2, | |||
| float a0, float a1 ,float a2); | |||
| float a[3]; | |||
| float b[3]; | |||
| }; | |||
| static response computeResponse(int type, | |||
| float freq, float pq, int stages, float g, float fs); | |||
| private: | |||
| struct fstage { | |||
| float low, high, band, notch; | |||
| @@ -131,9 +131,12 @@ static const rtosc::Ports local_ports = { | |||
| //Return the old data for distruction | |||
| d.reply("/free", "sb", "EffectMgr", sizeof(EffectMgr*), &eff_); | |||
| }}, | |||
| rSubtype(Echo), | |||
| rSubtype(Alienwah), | |||
| rSubtype(Chorus), | |||
| rSubtype(Distorsion), | |||
| rSubtype(Echo), | |||
| rSubtype(Phaser), | |||
| rSubtype(Reverb), | |||
| }; | |||
| const rtosc::Ports &EffectMgr::ports = local_ports; | |||
| @@ -34,21 +34,21 @@ rtosc::Ports Phaser::ports = { | |||
| rBegin; | |||
| rEnd}, | |||
| //Pvolume/Ppanning are common | |||
| rEffPar(lfo.Pfreq, 2, ""), | |||
| rEffPar(lfo.Prandomness, 3, ""), | |||
| rEffPar(lfo.PLFOtype, 4, ""), | |||
| rEffPar(lfo.Pstereo, 5, ""), | |||
| rEffPar(Pdepth, 6, ""), | |||
| rEffPar(Pfb, 7, ""), | |||
| rEffPar(Pstages, 8, ""), | |||
| rEffPar(Plrcross, 9, ""), | |||
| rEffPar(Poffset, 9, ""), | |||
| rEffParTF(Poutsub, 10, ""), | |||
| rEffPar(Pphase, 11, ""), | |||
| rEffPar(Pwidth, 11, ""), | |||
| rEffPar(Phyper, 12, ""), | |||
| rEffPar(Pdistortion, 13, ""), | |||
| rEffPar(Panalog, 14, ""), | |||
| rEffPar(lfo.Pfreq, 2, rShort("freq"), ""), | |||
| rEffPar(lfo.Prandomness, 3, rShort("rnd."), ""), | |||
| rEffPar(lfo.PLFOtype, 4, rShort("type"), ""), | |||
| rEffParTF(lfo.Pstereo, 5, rShort("stereo"), ""), | |||
| rEffPar(Pdepth, 6, rShort("depth"), ""), | |||
| rEffPar(Pfb, 7, rShort("fb"), ""), | |||
| rEffPar(Pstages, 8, rShort("stages"), ""), | |||
| rEffPar(Plrcross, 9, rShort("cross"), ""), | |||
| rEffPar(Poffset, 9, rShort("off"), ""), | |||
| rEffParTF(Poutsub, 10, rShort("sub") ""), | |||
| rEffPar(Pphase, 11, rShort("phase"), ""), | |||
| rEffPar(Pwidth, 11, rShort("width"), ""), | |||
| rEffParTF(Phyper, 12, rShort("hyp."), ""), | |||
| rEffPar(Pdistortion, 13, rShort("distort"), "Distortion"), | |||
| rEffParTF(Panalog, 14, rShort("analog"), ""), | |||
| }; | |||
| #undef rBegin | |||
| #undef rEnd | |||
| @@ -17,6 +17,36 @@ | |||
| #include "../DSP/AnalogFilter.h" | |||
| #include "../DSP/Unison.h" | |||
| #include <cmath> | |||
| #include <rtosc/ports.h> | |||
| #include <rtosc/port-sugar.h> | |||
| #define rObject Reverb | |||
| #define rBegin [](const char *, rtosc::RtData &) { | |||
| #define rEnd } | |||
| rtosc::Ports Reverb::ports = { | |||
| {"preset::i", rOptions(Cathedral1, Cathedral2, Cathedral3, | |||
| Hall1, Hall2, Room1, Room2, Basement, | |||
| Tunnel, Echoed1, Echoed2, VeryLong1, VeryLong2) | |||
| rProp(parameter) | |||
| rDoc("Instrument Presets"), 0, | |||
| rBegin; | |||
| rEnd}, | |||
| //Pvolume/Ppanning are common | |||
| rEffPar(Ptime, 2, rShort("time"), "Length of Reverb"), | |||
| rEffPar(Pidelay, 3, rShort("i.time"), "Delay for first impulse"), | |||
| rEffPar(Pidelayfb,4, rShort("i.fb"), "Feedback for first impulse"), | |||
| rEffPar(Plpf, 7, rShort("lpf"), "Low pass filter"), | |||
| rEffPar(Phpf, 8, rShort("lpf"), "High pass filter"), | |||
| rEffPar(Plohidamp,9, rShort("damp"), "Dampening"), | |||
| //Todo make this a selector | |||
| rEffPar(Ptype, 10,rShort("type"), "Type"), | |||
| rEffPar(Proomsize,11,rShort("size"), "Room Size"), | |||
| rEffPar(Pbandwidth,12,rShort("bw"), "Bandwidth"), | |||
| }; | |||
| #undef rBegin | |||
| #undef rEnd | |||
| #undef rObject | |||
| Reverb::Reverb(EffectParams pars) | |||
| :Effect(pars), | |||
| @@ -32,6 +32,7 @@ class Reverb:public Effect | |||
| void changepar(int npar, unsigned char value); | |||
| unsigned char getpar(int npar) const; | |||
| static rtosc::Ports ports; | |||
| private: | |||
| //Parametrii | |||
| unsigned char Pvolume; | |||
| @@ -16,7 +16,7 @@ | |||
| #include <mxml.h> | |||
| #include <string> | |||
| #include <vector> | |||
| #include "../version.h" | |||
| #include "../zyn-version.h" | |||
| #ifndef XML_WRAPPER_H | |||
| #define XML_WRAPPER_H | |||
| @@ -15,6 +15,7 @@ | |||
| #include "../Misc/Util.h" | |||
| #include "../Misc/Time.h" | |||
| #include "../DSP/AnalogFilter.h" | |||
| #include "../DSP/SVFilter.h" | |||
| #include <cmath> | |||
| #include <cstdio> | |||
| #include <cstdlib> | |||
| @@ -89,6 +90,9 @@ const rtosc::Ports FilterParams::ports = { | |||
| rToggle(Psequencereversed, "If the modulator input is inverted"), | |||
| //{"Psequence#" FF_MAX_SEQUENCE "/nvowel", "", NULL, [](){}}, | |||
| {"type-svf::i", rProp(parameter) rShort("type") | |||
| rOptions(low, high, band, notch) | |||
| rDoc("Filter Type"), 0, rOptionCb(Ptype)}, | |||
| //UI reader | |||
| {"Pvowels:", rDoc("Get Formant Vowels"), NULL, | |||
| @@ -132,24 +136,37 @@ const rtosc::Ports FilterParams::ports = { | |||
| rDoc("Get a frequency response"), | |||
| NULL, [](const char *, RtData &d) { | |||
| FilterParams *obj = (FilterParams *) d.obj; | |||
| int order = 0; | |||
| float gain = dB2rap(obj->getgain()); | |||
| if(obj->Ptype != 6 && obj->Ptype != 7 && obj->Ptype != 8) | |||
| gain = 1.0; | |||
| auto cf = AnalogFilter::computeCoeff(obj->Ptype, | |||
| Filter::getrealfreq(obj->getfreq()), | |||
| obj->getq(), obj->Pstages, | |||
| gain, 48000, order); | |||
| if(order == 2) { | |||
| if(obj->Pcategory == 0) { | |||
| int order = 0; | |||
| float gain = dB2rap(obj->getgain()); | |||
| if(obj->Ptype != 6 && obj->Ptype != 7 && obj->Ptype != 8) | |||
| gain = 1.0; | |||
| auto cf = AnalogFilter::computeCoeff(obj->Ptype, | |||
| Filter::getrealfreq(obj->getfreq()), | |||
| obj->getq(), obj->Pstages, | |||
| gain, 48000, order); | |||
| if(order == 2) { | |||
| d.reply(d.loc, "fffffff", | |||
| (float)obj->Pstages, | |||
| cf.c[0], cf.c[1], cf.c[2], | |||
| 0.0, cf.d[1], cf.d[2]); | |||
| } else if(order == 1) { | |||
| d.reply(d.loc, "fffff", | |||
| (float)obj->Pstages, | |||
| cf.c[0], cf.c[1], | |||
| 0.0, cf.d[1]); | |||
| } | |||
| } else if(obj->Pcategory == 2) { | |||
| int order = 0; | |||
| float gain = dB2rap(obj->getgain()); | |||
| auto cf = SVFilter::computeResponse(obj->Ptype, | |||
| Filter::getrealfreq(obj->getfreq()), | |||
| obj->getq(), obj->Pstages, | |||
| gain, 48000); | |||
| d.reply(d.loc, "fffffff", | |||
| (float)obj->Pstages, | |||
| cf.c[0], cf.c[1], cf.c[2], | |||
| 0.0, cf.d[1], cf.d[2]); | |||
| } else if(order == 1) { | |||
| d.reply(d.loc, "fffff", | |||
| (float)obj->Pstages, | |||
| cf.c[0], cf.c[1], | |||
| 0.0, cf.d[1]); | |||
| cf.b[0], cf.b[1], cf.b[2], | |||
| 0.0, -cf.a[1], -cf.a[2]); | |||
| } | |||
| }}, | |||
| // "", NULL, [](){}},"/freq" | |||
| @@ -35,7 +35,7 @@ | |||
| #include "Misc/Master.h" | |||
| #include "Misc/Part.h" | |||
| #include "Misc/Util.h" | |||
| #include "version.h" | |||
| #include "zyn-version.h" | |||
| //Nio System | |||
| #include "Nio/Nio.h" | |||
| @@ -27,6 +27,7 @@ | |||
| //Hack to workaround old incomplete decltype implementations | |||
| #ifdef __GNUC__ | |||
| #ifndef __clang__ | |||
| #if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ <= 7) | |||
| template<typename T> | |||
| struct rtosc_hack_decltype_t | |||
| @@ -37,6 +38,7 @@ struct rtosc_hack_decltype_t | |||
| #define decltype(expr) rtosc_hack_decltype_t<decltype(expr)>::type | |||
| #endif | |||
| #endif | |||
| #endif | |||
| //General macro utilities | |||
| #define STRINGIFY2(a) #a | |||
| @@ -13,7 +13,7 @@ | |||
| #include <iostream> | |||
| #include "version.h" | |||
| #include "zyn-version.h" | |||
| constexpr int version_type::v_strcmp(const version_type& v2, int i) const | |||
| { | |||
| @@ -33,7 +33,7 @@ public: | |||
| //! constructs the current zynaddsubfx version | |||
| constexpr version_type() : | |||
| version_type(2, 5, 4) | |||
| version_type(2, 4, 4) | |||
| { | |||
| } | |||