#include "FXProcessor.h" #include "EffectUnits/Hyper.h" #include "EffectUnits/Chorus.h" #include "EffectUnits/Flanger.h" #include "EffectUnits/Phaser.h" #include "EffectUnits/Distortion.h" #include "EffectUnits/EQ.h" #include "EffectUnits/Compressor.h" #include "EffectUnits/Delay.h" #include "EffectUnits/Reverb.h" namespace serum { FXProcessor::FXProcessor() { for (auto& slotUnits : units) { slotUnits[0] = std::make_unique(); slotUnits[1] = std::make_unique(); slotUnits[2] = std::make_unique(); slotUnits[3] = std::make_unique(); slotUnits[4] = std::make_unique(); slotUnits[5] = std::make_unique(); slotUnits[6] = std::make_unique(); slotUnits[7] = std::make_unique(); slotUnits[8] = std::make_unique(); } } FXProcessor::~FXProcessor() = default; void FXProcessor::prepare (double sampleRate, int maxBlockSize) { for (auto& slotUnits : units) for (auto& unit : slotUnits) unit->prepare (sampleRate, maxBlockSize); wet.setSize (2, maxBlockSize, false, false, true); reset(); } void FXProcessor::reset() { for (auto& slotUnits : units) for (auto& unit : slotUnits) unit->reset(); activeTypes.fill ((int) FxType::Off); wet.clear(); } juce::String FXProcessor::fxTypeName (int type) { switch ((FxType) type) { case FxType::Off: return "Off"; case FxType::Hyper: return "Hyper"; case FxType::Chorus: return "Chorus"; case FxType::Flanger: return "Flanger"; case FxType::Phaser: return "Phaser"; case FxType::Distortion: return "Distortion"; case FxType::EQ: return "EQ"; case FxType::Compressor: return "Compressor"; case FxType::Delay: return "Delay"; case FxType::Reverb: return "Reverb"; case FxType::Count: return {}; default: return {}; } } void FXProcessor::process (juce::AudioBuffer& buffer, const FxSlotParams* slots, int numSlots) { // The rack is stereo end to end; a mono buffer would read a channel that is not there. jassert (buffer.getNumChannels() >= 2); if (buffer.getNumChannels() < 2) return; const int n = buffer.getNumSamples(); jassert (n <= wet.getNumSamples()); if (n <= 0) return; for (int s = 0; s < juce::jmin (numSlots, kNumFxSlots); ++s) { const FxSlotParams& slot = slots[s]; const int unitIdx = slot.type - 1; if (unitIdx < 0 || unitIdx >= kNumEffectTypes) { activeTypes[(size_t) s] = (int) FxType::Off; continue; } auto& unit = *units[(size_t) s][(size_t) unitIdx]; if (activeTypes[(size_t) s] != slot.type) { unit.reset(); activeTypes[(size_t) s] = slot.type; } wet.copyFrom (0, 0, buffer, 0, 0, n); wet.copyFrom (1, 0, buffer, 1, 0, n); unit.process (wet.getWritePointer (0), wet.getWritePointer (1), n, slot.p); const float mix = juce::jlimit (0.0f, 1.0f, slot.mix); for (int ch = 0; ch < 2; ++ch) { float* out = buffer.getWritePointer (ch); const float* effect = wet.getReadPointer (ch); for (int i = 0; i < n; ++i) out[i] = out[i] * (1.0f - mix) + effect[i] * mix; } } } } // namespace serum