Initial grafting of the filters in the voice process (untested)
This commit is contained in:
parent
3aaf0005ab
commit
d455ee5232
5 changed files with 65 additions and 2 deletions
|
|
@ -53,7 +53,9 @@ namespace config {
|
|||
constexpr uint8_t numCCs { 143 };
|
||||
constexpr int chunkSize { 1024 };
|
||||
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
|
||||
modulated filter. The lower, the more CPU resources are consumed.
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ public:
|
|||
* @param state the associated midi state
|
||||
* @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
|
||||
*
|
||||
|
|
|
|||
|
|
@ -234,6 +234,9 @@ bool sfz::Synth::loadSfzFile(const fs::path& file)
|
|||
++lastRegion;
|
||||
};
|
||||
|
||||
size_t maxFilters { 0 };
|
||||
size_t maxEQs { 0 };
|
||||
|
||||
while (currentRegion < lastRegion.base()) {
|
||||
auto region = currentRegion->get();
|
||||
|
||||
|
|
@ -316,6 +319,8 @@ bool sfz::Synth::loadSfzFile(const fs::path& file)
|
|||
region->registerPitchWheel(0);
|
||||
region->registerAftertouch(0);
|
||||
region->registerTempo(2.0f);
|
||||
maxFilters = max(maxFilters, region->filters.size());
|
||||
maxEQs = max(maxEQs, region->equalizers.size());
|
||||
|
||||
++currentRegion;
|
||||
}
|
||||
|
|
@ -324,6 +329,11 @@ bool sfz::Synth::loadSfzFile(const fs::path& file)
|
|||
regions.resize(remainingRegions);
|
||||
modificationTime = checkModificationTime();
|
||||
|
||||
for (auto& voice: voices) {
|
||||
voice->setMaxFiltersPerVoice(maxFilters);
|
||||
voice->setMaxEQsPerVoice(maxEQs);
|
||||
}
|
||||
|
||||
return parserReturned;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@
|
|||
sfz::Voice::Voice(sfz::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
|
||||
|
|
@ -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()));
|
||||
|
||||
// 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();
|
||||
triggerDelay = delay;
|
||||
initialDelay = delay + static_cast<uint32_t>(region->getDelay() * sampleRate);
|
||||
|
|
@ -258,6 +272,12 @@ void sfz::Voice::renderBlock(AudioSpan<float> 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());
|
||||
}
|
||||
|
||||
if (!egEnvelope.isSmoothing())
|
||||
reset();
|
||||
|
||||
|
|
@ -528,6 +548,8 @@ void sfz::Voice::reset() noexcept
|
|||
sourcePosition = 0;
|
||||
floatPositionOffset = 0.0f;
|
||||
noteIsOff = false;
|
||||
filters.clear();
|
||||
equalizers.clear();
|
||||
}
|
||||
|
||||
float sfz::Voice::getMeanSquaredAverage() const noexcept
|
||||
|
|
@ -544,3 +566,17 @@ uint32_t sfz::Voice::getSourcePosition() const noexcept
|
|||
{
|
||||
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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -196,6 +196,18 @@ public:
|
|||
* @return
|
||||
*/
|
||||
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:
|
||||
/**
|
||||
* @brief Fill a span with data from a file source. This is the first step
|
||||
|
|
@ -283,6 +295,9 @@ private:
|
|||
|
||||
Resources& resources;
|
||||
|
||||
std::vector<FilterHolderPtr> filters;
|
||||
std::vector<FilterHolderPtr> equalizers;
|
||||
|
||||
ADSREnvelope<float> egEnvelope;
|
||||
LinearEnvelope<float> amplitudeEnvelope; // linear events
|
||||
LinearEnvelope<float> crossfadeEnvelope;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue