diff stk/include/SineWave.h @ 0:4606bd505630 tip

first import
author Fiore Martin <f.martin@qmul.ac.uk>
date Sat, 13 Jun 2015 15:08:10 +0100
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stk/include/SineWave.h	Sat Jun 13 15:08:10 2015 +0100
@@ -0,0 +1,159 @@
+#ifndef STK_SINEWAVE_H
+#define STK_SINEWAVE_H
+
+const unsigned long TABLE_SIZE = 2048;
+
+#include "Generator.h"
+
+namespace stk {
+
+/***************************************************/
+/*! \class SineWave
+    \brief STK sinusoid oscillator class.
+
+    This class computes and saves a static sine "table" that can be
+    shared by multiple instances.  It has an interface similar to the
+    WaveLoop class but inherits from the Generator class.  Output
+    values are computed using linear interpolation.
+
+    The "table" length, set in SineWave.h, is 2048 samples by default.
+
+    by Perry R. Cook and Gary P. Scavone, 1995--2014.
+*/
+/***************************************************/
+
+class SineWave : public Generator
+{
+public:
+  //! Default constructor.
+  SineWave( void );
+
+  //! Class destructor.
+  ~SineWave( void );
+
+  //! Clear output and reset time pointer to zero.
+  void reset( void );
+
+  //! Set the data read rate in samples.  The rate can be negative.
+  /*!
+    If the rate value is negative, the data is read in reverse order.
+  */
+  void setRate( StkFloat rate ) { rate_ = rate; };
+
+  //! Set the data interpolation rate based on a looping frequency.
+  /*!
+    This function determines the interpolation rate based on the file
+    size and the current Stk::sampleRate.  The \e frequency value
+    corresponds to file cycles per second.  The frequency can be
+    negative, in which case the loop is read in reverse order.
+   */
+  void setFrequency( StkFloat frequency );
+
+  //! Increment the read pointer by \e time in samples, modulo the table size.
+  void addTime( StkFloat time );
+
+  //! Increment the read pointer by a normalized \e phase value.
+  /*!
+    This function increments the read pointer by a normalized phase
+    value, such that \e phase = 1.0 corresponds to a 360 degree phase
+    shift.  Positive or negative values are possible.
+   */
+  void addPhase( StkFloat phase );
+
+  //! Add a normalized phase offset to the read pointer.
+  /*!
+    A \e phaseOffset = 1.0 corresponds to a 360 degree phase
+    offset.  Positive or negative values are possible.
+   */
+  void addPhaseOffset( StkFloat phaseOffset );
+
+  //! Return the last computed output value.
+  StkFloat lastOut( void ) const { return lastFrame_[0]; };
+
+  //! Compute and return one output sample.
+  StkFloat tick( void );
+
+  //! Fill a channel of the StkFrames object with computed outputs.
+  /*!
+    The \c channel argument must be less than the number of
+    channels in the StkFrames argument (the first channel is specified
+    by 0).  However, range checking is only performed if _STK_DEBUG_
+    is defined during compilation, in which case an out-of-range value
+    will trigger an StkError exception.
+  */
+  StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
+
+protected:
+
+  void sampleRateChanged( StkFloat newRate, StkFloat oldRate );
+
+  static StkFrames table_;
+  StkFloat time_;
+  StkFloat rate_;
+  StkFloat phaseOffset_;
+  unsigned int iIndex_;
+  StkFloat alpha_;
+
+};
+
+inline StkFloat SineWave :: tick( void )
+{
+  // Check limits of time address ... if necessary, recalculate modulo
+  // TABLE_SIZE.
+  while ( time_ < 0.0 )
+    time_ += TABLE_SIZE;
+  while ( time_ >= TABLE_SIZE )
+    time_ -= TABLE_SIZE;
+
+  iIndex_ = (unsigned int) time_;
+  alpha_ = time_ - iIndex_;
+  StkFloat tmp = table_[ iIndex_ ];
+  tmp += ( alpha_ * ( table_[ iIndex_ + 1 ] - tmp ) );
+
+  // Increment time, which can be negative.
+  time_ += rate_;
+
+  lastFrame_[0] = tmp;
+  return lastFrame_[0];
+}
+
+inline StkFrames& SineWave :: tick( StkFrames& frames, unsigned int channel )
+{
+#if defined(_STK_DEBUG_)
+  if ( channel >= frames.channels() ) {
+    oStream_ << "SineWave::tick(): channel and StkFrames arguments are incompatible!";
+    handleError( StkError::FUNCTION_ARGUMENT );
+  }
+#endif
+
+  StkFloat *samples = &frames[channel];
+  StkFloat tmp = 0.0;
+
+  unsigned int hop = frames.channels();
+  for ( unsigned int i=0; i<frames.frames(); i++, samples += hop ) {
+
+    // Check limits of time address ... if necessary, recalculate modulo
+    // TABLE_SIZE.
+    while ( time_ < 0.0 )
+      time_ += TABLE_SIZE;
+    while ( time_ >= TABLE_SIZE )
+      time_ -= TABLE_SIZE;
+
+    iIndex_ = (unsigned int) time_;
+    alpha_ = time_ - iIndex_;
+    tmp = table_[ iIndex_ ];
+    tmp += ( alpha_ * ( table_[ iIndex_ + 1 ] - tmp ) );
+    *samples = tmp;
+
+    // Increment time, which can be negative.
+    time_ += rate_;
+  }
+
+  lastFrame_[0] = tmp;
+  return frames;
+}
+
+} // stk namespace
+
+#endif
+