Main Page   Modules   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

/root/src/subsynth/syn/Util/Generator.h

Go to the documentation of this file.
00001 #ifndef SYN_GENERATOR_H
00002 #define SYN_GENERATOR_H
00003 
00004 #include <syn/Util/Math.h>
00005 
00027 namespace syn
00028 {
00032    class TriangleOsc
00033    {
00034    public:
00035       TriangleOsc() : mFreq( 80.0f ), mSamplingRateHz( 44100.0f ), dp( 1 )
00036       {
00037          this->reset();
00038       }
00039 
00042       inline float generate()
00043       {
00044          const float float_max = 1.0f;
00045          const float float_min = -1.0f;
00046 
00047          p += dp;
00048          if (p > float_max)
00049          {
00050             p = float_max;
00051             dp = -dp;
00052          }
00053          else if (p < float_min)
00054          {
00055             p = float_min;
00056             dp = -dp;
00057          }
00058 
00059          return p;
00060       }
00061       
00066       inline unsigned int samplesPerOsc()
00067       {
00068          // get samples per oscillation
00069          // mSamplingRateHz = samples/sec  and  mFreq = osc / sec
00070          // samples/sec  *  sec / osc
00071          return (unsigned int)(mSamplingRateHz / mFreq);
00072       }
00073 
00076       inline void setFreq( float freqHz )
00077       { 
00078          if (freqHz != mFreq)
00079          {
00080             mFreq = freqHz;
00081             on_change_of_freq_or_samprate();
00082          }
00083       }
00084 
00088       inline void setSampRate( float samplingRateHz )
00089       { 
00090          if (samplingRateHz != mSamplingRateHz)
00091          {
00092             mSamplingRateHz = samplingRateHz;
00093             on_change_of_freq_or_samprate();
00094          }
00095       }
00096 
00099       inline void reset()
00100       {
00101          p = 0.0f;
00102          dp = 1.0f;
00103          on_change_of_freq_or_samprate();
00104       }
00105 
00106    private:
00108       inline void on_change_of_freq_or_samprate()
00109       {
00110          // TODO: document this magic number... 
00111          //       it causes the generated wav to match 
00112          //       soundforge and other func gens.
00113          float delta = 2.00495f * mFreq / mSamplingRateHz;
00114 
00115          // set frequency...
00116          // 2 is the range of numbers dp will span [-1..1]
00117          const float float_range = 2.0f;
00118          if (dp > 0.0f) // preserve the direction we've been going
00119             dp = delta * float_range; 
00120          else
00121             dp = -delta * float_range;
00122       }
00123 
00124       /* func gen attributes. */
00125       float mFreq, mSamplingRateHz;
00126       float p, dp;
00127    };
00128 
00129 
00132    class SineOsc
00133    {
00134    public:
00135       SineOsc() : mFreq( 80.0f ), mSamplingRateHz( 44100.0f )
00136       {
00137          this->reset();
00138       }
00139 
00142       inline float generate()
00143       {
00144          const float float_range = 2.0f;
00145          s[0] = s[0] - a * s[1];   // sine == s[0]
00146          s[1] = s[1] + a * s[0];   // cos == s[1]
00147          return s[0] * float_range;
00148       }
00149       
00154       inline unsigned int samplesPerOsc()
00155       {
00156          // get samples per oscillation
00157          // mSamplingRateHz = samples/sec  and  mFreq = osc / sec
00158          // samples/sec  *  sec / osc
00159          return (unsigned int)(mSamplingRateHz / mFreq);
00160       }
00161 
00164       inline void setFreq( float freqHz )
00165       { 
00166          if (freqHz != mFreq)
00167          {
00168             mFreq = freqHz;
00169             on_change_of_freq_or_samprate();
00170          }
00171       }
00172 
00176       inline void setSampRate( float samplingRateHz )
00177       { 
00178          if (samplingRateHz != mSamplingRateHz)
00179          {
00180             mSamplingRateHz = samplingRateHz;
00181             on_change_of_freq_or_samprate();
00182          }
00183       }
00184 
00187       inline void reset()
00188       {
00189          s[0] = 0.5f; // sine yaxis begin
00190          s[1] = 0.0f; // cos yaxis begin
00191          on_change_of_freq_or_samprate();
00192       }
00193 
00194    private:
00196       inline void on_change_of_freq_or_samprate()
00197       {
00198          const float float_range = 2.0f;
00199          a = float_range * Math::sin( Math::PI * mFreq / mSamplingRateHz );
00200       }
00201 
00202       /* func gen attributes. */
00203       float mFreq, mSamplingRateHz;
00204       float s[2], a;
00205    };
00206 
00210    class SquareOsc
00211    {
00212    public:
00213       SquareOsc() : mFreq( 80.0f ), mSamplingRateHz( 44100.0f )
00214       {
00215          this->reset();
00216       }
00217 
00220       inline float generate()
00221       {
00222          (*((unsigned long *)&one)) &= 0x7FFFFFFF; // mask out sign bit 
00223          (*((unsigned long *)&one)) |= (intOver & 0x80000000); 
00224          intOver += intIncr;
00225          return float( long( intOver ) ) / float( long( 0x7FFFFFFF ) );
00226       }
00227       
00232       inline unsigned int samplesPerOsc()
00233       {
00234          // get samples per oscillation
00235          // mSamplingRateHz = samples/sec  and  mFreq = osc / sec
00236          // samples/sec  *  sec / osc
00237          return (unsigned int)( mSamplingRateHz / mFreq );
00238       }
00239 
00242       inline void setFreq( float freqHz )
00243       { 
00244          if (freqHz != mFreq)
00245          {
00246             mFreq = freqHz;
00247             on_change_of_freq_or_samprate();
00248          }
00249       }
00250 
00254       inline void setSampRate( float samplingRateHz )
00255       { 
00256          if (samplingRateHz != mSamplingRateHz)
00257          {
00258             mSamplingRateHz = samplingRateHz;
00259             on_change_of_freq_or_samprate();
00260          }
00261       }
00262 
00265       inline void reset()
00266       {
00267          one = 1.0f; 
00268          on_change_of_freq_or_samprate();
00269       }
00270 
00271    private:
00273       inline void on_change_of_freq_or_samprate()
00274       {
00275          intOver = 0L;// 4294967296
00276          intIncr = ((unsigned long)0xffffffff) / (unsigned long)(mSamplingRateHz / mFreq); 
00277       }
00278 
00279       /* func gen attributes. */
00280       float mFreq, mSamplingRateHz;
00281       unsigned long intOver, intIncr;
00282       float one;
00283    };
00284 
00285 
00286 
00289    class WhiteNoiseOsc
00290    {
00291    public:
00292       WhiteNoiseOsc() : mSamplingRateHz( 44100.0f )
00293       {
00294          this->reset();
00295          // 16 == rows, 24 == bits... ?
00296          long pmax = 0x7fffffff; // largest
00297          mScalar = 1.0f / pmax;
00298       }
00299 
00302       inline float generate()
00303       {
00304          // Calculate pseudo-random 32 bit number based on linear 
00305          // congruential method... scale it to our -1..1 float32 range...
00306          return (mScalar * (float)(long)(mRand = (mRand * 196314165) + 907633515));
00307       }
00308       
00311       inline void reset()
00312       {
00313          mRandSeed = 22222;
00314          mRand = mRandSeed;
00315       }
00316 
00322       inline unsigned int samplesPerOsc()
00323       {
00324          // just return something (1sec)...
00325          return (unsigned int)( mSamplingRateHz );
00326       }
00327 
00331       inline void setFreq( float freqHz ) {}
00332 
00337       inline void setSampRate( float samplingRateHz )
00338       { 
00339          mSamplingRateHz = samplingRateHz;
00340       }
00341 
00342    private:
00343       enum 
00344       {
00345          mRandomRows = 16,
00346          mRandomBits = 24
00347       };
00348       /* func gen attributes. */
00349       unsigned long mRandSeed, mRand;
00350       float mSamplingRateHz;
00351       float mScalar;       // Used to scale within range of -1.0 to +1.0
00352    };
00353 
00356    class PinkNoiseOsc
00357    {
00358    public:
00359       PinkNoiseOsc() : mSamplingRateHz( 44100.0f ), 
00360                        mRandomBits( 24 ), 
00361                        mRandomShift( sizeof( long ) * 8 - mRandomBits )
00362       {
00363          this->reset();
00364       }
00365 
00368       inline float generate()
00369       {
00370          long newRandom;
00371          
00372          /* Increment and mask index. */
00373          mIndex = (mIndex + 1) & mIndexMask;
00374          
00375          /* If index is zero, don't update any random values. */
00376          if( mIndex != 0 ) 
00377          {
00378             /* Determine how many trailing zeros in PinkIndex. */
00379             /* This algorithm will hang if n==0 so test first. */
00380             int numZeros = 0;
00381             int n = mIndex;
00382             while ((n & 1) == 0) 
00383             {
00384                n = n >> 1;
00385                ++numZeros;
00386             }
00387 
00388             /* Replace the indexed ROWS random value.
00389              * Subtract and add back to RunningSum instead of adding all the random
00390              * values together. Only one changes each time.
00391              */
00392             mRunningSum -= mRows[numZeros];
00393             newRandom = ((long)this->generateWhiteNoise()) >> mRandomShift;
00394             mRunningSum += newRandom;
00395             mRows[numZeros] = newRandom;
00396          }
00397      
00398          /* Add extra white noise value. */
00399          newRandom = ((long)this->generateWhiteNoise()) >> mRandomShift;
00400          
00401          /* Scale the sum to our -1..1 range */
00402          return mScalar * (float)(mRunningSum + newRandom);
00403       }
00404       
00407       inline void reset()
00408       {
00409          this->initializeWhiteNoise();
00410          this->initializePinkNoise();
00411       }
00412 
00418       inline unsigned int samplesPerOsc()
00419       {
00420          // just return something (1sec)...
00421          return (unsigned int)( mSamplingRateHz );
00422       }
00423 
00427       inline void setFreq( float freqHz ) {}
00428 
00433       inline void setSampRate( float samplingRateHz )
00434       { 
00435          mSamplingRateHz = samplingRateHz;
00436       }
00437 
00438    private:
00439       inline void initializeWhiteNoise()
00440       {
00441          mRandSeed = 22222;
00442          mRand = mRandSeed;
00443       }
00444       inline unsigned long generateWhiteNoise()
00445       {
00446          // Calculate pseudo-random 32 bit number based on linear
00447          // congruential method.
00448          return mRand = (mRand * 196314165) + 907633515;
00449       }
00450 
00451       /* Setup PinkNoise structure for N rows of generators. */
00452       void initializePinkNoise() 
00453       {
00454          int i;
00455          mIndex = 0;
00456          mIndexMask = (1 << mRandomRows) - 1;
00457 
00458          /* Calculate maximum possible signed random value. Extra 1 for white noise always added. */
00459          long pmax = (mRandomRows + 1) * (1 << (mRandomBits - 1));
00460          mScalar = 1.0f / pmax;
00461          
00462          /* Initialize rows. */
00463          for( i = 0; i < mRandomRows; ++i )
00464          {
00465             mRows[i] = 0;
00466          }
00467          mRunningSum = 0;
00468       }
00469 
00470       /* func gen attributes. */
00471       enum
00472       {
00473          mRandomRows = 16
00474       };
00475       float mSamplingRateHz;
00476       const int mRandomBits;
00477       const int mRandomShift;
00478       unsigned long mRandSeed, mRand;
00479       long      mRows[mRandomRows];     
00480       long      mRunningSum;   // Used to optimize summing of generators.
00481       int       mIndex;        // Incremented each sample.
00482       int       mIndexMask;    // Index wrapped by ANDing with this mask.
00483       float     mScalar;       // Used to scale within range of -1.0 to +1.0 
00484    };
00485 
00491    class AdsrEnvOsc
00492    {
00493    public:
00494       AdsrEnvOsc() : mSamplingRateHz( 44100.0f ), 
00495                      mAttackTime( 0.01f ), 
00496                      mDecayTime( 0.03f ), 
00497                      mSustainLevel( 0.5f ), 
00498                      mReleaseTime( 0.04f )
00499       {
00500          this->reset();
00501       }
00502 
00503       inline float lerp( const float lerpVal, const float from, const float to )
00504       {
00505           return from + (to - from) * lerpVal;
00506       }
00507 
00511       inline float generate()
00512       {
00513          // auto release() based on specified duration
00514          if (mDurationTime != -1)
00515          {
00516             ++mTotalTimeSamps;
00517             if (mTotalTimeSamps > mDurationSamps)
00518             {
00519                this->release();
00520             }
00521          }
00522          
00523          float count = mCount;// prev count...
00524          switch (mState)
00525          {
00526          case 0: // attack
00527             if (mCount++ >= mAttackSamps) 
00528             {
00529                mState = 1;
00530                mCount = 0;
00531             }
00532             return lerp( count / mAttackSamps, 0.0f, 1.0f );
00533             break;
00534          case 1: // decay
00535             if (mCount++ >= mDecaySamps)
00536             {
00537                mState = 2;
00538                mCount = 0;
00539             }
00540             return lerp( count / mDecaySamps, 1.0f, mSustainLevel );
00541             break;
00542          case 2: // sustain
00543             if (mReleased)
00544             {
00545                mState = 3;
00546                mReleased = false;
00547             }
00548             return mSustainLevel;
00549             break;
00550          case 3: // release
00551             if (mCount++ >= mReleaseSamps)
00552             {
00553                mState = 4;
00554                mCount = 0;
00555             }
00556             return lerp( count / mReleaseSamps, mSustainLevel, 0.0f );
00557             break;
00558          default:
00559          case 4: // done...
00560             return 0.0f;
00561             break;
00562          }
00563       }
00564       
00571       void trigger( float duration = -1 )
00572       {
00573          mState = 0;
00574          mDurationTime = duration;
00575          mDurationSamps = mDurationTime * mSamplingRateHz;
00576          mTotalTimeSamps = 0;
00577       }
00578 
00579       void release()
00580       {
00581          mReleased = true;
00582       }
00583 
00591       void setAttackTime( float t )
00592       {
00593          mAttackTime = t;
00594          // samps = sec * samps/sec
00595          mAttackSamps = mAttackTime * mSamplingRateHz;
00596       }
00597       float getAttackTime() { return mAttackTime; }
00598 
00606       void setDecayTime( float t )
00607       {
00608          mDecayTime = t;
00609          // samps = sec * samps/sec
00610          mDecaySamps = mDecayTime * mSamplingRateHz;
00611       }
00612       float getDecayTime() { return mDecayTime; }
00613 
00622       void setSustainLevel( float sustain )
00623       {
00624          mSustainLevel = sustain;
00625       }
00626       float getSustainLevel() { return mSustainLevel; }
00627 
00635       void setReleaseTime( float t )
00636       {
00637          mReleaseTime = t;
00638          mReleaseSamps = mReleaseTime * mSamplingRateHz;
00639       }
00640 
00641       float getReleaseTime() { return mReleaseTime; }
00642       
00647       inline unsigned int samplesPerOsc()
00648       {
00649          // get samples per oscillation
00650          // mSamplingRateHz = samples/sec  and  mFreq = osc / sec
00651          // samples/sec  *  sec / osc
00652 
00653          //sustain can go infinately, just choose something.
00654          return (unsigned int)( mAttackSamps + mDecaySamps + mDecaySamps + mReleaseSamps ); 
00655       }
00656 
00658       inline void setFreq( float freqHz ) {}
00659 
00663       inline void setSampRate( float samplingRateHz )
00664       { 
00665          if (samplingRateHz != mSamplingRateHz)
00666          {
00667             mSamplingRateHz = samplingRateHz;
00668             on_change_of_samprate();
00669          }
00670       }
00671 
00674       inline void reset()
00675       {
00676          mState = 4;
00677          mCount = 0.0f;
00678          mReleased = false;
00679          on_change_of_samprate();
00680       }
00681 
00682    private:
00684       inline void on_change_of_samprate()
00685       {
00686          this->setAttackTime( mAttackTime );
00687          this->setDecayTime( mDecayTime );
00688          this->setSustainLevel( mSustainLevel );
00689          this->setReleaseTime( mReleaseTime );
00690          mDurationSamps = mDurationTime * mSamplingRateHz;
00691       }
00692 
00693       /* func gen attributes. */
00694       float mSamplingRateHz;
00695       float mAttackTime, mDecayTime, mSustainLevel, mReleaseTime;
00696       float mCount;
00697       float mAttackSamps, mDecaySamps, mReleaseSamps;
00698       unsigned int mState;
00699       bool mTriggered;
00700       bool mReleased;
00701       float mDurationSamps, mDurationTime, mTotalTimeSamps;
00702    };
00703 } // end namespace syn
00704 
00705 #endif

Generated at Mon Apr 15 09:26:08 2002 for subsynth by doxygen1.2.8.1 written by Dimitri van Heesch, © 1997-2001