//----------------------------------------------------------------------------- // This is a virtual analog model of the Korg 35 LP filter. // The KorgThreeFiveLPF and VAOnePoleFilter are taken directly from // Will Pirkle's applications notes, and can be found at // // http://www.willpirkle.com/Downloads/AN-5Korg35_V3.pdf // // Ported by Owen Vallis 2015 // // This is a Chugin boilerplate, generated by chuginate! //----------------------------------------------------------------------------- // this should align with the correct versions of these ChucK files #include "chuck_dl.h" #include "chuck_def.h" // general includes #include #include //Pirckle files #include "KorgThreeFiveLPF.h" // declaration of chugin constructor CK_DLL_CTOR(wpkorg35_ctor); // declaration of chugin desctructor CK_DLL_DTOR(wpkorg35_dtor); // Resonance goes between [0...2) CK_DLL_MFUN(wpkorg35_setResonance); CK_DLL_MFUN(wpkorg35_getResonance); // Cuttoff is in Hz [0..Nyquist) CK_DLL_MFUN(wpkorg35_setCutoff); CK_DLL_MFUN(wpkorg35_getCutoff); // Saturation is a scalar gain and // can be used to drive the signal // into the non linear saturator CK_DLL_MFUN(wpkorg35_setSaturation); CK_DLL_MFUN(wpkorg35_getSaturation); // Enable non linear saturator CK_DLL_MFUN(wpkorg35_setNonLinearProcessing); CK_DLL_MFUN(wpkorg35_getNonLinearProcessing); // for Chugins extending UGen, this is mono synthesis function for 1 sample CK_DLL_TICK(wpkorg35_tick); // this is a special offset reserved for Chugin internal data t_CKINT wpkorg35_data_offset = 0; // class definition for internal Chugin data // (note: this isn't strictly necessary, but serves as example // of one recommended approach) class WPKorg35 { public: // constructor WPKorg35( t_CKFLOAT fs) { korgFilter.prepareForPlay(fs); } // for Chugins extending UGen SAMPLE tick( SAMPLE in ) { // default: this passes whatever input is patched into Chugin return korgFilter.doFilter(in); } float setResonance( t_CKFLOAT p ) { korgFilter.m_dK = p; korgFilter.updateFilters(); return p; } float getResonance() { return korgFilter.m_dK; } float setCutoff( t_CKFLOAT p ) { korgFilter.m_dFc = p; korgFilter.updateFilters(); return p; } float getCutoff() { return korgFilter.m_dFc; } float setSaturation( t_CKFLOAT p ) { korgFilter.m_dSaturation = p; return p; } float getSaturation() { return korgFilter.m_dSaturation; } bool setNonLinearProcessing( t_CKBOOL p ) { korgFilter.m_uNonLinearProcessing = p; return p; } bool getNonLinearProcessing() { return korgFilter.m_uNonLinearProcessing; } private: // instance data CKorgThreeFiveLPF korgFilter; }; // query function: chuck calls this when loading the Chugin // NOTE: developer will need to modify this function to // add additional functions to this Chugin CK_DLL_QUERY( WPKorg35 ) { // hmm, don't change this... QUERY->setname(QUERY, "WPKorg35"); // begin the class definition // can change the second argument to extend a different ChucK class QUERY->begin_class(QUERY, "WPKorg35", "UGen"); QUERY->doc_class(QUERY, "Virtual analog low pass filter based on Will Pirkle's Korg35 application notes"); QUERY->add_ex(QUERY, "filter/WPKorg35.ck"); // register the constructor (probably no need to change) QUERY->add_ctor(QUERY, wpkorg35_ctor); // register the destructor (probably no need to change) QUERY->add_dtor(QUERY, wpkorg35_dtor); // for UGen's only: add tick function QUERY->add_ugen_func(QUERY, wpkorg35_tick, NULL, 1, 1); // NOTE: if this is to be a UGen with more than 1 channel, // e.g., a multichannel UGen -- will need to use add_ugen_funcf() // and declare a tickf function using CK_DLL_TICKF QUERY->add_mfun(QUERY, wpkorg35_setResonance, "float", "resonance"); QUERY->add_arg(QUERY, "float", "arg"); QUERY->doc_func(QUERY, "Resonance goes between [0...2). "); QUERY->add_mfun(QUERY, wpkorg35_getResonance, "float", "resonance"); QUERY->doc_func(QUERY, "Get resonance [0 - 2)."); QUERY->add_mfun(QUERY, wpkorg35_setCutoff, "float", "cutoff"); QUERY->add_arg(QUERY, "float", "arg"); QUERY->doc_func(QUERY, "Cuttoff is in Hz [0..Nyquist). "); QUERY->add_mfun(QUERY, wpkorg35_getCutoff, "float", "cutoff"); QUERY->doc_func(QUERY, "Get cutoff in Hz [0..Nyquist)."); QUERY->add_mfun(QUERY, wpkorg35_setSaturation, "float", "saturation"); QUERY->add_arg(QUERY, "float", "arg"); QUERY->doc_func(QUERY, "Saturation is a scalar gain, and can be used to drive the non-linearity. "); QUERY->add_mfun(QUERY, wpkorg35_getSaturation, "float", "saturation"); QUERY->doc_func(QUERY, "Get saturation. Saturation is a scalar gain, and can be used to drive the non-linearity."); QUERY->add_mfun(QUERY, wpkorg35_setNonLinearProcessing, "int", "nonlinear"); QUERY->add_arg(QUERY, "int", "arg"); QUERY->doc_func(QUERY, "Enable non linear saturator. "); QUERY->add_mfun(QUERY, wpkorg35_getNonLinearProcessing, "int", "nonlinear"); QUERY->doc_func(QUERY, "Get non-linear saturator setting. 1 is enabled."); // this reserves a variable in the ChucK internal class to store // referene to the c++ class we defined above wpkorg35_data_offset = QUERY->add_mvar(QUERY, "int", "@wpk35_data", false); // end the class definition // IMPORTANT: this MUST be called! QUERY->end_class(QUERY); // wasn't that a breeze? return TRUE; } // implementation for the constructor CK_DLL_CTOR(wpkorg35_ctor) { // get the offset where we'll store our internal c++ class pointer OBJ_MEMBER_INT(SELF, wpkorg35_data_offset) = 0; // instantiate our internal c++ class representation WPKorg35 * bcdata = new WPKorg35(API->vm->get_srate(API, SHRED)); // store the pointer in the ChucK object member OBJ_MEMBER_INT(SELF, wpkorg35_data_offset) = (t_CKINT) bcdata; } // implementation for the destructor CK_DLL_DTOR(wpkorg35_dtor) { // get our c++ class pointer WPKorg35 * bcdata = (WPKorg35 *) OBJ_MEMBER_INT(SELF, wpkorg35_data_offset); // check it if( bcdata ) { // clean up delete bcdata; OBJ_MEMBER_INT(SELF, wpkorg35_data_offset) = 0; bcdata = NULL; } } // implementation for tick function CK_DLL_TICK(wpkorg35_tick) { // get our c++ class pointer WPKorg35 * c = (WPKorg35 *) OBJ_MEMBER_INT(SELF, wpkorg35_data_offset); // invoke our tick function; store in the magical out variable if(c) *out = c->tick(in); // yes return TRUE; } // example implementation for setter CK_DLL_MFUN(wpkorg35_setResonance) { // get our c++ class pointer WPKorg35 * bcdata = (WPKorg35 *) OBJ_MEMBER_INT(SELF, wpkorg35_data_offset); // set the return value RETURN->v_float = bcdata->setResonance(GET_NEXT_FLOAT(ARGS)); } // example implementation for getter CK_DLL_MFUN(wpkorg35_getResonance) { // get our c++ class pointer WPKorg35 * bcdata = (WPKorg35 *) OBJ_MEMBER_INT(SELF, wpkorg35_data_offset); // set the return value RETURN->v_float = bcdata->getResonance(); } // example implementation for setter CK_DLL_MFUN(wpkorg35_setCutoff) { // get our c++ class pointer WPKorg35 * bcdata = (WPKorg35 *) OBJ_MEMBER_INT(SELF, wpkorg35_data_offset); // set the return value RETURN->v_float = bcdata->setCutoff(GET_NEXT_FLOAT(ARGS)); } // example implementation for getter CK_DLL_MFUN(wpkorg35_getCutoff) { // get our c++ class pointer WPKorg35 * bcdata = (WPKorg35 *) OBJ_MEMBER_INT(SELF, wpkorg35_data_offset); // set the return value RETURN->v_float = bcdata->getCutoff(); } // example implementation for setter CK_DLL_MFUN(wpkorg35_setSaturation) { // get our c++ class pointer WPKorg35 * bcdata = (WPKorg35 *) OBJ_MEMBER_INT(SELF, wpkorg35_data_offset); // set the return value RETURN->v_float = bcdata->setSaturation(GET_NEXT_FLOAT(ARGS)); } // example implementation for getter CK_DLL_MFUN(wpkorg35_getSaturation) { // get our c++ class pointer WPKorg35 * bcdata = (WPKorg35 *) OBJ_MEMBER_INT(SELF, wpkorg35_data_offset); // set the return value RETURN->v_float = bcdata->getSaturation(); } // example implementation for setter CK_DLL_MFUN(wpkorg35_setNonLinearProcessing) { // get our c++ class pointer WPKorg35 * bcdata = (WPKorg35 *) OBJ_MEMBER_INT(SELF, wpkorg35_data_offset); // set the return value RETURN->v_float = bcdata->setNonLinearProcessing(GET_NEXT_FLOAT(ARGS)); } // example implementation for getter CK_DLL_MFUN(wpkorg35_getNonLinearProcessing) { // get our c++ class pointer WPKorg35 * bcdata = (WPKorg35 *) OBJ_MEMBER_INT(SELF, wpkorg35_data_offset); // set the return value RETURN->v_float = bcdata->getNonLinearProcessing(); }