#ifdef WIN32 #include "windows.h" #define DLGCLASS CSDelayDialog #define GUICLASS sdelay_gui #include "ospguiatl.h" #endif #define OSP_STD_CHANBUF_SIZE 2 // Support maximum 2 channels #include "osputil.h" #include class sdelay_dsp : public osp_std_plugin { public: OSP_INFO_BEGIN OSP_RATE_MINMAX(4000,52427) // these sample rates // sample rate is limited // due to fixed delay buffer size // (262144), and parameters, which // allow max 5 sec // Supported transforms // SUGGESTED IN/OUT OSP_TRANSFORM_AUD(1,1) // mono to mono OSP_SUGGEST OSP_TRANSFORM_AUD(1,2) // mono to stereo --> suggest it OSP_SUGGEST OSP_TRANSFORM_AUD(2,2) // stereo to stereo OSP_INFO_END // Parameters osp_param_delay delayL; /* 0 */ osp_param_volume feedbackL; /* 1 */ osp_param_volume wetL; /* 2 */ osp_param_volume dryL; /* 3 */ osp_param_check invL; /* 4 */ osp_param_delay delayR; /* 5 */ osp_param_volume feedbackR; /* 6 */ osp_param_volume wetR; /* 7 */ osp_param_volume dryR; /* 8 */ osp_param_check invR; /* 9 */ // Internal data float buffer[2][262144]; // delay buffer, normally is enough // for 5 sec delay for 44100 int index[2]; // circular pointer within delay buffer // Plugin information static const char *getstr(int idx) { static const char *data[]= { // 12345678901234567890 "wintermann-sdelay-1", // uniqueid (max 20 chars) "Stereo Delay", "1.0", // name and version "S-Delay", // short name "Alex E.Wintermann", // vendor "http://brest.linux.by", // support URL "Sample stereo delay plugin", // description "Copyright(C)2003 Alex E.Wintermann" // copyright }; return (((unsigned int)idx)>7)?NULL:data[idx]; } // constructor and parameter initialization // // note, that order of initialization should be the same // as the order of declaration. // // this example's GUI has parameter numbers hardcoded, so // changing order of these parameters may result in // unpredictable failures sdelay_dsp() : delayL(this,"Delay (L)",0.5f,0.0005f,5.0f),// default/min/max,in secs feedbackL(this,"Feedback(L)",.5f, 0.f, 1.0f), // 0=-INFdB 1.0=0dB wetL(this,"wet (L)",.5f), dryL(this,"dry (L)",.5f, 0.f, 2.0f), invL(this,"inv(L)",0), // checkbox, default=unchecked delayR(this,"Delay (R)",0.5f,0.0005f,5.0f),// default/min/max,in secs feedbackR(this,"Feedback(R)",.5f, 0.f, 1.0f), wetR(this,"wet (R)",.5f), dryR(this,"dry (R)",.5f, 0.f, 2.0f), invR(this,"inv(R)",0) { OSP_ALIAS(delayL) OSP_ALIAS(feedbackL) OSP_ALIAS(wetL) OSP_ALIAS(dryL) OSP_ALIAS(invL) OSP_ALIAS(delayR) OSP_ALIAS(feedbackR) OSP_ALIAS(wetR) OSP_ALIAS(dryR) OSP_ALIAS(invR) // NOTE: if you ever will want to assign parameter inside filter, // use paramvalue/paramint(param.id, newvalue) or // param.setfloat/setint // // do not use param = value, since that is not going to work // // normally, parameters should be only changed from GUI using // paramvalue and paramint // alter parameter options - in this case parameters // support automation of order2 (velocity and acceleration) dryL.automation(ORDER2); dryR.automation(ORDER2); wetL.automation(ORDER2); wetR.automation(ORDER2); feedbackL.automation(ORDER2); feedbackR.automation(ORDER2); // defaults osp_init_info(); // should be called BEFORE we want to set defaults nports(AUD_IN,2); nports(AUD_OUT,2); rate(44100); } // UNCOMMEND IF NEEDED // // void rateupdated() // { // osp_std_plugin::rateupdated(); // // // TODO: add code when rate is updated? // } // UNCOMMEND IF NEEDED // // void nportsupdated(int type,int n) // { // osp_std_plugin::nportsupdated(type,n); // // // TODO: add code when number of ports changed? // } void reset() // initialize buffers { memset(index,0,sizeof(index)); memset(buffer,0,sizeof(buffer)); } // processing function // // osp_std_plugin::processf() function parses events, splits // audio to blocks (between events) and calls this function // void processBLOCK(int64 stamp,float **in, int instep, float **out, int outstep, int sz) { int nch=nports(AUD_IN); if ((nch==1)&&(nports(AUD_OUT)==2)) { in[1]=in[0]; // create shadow of first buffer // array won't overflow, since // due to osp_std_plugin implementation // it will be sized [OSP_STD_CHANBUF_SIZE] // note, that due to later implementation // (out[0] is written before in[1] is read), // this function is not inplace-processing compatible nch=2; } int t,k; float dry[]={dryL,dryR}; float dryv[]={dryL.velocity,dryR.velocity}; float drya[]={dryL.accel,dryR.accel}; float wet[]={wetL,wetR}; float wetv[]={wetL.velocity,wetR.velocity}; float weta[]={wetL.accel,wetR.accel}; float fb[]={feedbackL,feedbackR}; float fbv[]={feedbackL.velocity,feedbackR.velocity}; float fba[]={feedbackL.accel,feedbackR.accel}; int delay[]={(int)(delayL*rate()),(int)(delayR*rate())}; if (invL) {fb[0]=-fb[0];fbv[0]=-fbv[0];fba[0]=-fba[0];} if (invR) {fb[1]=-fb[1];fbv[1]=-fbv[1];fba[1]=-fba[1];} if (bypass()) { osp_std_plugin::processBLOCK(stamp,in,instep,out,outstep,sz); return; } for(t=0;t