zynaddsubfx

ZynAddSubFX open source synthesizer
Log | Files | Refs | Submodules | LICENSE

commit ad75e3744776a25a307cc0809a14867bec751923
parent 8e2d5b49dc03517c60f363b1048dcfc93277f48e
Author: fundamental <mark.d.mccurry@gmail.com>
Date:   Mon, 30 May 2016 09:35:43 -0400

FilterParams: Add OSC Method To Get Response

Diffstat:
Msrc/DSP/AnalogFilter.cpp | 76+++++++++++++++++++++++++++++++++++++++++-----------------------------------
Msrc/DSP/AnalogFilter.h | 3+++
Msrc/Params/FilterParams.cpp | 29+++++++++++++++++++++++------
Msrc/Synth/Envelope.cpp | 2+-
4 files changed, 68 insertions(+), 42 deletions(-)

diff --git a/src/DSP/AnalogFilter.cpp b/src/DSP/AnalogFilter.cpp @@ -61,28 +61,35 @@ void AnalogFilter::cleanup() needsinterpolation = false; } -void AnalogFilter::computefiltercoefs(void) +AnalogFilter::Coeff AnalogFilter::computeCoeff(int type, float cutoff, float q, + int stages, float gain, float fs, int &order) { - float tmp; + AnalogFilter::Coeff coeff; bool zerocoefs = false; //this is used if the freq is too high + const float samplerate_f = fs; + const float halfsamplerate_f = fs/2; + //do not allow frequencies bigger than samplerate/2 - float freq = this->freq; + float freq = cutoff; if(freq > (halfsamplerate_f - 500.0f)) { freq = halfsamplerate_f - 500.0f; zerocoefs = true; } + if(freq < 0.1f) freq = 0.1f; + //do not allow bogus Q if(q < 0.0f) q = 0.0f; + + float tmpq, tmpgain; if(stages == 0) { tmpq = q; tmpgain = gain; - } - else { + } else { tmpq = (q > 1.0f) ? powf(q, 1.0f / (stages + 1)) : q; tmpgain = powf(gain, 1.0f / (stages + 1)); } @@ -100,6 +107,9 @@ void AnalogFilter::computefiltercoefs(void) //the "Cookbook formulae for audio EQ" by Robert Bristow-Johnson //The original location of the Cookbook is: //http://www.harmony-central.com/Computer/Programming/Audio-EQ-Cookbook.txt + float tmp; + float tgp1; + float tgm1; switch(type) { case 0: //LPF 1 pole if(!zerocoefs) @@ -205,20 +215,15 @@ void AnalogFilter::computefiltercoefs(void) if(!zerocoefs) { tmpq = sqrtf(tmpq); beta = sqrtf(tmpgain) / tmpq; - tmp = (tmpgain + 1.0f) + (tmpgain - 1.0f) * cs + beta * sn; - - c[0] = tmpgain - * ((tmpgain - + 1.0f) - (tmpgain - 1.0f) * cs + beta * sn) / tmp; - c[1] = 2.0f * tmpgain - * ((tmpgain - 1.0f) - (tmpgain + 1.0f) * cs) / tmp; - c[2] = tmpgain - * ((tmpgain - + 1.0f) - (tmpgain - 1.0f) * cs - beta * sn) / tmp; - d[1] = -2.0f * ((tmpgain - 1.0f) + (tmpgain + 1.0f) * cs) - / tmp * -1.0f; - d[2] = ((tmpgain + 1.0f) + (tmpgain - 1.0f) * cs - beta * sn) - / tmp * -1.0f; + tgp1 = tmpgain + 1.0f; + tgm1 = tmpgain - 1.0f; + tmp = tgp1 + tgm1 * cs + beta * sn; + + c[0] = tmpgain * (tgp1 - tgm1 * cs + beta * sn) / tmp; + c[1] = 2.0f * tmpgain * (tgm1 - tgp1 * cs) / tmp; + c[2] = tmpgain * (tgp1 - tgm1 * cs - beta * sn) / tmp; + d[1] = -2.0f * (tgm1 + tgp1 * cs) / tmp * -1.0f; + d[2] = (tgp1 + tgm1 * cs - beta * sn) / tmp * -1.0f; } else { c[0] = tmpgain; @@ -230,20 +235,15 @@ void AnalogFilter::computefiltercoefs(void) if(!zerocoefs) { tmpq = sqrtf(tmpq); beta = sqrtf(tmpgain) / tmpq; - tmp = (tmpgain + 1.0f) - (tmpgain - 1.0f) * cs + beta * sn; - - c[0] = tmpgain - * ((tmpgain - + 1.0f) + (tmpgain - 1.0f) * cs + beta * sn) / tmp; - c[1] = -2.0f * tmpgain - * ((tmpgain - 1.0f) + (tmpgain + 1.0f) * cs) / tmp; - c[2] = tmpgain - * ((tmpgain - + 1.0f) + (tmpgain - 1.0f) * cs - beta * sn) / tmp; - d[1] = 2.0f * ((tmpgain - 1.0f) - (tmpgain + 1.0f) * cs) - / tmp * -1.0f; - d[2] = ((tmpgain + 1.0f) - (tmpgain - 1.0f) * cs - beta * sn) - / tmp * -1.0f; + tgp1 = tmpgain + 1.0f; + tgm1 = tmpgain - 1.0f; + tmp = tgp1 - tgm1 * cs + beta * sn; + + c[0] = tmpgain * (tgp1 + tgm1 * cs + beta * sn) / tmp; + c[1] = -2.0f * tmpgain * (tgm1 + tgp1 * cs) / tmp; + c[2] = tmpgain * (tgp1 + tgm1 * cs - beta * sn) / tmp; + d[1] = 2.0f * (tgm1 - tgp1 * cs) / tmp * -1.0f; + d[2] = (tgp1 - tgm1 * cs - beta * sn) / tmp * -1.0f; } else { c[0] = 1.0f; @@ -252,10 +252,16 @@ void AnalogFilter::computefiltercoefs(void) order = 2; break; default: //wrong type - type = 0; - computefiltercoefs(); + assert(false && "wrong type for a filter"); break; } + return coeff; +} + +void AnalogFilter::computefiltercoefs(void) +{ + coeff = AnalogFilter::computeCoeff(type, freq, q, stages, gain, + samplerate_f, order); } diff --git a/src/DSP/AnalogFilter.h b/src/DSP/AnalogFilter.h @@ -46,6 +46,9 @@ class AnalogFilter:public Filter d[3]; //Feed Back } coeff, oldCoeff; + static Coeff computeCoeff(int type, float cutoff, float q, int stages, + float gain, float fs, int &order); + private: struct fstage { float x1, x2; //Input History diff --git a/src/Params/FilterParams.cpp b/src/Params/FilterParams.cpp @@ -14,6 +14,7 @@ #include "FilterParams.h" #include "../Misc/Util.h" #include "../Misc/Time.h" +#include "../DSP/AnalogFilter.h" #include <cmath> #include <cstdio> #include <cstdlib> @@ -117,6 +118,25 @@ const rtosc::Ports FilterParams::ports = { FilterParams *obj = (FilterParams *) d.obj; d.reply(d.loc, "f", obj->getoctavesfreq()); }}, + {"response:", + 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) { + 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]); + } + }}, // "", NULL, [](){}},"/freq" //{"Pvowels#" FF_MAX_VOWELS "/formants#" FF_MAX_FORMANTS "/amp", // "", NULL, [](){}}, @@ -294,21 +314,18 @@ float FilterParams::getfreqpos(float freq) const */ float FilterParams::getformantfreq(unsigned char freq) const { - float result = getfreqx(freq / 127.0f); - return result; + return getfreqx(freq / 127.0f); } float FilterParams::getformantamp(unsigned char amp) const { - float result = powf(0.1f, (1.0f - amp / 127.0f) * 4.0f); - return result; + return powf(0.1f, (1.0f - amp / 127.0f) * 4.0f); } float FilterParams::getformantq(unsigned char q) const { //temp - float result = powf(25.0f, (q - 32.0f) / 64.0f); - return result; + return powf(25.0f, (q - 32.0f) / 64.0f); } diff --git a/src/Synth/Envelope.cpp b/src/Synth/Envelope.cpp @@ -90,7 +90,7 @@ void Envelope::releasekey() if(keyreleased) return; keyreleased = true; - if(forcedrelease != 0) + if(forcedrelease) t = 0.0f; }