From 56e0212cba3748b54743577e7449fa6516734dac Mon Sep 17 00:00:00 2001 From: Paul Ferrand Date: Mon, 10 Feb 2020 11:12:46 +0100 Subject: [PATCH] Adapt the processing to mono/stereo --- src/sfizz/EQPool.cpp | 9 +++++---- src/sfizz/EQPool.h | 10 ++++++---- src/sfizz/FilterPool.cpp | 9 +++++---- src/sfizz/FilterPool.h | 8 +++++--- src/sfizz/Voice.cpp | 39 ++++++++++++++++++++++++++------------- 5 files changed, 47 insertions(+), 28 deletions(-) diff --git a/src/sfizz/EQPool.cpp b/src/sfizz/EQPool.cpp index b0b76289..1004328a 100644 --- a/src/sfizz/EQPool.cpp +++ b/src/sfizz/EQPool.cpp @@ -8,7 +8,7 @@ using namespace std::chrono_literals; sfz::EQHolder::EQHolder(const MidiState& state) :midiState(state) { - eq.setChannels(2); + } void sfz::EQHolder::reset() @@ -16,9 +16,10 @@ void sfz::EQHolder::reset() eq.clear(); } -void sfz::EQHolder::setup(const EQDescription& description, uint8_t velocity) +void sfz::EQHolder::setup(const EQDescription& description, unsigned numChannels, uint8_t velocity) { reset(); + eq.setChannels(numChannels); this->description = &description; const auto normalizedVelocity = normalizeVelocity(velocity); @@ -80,7 +81,7 @@ sfz::EQPool::EQPool(const MidiState& state, int numEQs) setnumEQs(numEQs); } -sfz::EQHolderPtr sfz::EQPool::getEQ(const EQDescription& description, uint8_t velocity) +sfz::EQHolderPtr sfz::EQPool::getEQ(const EQDescription& description, unsigned numChannels, uint8_t velocity) { AtomicGuard guard { givingOutEQs }; if (!canGiveOutEQs) @@ -93,7 +94,7 @@ sfz::EQHolderPtr sfz::EQPool::getEQ(const EQDescription& description, uint8_t ve if (eq == eqs.end()) return {}; - (**eq).setup(description, velocity); + (**eq).setup(description, numChannels, velocity); return *eq; } diff --git a/src/sfizz/EQPool.h b/src/sfizz/EQPool.h index f3e2ddbf..879a2cdd 100644 --- a/src/sfizz/EQPool.h +++ b/src/sfizz/EQPool.h @@ -17,8 +17,10 @@ public: * @brief Setup a new EQ based on an EQ description. * * @param description the EQ description + * @param numChannels the number of channels for the EQ + * @param description the triggering velocity/value */ - void setup(const EQDescription& description, uint8_t velocity); + void setup(const EQDescription& description, unsigned numChannels, uint8_t velocity); /** * @brief Process a block of stereo inputs * @@ -84,11 +86,11 @@ public: * @brief Get an EQ object to use in Voices * * @param description the filter description to bind to the EQ - * @param noteNumber the triggering note number - * @param velocity the triggering note velocity + * @param numChannels the number of channels for the EQ + * @param velocity the triggering note velocity/value * @return EQHolderPtr release this when done with the filter; no deallocation will be done */ - EQHolderPtr getEQ(const EQDescription& description, uint8_t velocity); + EQHolderPtr getEQ(const EQDescription& description, unsigned numChannels, uint8_t velocity); /** * @brief Get the number of active EQs * diff --git a/src/sfizz/FilterPool.cpp b/src/sfizz/FilterPool.cpp index e64b9bde..5eb6cb3f 100644 --- a/src/sfizz/FilterPool.cpp +++ b/src/sfizz/FilterPool.cpp @@ -9,7 +9,7 @@ using namespace std::chrono_literals; sfz::FilterHolder::FilterHolder(const MidiState& midiState) : midiState(midiState) { - filter.setChannels(2); + } void sfz::FilterHolder::reset() @@ -17,11 +17,12 @@ void sfz::FilterHolder::reset() filter.clear(); } -void sfz::FilterHolder::setup(const FilterDescription& description, int noteNumber, uint8_t velocity) +void sfz::FilterHolder::setup(const FilterDescription& description, unsigned numChannels, int noteNumber, uint8_t velocity) { reset(); this->description = &description; filter.setType(description.type); + filter.setChannels(numChannels); baseCutoff = description.cutoff; if (description.random != 0) { @@ -88,7 +89,7 @@ sfz::FilterPool::FilterPool(const MidiState& state, int numFilters) setNumFilters(numFilters); } -sfz::FilterHolderPtr sfz::FilterPool::getFilter(const FilterDescription& description, int noteNumber, uint8_t velocity) +sfz::FilterHolderPtr sfz::FilterPool::getFilter(const FilterDescription& description, unsigned numChannels, int noteNumber, uint8_t velocity) { AtomicGuard guard { givingOutFilters }; if (!canGiveOutFilters) @@ -101,7 +102,7 @@ sfz::FilterHolderPtr sfz::FilterPool::getFilter(const FilterDescription& descrip if (filter == filters.end()) return {}; - (**filter).setup(description, noteNumber, velocity); + (**filter).setup(description, numChannels, noteNumber, velocity); return *filter; } diff --git a/src/sfizz/FilterPool.h b/src/sfizz/FilterPool.h index b76d48da..792777c6 100644 --- a/src/sfizz/FilterPool.h +++ b/src/sfizz/FilterPool.h @@ -17,10 +17,11 @@ public: * @brief Setup a new filter based on a filter description, and a triggering note parameters. * * @param description the filter description + * @param numChannels the number of channels * @param noteNumber the triggering note number - * @param velocity the triggering note velocity + * @param velocity the triggering note velocity/value */ - void setup(const FilterDescription& description, int noteNumber = static_cast(Default::filterKeycenter), uint8_t velocity = 0); + void setup(const FilterDescription& description, unsigned numChannels, int noteNumber = static_cast(Default::filterKeycenter), uint8_t velocity = 0); /** * @brief Process a block of stereo inputs * @@ -88,11 +89,12 @@ public: * @brief Get a filter object to use in Voices * * @param description the filter description to bind to the filter + * @param numChannels the number of channels in the underlying filter * @param noteNumber the triggering note number * @param velocity the triggering note velocity * @return FilterHolderPtr release this when done with the filter; no deallocation will be done */ - FilterHolderPtr getFilter(const FilterDescription& description, int noteNumber = static_cast(Default::filterKeycenter), uint8_t velocity = 0); + FilterHolderPtr getFilter(const FilterDescription& description, unsigned numChannels, int noteNumber = static_cast(Default::filterKeycenter), uint8_t velocity = 0); /** * @brief Get the number of active filters * diff --git a/src/sfizz/Voice.cpp b/src/sfizz/Voice.cpp index 939d1250..2a36a27c 100644 --- a/src/sfizz/Voice.cpp +++ b/src/sfizz/Voice.cpp @@ -91,14 +91,15 @@ void sfz::Voice::startVoice(Region* region, int delay, int number, uint8_t value ASSERT((filters.capacity() - filters.size()) >= region->filters.size()); ASSERT((equalizers.capacity() - equalizers.size()) >= region->equalizers.size()); + const unsigned numChannels = region->isStereo ? 2 : 1; for (auto& filter: region->filters) { - auto newFilter = resources.filterPool.getFilter(filter, number, value); + auto newFilter = resources.filterPool.getFilter(filter, numChannels, number, value); if (newFilter) filters.push_back(newFilter); } for (auto& eq: region->equalizers) { - auto newEQ = resources.eqPool.getEQ(eq, value); + auto newEQ = resources.eqPool.getEQ(eq, numChannels, value); if (newEQ) equalizers.push_back(newEQ); } @@ -276,17 +277,6 @@ void sfz::Voice::renderBlock(AudioSpan buffer) noexcept else processMono(buffer); - const float* inputChannels[2] { buffer.getChannel(0), buffer.getChannel(1) }; - float* outputChannels[2] { buffer.getChannel(0), buffer.getChannel(1) }; - - for (auto& filter: filters) { - filter->process(inputChannels, outputChannels, buffer.getNumFrames()); - } - - for (auto& eq: equalizers) { - eq->process(inputChannels, outputChannels, buffer.getNumFrames()); - } - if (!egEnvelope.isSmoothing()) reset(); @@ -319,6 +309,17 @@ void sfz::Voice::processMono(AudioSpan buffer) noexcept egEnvelope.getBlock(span1); applyGain(span1, leftBuffer); + // Filtering and EQ + const float* inputChannel[1] { leftBuffer.data() }; + float* outputChannel[1] { leftBuffer.data() }; + for (auto& filter: filters) { + filter->process(inputChannel, outputChannel, numSamples); + } + + for (auto& eq: equalizers) { + eq->process(inputChannel, outputChannel, numSamples); + } + // Prepare for stereo output copy(leftBuffer, rightBuffer); @@ -390,6 +391,18 @@ void sfz::Voice::processStereo(AudioSpan buffer) noexcept multiplyAdd(span2, span3, rightBuffer); applyGain(sqrtTwoInv, leftBuffer); applyGain(sqrtTwoInv, rightBuffer); + + // Filtering and EQ + const float* inputChannels[2] { leftBuffer.data(), rightBuffer.data() }; + float* outputChannels[2] { leftBuffer.data(), rightBuffer.data() }; + + for (auto& filter: filters) { + filter->process(inputChannels, outputChannels, numSamples); + } + + for (auto& eq: equalizers) { + eq->process(inputChannels, outputChannels, numSamples); + } } void sfz::Voice::fillWithData(AudioSpan buffer) noexcept