From 8a6b429f39487e08eb771931dd7b0b9d099dc771 Mon Sep 17 00:00:00 2001 From: GruffModular <40403174+RachelMaryamLocke@users.noreply.github.com> Date: Mon, 10 Jul 2023 22:23:10 +0100 Subject: [PATCH] Gate Level Tracking (#318) * Gate processAudio Adapted for Level Tracking I/O * Gate processAudioBypassed Added * Apply clang-format --------- Co-authored-by: github-actions[bot] --- src/processors/other/Gate.cpp | 86 +++++++++++++++++++++++++++-------- src/processors/other/Gate.h | 4 +- 2 files changed, 71 insertions(+), 19 deletions(-) diff --git a/src/processors/other/Gate.cpp b/src/processors/other/Gate.cpp index 681404c3..d4f5e6c1 100644 --- a/src/processors/other/Gate.cpp +++ b/src/processors/other/Gate.cpp @@ -1,4 +1,5 @@ #include "Gate.h" +#include "../BufferHelpers.h" #include "../ParameterHelpers.h" class Gate::GateEnvelope @@ -146,7 +147,8 @@ ParamLayout Gate::createParameterLayout() void Gate::prepare (double sampleRate, int samplesPerBlock) { - levelBuffer.setSize (1, samplesPerBlock); + audioOutBuffer.setSize (2, samplesPerBlock); + levelOutBuffer.setSize (1, samplesPerBlock); gateEnvelope->prepare (sampleRate, samplesPerBlock); @@ -156,33 +158,81 @@ void Gate::prepare (double sampleRate, int samplesPerBlock) void Gate::processAudio (AudioBuffer& buffer) { - const auto numChannels = buffer.getNumChannels(); const auto numSamples = buffer.getNumSamples(); - // set up level buffer - if (numChannels == 1) + //set up level output + levelOutBuffer.setSize (1, numSamples, false, false, true); + if (inputsConnected.contains (LevelInput)) { - levelBuffer.makeCopyOf (buffer); + BufferHelpers::collapseToMonoBuffer (getInputBuffer (LevelInput), levelOutBuffer); } else { - levelBuffer.setSize (1, numSamples, true, true, false); - levelBuffer.copyFrom (0, 0, buffer, 0, 0, numSamples); + if (inputsConnected.contains (AudioInput)) + { + BufferHelpers::collapseToMonoBuffer (getInputBuffer (AudioInput), levelOutBuffer); + } + else + { + levelOutBuffer.clear(); + } + } - for (int ch = 1; ch < numChannels; ++ch) - levelBuffer.addFrom (0, 0, buffer, ch, 0, numSamples); + if (inputsConnected.contains (AudioInput)) + { + gateEnvelope->setParameters (*threshDBParam, *attackMsParam, *holdMsParam, *releaseMsParam); + gateEnvelope->process (levelOutBuffer); - levelBuffer.applyGain (1.0f / (float) numChannels); + auto& audioInBuffer = getInputBuffer (AudioInput); + const auto numChannels = audioInBuffer.getNumChannels(); + audioOutBuffer.setSize (numChannels, numSamples, false, false, true); + for (int ch = 0; ch < numChannels; ++ch) + { + FloatVectorOperations::multiply (audioOutBuffer.getWritePointer (ch), audioInBuffer.getReadPointer (ch), gateEnvelope->gainBlock.getChannelPointer (0), numSamples); + } + + auto&& audioOutBlock = dsp::AudioBlock { audioOutBuffer }; + makeupGain.setGainDecibels (*makeupDBParam); + makeupGain.process (dsp::ProcessContextReplacing { audioOutBlock }); + } + else + { + audioOutBuffer.setSize (1, numSamples, false, false, true); + audioOutBuffer.clear(); } - auto&& levelBlock = dsp::AudioBlock { levelBuffer }; - gateEnvelope->setParameters (*threshDBParam, *attackMsParam, *holdMsParam, *releaseMsParam); - gateEnvelope->process (levelBlock); + outputBuffers.getReference (AudioOutput) = &audioOutBuffer; + outputBuffers.getReference (LevelOutput) = &levelOutBuffer; +} + +void Gate::processAudioBypassed (AudioBuffer& buffer) +{ + const auto numSamples = buffer.getNumSamples(); - auto&& block = dsp::AudioBlock { buffer }; - for (int ch = 0; ch < numChannels; ++ch) - block.getSingleChannelBlock ((size_t) ch) *= gateEnvelope->gainBlock; + levelOutBuffer.setSize (1, numSamples, false, false, true); + if (inputsConnected.contains (LevelInput)) //make mono and pass samples through + { + const auto& levelInputBuffer = getInputBuffer (LevelInput); + BufferHelpers::collapseToMonoBuffer (levelInputBuffer, levelOutBuffer); + } + else + { + levelOutBuffer.clear(); + } - makeupGain.setGainDecibels (*makeupDBParam); - makeupGain.process (dsp::ProcessContextReplacing { block }); + if (inputsConnected.contains (AudioInput)) + { + const auto& audioInBuffer = getInputBuffer (AudioInput); + const auto numChannels = audioInBuffer.getNumChannels(); + audioOutBuffer.setSize (numChannels, numSamples, false, false, true); + for (int ch = 0; ch < numChannels; ++ch) + audioOutBuffer.copyFrom (ch, 0, audioInBuffer, ch % numChannels, 0, numSamples); + } + else + { + audioOutBuffer.setSize (1, numSamples, false, false, true); + audioOutBuffer.clear(); + } + outputBuffers.getReference (AudioOutput) = &audioOutBuffer; + outputBuffers.getReference (LevelOutput) = &levelOutBuffer; } diff --git a/src/processors/other/Gate.h b/src/processors/other/Gate.h index 6ca4d663..764cc946 100644 --- a/src/processors/other/Gate.h +++ b/src/processors/other/Gate.h @@ -13,6 +13,7 @@ class Gate : public BaseProcessor void prepare (double sampleRate, int samplesPerBlock) override; void processAudio (AudioBuffer& buffer) override; + void processAudioBypassed (AudioBuffer& buffer) override; enum InputPort { @@ -36,7 +37,8 @@ class Gate : public BaseProcessor chowdsp::FloatParameter* releaseMsParam = nullptr; chowdsp::FloatParameter* makeupDBParam = nullptr; - AudioBuffer levelBuffer; + AudioBuffer levelOutBuffer; + AudioBuffer audioOutBuffer; class GateEnvelope; std::unique_ptr gateEnvelope;