Adapt the processing to mono/stereo
This commit is contained in:
parent
d11576771d
commit
56e0212cba
5 changed files with 47 additions and 28 deletions
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue