Delay.h (6847B)
1 /* 2 ============================================================================== 3 4 Delay 5 6 ============================================================================== 7 */ 8 #include "../JuceLibraryCode/JuceHeader.h" 9 10 #pragma once 11 12 //============================================================================== 13 template <typename Type> 14 class DelayLine 15 { 16 public: 17 void clear() noexcept 18 { 19 std::fill (rawData.begin(), rawData.end(), Type (0)); 20 } 21 22 size_t size() const noexcept 23 { 24 return rawData.size(); 25 } 26 27 void resize (size_t newValue) 28 { 29 rawData.resize (newValue); 30 leastRecentIndex = 0; 31 } 32 33 Type back() const noexcept 34 { 35 return rawData[leastRecentIndex]; 36 } 37 38 Type get (size_t delayInSamples) const noexcept 39 { 40 jassert (delayInSamples >= 0 && delayInSamples < size()); 41 42 return rawData[(leastRecentIndex + 1 + delayInSamples) % size()]; // [3] 43 } 44 45 /** Set the specified sample in the delay line */ 46 void set (size_t delayInSamples, Type newValue) noexcept 47 { 48 jassert (delayInSamples >= 0 && delayInSamples < size()); 49 50 rawData[(leastRecentIndex + 1 + delayInSamples) % size()] = newValue; // [4] 51 } 52 53 /** Adds a new value to the delay line, overwriting the least recently added sample */ 54 void push (Type valueToAdd) noexcept 55 { 56 rawData[leastRecentIndex] = valueToAdd; // [1] 57 leastRecentIndex = leastRecentIndex == 0 ? size() - 1 : leastRecentIndex - 1; // [2] 58 } 59 60 private: 61 std::vector<Type> rawData; 62 size_t leastRecentIndex = 0; 63 }; 64 65 //============================================================================== 66 template <typename Type, size_t maxNumChannels = 2> 67 class Delay 68 { 69 public: 70 //============================================================================== 71 Delay() 72 { 73 setMaxDelayTime (2.0f); 74 setDelayTime (0, 0.7f); 75 setDelayTime (1, 0.5f); 76 setWetLevel (0.8f); 77 setFeedback (0.5f); 78 } 79 80 //============================================================================== 81 void prepare (const juce::dsp::ProcessSpec& spec) 82 { 83 jassert (spec.numChannels <= maxNumChannels); 84 sampleRate = (Type) spec.sampleRate; 85 updateDelayLineSize(); 86 updateDelayTime(); 87 88 //filterCoefs = juce::dsp::IIR::Coefficients<Type>::makeFirstOrderLowPass (sampleRate, Type (1e3)); 89 filterCoefs = juce::dsp::IIR::Coefficients<Type>::makeFirstOrderHighPass (sampleRate, Type (1e3)); 90 91 for (auto& f : filters) 92 { 93 f.prepare (spec); 94 f.coefficients = filterCoefs; 95 } 96 } 97 98 //============================================================================== 99 void reset() noexcept 100 { 101 for (auto& f : filters) 102 f.reset(); // [5] 103 104 for (auto& dline : delayLines) 105 dline.clear(); // [6] 106 } 107 108 //============================================================================== 109 size_t getNumChannels() const noexcept 110 { 111 return delayLines.size(); 112 } 113 114 //============================================================================== 115 void setMaxDelayTime (Type newValue) 116 { 117 jassert (newValue > Type (0)); 118 maxDelayTime = newValue; 119 updateDelayLineSize(); // [1] 120 } 121 122 //============================================================================== 123 void setFeedback (Type newValue) noexcept 124 { 125 jassert (newValue >= Type (0) && newValue <= Type (1)); 126 feedback = newValue; 127 } 128 129 //============================================================================== 130 void setWetLevel (Type newValue) noexcept 131 { 132 jassert (newValue >= Type (0) && newValue <= Type (1)); 133 wetLevel = newValue; 134 } 135 136 //============================================================================== 137 void setDelayTime (size_t channel, Type newValue) 138 { 139 if (channel >= getNumChannels()) 140 { 141 jassertfalse; 142 return; 143 } 144 145 jassert (newValue >= Type (0)); 146 delayTimes[channel] = newValue; 147 148 updateDelayTime(); // [3] 149 } 150 151 //============================================================================== 152 template <typename ProcessContext> 153 void process (const ProcessContext& context) noexcept 154 { 155 auto& inputBlock = context.getInputBlock(); 156 auto& outputBlock = context.getOutputBlock(); 157 auto numSamples = outputBlock.getNumSamples(); 158 auto numChannels = outputBlock.getNumChannels(); 159 160 jassert (inputBlock.getNumSamples() == numSamples); 161 jassert (inputBlock.getNumChannels() == numChannels); 162 163 for (size_t ch = 0; ch < numChannels; ++ch) 164 { 165 auto* input = inputBlock .getChannelPointer (ch); 166 auto* output = outputBlock.getChannelPointer (ch); 167 auto& dline = delayLines[ch]; 168 auto delayTime = delayTimesSample[ch]; 169 auto& filter = filters[ch]; 170 171 for (size_t i = 0; i < numSamples; ++i) 172 { 173 //auto delayedSample = dline.get (delayTime); 174 auto delayedSample = filter.processSample (dline.get (delayTime)); 175 auto inputSample = input[i]; 176 auto dlineInputSample = std::tanh (inputSample + feedback * delayedSample); 177 dline.push (dlineInputSample); 178 auto outputSample = inputSample + wetLevel * delayedSample; 179 output[i] = outputSample; 180 } 181 } 182 } 183 184 private: 185 //============================================================================== 186 std::array<DelayLine<Type>, maxNumChannels> delayLines; 187 std::array<size_t, maxNumChannels> delayTimesSample; 188 std::array<Type, maxNumChannels> delayTimes; 189 Type feedback { Type (0) }; 190 Type wetLevel { Type (0) }; 191 192 std::array<juce::dsp::IIR::Filter<Type>, maxNumChannels> filters; 193 typename juce::dsp::IIR::Coefficients<Type>::Ptr filterCoefs; 194 195 Type sampleRate { Type (44.1e3) }; 196 Type maxDelayTime { Type (2) }; 197 198 //============================================================================== 199 void updateDelayLineSize() 200 { 201 auto delayLineSizeSamples = (size_t) std::ceil (maxDelayTime * sampleRate); 202 203 for (auto& dline : delayLines) 204 dline.resize (delayLineSizeSamples); // [2] 205 } 206 207 //============================================================================== 208 void updateDelayTime() noexcept 209 { 210 for (size_t ch = 0; ch < maxNumChannels; ++ch) 211 delayTimesSample[ch] = (size_t) juce::roundToInt (delayTimes[ch] * sampleRate); 212 } 213 214 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(Delay) 215 };