You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

210 lines
6.9KB

  1. #ifndef STK_GRANULATE_H
  2. #define STK_GRANULATE_H
  3. #include <vector>
  4. #include "Generator.h"
  5. #include "Envelope.h"
  6. #include "Noise.h"
  7. namespace stk {
  8. /***************************************************/
  9. /*! \class Granulate
  10. \brief STK granular synthesis class.
  11. This class implements a real-time granular synthesis algorithm
  12. that operates on an input soundfile. Multi-channel files are
  13. supported. Various functions are provided to allow control over
  14. voice and grain parameters.
  15. The functionality of this class is based on the program MacPod by
  16. Chris Rolfe and Damian Keller, though there are likely to be a
  17. number of differences in the actual implementation.
  18. by Gary Scavone, 2005 - 2010.
  19. */
  20. /***************************************************/
  21. class Granulate: public Generator
  22. {
  23. public:
  24. //! Default constructor.
  25. Granulate( void );
  26. //! Constructor taking input audio file and number of voices arguments.
  27. Granulate( unsigned int nVoices, std::string fileName, bool typeRaw = false );
  28. //! Class destructor.
  29. ~Granulate( void );
  30. //! Load a monophonic soundfile to be "granulated".
  31. /*!
  32. An StkError will be thrown if the file is not found, its format
  33. is unknown or unsupported, or the file has more than one channel.
  34. */
  35. void openFile( std::string fileName, bool typeRaw = false );
  36. //! Reset the file pointer and all existing grains to the file start.
  37. /*!
  38. Multiple grains are offset from one another in time by grain
  39. duration / nVoices.
  40. */
  41. void reset( void );
  42. //! Set the number of simultaneous grain "voices" to use.
  43. /*!
  44. Multiple grains are offset from one another in time by grain
  45. duration / nVoices. For this reason, it is best to set the grain
  46. parameters before calling this function (during initialization).
  47. */
  48. void setVoices( unsigned int nVoices = 1 );
  49. //! Set the stretch factor used for grain playback (1 - 1000).
  50. /*!
  51. Granular synthesis allows for time-stetching without affecting
  52. the original pitch of a sound. A stretch factor of 4 will produce
  53. a resulting sound of length 4 times the orignal sound. The
  54. default parameter of 1 produces no stretching.
  55. */
  56. void setStretch( unsigned int stretchFactor = 1 );
  57. //! Set global grain parameters used to determine individual grain settings.
  58. /*!
  59. Each grain is defined as having a length of \e duration
  60. milliseconds which must be greater than zero. For values of \e
  61. rampPercent (0 - 100) greater than zero, a linear envelope will be
  62. applied to each grain. If \e rampPercent = 100, the resultant
  63. grain "window" is triangular while \e rampPercent = 50 produces a
  64. trapezoidal window. In addition, each grain can have a time delay
  65. of length \e delay and a grain pointer increment of length \e
  66. offset, which can be negative, before the next ramp onset (in
  67. milliseconds). The \e offset parameter controls grain pointer
  68. jumps between enveloped grain segments, while the \e delay
  69. parameter causes grain calculations to pause between grains. The
  70. actual values calculated for each grain will be randomized by a
  71. factor set using the setRandomFactor() function.
  72. */
  73. void setGrainParameters( unsigned int duration = 30, unsigned int rampPercent = 50,
  74. int offset = 0, unsigned int delay = 0 );
  75. //! This factor is used when setting individual grain parameters (0.0 - 1.0).
  76. /*!
  77. This random factor is applied when all grain state durations
  78. are calculated. If set to 0.0, no randomness occurs. When
  79. randomness = 1.0, a grain segment of length \e duration will be
  80. randomly augmented by up to +- \e duration seconds (i.e., a 30
  81. millisecond length will be augmented by an extra length of up to
  82. +30 or -30 milliseconds).
  83. */
  84. void setRandomFactor( StkFloat randomness = 0.1 );
  85. //! Return the specified channel value of the last computed frame.
  86. /*!
  87. The \c channel argument must be less than the number of output
  88. channels, which can be determined with the channelsOut() function
  89. (the first channel is specified by 0). However, range checking is
  90. only performed if _STK_DEBUG_ is defined during compilation, in
  91. which case an out-of-range value will trigger an StkError
  92. exception. \sa lastFrame()
  93. */
  94. StkFloat lastOut( unsigned int channel = 0 );
  95. //! Compute one sample frame and return the specified \c channel value.
  96. StkFloat tick( unsigned int channel = 0 );
  97. //! Fill the StkFrames object with computed sample frames, starting at the specified channel.
  98. /*!
  99. The \c channel argument plus the number of output channels must
  100. be less than the number of channels in the StkFrames argument (the
  101. first channel is specified by 0). However, range checking is only
  102. performed if _STK_DEBUG_ is defined during compilation, in which
  103. case an out-of-range value will trigger an StkError exception.
  104. */
  105. StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
  106. enum GrainState {
  107. GRAIN_STOPPED,
  108. GRAIN_FADEIN,
  109. GRAIN_SUSTAIN,
  110. GRAIN_FADEOUT
  111. };
  112. protected:
  113. struct Grain {
  114. StkFloat eScaler;
  115. StkFloat eRate;
  116. unsigned long attackCount;
  117. unsigned long sustainCount;
  118. unsigned long decayCount;
  119. unsigned long delayCount;
  120. unsigned long counter;
  121. //unsigned long pointer;
  122. StkFloat pointer;
  123. unsigned long startPointer;
  124. unsigned int repeats;
  125. GrainState state;
  126. // Default constructor.
  127. Grain()
  128. :eScaler(0.0), eRate(0.0), attackCount(0), sustainCount(0), decayCount(0),
  129. delayCount(0), counter(0), pointer(0), startPointer(0), repeats(0), state(GRAIN_STOPPED) {}
  130. };
  131. void calculateGrain( Granulate::Grain& grain );
  132. StkFrames data_;
  133. std::vector<Grain> grains_;
  134. Noise noise;
  135. //long gPointer_;
  136. StkFloat gPointer_;
  137. // Global grain parameters.
  138. unsigned int gDuration_;
  139. unsigned int gRampPercent_;
  140. unsigned int gDelay_;
  141. unsigned int gStretch_;
  142. unsigned int stretchCounter_;
  143. int gOffset_;
  144. StkFloat gRandomFactor_;
  145. StkFloat gain_;
  146. };
  147. inline StkFloat Granulate :: lastOut( unsigned int channel )
  148. {
  149. #if defined(_STK_DEBUG_)
  150. if ( channel >= lastFrame_.channels() ) {
  151. oStream_ << "Granulate::lastOut(): channel argument is invalid!";
  152. handleError( StkError::FUNCTION_ARGUMENT );
  153. }
  154. #endif
  155. return lastFrame_[channel];
  156. }
  157. inline StkFrames& Granulate :: tick( StkFrames& frames, unsigned int channel )
  158. {
  159. unsigned int nChannels = lastFrame_.channels();
  160. #if defined(_STK_DEBUG_)
  161. if ( channel > frames.channels() - nChannels ) {
  162. oStream_ << "Granulate::tick(): channel and StkFrames arguments are incompatible!";
  163. handleError( StkError::FUNCTION_ARGUMENT );
  164. }
  165. #endif
  166. StkFloat *samples = &frames[channel];
  167. unsigned int j, hop = frames.channels() - nChannels;
  168. for ( unsigned int i=0; i<frames.frames(); i++, samples += hop ) {
  169. *samples++ = tick();
  170. for ( j=1; j<nChannels; j++ )
  171. *samples++ = lastFrame_[j];
  172. }
  173. return frames;
  174. }
  175. } // stk namespace
  176. #endif