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.

133 lines
5.5KB

  1. /*
  2. ==============================================================================
  3. NoiseGate.cpp
  4. Created: 23 Nov 2015 3:08:33pm
  5. Author: Fabian Renn
  6. ==============================================================================
  7. */
  8. #include "../JuceLibraryCode/JuceHeader.h"
  9. #include "../../GenericEditor.h"
  10. class NoiseGate : public AudioProcessor
  11. {
  12. public:
  13. //==============================================================================
  14. NoiseGate()
  15. {
  16. addParameter (threshold = new AudioParameterFloat ("threshold", "Threshold", 0.0f, 1.0f, 0.5f));
  17. addParameter (alpha = new AudioParameterFloat ("alpha", "Alpha", 0.0f, 1.0f, 0.8f));
  18. // add single side-chain bus
  19. busArrangement.inputBuses. add (AudioProcessorBus ("Sidechain In", AudioChannelSet::stereo()));
  20. busArrangement.outputBuses.add (AudioProcessorBus ("Sidechain Out", AudioChannelSet::stereo()));
  21. }
  22. ~NoiseGate() {}
  23. //==============================================================================
  24. bool setPreferredBusArrangement (bool isInputBus, int busIndex, const AudioChannelSet& preferred) override
  25. {
  26. const int numChannels = preferred.size();
  27. // do not allow disabling channels
  28. if (numChannels == 0) return false;
  29. // only allow stereo on the side-chain bus
  30. if (busIndex == 1 && numChannels != 2) return false;
  31. // always have the same channel layout on both input and output on the main bus
  32. if (! AudioProcessor::setPreferredBusArrangement (! isInputBus, busIndex, preferred))
  33. return false;
  34. return AudioProcessor::setPreferredBusArrangement (isInputBus, busIndex, preferred);
  35. }
  36. //==============================================================================
  37. void prepareToPlay (double /*sampleRate*/, int /*maxBlockSize*/) override { lowPassCoeff = 0.0f; sampleCountDown = 0; }
  38. void releaseResources() override {}
  39. void processBlock (AudioSampleBuffer& buffer, MidiBuffer&) override
  40. {
  41. for (int i = getTotalNumInputChannels(); i < getTotalNumOutputChannels(); ++i)
  42. buffer.clear (i, 0, buffer.getNumSamples());
  43. AudioSampleBuffer mainInputOutput = busArrangement.getBusBuffer (buffer, true, 0);
  44. AudioSampleBuffer sideChainInput = busArrangement.getBusBuffer (buffer, true, 1);
  45. float alphaCopy = *alpha;
  46. float thresholdCopy = *threshold;
  47. for (int j = 0; j < buffer.getNumSamples(); ++j)
  48. {
  49. float mixedSamples = 0.0f;
  50. for (int i = 0; i < sideChainInput.getNumChannels(); ++i)
  51. mixedSamples += sideChainInput.getReadPointer (i) [j];
  52. mixedSamples /= static_cast<float> (sideChainInput.getNumChannels());
  53. lowPassCoeff = (alphaCopy * lowPassCoeff) + ((1.0f - alphaCopy) * mixedSamples);
  54. if (lowPassCoeff >= thresholdCopy)
  55. sampleCountDown = (int) getSampleRate();
  56. // very in-effective way of doing this
  57. for (int i = 0; i < mainInputOutput.getNumChannels(); ++i)
  58. *mainInputOutput.getWritePointer (i, j) = sampleCountDown > 0 ? *mainInputOutput.getReadPointer (i, j) : 0.0f;
  59. if (sampleCountDown > 0)
  60. --sampleCountDown;
  61. }
  62. }
  63. //==============================================================================
  64. AudioProcessorEditor* createEditor() override { return new GenericEditor (*this); }
  65. bool hasEditor() const override { return true; }
  66. const String getName() const override { return "NoiseGate"; }
  67. bool acceptsMidi() const override { return false; }
  68. bool producesMidi() const override { return false; }
  69. bool silenceInProducesSilenceOut() const override { return true; }
  70. double getTailLengthSeconds() const override { return 0.0; }
  71. int getNumPrograms() override { return 1; }
  72. int getCurrentProgram() override { return 0; }
  73. void setCurrentProgram (int) override {}
  74. const String getProgramName (int) override { return ""; }
  75. void changeProgramName (int, const String&) override {}
  76. //==============================================================================
  77. void getStateInformation (MemoryBlock& destData) override
  78. {
  79. MemoryOutputStream stream (destData, true);
  80. stream.writeFloat (*threshold);
  81. stream.writeFloat (*alpha);
  82. }
  83. void setStateInformation (const void* data, int sizeInBytes) override
  84. {
  85. MemoryInputStream stream (data, static_cast<size_t> (sizeInBytes), false);
  86. threshold->setValueNotifyingHost (stream.readFloat());
  87. alpha->setValueNotifyingHost (stream.readFloat());
  88. }
  89. private:
  90. //==============================================================================
  91. AudioParameterFloat* threshold;
  92. AudioParameterFloat* alpha;
  93. int sampleCountDown;
  94. float lowPassCoeff;
  95. //==============================================================================
  96. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (NoiseGate)
  97. };
  98. //==============================================================================
  99. // This creates new instances of the plugin..
  100. AudioProcessor* JUCE_CALLTYPE createPluginFilter()
  101. {
  102. return new NoiseGate();
  103. }