FilterPool (untested yet)

This commit is contained in:
Paul Fd 2020-02-08 12:09:19 +01:00
parent 7f1d825961
commit 290860502f
6 changed files with 146 additions and 1 deletions

View file

@ -3,6 +3,7 @@ include(CheckLibraryExists)
set (SFIZZ_SOURCES
sfizz/Synth.cpp
sfizz/FilePool.cpp
sfizz/FilterPool.cpp
sfizz/Region.cpp
sfizz/Voice.cpp
sfizz/ScopedFTZ.cpp

View file

@ -86,7 +86,9 @@ public:
*/
bool contains(int index) const noexcept { return container.find(index) != container.end(); }
typename std::map<int, ValueType>::iterator begin() { return container.begin(); }
typename std::map<int, ValueType>::const_iterator begin() const { return container.cbegin(); }
typename std::map<int, ValueType>::iterator end() { return container.end(); }
typename std::map<int, ValueType>::const_iterator end() const { return container.cend(); }
private:
const ValueType defaultValue;
std::map<int, ValueType> container;

View file

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

View file

@ -131,7 +131,7 @@ namespace Default
constexpr float filterGain { 0 };
constexpr int filterKeytrack { 0 };
constexpr uint8_t filterKeycenter { 60 };
constexpr int filterRandom { 60 };
constexpr int filterRandom { 0 };
constexpr int filterVeltrack { 0 };
constexpr int filterCutoffCC { 0 };
constexpr float filterResonanceCC { 0 };

97
src/sfizz/FilterPool.cpp Normal file
View file

@ -0,0 +1,97 @@
#include "FilterPool.h"
#include "SIMDHelpers.h"
#include "absl/algorithm/container.h"
sfz::FilterHolder::FilterHolder(const MidiState& midiState)
: midiState(midiState)
{
filter.setChannels(2);
}
void sfz::FilterHolder::reset()
{
filter.clear();
}
void sfz::FilterHolder::setup(const FilterDescription& description, int noteNumber, uint8_t velocity)
{
reset();
this->description = &description;
filter.setType(description.type);
baseCutoff = description.cutoff;
if (description.random != 0) {
dist.param(filterRandomDist::param_type(0, description.random));
baseCutoff *= centsFactor(dist(Random::randomGenerator));
}
const auto keytrack = description.keytrack * (noteNumber - description.keycenter);
baseCutoff *= centsFactor(keytrack);
const auto veltrack = description.veltrack * velocity;
baseCutoff *= centsFactor(veltrack);
baseGain = description.gain;
baseResonance = description.resonance;
}
void sfz::FilterHolder::process(const float** inputs, float** outputs, unsigned numFrames)
{
if (description == nullptr) {
for (unsigned channelIdx = 0; channelIdx < filter.channels(); channelIdx++)
copy<float>({ inputs[channelIdx], numFrames }, { outputs[channelIdx], numFrames });
return;
}
// TODO: Once the midistate envelopes are done, add modulation in there!
// For now we take the last value
auto cutoff = baseCutoff;
for (auto& mod: description->cutoffCC) {
cutoff *= centsFactor(midiState.getCCValue(mod.first) * mod.second);
}
auto resonance = baseResonance;
for (auto& mod: description->resonanceCC) {
resonance += midiState.getCCValue(mod.first) * mod.second;
}
auto gain = baseGain;
for (auto& mod: description->gainCC) {
gain += midiState.getCCValue(mod.first) * mod.second;
}
filter.process(inputs, outputs, cutoff, resonance, gain,numFrames);
}
sfz::FilterPool::FilterPool(const MidiState& state, int numFilters)
: midiState(state)
{
setNumFilters(numFilters);
}
sfz::FilterHolderPtr sfz::FilterPool::getFilter(const FilterDescription& description, int noteNumber, uint8_t velocity)
{
auto filter = absl::c_find_if(filters, [](const FilterHolderPtr& holder) {
return holder.use_count() == 1;
});
if (filter == filters.end())
return {};
(**filter).setup(description, noteNumber, velocity);
return *filter;
}
int sfz::FilterPool::getActiveFilters() const
{
return absl::c_count_if(filters, [](const FilterHolderPtr& holder) {
return holder.use_count() > 1;
});
}
void sfz::FilterPool::setNumFilters(int numFilters)
{
filters.clear();
filters.reserve(numFilters);
for (int i = 0; i < numFilters; ++i)
filters.emplace_back(std::make_shared<FilterHolder>(midiState));
}

44
src/sfizz/FilterPool.h Normal file
View file

@ -0,0 +1,44 @@
#pragma once
#include "SfzFilter.h"
#include "FilterDescription.h"
#include "MidiState.h"
#include <vector>
#include <memory>
namespace sfz
{
class FilterHolder
{
public:
FilterHolder() = delete;
FilterHolder(const MidiState& state);
void reset();
void setup(const FilterDescription& description, int noteNumber = static_cast<int>(Default::filterKeycenter), uint8_t velocity = 0);
void process(const float** inputs, float** outputs, unsigned numFrames);
private:
const MidiState& midiState;
const FilterDescription* description;
Filter filter;
float baseCutoff { Default::filterCutoff };
float baseResonance { Default::filterResonance };
float baseGain { Default::filterGain };
using filterRandomDist = std::uniform_int_distribution<int>;
filterRandomDist dist { 0, sfz::Default::filterRandom };
};
using FilterHolderPtr = std::shared_ptr<FilterHolder>;
class FilterPool
{
public:
FilterPool() = delete;
FilterPool(const MidiState& state, int numFilters = config::defaultNumFilters);
FilterHolderPtr getFilter(const FilterDescription& description, int noteNumber = static_cast<int>(Default::filterKeycenter), uint8_t velocity = 0);
int getActiveFilters() const;
void setNumFilters(int numFilters);
private:
const MidiState& midiState;
std::vector<FilterHolderPtr> filters;
};
}