[IPLUG/EXAMPLES] fix IPlugChunks example
[wdl/wdl-ol.git] / IPlugExamples / IPlugPolySynth / IPlugPolySynthDSP.h
blob196c2e69c584fc93a22765e4e3edfa9ae6d8f6de
2 #ifndef __IPLUGPOLYSYNTHDSP__
3 #define __IPLUGPOLYSYNTHDSP__
5 const double ENV_VALUE_LOW = 0.000001; // -120dB
6 const double ENV_VALUE_HIGH = 0.999;
7 const double MIN_ENV_TIME_MS = 0.5;
8 const double MAX_ENV_TIME_MS = 60000.;
10 inline double midi2CPS(double pitch)
12 return 440. * pow(2., (pitch - 69.) / 12.);
15 inline double fastClip(double x, double low, double high)
17 double x1 = fabs(x-low);
18 double x2 = fabs(x-high);
19 x = x1+low+high-x2;
21 return x * 0.5;
24 inline double wrap(double x, double low = 0., double high = 1.)
26 while (x >= high) x -= high;
27 while (x < low) x += high - low;
29 return x;
32 inline double lerp(double phase, const double* buffer, unsigned long int mask)
34 const int intPart = (int) phase;
35 const double fracPart = phase-intPart;
37 const double a = buffer[intPart & mask];
38 const double b = buffer[(intPart+1) & mask];
40 return a + (b - a) * fracPart;
43 inline double calcIncrFromTimeLinear(double timeMS, double sr)
45 if (timeMS <= 0.) return 0.;
46 else return (1./sr) / (timeMS/1000.);
49 struct CWTOscState
51 double mPhase; // float phase (goes between 0. and 1.)
52 double mPhaseIncr; // freq * mPhaseStep
54 CWTOscState()
56 mPhase = 0.;
57 mPhaseIncr = 0.;
60 } WDL_FIXALIGN;
62 class CWTOsc
64 protected:
65 const double* mLUT; // pointer to waveform lookup table, const because the oscilator doesn't change the table data
66 unsigned long int mLUTSize; // wavetable size
67 unsigned long int mLUTSizeM; // wavetable Mask (size -1)
68 double mLUTSizeF; // float version
70 public:
72 CWTOsc(const double* LUT, unsigned long int LUTSize)
74 setLUT(LUT, LUTSize);
77 ~CWTOsc() {}
79 void setLUT(const double* LUT, unsigned long int LUTSize)
81 mLUTSize = LUTSize;
82 mLUTSizeM = LUTSize-1;
83 mLUTSizeF = (double) LUTSize;
84 mLUT = LUT;
87 inline double process(CWTOscState* pState)
89 pState->mPhase = wrap(pState->mPhase, 0., 1.);
90 const double output = lerp(pState->mPhase * mLUTSizeF, mLUT, mLUTSizeM);
91 pState->mPhase += pState->mPhaseIncr;
93 return output;
96 } WDL_FIXALIGN;
98 enum EADSREnvStage
100 kIdle = 0,
101 kStageAttack,
102 kStageDecay,
103 kStageSustain,
104 kStageRelease,
107 struct CADSREnvLState
109 double mEnvValue; // current value of the envelope
110 int mStage; // idle, attack, decay, sustain, release
111 double mLevel; // envelope depth
112 double mPrev;
113 double mReleaseLevel;
115 CADSREnvLState()
117 mEnvValue = 0.;
118 mStage = kIdle;
119 mLevel = 0.;
120 mReleaseLevel = 0.;
121 mPrev = 0.;
124 } WDL_FIXALIGN;
126 class CADSREnvL
128 protected:
129 double mAttackIncr, mDecayIncr, mReleaseIncr;
130 double mSustainLevel, mReleaseLevel;
131 double mPrev;
132 double mSampleRate;
134 public:
135 CADSREnvL()
137 mSustainLevel = 1.;
138 mReleaseLevel = 0.;
139 mPrev = 0.;
140 mSampleRate = 44100.;
142 setStageTime(kStageAttack, 1.);
143 setStageTime(kStageDecay, 100.);
144 setStageTime(kStageRelease, 20.);
147 void setStageTime(int stage, double timeMS)
149 const double incr = calcIncrFromTimeLinear(fastClip(timeMS, MIN_ENV_TIME_MS, MAX_ENV_TIME_MS), mSampleRate);
151 switch(stage)
153 case kStageAttack:
154 mAttackIncr = incr;
155 break;
156 case kStageDecay:
157 mDecayIncr = incr;
158 break;
159 case kStageRelease:
160 mReleaseIncr = incr;
161 break;
162 default:
163 //error
164 break;
168 void setSustainLevel(double sustainLevel)
170 mSustainLevel = sustainLevel;
173 virtual void setSampleRate(double sr)
175 mSampleRate = sr;
178 inline double process(CADSREnvLState* pS)
180 double result = 0.;
182 switch(pS->mStage)
184 case kIdle:
185 result = pS->mEnvValue;
186 break;
187 case kStageAttack:
188 pS->mEnvValue += mAttackIncr;
189 if (pS->mEnvValue > ENV_VALUE_HIGH || mAttackIncr == 0.)
191 pS->mStage = kStageDecay;
192 pS->mEnvValue = 1.0;
194 result = pS->mEnvValue;
195 break;
196 case kStageDecay:
197 pS->mEnvValue -= mDecayIncr;
198 result = (pS->mEnvValue * (1.-mSustainLevel)) + mSustainLevel;
199 if (pS->mEnvValue < ENV_VALUE_LOW)
201 pS->mStage = kStageSustain;
202 pS->mEnvValue = 1.;
203 result = mSustainLevel;
205 break;
206 case kStageSustain:
207 result = mSustainLevel;
208 break;
209 case kStageRelease:
210 pS->mEnvValue -= mReleaseIncr;
211 if(pS->mEnvValue < ENV_VALUE_LOW || mReleaseIncr == 0.)
213 pS->mStage = kIdle;
214 pS->mEnvValue = 0.0;
216 result = pS->mEnvValue * pS->mReleaseLevel;
217 break;
218 default:
219 result = pS->mEnvValue;
220 break;
223 pS->mPrev = result;
225 return result * pS->mLevel;
228 } WDL_FIXALIGN ;
230 // http://www.musicdsp.org/archive.php?classid=3#257
232 //class CParamSmooth
234 //public:
235 // CParamSmooth() { a = 0.99; b = 1. - a; z = 0.; };
236 // ~CParamSmooth() {};
237 // inline double Process(double in) { z = (in * b) + (z * a); return z; }
238 //private:
239 // double a, b, z;
240 //};
242 struct CVoiceState
244 CWTOscState mOsc_ctx;
245 CADSREnvLState mEnv_ctx;
246 //bool mLastBusy;
247 int mKey;
249 CVoiceState()
251 mKey = -1;
252 //mLastBusy = false;
255 bool GetBusy()
257 if (mEnv_ctx.mStage == kIdle)
258 return false;
259 else
260 return true;
265 #endif //__IPLUGPOLYSYNTHDSP__