Initial grafting of the filters in the voice process (untested)

This commit is contained in:
Paul Fd 2020-02-09 14:45:11 +01:00
parent 3aaf0005ab
commit d455ee5232
5 changed files with 65 additions and 2 deletions

View file

@ -53,7 +53,9 @@ namespace config {
constexpr uint8_t numCCs { 143 }; constexpr uint8_t numCCs { 143 };
constexpr int chunkSize { 1024 }; constexpr int chunkSize { 1024 };
constexpr float defaultAmpEGRelease { 0.02f }; constexpr float defaultAmpEGRelease { 0.02f };
constexpr int defaultNumFilters { maxVoices * 2 }; constexpr int filtersInPool { maxVoices * 2 };
constexpr int filtersPerVoice { 2 };
constexpr int eqsPerVoice { 3 };
/** /**
Minimum interval in frames between recomputations of coefficients of the Minimum interval in frames between recomputations of coefficients of the
modulated filter. The lower, the more CPU resources are consumed. modulated filter. The lower, the more CPU resources are consumed.

View file

@ -77,7 +77,7 @@ public:
* @param state the associated midi state * @param state the associated midi state
* @param numFilters the number of inactive filters to hold in the pool * @param numFilters the number of inactive filters to hold in the pool
*/ */
FilterPool(const MidiState& state, int numFilters = config::defaultNumFilters); FilterPool(const MidiState& state, int numFilters = config::filtersInPool);
/** /**
* @brief Get a filter object to use in Voices * @brief Get a filter object to use in Voices
* *

View file

@ -234,6 +234,9 @@ bool sfz::Synth::loadSfzFile(const fs::path& file)
++lastRegion; ++lastRegion;
}; };
size_t maxFilters { 0 };
size_t maxEQs { 0 };
while (currentRegion < lastRegion.base()) { while (currentRegion < lastRegion.base()) {
auto region = currentRegion->get(); auto region = currentRegion->get();
@ -316,6 +319,8 @@ bool sfz::Synth::loadSfzFile(const fs::path& file)
region->registerPitchWheel(0); region->registerPitchWheel(0);
region->registerAftertouch(0); region->registerAftertouch(0);
region->registerTempo(2.0f); region->registerTempo(2.0f);
maxFilters = max(maxFilters, region->filters.size());
maxEQs = max(maxEQs, region->equalizers.size());
++currentRegion; ++currentRegion;
} }
@ -324,6 +329,11 @@ bool sfz::Synth::loadSfzFile(const fs::path& file)
regions.resize(remainingRegions); regions.resize(remainingRegions);
modificationTime = checkModificationTime(); modificationTime = checkModificationTime();
for (auto& voice: voices) {
voice->setMaxFiltersPerVoice(maxFilters);
voice->setMaxEQsPerVoice(maxEQs);
}
return parserReturned; return parserReturned;
} }

View file

@ -17,6 +17,8 @@
sfz::Voice::Voice(sfz::Resources& resources) sfz::Voice::Voice(sfz::Resources& resources)
: resources(resources) : resources(resources)
{ {
filters.reserve(config::filtersPerVoice);
equalizers.reserve(config::filtersPerVoice);
} }
void sfz::Voice::startVoice(Region* region, int delay, int number, uint8_t value, sfz::Voice::TriggerType triggerType) noexcept void sfz::Voice::startVoice(Region* region, int delay, int number, uint8_t value, sfz::Voice::TriggerType triggerType) noexcept
@ -85,6 +87,18 @@ void sfz::Voice::startVoice(Region* region, int delay, int number, uint8_t value
}); });
pitchBendEnvelope.reset(static_cast<float>(resources.midiState.getPitchBend())); pitchBendEnvelope.reset(static_cast<float>(resources.midiState.getPitchBend()));
// Check that we can handle the number of filters; filters should be cleared here
ASSERT((filters.capacity() - filters.size()) >= region->filters.size());
ASSERT((equalizers.capacity() - equalizers.size()) >= region->equalizers.size());
for(auto& filter: region->filters) {
auto newFilter = resources.filterPool.getFilter(filter, number, value);
if (newFilter)
filters.push_back(newFilter);
}
// TODO: Equalizers
sourcePosition = region->getOffset(); sourcePosition = region->getOffset();
triggerDelay = delay; triggerDelay = delay;
initialDelay = delay + static_cast<uint32_t>(region->getDelay() * sampleRate); initialDelay = delay + static_cast<uint32_t>(region->getDelay() * sampleRate);
@ -258,6 +272,12 @@ 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());
}
if (!egEnvelope.isSmoothing()) if (!egEnvelope.isSmoothing())
reset(); reset();
@ -528,6 +548,8 @@ void sfz::Voice::reset() noexcept
sourcePosition = 0; sourcePosition = 0;
floatPositionOffset = 0.0f; floatPositionOffset = 0.0f;
noteIsOff = false; noteIsOff = false;
filters.clear();
equalizers.clear();
} }
float sfz::Voice::getMeanSquaredAverage() const noexcept float sfz::Voice::getMeanSquaredAverage() const noexcept
@ -544,3 +566,17 @@ uint32_t sfz::Voice::getSourcePosition() const noexcept
{ {
return sourcePosition; return sourcePosition;
} }
void sfz::Voice::setMaxFiltersPerVoice(size_t numFilters)
{
// There are filters in there, this call is unexpected
ASSERT(filters.size() == 0);
filters.reserve(numFilters);
}
void sfz::Voice::setMaxEQsPerVoice(size_t numFilters)
{
// There are filters in there, this call is unexpected
ASSERT(filters.size() == 0);
filters.reserve(numFilters);
}

View file

@ -196,6 +196,18 @@ public:
* @return * @return
*/ */
const Region* getRegion() const noexcept { return region; } const Region* getRegion() const noexcept { return region; }
/**
* @brief Set the max number of filters per voice
*
* @param numFilters
*/
void setMaxFiltersPerVoice(size_t numFilters);
/**
* @brief Set the max number of EQs per voice
*
* @param numFilters
*/
void setMaxEQsPerVoice(size_t numEQs);
private: private:
/** /**
* @brief Fill a span with data from a file source. This is the first step * @brief Fill a span with data from a file source. This is the first step
@ -283,6 +295,9 @@ private:
Resources& resources; Resources& resources;
std::vector<FilterHolderPtr> filters;
std::vector<FilterHolderPtr> equalizers;
ADSREnvelope<float> egEnvelope; ADSREnvelope<float> egEnvelope;
LinearEnvelope<float> amplitudeEnvelope; // linear events LinearEnvelope<float> amplitudeEnvelope; // linear events
LinearEnvelope<float> crossfadeEnvelope; LinearEnvelope<float> crossfadeEnvelope;