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 set (SFIZZ_SOURCES
sfizz/Synth.cpp sfizz/Synth.cpp
sfizz/FilePool.cpp sfizz/FilePool.cpp
sfizz/FilterPool.cpp
sfizz/Region.cpp sfizz/Region.cpp
sfizz/Voice.cpp sfizz/Voice.cpp
sfizz/ScopedFTZ.cpp sfizz/ScopedFTZ.cpp

View file

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

View file

@ -53,6 +53,7 @@ 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 };
/** /**
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

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