/*----------------------------------------------------------------------------- File: Modules.hpp Description: Library of useful C++ modules such as delay lines, filters oscillators, etc. Author: Jasmin Frenette Date: 11/27/2000 -----------------------------------------------------------------------------*/ #ifndef _MODULES_HPP #define _MODULES_HPP #define PI 3.1415926535897932384626433832795 #define TWOPI 6.28318530717958647692528676655901 #define PI_DIV_BY_2 1.57079632679489661923132169163975 #define SCALING_FACTOR 0.0000000004656612874161594f // 2/(2^32-1) class Module { public: Module() {} ~Module() {} virtual void Suspend() {} virtual long GetMem() {return 0;} void UpdateMemory(long* &pMem, long newSize); void UpdateMemory(float* &pMem, long newSize); void UpdateMemory(float** &pMem, long newSize); }; /* //----------------------------------------------------------------------------- // 1st order FIR Low Pass Filter Module (version a) //----------------------------------------------------------------------------- in -----[b0]-->0-------------> out ^ | | [z-1] | | --[-a1]-- */ class MLPF1a : public Module { public: MLPF1a(); ~MLPF1a() {} void SetCoeffs(float in_b0, float in_a1); void GetCoeffs(float* out_b0, float* out_a1); void Suspend(void); void Process(float &in, float &out){ out = in*b0 - buffer*a1; buffer = out; } private: float buffer; float b0, a1; // filter coefficients }; /* //----------------------------------------------------------------------------- // 1st order FIR Low Pass Filter Module (version b) //----------------------------------------------------------------------------- in --[k]---------->0------------> out | ^ | [z-1] | [z-1] | | | -------^--[-a1]-- */ class MLPF1b: public Module { public: MLPF1b(); ~MLPF1b() {} void SetCoeffs(float in_k, float in_a1); void GetCoeffs(float* out_k, float* out_a1); void Suspend(void); void Process(float &in, float &out){ float temp; temp = in * k; out = temp + bufferX - bufferY*a1; bufferX = temp; bufferY = out; } private: float bufferX, bufferY; float k, a1; // filter coefficients }; /* //----------------------------------------------------------------------------- // 2nd order FIR Low Pass Filter Module //----------------------------------------------------------------------------- in --[k]--------->0------------> out | ^ | [z-1] | [z-1] | | | --[b1]--^--[-a1]-- | | | [z-1] | [z-1] | | | --------^--[-a2]-- */ class MLPF2b: public Module { public: MLPF2b(); ~MLPF2b() {} void SetCoeffs(double in_k, double in_b1, double in_a1, double in_a2); void GetCoeffs(double* out_k, double* out_b1, double* out_a1, double* out_a2); void Suspend(void); void Process(double &in, double &out){ double temp; temp = in * k; out = temp + bufferX1*b1 + bufferX2 - bufferY1*a1 - bufferY2*a2; bufferX2 = bufferX1; bufferX1 = temp; bufferY2 = bufferY1; bufferY1 = out; } private: double k, b1, a1, a2; // filter coefficients double bufferX1, bufferX2, bufferY1, bufferY2; }; //----------------------------------------------------------------------------- // Modulator (base class) //----------------------------------------------------------------------------- class MModulator { public: MModulator() {} ~MModulator() {} virtual float GetCurValue() = 0; }; //----------------------------------------------------------------------------- // Sinusoidal Oscillator Module //----------------------------------------------------------------------------- class MSinOsc : public MModulator { public: MSinOsc(); ~MSinOsc(); void SetFreq(float freq, float sampleRate, float phase); float GetFreq(); void Suspend(void); float GetCurValue(void){ double out; out = a * buffer1 - buffer2; // Two special cases to avoid instability due to // round-off errors. if(out >= 1.0) { out = 1.0; buffer2 = resetBuffer2; } else if(out <= -1.0) { out = -1.0; buffer2 = -resetBuffer2; } else buffer2 = buffer1; buffer1 = out; return (float) out; } private: float fFreq; // Osc. Frequency (in Hertz) double a; // Coefficient: a=2*cos(w) double buffer1; // Osc. buffer1 double buffer2; // Osc. buffer2 double resetBuffer2; // Osc. reset value of buffer2 }; //----------------------------------------------------------------------------- // Random Number Generator Module // x(n+1) = (ax(n) + c) mod 2^32 //----------------------------------------------------------------------------- class MRNG : public MModulator { public: MRNG(); ~MRNG(); void SetParams(unsigned int in_a, unsigned int in_c, unsigned int in_seed); void GetParams(unsigned int* out_a, unsigned int* out_c, unsigned int* out_seed); void Suspend(void); float GetCurValue(void){ float out; // Generate a random number from 0 to (2^32)-1 buffer = a * buffer + c; // Scale to [-1.0, 1.0] out = (float)buffer * SCALING_FACTOR - 1.0f; return out; } private: unsigned long a, c, seed; unsigned long buffer; }; //----------------------------------------------------------------------------- // Low-Pass Filtered (4rth order) Modulator //----------------------------------------------------------------------------- class MLPFMod : public MModulator { public: MLPFMod(); ~MLPFMod(); void SetRefreshRate(long rate); void SetModulator(MModulator* mod); void SetLPF1(MLPF2b* lpf); void SetLPF2(MLPF2b* lpf); long GetRefreshRate(void); MModulator* GetModulator(void); MLPF2b* GetLPF1(void); MLPF2b* GetLPF2(void); float GetCurValue(void); private: long lRate; // Refresh rate (in samples) MModulator* pMod; // modulator MLPF2b* pLPF1; // 1st Low-Pass Filter MLPF2b* pLPF2; // 2nd Low-Pass Filter long index; }; //----------------------------------------------------------------------------- // Delay Line Module //----------------------------------------------------------------------------- class MDelayLine : public Module { public: MDelayLine(); ~MDelayLine(); void SetMaxDelay(long delay); long GetMaxDelay(void); void Suspend(void); long GetMem(void); void Push(float &value){ *(pfInPos) = value; if(++pfInPos >= pfBufferEnd) pfInPos -= lBufferSize; } float GetLast(void){ float out = *(pfOutPos); if(++pfOutPos >= pfBufferEnd) pfOutPos -= lBufferSize; return out; } float GetAt(long index){ if(index>=lBufferSize) DebugBreak(); float* pfRealIndex = pfInPos - index - 1; // Minus one because input has // been incremented after the push if(pfRealIndex < pfBuffer) pfRealIndex += lBufferSize; return *(pfRealIndex); } protected: // Buffer parameters float *pfBuffer, *pfBufferEnd; long lBufferSize; float *pfInPos, *pfOutPos; long lMaxDelay; // delay (in samples) }; //----------------------------------------------------------------------------- // Modulated Delay Line Module (base class) //----------------------------------------------------------------------------- class MModDelayLine : public MDelayLine { public: MModDelayLine(); ~MModDelayLine() {} virtual float GetCurValue(void) = 0; void SetNomDelay(long delay); void SetModDepth(long depth); void SetModulator(MModulator* mod); long GetNomDelay(void); long GetModDepth(void); MModulator* GetModulator(void); protected: // Buffer parameters float fModOutPos; // modulation output position long lNomDelay; // nominal delay (in samples) long lModDepth; // modulation depth (in samples) MModulator* pMod; // modulation module }; //----------------------------------------------------------------------------- // Simplified 1st order All-Pass Modulated Delay Line Module //----------------------------------------------------------------------------- class MSAP1ModDelayLine : public MModDelayLine { public: MSAP1ModDelayLine() {buffer = 0;} ~MSAP1ModDelayLine() {} float GetCurValue(void); private: float buffer; }; //----------------------------------------------------------------------------- // 1st order All-Pass Modulated Delay Line Module //----------------------------------------------------------------------------- class MAP1ModDelayLine : public MModDelayLine { public: MAP1ModDelayLine() {buffer = 0;} ~MAP1ModDelayLine() {} float GetCurValue(void); private: float buffer; }; //----------------------------------------------------------------------------- // 1st order Low-Pass Modulated Delay Line Module //----------------------------------------------------------------------------- class MLP1ModDelayLine : public MModDelayLine { public: MLP1ModDelayLine() {} ~MLP1ModDelayLine() {} float GetCurValue(void); }; //----------------------------------------------------------------------------- // 2nd order Low-Pass Modulated Delay Line Module //----------------------------------------------------------------------------- class MLP2ModDelayLine : public MModDelayLine { public: MLP2ModDelayLine() {} ~MLP2ModDelayLine() {} float GetCurValue(void); }; //----------------------------------------------------------------------------- // 3rd order Low-Pass Modulated Delay Line Module //----------------------------------------------------------------------------- class MLP3ModDelayLine : public MModDelayLine { public: MLP3ModDelayLine() {} ~MLP3ModDelayLine() {} float GetCurValue(void); }; //----------------------------------------------------------------------------- // 4th order Low-Pass Modulated Delay Line Module //----------------------------------------------------------------------------- class MLP4ModDelayLine : public MModDelayLine { public: MLP4ModDelayLine() {} ~MLP4ModDelayLine() {} float GetCurValue(void); }; //----------------------------------------------------------------------------- // Simplified Variable Rate 1st order All-Pass Modulated Delay Line Module //----------------------------------------------------------------------------- class MSVRAP1ModDelayLine : public MModDelayLine { public: MSVRAP1ModDelayLine() { index = 0; lModRate = 1; buffer = 0; fOne_m_D = 0; } ~MSVRAP1ModDelayLine() {} float GetCurValue(void); void SetModRate(long rate); long GetModRate(void); private: long index, lModRate; float fOne_m_D; float buffer; }; #endif // _MODULES_HPP