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.

153 lines
5.0KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE 7 technical preview.
  4. Copyright (c) 2022 - 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 the technical preview this file cannot be licensed commercially.
  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. JUCE_BEGIN_IGNORE_WARNINGS_MSVC (6255 6386)
  100. auto* biases = static_cast<FloatType*> (alloca (sizeof (FloatType) * len));
  101. for (size_t i = 0; i < len; ++i)
  102. biases[i] = bias.getNextValue();
  103. for (size_t chan = 0; chan < numChannels; ++chan)
  104. FloatVectorOperations::add (outBlock.getChannelPointer (chan),
  105. inBlock.getChannelPointer (chan),
  106. biases, static_cast<int> (len));
  107. JUCE_END_IGNORE_WARNINGS_MSVC
  108. }
  109. }
  110. private:
  111. //==============================================================================
  112. SmoothedValue<FloatType> bias;
  113. double sampleRate = 0, rampDurationSeconds = 0;
  114. void updateRamp() noexcept
  115. {
  116. if (sampleRate > 0)
  117. bias.reset (sampleRate, rampDurationSeconds);
  118. }
  119. };
  120. } // namespace dsp
  121. } // namespace juce