The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
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.

151 lines
4.9KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE 6 technical preview.
  4. Copyright (c) 2020 - Raw Material Software Limited
  5. You may use this code under the terms of the GPL v3
  6. (see www.gnu.org/licenses).
  7. For this technical preview, this file is not subject to commercial licensing.
  8. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  9. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  10. DISCLAIMED.
  11. ==============================================================================
  12. */
  13. namespace juce
  14. {
  15. namespace dsp
  16. {
  17. /**
  18. Adds a DC offset (voltage bias) to the audio samples.
  19. This is a useful preprocessor for asymmetric waveshaping when a waveshaper is
  20. bookended by a bias on input and a DC-offset removing high pass filter on output.
  21. This is an extremely simple bias implementation that simply adds a value to a signal.
  22. More complicated bias behaviours exist in real circuits - for your homework ;).
  23. @tags{DSP}
  24. */
  25. template <typename FloatType>
  26. class Bias
  27. {
  28. public:
  29. Bias() noexcept = default;
  30. //==============================================================================
  31. /** Sets the DC bias
  32. @param newBias DC offset in range [-1, 1]
  33. */
  34. void setBias (FloatType newBias) noexcept
  35. {
  36. jassert (newBias >= static_cast<FloatType> (-1) && newBias <= static_cast<FloatType> (1));
  37. bias.setTargetValue (newBias);
  38. }
  39. //==============================================================================
  40. /** Returns the DC bias
  41. @return DC bias, which should be in the range [-1, 1]
  42. */
  43. FloatType getBias() const noexcept { return bias.getTargetValue(); }
  44. /** Sets the length of the ramp used for smoothing gain changes. */
  45. void setRampDurationSeconds (double newDurationSeconds) noexcept
  46. {
  47. if (rampDurationSeconds != newDurationSeconds)
  48. {
  49. rampDurationSeconds = newDurationSeconds;
  50. updateRamp();
  51. }
  52. }
  53. double getRampDurationSeconds() const noexcept { return rampDurationSeconds; }
  54. //==============================================================================
  55. /** Called before processing starts */
  56. void prepare (const ProcessSpec& spec) noexcept
  57. {
  58. sampleRate = spec.sampleRate;
  59. updateRamp();
  60. }
  61. void reset() noexcept
  62. {
  63. bias.reset (sampleRate, rampDurationSeconds);
  64. }
  65. //==============================================================================
  66. /** Returns the result of processing a single sample. */
  67. template <typename SampleType>
  68. SampleType processSample (SampleType inputSample) noexcept
  69. {
  70. return inputSample + bias.getNextValue();
  71. }
  72. //==============================================================================
  73. /** Processes the input and output buffers supplied in the processing context. */
  74. template<typename ProcessContext>
  75. void process (const ProcessContext& context) noexcept
  76. {
  77. auto&& inBlock = context.getInputBlock();
  78. auto&& outBlock = context.getOutputBlock();
  79. jassert (inBlock.getNumChannels() == outBlock.getNumChannels());
  80. jassert (inBlock.getNumSamples() == outBlock.getNumSamples());
  81. auto len = inBlock.getNumSamples();
  82. auto numChannels = inBlock.getNumChannels();
  83. if (context.isBypassed)
  84. {
  85. bias.skip (static_cast<int> (len));
  86. if (context.usesSeparateInputAndOutputBlocks())
  87. outBlock.copyFrom (inBlock);
  88. return;
  89. }
  90. if (numChannels == 1)
  91. {
  92. auto* src = inBlock.getChannelPointer (0);
  93. auto* dst = outBlock.getChannelPointer (0);
  94. for (size_t i = 0; i < len; ++i)
  95. dst[i] = src[i] + bias.getNextValue();
  96. }
  97. else
  98. {
  99. auto* biases = static_cast<FloatType*> (alloca (sizeof (FloatType) * len));
  100. for (size_t i = 0; i < len; ++i)
  101. biases[i] = bias.getNextValue();
  102. for (size_t chan = 0; chan < numChannels; ++chan)
  103. FloatVectorOperations::add (outBlock.getChannelPointer (chan),
  104. inBlock.getChannelPointer (chan),
  105. biases, static_cast<int> (len));
  106. }
  107. }
  108. private:
  109. //==============================================================================
  110. SmoothedValue<FloatType> bias;
  111. double sampleRate = 0, rampDurationSeconds = 0;
  112. void updateRamp() noexcept
  113. {
  114. if (sampleRate > 0)
  115. bias.reset (sampleRate, rampDurationSeconds);
  116. }
  117. };
  118. } // namespace dsp
  119. } // namespace juce