Audio plugin host https://kx.studio/carla
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.

207 lines
7.1KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2022 - Raw Material Software Limited
  5. JUCE is an open source library subject to commercial or open-source
  6. licensing.
  7. By using JUCE, you agree to the terms of both the JUCE 7 End-User License
  8. Agreement and JUCE Privacy Policy.
  9. End User License Agreement: www.juce.com/juce-7-licence
  10. Privacy Policy: www.juce.com/juce-privacy-policy
  11. Or: You may also use this code under the terms of the GPL v3 (see
  12. www.gnu.org/licenses).
  13. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  14. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  15. DISCLAIMED.
  16. ==============================================================================
  17. */
  18. namespace juce
  19. {
  20. namespace dsp
  21. {
  22. /**
  23. A 6 stage phaser that modulates first order all-pass filters to create sweeping
  24. notches in the magnitude frequency response.
  25. This audio effect can be controlled with standard phaser parameters: the speed
  26. and depth of the LFO controlling the frequency response, a mix control, a
  27. feedback control, and the centre frequency of the modulation.
  28. @tags{DSP}
  29. */
  30. template <typename SampleType>
  31. class Phaser
  32. {
  33. public:
  34. //==============================================================================
  35. /** Constructor. */
  36. Phaser();
  37. //==============================================================================
  38. /** Sets the rate (in Hz) of the LFO modulating the phaser all-pass filters. This
  39. rate must be lower than 100 Hz.
  40. */
  41. void setRate (SampleType newRateHz);
  42. /** Sets the volume (between 0 and 1) of the LFO modulating the phaser all-pass
  43. filters.
  44. */
  45. void setDepth (SampleType newDepth);
  46. /** Sets the centre frequency (in Hz) of the phaser all-pass filters modulation.
  47. */
  48. void setCentreFrequency (SampleType newCentreHz);
  49. /** Sets the feedback volume (between -1 and 1) of the phaser. Negative can be
  50. used to get specific phaser sounds.
  51. */
  52. void setFeedback (SampleType newFeedback);
  53. /** Sets the amount of dry and wet signal in the output of the phaser (between 0
  54. for full dry and 1 for full wet).
  55. */
  56. void setMix (SampleType newMix);
  57. //==============================================================================
  58. /** Initialises the processor. */
  59. void prepare (const ProcessSpec& spec);
  60. /** Resets the internal state variables of the processor. */
  61. void reset();
  62. //==============================================================================
  63. /** Processes the input and output samples supplied in the processing context. */
  64. template <typename ProcessContext>
  65. void process (const ProcessContext& context) noexcept
  66. {
  67. const auto& inputBlock = context.getInputBlock();
  68. auto& outputBlock = context.getOutputBlock();
  69. const auto numChannels = outputBlock.getNumChannels();
  70. const auto numSamples = outputBlock.getNumSamples();
  71. jassert (inputBlock.getNumChannels() == numChannels);
  72. jassert (inputBlock.getNumChannels() == lastOutput.size());
  73. jassert (inputBlock.getNumSamples() == numSamples);
  74. if (context.isBypassed)
  75. {
  76. outputBlock.copyFrom (inputBlock);
  77. return;
  78. }
  79. int numSamplesDown = 0;
  80. auto counter = updateCounter;
  81. for (size_t i = 0; i < numSamples; ++i)
  82. {
  83. if (counter == 0)
  84. numSamplesDown++;
  85. counter++;
  86. if (counter == maxUpdateCounter)
  87. counter = 0;
  88. }
  89. if (numSamplesDown > 0)
  90. {
  91. auto freqBlock = AudioBlock<SampleType>(bufferFrequency).getSubBlock (0, (size_t) numSamplesDown);
  92. auto contextFreq = ProcessContextReplacing<SampleType> (freqBlock);
  93. freqBlock.clear();
  94. osc.process (contextFreq);
  95. freqBlock.multiplyBy (oscVolume);
  96. }
  97. auto* freqSamples = bufferFrequency.getWritePointer (0);
  98. for (int i = 0; i < numSamplesDown; ++i)
  99. {
  100. auto lfo = jlimit (static_cast<SampleType> (0.0),
  101. static_cast<SampleType> (1.0),
  102. freqSamples[i] + normCentreFrequency);
  103. freqSamples[i] = mapToLog10 (lfo, static_cast<SampleType> (20.0),
  104. static_cast<SampleType> (jmin (20000.0, 0.49 * sampleRate)));
  105. }
  106. auto currentFrequency = filters[0]->getCutoffFrequency();
  107. dryWet.pushDrySamples (inputBlock);
  108. for (size_t channel = 0; channel < numChannels; ++channel)
  109. {
  110. counter = updateCounter;
  111. int k = 0;
  112. auto* inputSamples = inputBlock .getChannelPointer (channel);
  113. auto* outputSamples = outputBlock.getChannelPointer (channel);
  114. for (size_t i = 0; i < numSamples; ++i)
  115. {
  116. auto input = inputSamples[i];
  117. auto output = input - lastOutput[channel];
  118. if (i == 0 && counter != 0)
  119. for (int n = 0; n < numStages; ++n)
  120. filters[n]->setCutoffFrequency (currentFrequency);
  121. if (counter == 0)
  122. {
  123. for (int n = 0; n < numStages; ++n)
  124. filters[n]->setCutoffFrequency (freqSamples[k]);
  125. k++;
  126. }
  127. for (int n = 0; n < numStages; ++n)
  128. output = filters[n]->processSample ((int) channel, output);
  129. outputSamples[i] = output;
  130. lastOutput[channel] = output * feedbackVolume[channel].getNextValue();
  131. counter++;
  132. if (counter == maxUpdateCounter)
  133. counter = 0;
  134. }
  135. }
  136. dryWet.mixWetSamples (outputBlock);
  137. updateCounter = (updateCounter + (int) numSamples) % maxUpdateCounter;
  138. }
  139. private:
  140. //==============================================================================
  141. void update();
  142. //==============================================================================
  143. Oscillator<SampleType> osc;
  144. OwnedArray<FirstOrderTPTFilter<SampleType>> filters;
  145. SmoothedValue<SampleType, ValueSmoothingTypes::Linear> oscVolume;
  146. std::vector<SmoothedValue<SampleType, ValueSmoothingTypes::Linear>> feedbackVolume { 2 };
  147. DryWetMixer<SampleType> dryWet;
  148. std::vector<SampleType> lastOutput { 2 };
  149. AudioBuffer<SampleType> bufferFrequency;
  150. SampleType normCentreFrequency = 0.5;
  151. double sampleRate = 44100.0;
  152. int updateCounter = 0;
  153. static constexpr int maxUpdateCounter = 4;
  154. SampleType rate = 1.0, depth = 0.5, feedback = 0.0, mix = 0.5;
  155. SampleType centreFrequency = 1300.0;
  156. static constexpr int numStages = 6;
  157. };
  158. } // namespace dsp
  159. } // namespace juce