1 /***************************************************/ 2 /*! \class DelayL 3 \brief STK linear interpolating delay line class. 4 5 This Delay subclass implements a fractional- 6 length digital delay-line using first-order 7 linear interpolation. A fixed maximum length 8 of 4095 and a delay of zero is set using the 9 default constructor. Alternatively, the 10 delay and maximum length can be set during 11 instantiation with an overloaded constructor. 12 13 Linear interpolation is an efficient technique 14 for achieving fractional delay lengths, though 15 it does introduce high-frequency signal 16 attenuation to varying degrees depending on the 17 fractional delay setting. The use of higher 18 order Lagrange interpolators can typically 19 improve (minimize) this attenuation characteristic. 20 21 by Perry R. Cook and Gary P. Scavone, 1995 - 2005. 22 */ 23 /***************************************************/ 24 25 #include "DelayL.h" 26 27 using namespace Nyq; 28 DelayL()29DelayL :: DelayL() : Delay() 30 { 31 doNextOut_ = true; 32 } 33 DelayL(StkFloat delay,unsigned long maxDelay)34DelayL :: DelayL(StkFloat delay, unsigned long maxDelay) 35 { 36 if ( delay < 0.0 || maxDelay < 1 ) { 37 errorString_ << "DelayL::DelayL: delay must be >= 0.0, maxDelay must be > 0!"; 38 handleError( StkError::FUNCTION_ARGUMENT ); 39 } 40 41 if ( delay > (StkFloat) maxDelay ) { 42 errorString_ << "DelayL::DelayL: maxDelay must be > than delay argument!"; 43 handleError( StkError::FUNCTION_ARGUMENT ); 44 } 45 46 // Writing before reading allows delays from 0 to length-1. 47 if ( maxDelay > inputs_.size()-1 ) { 48 inputs_.resize( maxDelay+1 ); 49 this->clear(); 50 } 51 52 inPoint_ = 0; 53 this->setDelay(delay); 54 doNextOut_ = true; 55 } 56 ~DelayL()57DelayL :: ~DelayL() 58 { 59 } 60 setDelay(StkFloat delay)61void DelayL :: setDelay(StkFloat delay) 62 { 63 StkFloat outPointer; 64 65 if ( delay > inputs_.size() - 1 ) { // The value is too big. 66 errorString_ << "DelayL::setDelay: argument (" << delay << ") too big ... setting to maximum!"; 67 handleError( StkError::WARNING ); 68 69 // Force delay to maxLength 70 outPointer = inPoint_ + 1.0; 71 delay_ = inputs_.size() - 1; 72 } 73 else if (delay < 0 ) { 74 errorString_ << "DelayL::setDelay: argument (" << delay << ") less than zero ... setting to zero!"; 75 handleError( StkError::WARNING ); 76 77 outPointer = inPoint_; 78 delay_ = 0; 79 } 80 else { 81 outPointer = inPoint_ - delay; // read chases write 82 delay_ = delay; 83 } 84 85 while (outPointer < 0) 86 outPointer += inputs_.size(); // modulo maximum length 87 88 outPoint_ = (long) outPointer; // integer part 89 if ( outPoint_ == inputs_.size() ) outPoint_ = 0; 90 alpha_ = outPointer - outPoint_; // fractional part 91 omAlpha_ = (StkFloat) 1.0 - alpha_; 92 } 93 getDelay(void) const94StkFloat DelayL :: getDelay(void) const 95 { 96 return delay_; 97 } 98 nextOut(void)99StkFloat DelayL :: nextOut(void) 100 { 101 if ( doNextOut_ ) { 102 // First 1/2 of interpolation 103 nextOutput_ = inputs_[outPoint_] * omAlpha_; 104 // Second 1/2 of interpolation 105 if (outPoint_+1 < inputs_.size()) 106 nextOutput_ += inputs_[outPoint_+1] * alpha_; 107 else 108 nextOutput_ += inputs_[0] * alpha_; 109 doNextOut_ = false; 110 } 111 112 return nextOutput_; 113 } 114 computeSample(StkFloat input)115StkFloat DelayL :: computeSample( StkFloat input ) 116 { 117 inputs_[inPoint_++] = input; 118 119 // Increment input pointer modulo length. 120 if (inPoint_ == inputs_.size()) 121 inPoint_ = 0; 122 123 outputs_[0] = nextOut(); 124 doNextOut_ = true; 125 126 // Increment output pointer modulo length. 127 if (++outPoint_ == inputs_.size()) 128 outPoint_ = 0; 129 130 return outputs_[0]; 131 } 132 133