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 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.
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue