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.

118 lines
3.2KB

  1. /***************************************************/
  2. /*! \class DelayA
  3. \brief STK allpass interpolating delay line class.
  4. This class implements a fractional-length digital delay-line using
  5. a first-order allpass filter. If the delay and maximum length are
  6. not specified during instantiation, a fixed maximum length of 4095
  7. and a delay of zero is set.
  8. An allpass filter has unity magnitude gain but variable phase
  9. delay properties, making it useful in achieving fractional delays
  10. without affecting a signal's frequency magnitude response. In
  11. order to achieve a maximally flat phase delay response, the
  12. minimum delay possible in this implementation is limited to a
  13. value of 0.5.
  14. by Perry R. Cook and Gary P. Scavone, 1995--2017.
  15. */
  16. /***************************************************/
  17. #include "DelayA.h"
  18. namespace stk {
  19. DelayA :: DelayA( StkFloat delay, unsigned long maxDelay )
  20. {
  21. if ( delay < 0.5 ) {
  22. oStream_ << "DelayA::DelayA: delay must be >= 0.5!";
  23. handleError( StkError::FUNCTION_ARGUMENT );
  24. }
  25. if ( delay > (StkFloat) maxDelay ) {
  26. oStream_ << "DelayA::DelayA: maxDelay must be > than delay argument!";
  27. handleError( StkError::FUNCTION_ARGUMENT );
  28. }
  29. // Writing before reading allows delays from 0 to length-1.
  30. if ( maxDelay + 1 > inputs_.size() )
  31. inputs_.resize( maxDelay + 1, 1, 0.0 );
  32. inPoint_ = 0;
  33. this->setDelay( delay );
  34. apInput_ = 0.0;
  35. doNextOut_ = true;
  36. }
  37. DelayA :: ~DelayA()
  38. {
  39. }
  40. void DelayA :: clear()
  41. {
  42. for ( unsigned int i=0; i<inputs_.size(); i++ )
  43. inputs_[i] = 0.0;
  44. lastFrame_[0] = 0.0;
  45. apInput_ = 0.0;
  46. }
  47. void DelayA :: setMaximumDelay( unsigned long delay )
  48. {
  49. if ( delay < inputs_.size() ) return;
  50. inputs_.resize(delay + 1, 1, 0.0);
  51. }
  52. void DelayA :: setDelay( StkFloat delay )
  53. {
  54. unsigned long length = inputs_.size();
  55. if ( delay + 1 > length ) { // The value is too big.
  56. oStream_ << "DelayA::setDelay: argument (" << delay << ") greater than maximum!";
  57. handleError( StkError::WARNING ); return;
  58. }
  59. if ( delay < 0.5 ) {
  60. oStream_ << "DelayA::setDelay: argument (" << delay << ") less than 0.5 not possible!";
  61. handleError( StkError::WARNING );
  62. }
  63. StkFloat outPointer = inPoint_ - delay + 1.0; // outPoint chases inpoint
  64. delay_ = delay;
  65. while ( outPointer < 0 )
  66. outPointer += length; // modulo maximum length
  67. outPoint_ = (long) outPointer; // integer part
  68. if ( outPoint_ == length ) outPoint_ = 0;
  69. alpha_ = 1.0 + outPoint_ - outPointer; // fractional part
  70. if ( alpha_ < 0.5 ) {
  71. // The optimal range for alpha is about 0.5 - 1.5 in order to
  72. // achieve the flattest phase delay response.
  73. outPoint_ += 1;
  74. if ( outPoint_ >= length ) outPoint_ -= length;
  75. alpha_ += (StkFloat) 1.0;
  76. }
  77. coeff_ = (1.0 - alpha_) / (1.0 + alpha_); // coefficient for allpass
  78. }
  79. StkFloat DelayA :: tapOut( unsigned long tapDelay )
  80. {
  81. long tap = inPoint_ - tapDelay - 1;
  82. while ( tap < 0 ) // Check for wraparound.
  83. tap += inputs_.size();
  84. return inputs_[tap];
  85. }
  86. void DelayA :: tapIn( StkFloat value, unsigned long tapDelay )
  87. {
  88. long tap = inPoint_ - tapDelay - 1;
  89. while ( tap < 0 ) // Check for wraparound.
  90. tap += inputs_.size();
  91. inputs_[tap] = value;
  92. }
  93. } // stk namespace