Adapt the processing to mono/stereo

This commit is contained in:
Paul Ferrand 2020-02-10 11:12:46 +01:00
parent d11576771d
commit 56e0212cba
5 changed files with 47 additions and 28 deletions

View file

@ -8,7 +8,7 @@ using namespace std::chrono_literals;
sfz::EQHolder::EQHolder(const MidiState& state) sfz::EQHolder::EQHolder(const MidiState& state)
:midiState(state) :midiState(state)
{ {
eq.setChannels(2);
} }
void sfz::EQHolder::reset() void sfz::EQHolder::reset()
@ -16,9 +16,10 @@ void sfz::EQHolder::reset()
eq.clear(); 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(); reset();
eq.setChannels(numChannels);
this->description = &description; this->description = &description;
const auto normalizedVelocity = normalizeVelocity(velocity); const auto normalizedVelocity = normalizeVelocity(velocity);
@ -80,7 +81,7 @@ sfz::EQPool::EQPool(const MidiState& state, int numEQs)
setnumEQs(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 }; AtomicGuard guard { givingOutEQs };
if (!canGiveOutEQs) if (!canGiveOutEQs)
@ -93,7 +94,7 @@ sfz::EQHolderPtr sfz::EQPool::getEQ(const EQDescription& description, uint8_t ve
if (eq == eqs.end()) if (eq == eqs.end())
return {}; return {};
(**eq).setup(description, velocity); (**eq).setup(description, numChannels, velocity);
return *eq; return *eq;
} }

View file

@ -17,8 +17,10 @@ public:
* @brief Setup a new EQ based on an EQ description. * @brief Setup a new EQ based on an EQ description.
* *
* @param description the 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 * @brief Process a block of stereo inputs
* *
@ -84,11 +86,11 @@ public:
* @brief Get an EQ object to use in Voices * @brief Get an EQ object to use in Voices
* *
* @param description the filter description to bind to the EQ * @param description the filter description to bind to the EQ
* @param noteNumber the triggering note number * @param numChannels the number of channels for the EQ
* @param velocity the triggering note velocity * @param velocity the triggering note velocity/value
* @return EQHolderPtr release this when done with the filter; no deallocation will be done * @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 * @brief Get the number of active EQs
* *

View file

@ -9,7 +9,7 @@ using namespace std::chrono_literals;
sfz::FilterHolder::FilterHolder(const MidiState& midiState) sfz::FilterHolder::FilterHolder(const MidiState& midiState)
: midiState(midiState) : midiState(midiState)
{ {
filter.setChannels(2);
} }
void sfz::FilterHolder::reset() void sfz::FilterHolder::reset()
@ -17,11 +17,12 @@ void sfz::FilterHolder::reset()
filter.clear(); 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(); reset();
this->description = &description; this->description = &description;
filter.setType(description.type); filter.setType(description.type);
filter.setChannels(numChannels);
baseCutoff = description.cutoff; baseCutoff = description.cutoff;
if (description.random != 0) { if (description.random != 0) {
@ -88,7 +89,7 @@ sfz::FilterPool::FilterPool(const MidiState& state, int numFilters)
setNumFilters(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 }; AtomicGuard guard { givingOutFilters };
if (!canGiveOutFilters) if (!canGiveOutFilters)
@ -101,7 +102,7 @@ sfz::FilterHolderPtr sfz::FilterPool::getFilter(const FilterDescription& descrip
if (filter == filters.end()) if (filter == filters.end())
return {}; return {};
(**filter).setup(description, noteNumber, velocity); (**filter).setup(description, numChannels, noteNumber, velocity);
return *filter; return *filter;
} }

View file

@ -17,10 +17,11 @@ public:
* @brief Setup a new filter based on a filter description, and a triggering note parameters. * @brief Setup a new filter based on a filter description, and a triggering note parameters.
* *
* @param description the filter description * @param description the filter description
* @param numChannels the number of channels
* @param noteNumber the triggering note number * @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<int>(Default::filterKeycenter), uint8_t velocity = 0); void setup(const FilterDescription& description, unsigned numChannels, int noteNumber = static_cast<int>(Default::filterKeycenter), uint8_t velocity = 0);
/** /**
* @brief Process a block of stereo inputs * @brief Process a block of stereo inputs
* *
@ -88,11 +89,12 @@ public:
* @brief Get a filter object to use in Voices * @brief Get a filter object to use in Voices
* *
* @param description the filter description to bind to the filter * @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 noteNumber the triggering note number
* @param velocity the triggering note velocity * @param velocity the triggering note velocity
* @return FilterHolderPtr release this when done with the filter; no deallocation will be done * @return FilterHolderPtr release this when done with the filter; no deallocation will be done
*/ */
FilterHolderPtr getFilter(const FilterDescription& description, int noteNumber = static_cast<int>(Default::filterKeycenter), uint8_t velocity = 0); FilterHolderPtr getFilter(const FilterDescription& description, unsigned numChannels, int noteNumber = static_cast<int>(Default::filterKeycenter), uint8_t velocity = 0);
/** /**
* @brief Get the number of active filters * @brief Get the number of active filters
* *

View file

@ -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((filters.capacity() - filters.size()) >= region->filters.size());
ASSERT((equalizers.capacity() - equalizers.size()) >= region->equalizers.size()); ASSERT((equalizers.capacity() - equalizers.size()) >= region->equalizers.size());
const unsigned numChannels = region->isStereo ? 2 : 1;
for (auto& filter: region->filters) { for (auto& filter: region->filters) {
auto newFilter = resources.filterPool.getFilter(filter, number, value); auto newFilter = resources.filterPool.getFilter(filter, numChannels, number, value);
if (newFilter) if (newFilter)
filters.push_back(newFilter); filters.push_back(newFilter);
} }
for (auto& eq: region->equalizers) { for (auto& eq: region->equalizers) {
auto newEQ = resources.eqPool.getEQ(eq, value); auto newEQ = resources.eqPool.getEQ(eq, numChannels, value);
if (newEQ) if (newEQ)
equalizers.push_back(newEQ); equalizers.push_back(newEQ);
} }
@ -276,17 +277,6 @@ void sfz::Voice::renderBlock(AudioSpan<float> buffer) noexcept
else else
processMono(buffer); 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()) if (!egEnvelope.isSmoothing())
reset(); reset();
@ -319,6 +309,17 @@ void sfz::Voice::processMono(AudioSpan<float> buffer) noexcept
egEnvelope.getBlock(span1); egEnvelope.getBlock(span1);
applyGain<float>(span1, leftBuffer); applyGain<float>(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 // Prepare for stereo output
copy<float>(leftBuffer, rightBuffer); copy<float>(leftBuffer, rightBuffer);
@ -390,6 +391,18 @@ void sfz::Voice::processStereo(AudioSpan<float> buffer) noexcept
multiplyAdd<float>(span2, span3, rightBuffer); multiplyAdd<float>(span2, span3, rightBuffer);
applyGain<float>(sqrtTwoInv<float>, leftBuffer); applyGain<float>(sqrtTwoInv<float>, leftBuffer);
applyGain<float>(sqrtTwoInv<float>, rightBuffer); applyGain<float>(sqrtTwoInv<float>, 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<float> buffer) noexcept void sfz::Voice::fillWithData(AudioSpan<float> buffer) noexcept