FilterPool (untested yet)
This commit is contained in:
parent
7f1d825961
commit
290860502f
6 changed files with 146 additions and 1 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
97
src/sfizz/FilterPool.cpp
Normal 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
44
src/sfizz/FilterPool.h
Normal 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;
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue