/***************************************************/ /*! \class MoogVCF \brief STK MoogVCF filter This class implements Tim Stilson's MoogVCF filter that was used in SynthBuilder. 2007 Nick Porcaro */ /***************************************************/ #include "MoogVCF.h" #include #define UNITCLIP(x) ((x) > 1.0 ? (1.0) : ((x) < -1.0 ? -1.0 :(x))) #define SATURATE(x) (UNITCLIP(x)) #define CLAMP_ZERO(a) ((((a)<(StkFloat)1e-12)&&((a)>(StkFloat)-1e-12))?(StkFloat)0.0:(a)) // This separation table is intended for use with the compromise version // of the MoogVCF (i.e. with the open-loop zeros on 0.3). // The range of the p coef is [-1.0, 0.1]. // The start of the list corresponsds to p=-1, and the end with p=0.1 #define DEFAULT_SEPARATION_TABLE_LEN 111 static StkFloat defaultSeparationTable[DEFAULT_SEPARATION_TABLE_LEN] = { 1.0, 1.000759196, 1.001498153, 1.002216252, 1.002913029, 1.003587982, 1.004240607, 1.004870396, 1.005476844, 1.006059443, 1.006617686, 1.007151068, 1.007659081, 1.008141221, 1.008596986, 1.009025875, 1.009427389, 1.009801035, 1.010146319, 1.010462756, 1.010749862, 1.011007158, 1.011234173, 1.011430441, 1.0115955, 1.011728898, 1.01183019, 1.011898939, 1.011934715, 1.011937099, 1.011905681, 1.01184006, 1.011739847, 1.011604663, 1.011434142, 1.011227929, 1.010985682, 1.01070707, 1.010391779, 1.010039506, 1.009649964, 1.00922288, 1.008757996, 1.008255069, 1.007713873, 1.007134198, 1.00651585, 1.005858653, 1.005162446, 1.004427088, 1.003652454, 1.002838436, 1.001984947, 1.001091916, 1.00015929, 0.999187036, 0.9981751393, 0.9971236034, 0.9960324505, 0.9949017219, 0.9937314773, 0.9925217953, 0.9912727731, 0.9899845263, 0.988657189, 0.9872909138, 0.9858858712, 0.9844422498, 0.9829602557, 0.981440113, 0.9798820625, 0.9782863624, 0.9766532874, 0.9749831287, 0.9732761933, 0.9715328041, 0.9697532993, 0.9679380319, 0.9660873695, 0.9642016937, 0.9622813998, 0.9603268964, 0.9583386048, 0.9563169585, 0.9542624029, 0.9521753946, 0.9500564013, 0.9479059007, 0.9457243805, 0.9435123377, 0.941270278, 0.9389987157, 0.9366981724, 0.9343691773, 0.9320122663, 0.9296279815, 0.9272168706, 0.9247794867, 0.9223163876, 0.9198281353, 0.9173152954, 0.914778437, 0.9122181316, 0.9096349535, 0.9070294785, 0.9044022837, 0.9017539476, 0.8990850488, 0.8963961661, 0.8936878782, 0.8909607627 }; MoogVCF :: MoogVCF() : Function() { this->clear(); } MoogVCF :: ~MoogVCF() { } void MoogVCF :: clear() { int i = 4; sfb_ = 0; while (i--) { s[0] = 0; } } void MoogVCF :: getDefaultSeparationTable(StkFloat **ptr) { *ptr = defaultSeparationTable; } int MoogVCF :: defaultSeparationTableLen() { return DEFAULT_SEPARATION_TABLE_LEN; } StkFloat MoogVCF :: computeSample(StkFloat input) { printf ("Invalid call to MoogVCF::computeSample"); return 0; } StkFloat MoogVCF :: tick(StkFloat input, StkFloat gain, StkFloat freq) { int j; StkFloat A; StkFloat tmp; StkFloat pval; A = sfb_; pval = ((StkFloat)0.55)*(freq)-((StkFloat)0.45); A = (StkFloat)0.25*(input - A); for (j=0; j<4; j++) { tmp = s[j]; A = SATURATE(((StkFloat)1.538461538461538*((StkFloat)1.0+pval)*A) - pval*tmp); s[j] = (StkFloat)CLAMP_ZERO(A); A = SATURATE((StkFloat)0.3*tmp + A); } lastOutput_ = (StkFloat)A; A *= gain; sfb_ = (StkFloat)A; return lastOutput_; }