Build time optimization: resources
This commit is contained in:
parent
f5bed98356
commit
8551caebf6
20 changed files with 494 additions and 268 deletions
|
|
@ -107,6 +107,7 @@ SFIZZ_SOURCES = \
|
|||
src/sfizz/PowerFollower.cpp \
|
||||
src/sfizz/Region.cpp \
|
||||
src/sfizz/RegionSet.cpp \
|
||||
src/sfizz/Resources.cpp \
|
||||
src/sfizz/RTSemaphore.cpp \
|
||||
src/sfizz/ScopedFTZ.cpp \
|
||||
src/sfizz/sfizz.cpp \
|
||||
|
|
|
|||
|
|
@ -161,6 +161,7 @@ set(SFIZZ_SOURCES
|
|||
sfizz/WindowedSinc.cpp
|
||||
sfizz/Interpolators.cpp
|
||||
sfizz/Layer.cpp
|
||||
sfizz/Resources.cpp
|
||||
sfizz/modulations/ModId.cpp
|
||||
sfizz/modulations/ModKey.cpp
|
||||
sfizz/modulations/ModKeyHash.cpp
|
||||
|
|
|
|||
|
|
@ -1,4 +1,7 @@
|
|||
#include "EQPool.h"
|
||||
#include "Region.h"
|
||||
#include "Resources.h"
|
||||
#include "BufferPool.h"
|
||||
#include "SIMDHelpers.h"
|
||||
#include "utility/SwapAndPop.h"
|
||||
#include <absl/algorithm/container.h>
|
||||
|
|
@ -31,9 +34,10 @@ void sfz::EQHolder::setup(const Region& region, unsigned eqId, float velocity)
|
|||
baseBandwidth = description->bandwidth;
|
||||
baseGain = description->gain + velocity * description->vel2gain;
|
||||
|
||||
gainTarget = resources.modMatrix.findTarget(ModKey::createNXYZ(ModId::EqGain, region.id, eqId));
|
||||
bandwidthTarget = resources.modMatrix.findTarget(ModKey::createNXYZ(ModId::EqBandwidth, region.id, eqId));
|
||||
frequencyTarget = resources.modMatrix.findTarget(ModKey::createNXYZ(ModId::EqFrequency, region.id, eqId));
|
||||
const ModMatrix& mm = resources.getModMatrix();
|
||||
gainTarget = mm.findTarget(ModKey::createNXYZ(ModId::EqGain, region.id, eqId));
|
||||
bandwidthTarget = mm.findTarget(ModKey::createNXYZ(ModId::EqBandwidth, region.id, eqId));
|
||||
frequencyTarget = mm.findTarget(ModKey::createNXYZ(ModId::EqFrequency, region.id, eqId));
|
||||
|
||||
// Disables smoothing of the parameters on the first call
|
||||
prepared = false;
|
||||
|
|
@ -47,10 +51,11 @@ void sfz::EQHolder::process(const float** inputs, float** outputs, unsigned numF
|
|||
return;
|
||||
}
|
||||
|
||||
ModMatrix& mm = resources.modMatrix;
|
||||
auto frequencySpan = resources.bufferPool.getBuffer(numFrames);
|
||||
auto bandwidthSpan = resources.bufferPool.getBuffer(numFrames);
|
||||
auto gainSpan = resources.bufferPool.getBuffer(numFrames);
|
||||
ModMatrix& mm = resources.getModMatrix();
|
||||
BufferPool& bufferPool = resources.getBufferPool();
|
||||
auto frequencySpan = bufferPool.getBuffer(numFrames);
|
||||
auto bandwidthSpan = bufferPool.getBuffer(numFrames);
|
||||
auto gainSpan = bufferPool.getBuffer(numFrames);
|
||||
|
||||
if (!frequencySpan || !bandwidthSpan || !gainSpan)
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -1,12 +1,14 @@
|
|||
#pragma once
|
||||
#include "SfzFilter.h"
|
||||
#include "Region.h"
|
||||
#include "Resources.h"
|
||||
#include "Defaults.h"
|
||||
#include "modulations/ModMatrix.h"
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
namespace sfz
|
||||
{
|
||||
namespace sfz {
|
||||
struct Region;
|
||||
class Resources;
|
||||
struct EQDescription;
|
||||
|
||||
class EQHolder
|
||||
{
|
||||
|
|
@ -52,4 +54,4 @@ private:
|
|||
ModMatrix::TargetId bandwidthTarget;
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace sfz
|
||||
|
|
|
|||
|
|
@ -1,4 +1,7 @@
|
|||
#include "FilterPool.h"
|
||||
#include "Region.h"
|
||||
#include "Resources.h"
|
||||
#include "BufferPool.h"
|
||||
#include "SIMDHelpers.h"
|
||||
#include "utility/SwapAndPop.h"
|
||||
#include <absl/algorithm/container.h>
|
||||
|
|
@ -42,7 +45,7 @@ void sfz::FilterHolder::setup(const Region& region, unsigned filterId, int noteN
|
|||
baseGain = description->gain;
|
||||
baseResonance = description->resonance;
|
||||
|
||||
ModMatrix& mm = resources.modMatrix;
|
||||
ModMatrix& mm = resources.getModMatrix();
|
||||
gainTarget = mm.findTarget(ModKey::createNXYZ(ModId::FilGain, region.id, filterId));
|
||||
cutoffTarget = mm.findTarget(ModKey::createNXYZ(ModId::FilCutoff, region.id, filterId));
|
||||
resonanceTarget = mm.findTarget(ModKey::createNXYZ(ModId::FilResonance, region.id, filterId));
|
||||
|
|
@ -62,10 +65,11 @@ void sfz::FilterHolder::process(const float** inputs, float** outputs, unsigned
|
|||
return;
|
||||
}
|
||||
|
||||
ModMatrix& mm = resources.modMatrix;
|
||||
auto cutoffSpan = resources.bufferPool.getBuffer(numFrames);
|
||||
auto resonanceSpan = resources.bufferPool.getBuffer(numFrames);
|
||||
auto gainSpan = resources.bufferPool.getBuffer(numFrames);
|
||||
ModMatrix& mm = resources.getModMatrix();
|
||||
BufferPool& bufferPool = resources.getBufferPool();
|
||||
auto cutoffSpan = bufferPool.getBuffer(numFrames);
|
||||
auto resonanceSpan = bufferPool.getBuffer(numFrames);
|
||||
auto gainSpan = bufferPool.getBuffer(numFrames);
|
||||
|
||||
if (!cutoffSpan || !resonanceSpan || !gainSpan)
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -1,13 +1,14 @@
|
|||
#pragma once
|
||||
#include "SfzFilter.h"
|
||||
#include "Region.h"
|
||||
#include "Resources.h"
|
||||
#include "Defaults.h"
|
||||
#include "modulations/ModMatrix.h"
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
namespace sfz
|
||||
{
|
||||
namespace sfz {
|
||||
struct Region;
|
||||
class Resources;
|
||||
struct FilterDescription;
|
||||
|
||||
class FilterHolder
|
||||
{
|
||||
|
|
@ -54,4 +55,4 @@ private:
|
|||
bool prepared { false };
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace sfz
|
||||
|
|
|
|||
|
|
@ -10,6 +10,10 @@
|
|||
#include "SIMDHelpers.h"
|
||||
#include "Config.h"
|
||||
#include "Resources.h"
|
||||
#include "BufferPool.h"
|
||||
#include "BeatClock.h"
|
||||
#include "MidiState.h"
|
||||
#include "modulations/ModMatrix.h"
|
||||
#include "modulations/ModKey.h"
|
||||
#include "modulations/ModId.h"
|
||||
#include <array>
|
||||
|
|
@ -61,7 +65,7 @@ void LFO::setSampleRate(double sampleRate)
|
|||
void LFO::configure(const LFODescription* desc)
|
||||
{
|
||||
Impl& impl = *impl_;
|
||||
ModMatrix& modMatrix = impl.resources_.modMatrix;
|
||||
ModMatrix& modMatrix = impl.resources_.getModMatrix();
|
||||
impl.desc_ = desc ? desc : &LFODescription::getDefault();
|
||||
impl.beatsKeyId = modMatrix.findTarget(desc->beatsKey);
|
||||
impl.freqKeyId = modMatrix.findTarget(desc->freqKey);
|
||||
|
|
@ -73,7 +77,7 @@ void LFO::start(unsigned triggerDelay)
|
|||
Impl& impl = *impl_;
|
||||
const LFODescription& desc = *impl.desc_;
|
||||
const float sampleRate = impl.sampleRate_;
|
||||
const MidiState& state = impl.resources_.midiState;
|
||||
const MidiState& state = impl.resources_.getMidiState();
|
||||
|
||||
impl.subPhases_.fill(0.0f);
|
||||
impl.sampleHoldMem_.fill(0.0f);
|
||||
|
|
@ -230,7 +234,7 @@ void LFO::process(absl::Span<float> out)
|
|||
{
|
||||
Impl& impl = *impl_;
|
||||
const LFODescription& desc = *impl.desc_;
|
||||
BufferPool& pool = impl.resources_.bufferPool;
|
||||
BufferPool& pool = impl.resources_.getBufferPool();
|
||||
size_t numFrames = out.size();
|
||||
|
||||
fill(out, 0.0f);
|
||||
|
|
@ -323,9 +327,9 @@ void LFO::processFadeIn(absl::Span<float> out)
|
|||
void LFO::generatePhase(unsigned nth, absl::Span<float> phases)
|
||||
{
|
||||
Impl& impl = *impl_;
|
||||
BufferPool& bufferPool = impl.resources_.bufferPool;
|
||||
BeatClock& beatClock = impl.resources_.beatClock;
|
||||
ModMatrix& modMatrix = impl.resources_.modMatrix;
|
||||
BufferPool& bufferPool = impl.resources_.getBufferPool();
|
||||
BeatClock& beatClock = impl.resources_.getBeatClock();
|
||||
ModMatrix& modMatrix = impl.resources_.getModMatrix();
|
||||
const LFODescription& desc = *impl.desc_;
|
||||
const LFODescription::Sub& sub = desc.sub[nth];
|
||||
const float samplePeriod = 1.0f / impl.sampleRate_;
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
#include <memory>
|
||||
|
||||
namespace sfz {
|
||||
struct Resources;
|
||||
class Resources;
|
||||
struct Region;
|
||||
|
||||
enum class LFOWave : int;
|
||||
|
|
|
|||
137
src/sfizz/Resources.cpp
Normal file
137
src/sfizz/Resources.cpp
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
// This code is part of the sfizz library and is licensed under a BSD 2-clause
|
||||
// license. You should have receive a LICENSE.md file along with the code.
|
||||
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
|
||||
|
||||
#include "Resources.h"
|
||||
#include "SynthConfig.h"
|
||||
#include "MidiState.h"
|
||||
#include "FilePool.h"
|
||||
#include "BufferPool.h"
|
||||
#include "Logger.h"
|
||||
#include "Wavetables.h"
|
||||
#include "Curve.h"
|
||||
#include "Tuning.h"
|
||||
#include "BeatClock.h"
|
||||
#include "Metronome.h"
|
||||
#include "modulations/ModMatrix.h"
|
||||
|
||||
namespace sfz {
|
||||
|
||||
struct Resources::Impl {
|
||||
SynthConfig synthConfig;
|
||||
BufferPool bufferPool;
|
||||
MidiState midiState;
|
||||
Logger logger;
|
||||
CurveSet curves;
|
||||
FilePool filePool { logger };
|
||||
WavetablePool wavePool;
|
||||
Tuning tuning;
|
||||
absl::optional<StretchTuning> stretch;
|
||||
ModMatrix modMatrix;
|
||||
BeatClock beatClock;
|
||||
Metronome metronome;
|
||||
};
|
||||
|
||||
Resources::Resources()
|
||||
: impl_(new Impl)
|
||||
{
|
||||
}
|
||||
|
||||
Resources::~Resources()
|
||||
{
|
||||
}
|
||||
|
||||
void Resources::setSampleRate(float samplerate)
|
||||
{
|
||||
Impl& impl = *impl_;
|
||||
impl.midiState.setSampleRate(samplerate);
|
||||
impl.modMatrix.setSampleRate(samplerate);
|
||||
impl.beatClock.setSampleRate(samplerate);
|
||||
impl.metronome.init(samplerate);
|
||||
}
|
||||
|
||||
void Resources::setSamplesPerBlock(int samplesPerBlock)
|
||||
{
|
||||
Impl& impl = *impl_;
|
||||
impl.bufferPool.setBufferSize(samplesPerBlock);
|
||||
impl.midiState.setSamplesPerBlock(samplesPerBlock);
|
||||
impl.modMatrix.setSamplesPerBlock(samplesPerBlock);
|
||||
impl.beatClock.setSamplesPerBlock(samplesPerBlock);
|
||||
}
|
||||
|
||||
void Resources::clear()
|
||||
{
|
||||
Impl& impl = *impl_;
|
||||
impl.curves = CurveSet::createPredefined();
|
||||
impl.filePool.clear();
|
||||
impl.wavePool.clearFileWaves();
|
||||
impl.logger.clear();
|
||||
impl.midiState.reset();
|
||||
impl.modMatrix.clear();
|
||||
impl.beatClock.clear();
|
||||
impl.metronome.clear();
|
||||
}
|
||||
|
||||
const SynthConfig& Resources::getSynthConfig() const noexcept
|
||||
{
|
||||
return impl_->synthConfig;
|
||||
}
|
||||
|
||||
const BufferPool& Resources::getBufferPool() const noexcept
|
||||
{
|
||||
return impl_->bufferPool;
|
||||
}
|
||||
|
||||
const MidiState& Resources::getMidiState() const noexcept
|
||||
{
|
||||
return impl_->midiState;
|
||||
}
|
||||
|
||||
const Logger& Resources::getLogger() const noexcept
|
||||
{
|
||||
return impl_->logger;
|
||||
}
|
||||
|
||||
const CurveSet& Resources::getCurves() const noexcept
|
||||
{
|
||||
return impl_->curves;
|
||||
}
|
||||
|
||||
const FilePool& Resources::getFilePool() const noexcept
|
||||
{
|
||||
return impl_->filePool;
|
||||
}
|
||||
|
||||
const WavetablePool& Resources::getWavePool() const noexcept
|
||||
{
|
||||
return impl_->wavePool;
|
||||
}
|
||||
|
||||
const Tuning& Resources::getTuning() const noexcept
|
||||
{
|
||||
return impl_->tuning;
|
||||
}
|
||||
|
||||
const absl::optional<StretchTuning>& Resources::getStretch() const noexcept
|
||||
{
|
||||
return impl_->stretch;
|
||||
}
|
||||
|
||||
const ModMatrix& Resources::getModMatrix() const noexcept
|
||||
{
|
||||
return impl_->modMatrix;
|
||||
}
|
||||
|
||||
const BeatClock& Resources::getBeatClock() const noexcept
|
||||
{
|
||||
return impl_->beatClock;
|
||||
}
|
||||
|
||||
const Metronome& Resources::getMetronome() const noexcept
|
||||
{
|
||||
return impl_->metronome;
|
||||
}
|
||||
|
||||
} // namespace sfz
|
||||
|
|
@ -5,64 +5,56 @@
|
|||
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
|
||||
|
||||
#pragma once
|
||||
#include "SynthConfig.h"
|
||||
#include "MidiState.h"
|
||||
#include "FilePool.h"
|
||||
#include "BufferPool.h"
|
||||
#include "Logger.h"
|
||||
#include "Wavetables.h"
|
||||
#include "Curve.h"
|
||||
#include "Tuning.h"
|
||||
#include "BeatClock.h"
|
||||
#include "Metronome.h"
|
||||
#include "modulations/ModMatrix.h"
|
||||
#include "absl/types/optional.h"
|
||||
#include <memory>
|
||||
|
||||
namespace sfz
|
||||
namespace sfz {
|
||||
|
||||
struct SynthConfig;
|
||||
class BufferPool;
|
||||
class MidiState;
|
||||
class Logger;
|
||||
class CurveSet;
|
||||
class FilePool;
|
||||
struct WavetablePool;
|
||||
class Tuning;
|
||||
class StretchTuning;
|
||||
class ModMatrix;
|
||||
class BeatClock;
|
||||
class Metronome;
|
||||
|
||||
class Resources
|
||||
{
|
||||
class WavetableMulti;
|
||||
public:
|
||||
Resources();
|
||||
~Resources();
|
||||
|
||||
struct Resources
|
||||
{
|
||||
SynthConfig synthConfig;
|
||||
BufferPool bufferPool;
|
||||
MidiState midiState;
|
||||
Logger logger;
|
||||
CurveSet curves;
|
||||
FilePool filePool { logger };
|
||||
WavetablePool wavePool;
|
||||
Tuning tuning;
|
||||
absl::optional<StretchTuning> stretch;
|
||||
ModMatrix modMatrix;
|
||||
BeatClock beatClock;
|
||||
Metronome metronome;
|
||||
void setSampleRate(float samplerate);
|
||||
void setSamplesPerBlock(int samplesPerBlock);
|
||||
void clear();
|
||||
|
||||
void setSampleRate(float samplerate)
|
||||
{
|
||||
midiState.setSampleRate(samplerate);
|
||||
modMatrix.setSampleRate(samplerate);
|
||||
beatClock.setSampleRate(samplerate);
|
||||
metronome.init(samplerate);
|
||||
}
|
||||
#define ACCESSOR_RW(Accessor, RetTy) \
|
||||
RetTy const& Accessor() const noexcept; \
|
||||
RetTy& Accessor() noexcept { return const_cast<RetTy&>(const_cast<const Resources*>(this)->Accessor()); }
|
||||
|
||||
void setSamplesPerBlock(int samplesPerBlock)
|
||||
{
|
||||
bufferPool.setBufferSize(samplesPerBlock);
|
||||
midiState.setSamplesPerBlock(samplesPerBlock);
|
||||
modMatrix.setSamplesPerBlock(samplesPerBlock);
|
||||
beatClock.setSamplesPerBlock(samplesPerBlock);
|
||||
}
|
||||
ACCESSOR_RW(getSynthConfig, SynthConfig);
|
||||
ACCESSOR_RW(getBufferPool, BufferPool);
|
||||
ACCESSOR_RW(getMidiState, MidiState);
|
||||
ACCESSOR_RW(getLogger, Logger);
|
||||
ACCESSOR_RW(getCurves, CurveSet);
|
||||
ACCESSOR_RW(getFilePool, FilePool);
|
||||
ACCESSOR_RW(getWavePool, WavetablePool);
|
||||
ACCESSOR_RW(getTuning, Tuning);
|
||||
ACCESSOR_RW(getStretch, absl::optional<StretchTuning>);
|
||||
ACCESSOR_RW(getModMatrix, ModMatrix);
|
||||
ACCESSOR_RW(getBeatClock, BeatClock);
|
||||
ACCESSOR_RW(getMetronome, Metronome);
|
||||
|
||||
void clear()
|
||||
{
|
||||
curves = CurveSet::createPredefined();
|
||||
filePool.clear();
|
||||
wavePool.clearFileWaves();
|
||||
logger.clear();
|
||||
midiState.reset();
|
||||
modMatrix.clear();
|
||||
beatClock.clear();
|
||||
metronome.clear();
|
||||
}
|
||||
#undef ACCESSOR_RW
|
||||
|
||||
private:
|
||||
struct Impl;
|
||||
std::unique_ptr<Impl> impl_;
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace sfz
|
||||
|
|
|
|||
|
|
@ -16,6 +16,13 @@
|
|||
#include "Region.h"
|
||||
#include "RegionSet.h"
|
||||
#include "Resources.h"
|
||||
#include "BufferPool.h"
|
||||
#include "FilePool.h"
|
||||
#include "Wavetables.h"
|
||||
#include "Tuning.h"
|
||||
#include "BeatClock.h"
|
||||
#include "Metronome.h"
|
||||
#include "SynthConfig.h"
|
||||
#include "ScopedFTZ.h"
|
||||
#include "utility/StringViewHelpers.h"
|
||||
#include "utility/XmlHelpers.h"
|
||||
|
|
@ -59,18 +66,19 @@ Synth::Impl::Impl()
|
|||
resetVoices(config::numVoices);
|
||||
|
||||
// modulation sources
|
||||
MidiState& midiState = resources_.getMidiState();
|
||||
genController_.reset(new ControllerSource(resources_, voiceManager_));
|
||||
genLFO_.reset(new LFOSource(voiceManager_));
|
||||
genFlexEnvelope_.reset(new FlexEnvelopeSource(voiceManager_));
|
||||
genADSREnvelope_.reset(new ADSREnvelopeSource(voiceManager_, resources_.midiState));
|
||||
genChannelAftertouch_.reset(new ChannelAftertouchSource(voiceManager_, resources_.midiState));
|
||||
genPolyAftertouch_.reset(new PolyAftertouchSource(voiceManager_, resources_.midiState));
|
||||
genADSREnvelope_.reset(new ADSREnvelopeSource(voiceManager_, midiState));
|
||||
genChannelAftertouch_.reset(new ChannelAftertouchSource(voiceManager_, midiState));
|
||||
genPolyAftertouch_.reset(new PolyAftertouchSource(voiceManager_, midiState));
|
||||
}
|
||||
|
||||
Synth::Impl::~Impl()
|
||||
{
|
||||
voiceManager_.reset();
|
||||
resources_.filePool.emptyFileLoadingQueues();
|
||||
resources_.getFilePool().emptyFileLoadingQueues();
|
||||
}
|
||||
|
||||
void Synth::Impl::onParseFullBlock(const std::string& header, const std::vector<Opcode>& members)
|
||||
|
|
@ -113,7 +121,7 @@ void Synth::Impl::onParseFullBlock(const std::string& header, const std::vector<
|
|||
buildRegion(members);
|
||||
break;
|
||||
case hash("curve"):
|
||||
resources_.curves.addCurveFromHeader(members);
|
||||
resources_.getCurves().addCurveFromHeader(members);
|
||||
break;
|
||||
case hash("effect"):
|
||||
handleEffectOpcodes(members);
|
||||
|
|
@ -138,7 +146,8 @@ void Synth::Impl::onParseWarning(const SourceRange& range, const std::string& me
|
|||
void Synth::Impl::buildRegion(const std::vector<Opcode>& regionOpcodes)
|
||||
{
|
||||
int regionNumber = static_cast<int>(layers_.size());
|
||||
Layer* lastLayer = new Layer(regionNumber, defaultPath_, resources_.midiState);
|
||||
MidiState& midiState = resources_.getMidiState();
|
||||
Layer* lastLayer = new Layer(regionNumber, defaultPath_, midiState);
|
||||
layers_.emplace_back(lastLayer);
|
||||
Region* lastRegion = &lastLayer->getRegion();
|
||||
|
||||
|
|
@ -221,8 +230,11 @@ void Synth::Impl::buildRegion(const std::vector<Opcode>& regionOpcodes)
|
|||
|
||||
void Synth::Impl::clear()
|
||||
{
|
||||
FilePool& filePool = resources_.getFilePool();
|
||||
MidiState& midiState = resources_.getMidiState();
|
||||
|
||||
// Clear the background queues before removing everyone
|
||||
resources_.filePool.waitForBackgroundLoading();
|
||||
filePool.waitForBackgroundLoading();
|
||||
|
||||
voiceManager_.reset();
|
||||
for (auto& list : lastKeyswitchLists_)
|
||||
|
|
@ -253,9 +265,9 @@ void Synth::Impl::clear()
|
|||
currentSwitch_ = absl::nullopt;
|
||||
defaultPath_ = "";
|
||||
image_ = "";
|
||||
resources_.midiState.reset();
|
||||
resources_.filePool.clear();
|
||||
resources_.filePool.setRamLoading(config::loadInRam);
|
||||
midiState.reset();
|
||||
filePool.clear();
|
||||
filePool.setRamLoading(config::loadInRam);
|
||||
clearCCLabels();
|
||||
currentUsedCCs_.clear();
|
||||
changedCCsThisCycle_.clear();
|
||||
|
|
@ -399,13 +411,16 @@ void Synth::Impl::handleControlOpcodes(const std::vector<Opcode>& members)
|
|||
octaveOffset_ = member.read(Default::octaveOffset);
|
||||
break;
|
||||
case hash("hint_ram_based"):
|
||||
{
|
||||
FilePool& filePool = resources_.getFilePool();
|
||||
if (member.value == "1")
|
||||
resources_.filePool.setRamLoading(true);
|
||||
filePool.setRamLoading(true);
|
||||
else if (member.value == "0")
|
||||
resources_.filePool.setRamLoading(false);
|
||||
filePool.setRamLoading(false);
|
||||
else
|
||||
DBG("Unsupported value for hint_ram_based: " << member.value);
|
||||
break;
|
||||
}
|
||||
case hash("hint_stealing"):
|
||||
switch(hash(member.value)) {
|
||||
case hash("first"):
|
||||
|
|
@ -550,7 +565,8 @@ bool Synth::loadSfzString(const fs::path& path, absl::string_view text)
|
|||
void Synth::Impl::finalizeSfzLoad()
|
||||
{
|
||||
const fs::path& rootDirectory = parser_.originalDirectory();
|
||||
resources_.filePool.setRootDirectory(rootDirectory);
|
||||
FilePool& filePool = resources_.getFilePool();
|
||||
filePool.setRootDirectory(rootDirectory);
|
||||
|
||||
// a string representation used for OSC purposes
|
||||
rootPath_ = rootDirectory.u8string();
|
||||
|
|
@ -583,13 +599,16 @@ void Synth::Impl::finalizeSfzLoad()
|
|||
|
||||
absl::optional<FileInformation> fileInformation;
|
||||
|
||||
FilePool& filePool = resources_.getFilePool();
|
||||
WavetablePool& wavePool = resources_.getWavePool();
|
||||
|
||||
if (!region.isGenerator()) {
|
||||
if (!resources_.filePool.checkSampleId(*region.sampleId)) {
|
||||
if (!filePool.checkSampleId(*region.sampleId)) {
|
||||
removeCurrentRegion();
|
||||
continue;
|
||||
}
|
||||
|
||||
fileInformation = resources_.filePool.getFileInformation(*region.sampleId);
|
||||
fileInformation = filePool.getFileInformation(*region.sampleId);
|
||||
if (!fileInformation) {
|
||||
removeCurrentRegion();
|
||||
continue;
|
||||
|
|
@ -598,7 +617,7 @@ void Synth::Impl::finalizeSfzLoad()
|
|||
region.hasWavetableSample = fileInformation->wavetable.has_value();
|
||||
|
||||
if (fileInformation->end < config::wavetableMaxFrames) {
|
||||
auto sample = resources_.filePool.loadFile(*region.sampleId);
|
||||
auto sample = filePool.loadFile(*region.sampleId);
|
||||
bool allZeros = true;
|
||||
int numChannels = sample->information.numChannels;
|
||||
for (int i = 0; i < numChannels; ++i) {
|
||||
|
|
@ -653,13 +672,13 @@ void Synth::Impl::finalizeSfzLoad()
|
|||
return Default::offsetMod.bounds.clamp(sumOffsetCC);
|
||||
}();
|
||||
|
||||
if (!resources_.filePool.preloadFile(*region.sampleId, maxOffset)) {
|
||||
if (!filePool.preloadFile(*region.sampleId, maxOffset)) {
|
||||
removeCurrentRegion();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (!region.isGenerator()) {
|
||||
if (!resources_.wavePool.createFileWave(resources_.filePool, std::string(region.sampleId->filename()))) {
|
||||
if (!wavePool.createFileWave(filePool, std::string(region.sampleId->filename()))) {
|
||||
removeCurrentRegion();
|
||||
continue;
|
||||
}
|
||||
|
|
@ -698,8 +717,9 @@ void Synth::Impl::finalizeSfzLoad()
|
|||
}
|
||||
|
||||
// Defaults
|
||||
MidiState& midiState = resources_.getMidiState();
|
||||
for (int cc = 0; cc < config::numCCs; cc++) {
|
||||
layer.registerCC(cc, resources_.midiState.getCCValue(cc));
|
||||
layer.registerCC(cc, midiState.getCCValue(cc));
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -819,37 +839,37 @@ void Synth::Impl::finalizeSfzLoad()
|
|||
bool Synth::loadScalaFile(const fs::path& path)
|
||||
{
|
||||
Impl& impl = *impl_;
|
||||
return impl.resources_.tuning.loadScalaFile(path);
|
||||
return impl.resources_.getTuning().loadScalaFile(path);
|
||||
}
|
||||
|
||||
bool Synth::loadScalaString(const std::string& text)
|
||||
{
|
||||
Impl& impl = *impl_;
|
||||
return impl.resources_.tuning.loadScalaString(text);
|
||||
return impl.resources_.getTuning().loadScalaString(text);
|
||||
}
|
||||
|
||||
void Synth::setScalaRootKey(int rootKey)
|
||||
{
|
||||
Impl& impl = *impl_;
|
||||
impl.resources_.tuning.setScalaRootKey(rootKey);
|
||||
impl.resources_.getTuning().setScalaRootKey(rootKey);
|
||||
}
|
||||
|
||||
int Synth::getScalaRootKey() const
|
||||
{
|
||||
Impl& impl = *impl_;
|
||||
return impl.resources_.tuning.getScalaRootKey();
|
||||
return impl.resources_.getTuning().getScalaRootKey();
|
||||
}
|
||||
|
||||
void Synth::setTuningFrequency(float frequency)
|
||||
{
|
||||
Impl& impl = *impl_;
|
||||
impl.resources_.tuning.setTuningFrequency(frequency);
|
||||
impl.resources_.getTuning().setTuningFrequency(frequency);
|
||||
}
|
||||
|
||||
float Synth::getTuningFrequency() const
|
||||
{
|
||||
Impl& impl = *impl_;
|
||||
return impl.resources_.tuning.getTuningFrequency();
|
||||
return impl.resources_.getTuning().getTuningFrequency();
|
||||
}
|
||||
|
||||
void Synth::loadStretchTuningByRatio(float ratio)
|
||||
|
|
@ -858,10 +878,11 @@ void Synth::loadStretchTuningByRatio(float ratio)
|
|||
SFIZZ_CHECK(ratio >= 0.0f && ratio <= 1.0f);
|
||||
ratio = clamp(ratio, 0.0f, 1.0f);
|
||||
|
||||
absl::optional<StretchTuning>& stretch = impl.resources_.getStretch();
|
||||
if (ratio > 0.0f)
|
||||
impl.resources_.stretch = StretchTuning::createRailsbackFromRatio(ratio);
|
||||
stretch = StretchTuning::createRailsbackFromRatio(ratio);
|
||||
else
|
||||
impl.resources_.stretch.reset();
|
||||
stretch.reset();
|
||||
}
|
||||
|
||||
int Synth::getNumActiveVoices() const noexcept
|
||||
|
|
@ -931,8 +952,12 @@ void Synth::renderBlock(AudioSpan<float> buffer) noexcept
|
|||
return;
|
||||
}
|
||||
|
||||
if (impl.resources_.synthConfig.freeWheeling)
|
||||
impl.resources_.filePool.waitForBackgroundLoading();
|
||||
const SynthConfig& synthConfig = impl.resources_.getSynthConfig();
|
||||
FilePool& filePool = impl.resources_.getFilePool();
|
||||
BufferPool& bufferPool = impl.resources_.getBufferPool();
|
||||
|
||||
if (synthConfig.freeWheeling)
|
||||
filePool.waitForBackgroundLoading();
|
||||
|
||||
const auto now = std::chrono::high_resolution_clock::now();
|
||||
const auto timeSinceLastCollection =
|
||||
|
|
@ -940,25 +965,27 @@ void Synth::renderBlock(AudioSpan<float> buffer) noexcept
|
|||
|
||||
if (timeSinceLastCollection.count() > config::fileClearingPeriod) {
|
||||
impl.lastGarbageCollection_ = now;
|
||||
impl.resources_.filePool.triggerGarbageCollection();
|
||||
filePool.triggerGarbageCollection();
|
||||
}
|
||||
|
||||
auto tempSpan = impl.resources_.bufferPool.getStereoBuffer(numFrames);
|
||||
auto tempMixSpan = impl.resources_.bufferPool.getStereoBuffer(numFrames);
|
||||
auto rampSpan = impl.resources_.bufferPool.getBuffer(numFrames);
|
||||
auto tempSpan = bufferPool.getStereoBuffer(numFrames);
|
||||
auto tempMixSpan = bufferPool.getStereoBuffer(numFrames);
|
||||
auto rampSpan = bufferPool.getBuffer(numFrames);
|
||||
if (!tempSpan || !tempMixSpan || !rampSpan) {
|
||||
DBG("[sfizz] Could not get a temporary buffer; exiting callback... ");
|
||||
return;
|
||||
}
|
||||
|
||||
ModMatrix& mm = impl.resources_.modMatrix;
|
||||
ModMatrix& mm = impl.resources_.getModMatrix();
|
||||
mm.beginCycle(numFrames);
|
||||
|
||||
BeatClock& bc = impl.resources_.beatClock;
|
||||
BeatClock& bc = impl.resources_.getBeatClock();
|
||||
bc.beginCycle(numFrames);
|
||||
|
||||
if (impl.playheadMoved_ && impl.resources_.beatClock.isPlaying()) {
|
||||
impl.resources_.midiState.flushEvents();
|
||||
MidiState& midiState = impl.resources_.getMidiState();
|
||||
|
||||
if (impl.playheadMoved_ && bc.isPlaying()) {
|
||||
midiState.flushEvents();
|
||||
impl.genController_->resetSmoothers();
|
||||
impl.playheadMoved_ = false;
|
||||
}
|
||||
|
|
@ -1028,7 +1055,8 @@ void Synth::renderBlock(AudioSpan<float> buffer) noexcept
|
|||
// Process the metronome (debugging tool for host time info)
|
||||
constexpr bool metronomeEnabled = false;
|
||||
if (metronomeEnabled) {
|
||||
impl.resources_.metronome.processAdding(
|
||||
Metronome& metro = impl.resources_.getMetronome();
|
||||
metro.processAdding(
|
||||
bc.getRunningBeatNumber().data(), bc.getRunningBeatsPerBar().data(),
|
||||
buffer.getChannel(0), buffer.getChannel(1), numFrames);
|
||||
}
|
||||
|
|
@ -1045,11 +1073,12 @@ void Synth::renderBlock(AudioSpan<float> buffer) noexcept
|
|||
|
||||
{ // Clear events and advance midi time
|
||||
ScopedTiming logger { impl.dispatchDuration_, ScopedTiming::Operation::addToDuration };
|
||||
impl.resources_.midiState.advanceTime(buffer.getNumFrames());
|
||||
midiState.advanceTime(buffer.getNumFrames());
|
||||
}
|
||||
|
||||
callbackBreakdown.dispatch = impl.dispatchDuration_;
|
||||
impl.resources_.logger.logCallbackTime(
|
||||
Logger& logger = impl.resources_.getLogger();
|
||||
logger.logCallbackTime(
|
||||
callbackBreakdown, impl.voiceManager_.getNumActiveVoices(), numFrames);
|
||||
|
||||
// Reset the dispatch counter
|
||||
|
|
@ -1073,7 +1102,7 @@ void Synth::hdNoteOn(int delay, int noteNumber, float normalizedVelocity) noexce
|
|||
ASSERT(noteNumber >= 0);
|
||||
Impl& impl = *impl_;
|
||||
ScopedTiming logger { impl.dispatchDuration_, ScopedTiming::Operation::addToDuration };
|
||||
impl.resources_.midiState.noteOnEvent(delay, noteNumber, normalizedVelocity);
|
||||
impl.resources_.getMidiState().noteOnEvent(delay, noteNumber, normalizedVelocity);
|
||||
impl.noteOnDispatch(delay, noteNumber, normalizedVelocity);
|
||||
}
|
||||
|
||||
|
|
@ -1093,8 +1122,9 @@ void Synth::hdNoteOff(int delay, int noteNumber, float normalizedVelocity) noexc
|
|||
// FIXME: Some keyboards (e.g. Casio PX5S) can send a real note-off velocity. In this case, do we have a
|
||||
// way in sfz to specify that a release trigger should NOT use the note-on velocity?
|
||||
// auto replacedVelocity = (velocity == 0 ? getNoteVelocity(noteNumber) : velocity);
|
||||
impl.resources_.midiState.noteOffEvent(delay, noteNumber, normalizedVelocity);
|
||||
const auto replacedVelocity = impl.resources_.midiState.getNoteVelocity(noteNumber);
|
||||
MidiState& midiState = impl.resources_.getMidiState();
|
||||
midiState.noteOffEvent(delay, noteNumber, normalizedVelocity);
|
||||
const auto replacedVelocity = midiState.getNoteVelocity(noteNumber);
|
||||
|
||||
for (auto& voice : impl.voiceManager_)
|
||||
voice.registerNoteOff(delay, noteNumber, replacedVelocity);
|
||||
|
|
@ -1275,6 +1305,8 @@ void Synth::Impl::performHdcc(int delay, int ccNumber, float normValue, bool asM
|
|||
|
||||
changedCCsThisCycle_.set(ccNumber);
|
||||
|
||||
MidiState& midiState = resources_.getMidiState();
|
||||
|
||||
if (asMidi) {
|
||||
if (ccNumber == config::resetCC) {
|
||||
resetAllControllers(delay);
|
||||
|
|
@ -1284,7 +1316,7 @@ void Synth::Impl::performHdcc(int delay, int ccNumber, float normValue, bool asM
|
|||
if (ccNumber == config::allNotesOffCC || ccNumber == config::allSoundOffCC) {
|
||||
for (auto& voice : voiceManager_)
|
||||
voice.reset();
|
||||
resources_.midiState.allNotesOff(delay);
|
||||
midiState.allNotesOff(delay);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -1293,7 +1325,7 @@ void Synth::Impl::performHdcc(int delay, int ccNumber, float normValue, bool asM
|
|||
voice.registerCC(delay, ccNumber, normValue);
|
||||
|
||||
ccDispatch(delay, ccNumber, normValue);
|
||||
resources_.midiState.ccEvent(delay, ccNumber, normValue);
|
||||
midiState.ccEvent(delay, ccNumber, normValue);
|
||||
}
|
||||
|
||||
void Synth::Impl::setDefaultHdcc(int ccNumber, float value)
|
||||
|
|
@ -1301,7 +1333,7 @@ void Synth::Impl::setDefaultHdcc(int ccNumber, float value)
|
|||
ASSERT(ccNumber >= 0);
|
||||
ASSERT(ccNumber < config::numCCs);
|
||||
defaultCCValues_[ccNumber] = value;
|
||||
resources_.midiState.ccEvent(0, ccNumber, value);
|
||||
resources_.getMidiState().ccEvent(0, ccNumber, value);
|
||||
}
|
||||
|
||||
float Synth::getHdcc(int ccNumber)
|
||||
|
|
@ -1309,7 +1341,7 @@ float Synth::getHdcc(int ccNumber)
|
|||
ASSERT(ccNumber >= 0);
|
||||
ASSERT(ccNumber < config::numCCs);
|
||||
Impl& impl = *impl_;
|
||||
return impl.resources_.midiState.getCCValue(ccNumber);
|
||||
return impl.resources_.getMidiState().getCCValue(ccNumber);
|
||||
}
|
||||
|
||||
float Synth::getDefaultHdcc(int ccNumber)
|
||||
|
|
@ -1331,7 +1363,7 @@ void Synth::hdPitchWheel(int delay, float normalizedPitch) noexcept
|
|||
Impl& impl = *impl_;
|
||||
|
||||
ScopedTiming logger { impl.dispatchDuration_, ScopedTiming::Operation::addToDuration };
|
||||
impl.resources_.midiState.pitchBendEvent(delay, normalizedPitch);
|
||||
impl.resources_.getMidiState().pitchBendEvent(delay, normalizedPitch);
|
||||
|
||||
for (const Impl::LayerPtr& layer : impl.layers_) {
|
||||
layer->registerPitchWheel(normalizedPitch);
|
||||
|
|
@ -1355,7 +1387,7 @@ void Synth::hdChannelAftertouch(int delay, float normAftertouch) noexcept
|
|||
Impl& impl = *impl_;
|
||||
ScopedTiming logger { impl.dispatchDuration_, ScopedTiming::Operation::addToDuration };
|
||||
|
||||
impl.resources_.midiState.channelAftertouchEvent(delay, normAftertouch);
|
||||
impl.resources_.getMidiState().channelAftertouchEvent(delay, normAftertouch);
|
||||
|
||||
for (const Impl::LayerPtr& layerPtr : impl.layers_) {
|
||||
layerPtr->registerAftertouch(normAftertouch);
|
||||
|
|
@ -1379,7 +1411,7 @@ void Synth::hdPolyAftertouch(int delay, int noteNumber, float normAftertouch) no
|
|||
Impl& impl = *impl_;
|
||||
ScopedTiming logger { impl.dispatchDuration_, ScopedTiming::Operation::addToDuration };
|
||||
|
||||
impl.resources_.midiState.polyAftertouchEvent(delay, noteNumber, normAftertouch);
|
||||
impl.resources_.getMidiState().polyAftertouchEvent(delay, noteNumber, normAftertouch);
|
||||
|
||||
for (auto& voice : impl.voiceManager_)
|
||||
voice.registerPolyAftertouch(delay, noteNumber, normAftertouch);
|
||||
|
|
@ -1393,7 +1425,7 @@ void Synth::tempo(int delay, float secondsPerBeat) noexcept
|
|||
Impl& impl = *impl_;
|
||||
ScopedTiming logger { impl.dispatchDuration_, ScopedTiming::Operation::addToDuration };
|
||||
|
||||
impl.resources_.beatClock.setTempo(delay, secondsPerBeat);
|
||||
impl.resources_.getBeatClock().setTempo(delay, secondsPerBeat);
|
||||
}
|
||||
|
||||
void Synth::bpmTempo(int delay, float beatsPerMinute) noexcept
|
||||
|
|
@ -1407,7 +1439,7 @@ void Synth::timeSignature(int delay, int beatsPerBar, int beatUnit)
|
|||
Impl& impl = *impl_;
|
||||
ScopedTiming logger { impl.dispatchDuration_, ScopedTiming::Operation::addToDuration };
|
||||
|
||||
impl.resources_.beatClock.setTimeSignature(delay, TimeSignature(beatsPerBar, beatUnit));
|
||||
impl.resources_.getBeatClock().setTimeSignature(delay, TimeSignature(beatsPerBar, beatUnit));
|
||||
}
|
||||
|
||||
void Synth::timePosition(int delay, int bar, double barBeat)
|
||||
|
|
@ -1415,16 +1447,18 @@ void Synth::timePosition(int delay, int bar, double barBeat)
|
|||
Impl& impl = *impl_;
|
||||
ScopedTiming logger { impl.dispatchDuration_, ScopedTiming::Operation::addToDuration };
|
||||
|
||||
BeatClock& beatClock = impl.resources_.getBeatClock();
|
||||
|
||||
const auto newPosition = BBT(bar, barBeat);
|
||||
const auto newBeatPosition = newPosition.toBeats(impl.resources_.beatClock.getTimeSignature());
|
||||
const auto currentBeatPosition = impl.resources_.beatClock.getLastBeatPosition();
|
||||
const auto newBeatPosition = newPosition.toBeats(beatClock.getTimeSignature());
|
||||
const auto currentBeatPosition = beatClock.getLastBeatPosition();
|
||||
const auto positionDifference = std::abs(newBeatPosition - currentBeatPosition);
|
||||
const auto threshold = config::playheadMovedFrames * impl.resources_.beatClock.getBeatsPerFrame();
|
||||
const auto threshold = config::playheadMovedFrames * beatClock.getBeatsPerFrame();
|
||||
|
||||
if (positionDifference > threshold)
|
||||
impl.playheadMoved_ = true;
|
||||
|
||||
impl.resources_.beatClock.setTimePosition(delay, newPosition);
|
||||
beatClock.setTimePosition(delay, newPosition);
|
||||
}
|
||||
|
||||
void Synth::playbackState(int delay, int playbackState)
|
||||
|
|
@ -1432,7 +1466,7 @@ void Synth::playbackState(int delay, int playbackState)
|
|||
Impl& impl = *impl_;
|
||||
ScopedTiming logger { impl.dispatchDuration_, ScopedTiming::Operation::addToDuration };
|
||||
|
||||
impl.resources_.beatClock.setPlaying(delay, playbackState == 1);
|
||||
impl.resources_.getBeatClock().setPlaying(delay, playbackState == 1);
|
||||
}
|
||||
|
||||
int Synth::getNumRegions() const noexcept
|
||||
|
|
@ -1456,7 +1490,7 @@ int Synth::getNumMasters() const noexcept
|
|||
int Synth::getNumCurves() const noexcept
|
||||
{
|
||||
Impl& impl = *impl_;
|
||||
return static_cast<int>(impl.resources_.curves.getNumCurves());
|
||||
return static_cast<int>(impl.resources_.getCurves().getNumCurves());
|
||||
}
|
||||
|
||||
std::string Synth::exportMidnam(absl::string_view model) const
|
||||
|
|
@ -1638,17 +1672,18 @@ const std::vector<std::string>& Synth::getUnknownOpcodes() const noexcept
|
|||
size_t Synth::getNumPreloadedSamples() const noexcept
|
||||
{
|
||||
Impl& impl = *impl_;
|
||||
return impl.resources_.filePool.getNumPreloadedSamples();
|
||||
return impl.resources_.getFilePool().getNumPreloadedSamples();
|
||||
}
|
||||
|
||||
int Synth::getSampleQuality(ProcessMode mode)
|
||||
{
|
||||
Impl& impl = *impl_;
|
||||
SynthConfig& synthConfig = impl.resources_.getSynthConfig();
|
||||
switch (mode) {
|
||||
case ProcessLive:
|
||||
return impl.resources_.synthConfig.liveSampleQuality;
|
||||
return synthConfig.liveSampleQuality;
|
||||
case ProcessFreewheeling:
|
||||
return impl.resources_.synthConfig.freeWheelingSampleQuality;
|
||||
return synthConfig.freeWheelingSampleQuality;
|
||||
default:
|
||||
SFIZZ_CHECK(false);
|
||||
return 0;
|
||||
|
|
@ -1660,13 +1695,14 @@ void Synth::setSampleQuality(ProcessMode mode, int quality)
|
|||
SFIZZ_CHECK(quality >= 0 && quality <= 10);
|
||||
Impl& impl = *impl_;
|
||||
quality = clamp(quality, 0, 10);
|
||||
SynthConfig& synthConfig = impl.resources_.getSynthConfig();
|
||||
|
||||
switch (mode) {
|
||||
case ProcessLive:
|
||||
impl.resources_.synthConfig.liveSampleQuality = quality;
|
||||
synthConfig.liveSampleQuality = quality;
|
||||
break;
|
||||
case ProcessFreewheeling:
|
||||
impl.resources_.synthConfig.freeWheelingSampleQuality = quality;
|
||||
synthConfig.freeWheelingSampleQuality = quality;
|
||||
break;
|
||||
default:
|
||||
SFIZZ_CHECK(false);
|
||||
|
|
@ -1677,11 +1713,12 @@ void Synth::setSampleQuality(ProcessMode mode, int quality)
|
|||
int Synth::getOscillatorQuality(ProcessMode mode)
|
||||
{
|
||||
Impl& impl = *impl_;
|
||||
SynthConfig& synthConfig = impl.resources_.getSynthConfig();
|
||||
switch (mode) {
|
||||
case ProcessLive:
|
||||
return impl.resources_.synthConfig.liveOscillatorQuality;
|
||||
return synthConfig.liveOscillatorQuality;
|
||||
case ProcessFreewheeling:
|
||||
return impl.resources_.synthConfig.freeWheelingOscillatorQuality;
|
||||
return synthConfig.freeWheelingOscillatorQuality;
|
||||
default:
|
||||
SFIZZ_CHECK(false);
|
||||
return 0;
|
||||
|
|
@ -1693,13 +1730,14 @@ void Synth::setOscillatorQuality(ProcessMode mode, int quality)
|
|||
SFIZZ_CHECK(quality >= 0 && quality <= 3);
|
||||
Impl& impl = *impl_;
|
||||
quality = clamp(quality, 0, 3);
|
||||
SynthConfig& synthConfig = impl.resources_.getSynthConfig();
|
||||
|
||||
switch (mode) {
|
||||
case ProcessLive:
|
||||
impl.resources_.synthConfig.liveOscillatorQuality = quality;
|
||||
synthConfig.liveOscillatorQuality = quality;
|
||||
break;
|
||||
case ProcessFreewheeling:
|
||||
impl.resources_.synthConfig.freeWheelingOscillatorQuality = quality;
|
||||
synthConfig.freeWheelingOscillatorQuality = quality;
|
||||
break;
|
||||
default:
|
||||
SFIZZ_CHECK(false);
|
||||
|
|
@ -1770,7 +1808,7 @@ void Synth::Impl::applySettingsPerVoice()
|
|||
|
||||
void Synth::Impl::setupModMatrix()
|
||||
{
|
||||
ModMatrix& mm = resources_.modMatrix;
|
||||
ModMatrix& mm = resources_.getModMatrix();
|
||||
|
||||
for (const LayerPtr& layerPtr : layers_) {
|
||||
const Region& region = layerPtr->getRegion();
|
||||
|
|
@ -1851,40 +1889,43 @@ void Synth::Impl::setupModMatrix()
|
|||
void Synth::setPreloadSize(uint32_t preloadSize) noexcept
|
||||
{
|
||||
Impl& impl = *impl_;
|
||||
FilePool& filePool = impl.resources_.getFilePool();
|
||||
|
||||
// fast path
|
||||
if (preloadSize == impl.resources_.filePool.getPreloadSize())
|
||||
if (preloadSize == filePool.getPreloadSize())
|
||||
return;
|
||||
|
||||
impl.resources_.filePool.setPreloadSize(preloadSize);
|
||||
filePool.setPreloadSize(preloadSize);
|
||||
}
|
||||
|
||||
uint32_t Synth::getPreloadSize() const noexcept
|
||||
{
|
||||
Impl& impl = *impl_;
|
||||
return impl.resources_.filePool.getPreloadSize();
|
||||
return impl.resources_.getFilePool().getPreloadSize();
|
||||
}
|
||||
|
||||
void Synth::enableFreeWheeling() noexcept
|
||||
{
|
||||
Impl& impl = *impl_;
|
||||
if (!impl.resources_.synthConfig.freeWheeling) {
|
||||
impl.resources_.synthConfig.freeWheeling = true;
|
||||
SynthConfig& synthConfig = impl.resources_.getSynthConfig();
|
||||
if (!synthConfig.freeWheeling) {
|
||||
synthConfig.freeWheeling = true;
|
||||
DBG("Enabling freewheeling");
|
||||
}
|
||||
}
|
||||
void Synth::disableFreeWheeling() noexcept
|
||||
{
|
||||
Impl& impl = *impl_;
|
||||
if (impl.resources_.synthConfig.freeWheeling) {
|
||||
impl.resources_.synthConfig.freeWheeling = false;
|
||||
SynthConfig& synthConfig = impl.resources_.getSynthConfig();
|
||||
if (synthConfig.freeWheeling) {
|
||||
synthConfig.freeWheeling = false;
|
||||
DBG("Disabling freewheeling");
|
||||
}
|
||||
}
|
||||
|
||||
void Synth::Impl::resetAllControllers(int delay) noexcept
|
||||
{
|
||||
resources_.midiState.resetAllControllers(delay);
|
||||
resources_.getMidiState().resetAllControllers(delay);
|
||||
|
||||
for (auto& voice : voiceManager_) {
|
||||
voice.registerPitchWheel(delay, 0);
|
||||
|
|
@ -1931,19 +1972,19 @@ bool Synth::shouldReloadFile()
|
|||
bool Synth::shouldReloadScala()
|
||||
{
|
||||
Impl& impl = *impl_;
|
||||
return impl.resources_.tuning.shouldReloadScala();
|
||||
return impl.resources_.getTuning().shouldReloadScala();
|
||||
}
|
||||
|
||||
void Synth::enableLogging(absl::string_view prefix) noexcept
|
||||
{
|
||||
Impl& impl = *impl_;
|
||||
impl.resources_.logger.enableLogging(prefix);
|
||||
impl.resources_.getLogger().enableLogging(prefix);
|
||||
}
|
||||
|
||||
void Synth::disableLogging() noexcept
|
||||
{
|
||||
Impl& impl = *impl_;
|
||||
impl.resources_.logger.disableLogging();
|
||||
impl.resources_.getLogger().disableLogging();
|
||||
}
|
||||
|
||||
void Synth::allSoundOff() noexcept
|
||||
|
|
@ -2038,7 +2079,7 @@ BitArray<config::numCCs> Synth::Impl::collectAllUsedCCs()
|
|||
BitArray<config::numCCs> used;
|
||||
for (const LayerPtr& layerPtr : layers_)
|
||||
collectUsedCCsFromRegion(used, layerPtr->getRegion());
|
||||
collectUsedCCsFromModulations(used, resources_.modMatrix);
|
||||
collectUsedCCsFromModulations(used, resources_.getModMatrix());
|
||||
return used;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,9 @@
|
|||
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
|
||||
|
||||
#include "SynthPrivate.h"
|
||||
#include "FilePool.h"
|
||||
#include "Curve.h"
|
||||
#include "MidiState.h"
|
||||
#include "utility/StringViewHelpers.h"
|
||||
#include <absl/strings/ascii.h>
|
||||
#include <cstring>
|
||||
|
|
@ -67,11 +70,11 @@ void sfz::Synth::dispatchMessage(Client& client, int delay, const char* path, co
|
|||
} break;
|
||||
|
||||
MATCH("/num_curves", "") {
|
||||
client.receive<'i'>(delay, path, int(impl.resources_.curves.getNumCurves()));
|
||||
client.receive<'i'>(delay, path, int(impl.resources_.getCurves().getNumCurves()));
|
||||
} break;
|
||||
|
||||
MATCH("/num_samples", "") {
|
||||
client.receive<'i'>(delay, path, int(impl.resources_.filePool.getNumPreloadedSamples()));
|
||||
client.receive<'i'>(delay, path, int(impl.resources_.getFilePool().getNumPreloadedSamples()));
|
||||
} break;
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
|
@ -139,13 +142,13 @@ void sfz::Synth::dispatchMessage(Client& client, int delay, const char* path, co
|
|||
if (indices[0] >= config::numCCs)
|
||||
break;
|
||||
// Note: result value is not frame-exact
|
||||
client.receive<'f'>(delay, path, impl.resources_.midiState.getCCValue(indices[0]));
|
||||
client.receive<'f'>(delay, path, impl.resources_.getMidiState().getCCValue(indices[0]));
|
||||
} break;
|
||||
|
||||
MATCH("/cc&/value", "f") {
|
||||
if (indices[0] >= config::numCCs)
|
||||
break;
|
||||
impl.resources_.midiState.ccEvent(delay, indices[0], args[0].f);
|
||||
impl.resources_.getMidiState().ccEvent(delay, indices[0], args[0].f);
|
||||
} break;
|
||||
|
||||
MATCH("/cc&/label", "") {
|
||||
|
|
|
|||
|
|
@ -26,6 +26,11 @@
|
|||
#include "SfzHelpers.h"
|
||||
#include "SIMDHelpers.h"
|
||||
#include "Smoothers.h"
|
||||
#include "FilePool.h"
|
||||
#include "Wavetables.h"
|
||||
#include "Tuning.h"
|
||||
#include "BufferPool.h"
|
||||
#include "SynthConfig.h"
|
||||
#include "utility/Macros.h"
|
||||
#include <absl/algorithm/container.h>
|
||||
#include <absl/types/span.h>
|
||||
|
|
@ -387,10 +392,11 @@ const ExtendedCCValues& Voice::getExtendedCCValues() const noexcept
|
|||
|
||||
void Voice::Impl::updateExtendedCCValues() noexcept
|
||||
{
|
||||
extendedCCValues_.unipolar = resources_.midiState.getCCValue(ExtendedCCs::unipolarRandom);
|
||||
extendedCCValues_.bipolar = resources_.midiState.getCCValue(ExtendedCCs::bipolarRandom);
|
||||
extendedCCValues_.alternate = resources_.midiState.getCCValue(ExtendedCCs::alternate);
|
||||
extendedCCValues_.noteGate = resources_.midiState.getCCValue(ExtendedCCs::keyboardNoteGate);
|
||||
MidiState& midiState = resources_.getMidiState();
|
||||
extendedCCValues_.unipolar = midiState.getCCValue(ExtendedCCs::unipolarRandom);
|
||||
extendedCCValues_.bipolar = midiState.getCCValue(ExtendedCCs::bipolarRandom);
|
||||
extendedCCValues_.alternate = midiState.getCCValue(ExtendedCCs::alternate);
|
||||
extendedCCValues_.noteGate = midiState.getCCValue(ExtendedCCs::keyboardNoteGate);
|
||||
}
|
||||
|
||||
bool Voice::startVoice(Layer* layer, int delay, const TriggerEvent& event) noexcept
|
||||
|
|
@ -399,6 +405,7 @@ bool Voice::startVoice(Layer* layer, int delay, const TriggerEvent& event) noexc
|
|||
ASSERT(event.value >= 0.0f && event.value <= 1.0f);
|
||||
|
||||
Resources& resources = impl.resources_;
|
||||
MidiState& midiState = resources.getMidiState();
|
||||
|
||||
const Region& region = layer->getRegion();
|
||||
impl.region_ = ®ion;
|
||||
|
|
@ -408,7 +415,7 @@ bool Voice::startVoice(Layer* layer, int delay, const TriggerEvent& event) noexc
|
|||
impl.triggerEvent_.number = region.pitchKeycenter;
|
||||
|
||||
if (region.velocityOverride == VelocityOverride::previous)
|
||||
impl.triggerEvent_.value = resources.midiState.getVelocityOverride();
|
||||
impl.triggerEvent_.value = midiState.getVelocityOverride();
|
||||
|
||||
if (region.disabled()) {
|
||||
impl.switchState(State::cleanMeUp);
|
||||
|
|
@ -424,26 +431,27 @@ bool Voice::startVoice(Layer* layer, int delay, const TriggerEvent& event) noexc
|
|||
delay = 0;
|
||||
|
||||
if (region.isOscillator()) {
|
||||
WavetablePool& wavePool = resources.getWavePool();
|
||||
const WavetableMulti* wave = nullptr;
|
||||
if (!region.isGenerator())
|
||||
wave = resources.wavePool.getFileWave(region.sampleId->filename());
|
||||
wave = wavePool.getFileWave(region.sampleId->filename());
|
||||
else {
|
||||
switch (hash(region.sampleId->filename())) {
|
||||
default:
|
||||
case hash("*silence"):
|
||||
break;
|
||||
case hash("*sine"):
|
||||
wave = resources.wavePool.getWaveSin();
|
||||
wave = wavePool.getWaveSin();
|
||||
break;
|
||||
case hash("*triangle"): // fallthrough
|
||||
case hash("*tri"):
|
||||
wave = resources.wavePool.getWaveTriangle();
|
||||
wave = wavePool.getWaveTriangle();
|
||||
break;
|
||||
case hash("*square"):
|
||||
wave = resources.wavePool.getWaveSquare();
|
||||
wave = wavePool.getWaveSquare();
|
||||
break;
|
||||
case hash("*saw"):
|
||||
wave = resources.wavePool.getWaveSaw();
|
||||
wave = wavePool.getWaveSaw();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -457,27 +465,29 @@ bool Voice::startVoice(Layer* layer, int delay, const TriggerEvent& event) noexc
|
|||
}
|
||||
impl.setupOscillatorUnison();
|
||||
} else {
|
||||
impl.currentPromise_ = resources.filePool.getFilePromise(region.sampleId);
|
||||
FilePool& filePool = resources.getFilePool();
|
||||
impl.currentPromise_ = filePool.getFilePromise(region.sampleId);
|
||||
if (!impl.currentPromise_) {
|
||||
impl.switchState(State::cleanMeUp);
|
||||
return false;
|
||||
}
|
||||
impl.updateLoopInformation();
|
||||
impl.speedRatio_ = static_cast<float>(impl.currentPromise_->information.sampleRate / impl.sampleRate_);
|
||||
impl.sourcePosition_ = region.getOffset(resources.midiState);
|
||||
impl.sourcePosition_ = region.getOffset(midiState);
|
||||
}
|
||||
|
||||
// do Scala retuning and reconvert the frequency into a 12TET key number
|
||||
const float numberRetuned = resources.tuning.getKeyFractional12TET(impl.triggerEvent_.number);
|
||||
Tuning& tuning = resources.getTuning();
|
||||
const float numberRetuned = tuning.getKeyFractional12TET(impl.triggerEvent_.number);
|
||||
|
||||
impl.pitchRatio_ = region.getBasePitchVariation(numberRetuned, impl.triggerEvent_.value);
|
||||
|
||||
// apply stretch tuning if set
|
||||
if (resources.stretch)
|
||||
impl.pitchRatio_ *= resources.stretch->getRatioForFractionalKey(numberRetuned);
|
||||
if (absl::optional<StretchTuning>& stretch = resources.getStretch())
|
||||
impl.pitchRatio_ *= stretch->getRatioForFractionalKey(numberRetuned);
|
||||
|
||||
impl.pitchKeycenter_ = region.pitchKeycenter;
|
||||
impl.baseVolumedB_ = region.getBaseVolumedB(resources.midiState, impl.triggerEvent_.number);
|
||||
impl.baseVolumedB_ = region.getBaseVolumedB(midiState, impl.triggerEvent_.number);
|
||||
impl.baseGain_ = region.getBaseGain();
|
||||
if (impl.triggerEvent_.type != TriggerEventType::CC || region.velocityOverride == VelocityOverride::previous)
|
||||
impl.baseGain_ *= region.getNoteGain(impl.triggerEvent_.number, impl.triggerEvent_.value);
|
||||
|
|
@ -494,26 +504,27 @@ bool Voice::startVoice(Layer* layer, int delay, const TriggerEvent& event) noexc
|
|||
}
|
||||
|
||||
impl.triggerDelay_ = delay;
|
||||
impl.initialDelay_ = delay + static_cast<int>(region.getDelay(resources.midiState) * impl.sampleRate_);
|
||||
impl.baseFrequency_ = resources.tuning.getFrequencyOfKey(impl.triggerEvent_.number);
|
||||
impl.sampleEnd_ = int(region.getSampleEnd(resources.midiState));
|
||||
impl.initialDelay_ = delay + static_cast<int>(region.getDelay(midiState) * impl.sampleRate_);
|
||||
impl.baseFrequency_ = tuning.getFrequencyOfKey(impl.triggerEvent_.number);
|
||||
impl.sampleEnd_ = int(region.getSampleEnd(midiState));
|
||||
impl.sampleSize_ = impl.sampleEnd_- impl.sourcePosition_ - 1;
|
||||
impl.bendSmoother_.setSmoothing(region.bendSmooth, impl.sampleRate_);
|
||||
impl.bendSmoother_.reset(region.getBendInCents(resources.midiState.getPitchBend()));
|
||||
impl.bendSmoother_.reset(region.getBendInCents(midiState.getPitchBend()));
|
||||
|
||||
resources.modMatrix.initVoice(impl.id_, region.getId(), impl.initialDelay_);
|
||||
ModMatrix& modMatrix = resources.getModMatrix();
|
||||
modMatrix.initVoice(impl.id_, region.getId(), impl.initialDelay_);
|
||||
impl.saveModulationTargets(®ion);
|
||||
|
||||
if (region.checkSustain) {
|
||||
const bool sustainPressed =
|
||||
resources.midiState.getCCValue(region.sustainCC) >= region.sustainThreshold;
|
||||
midiState.getCCValue(region.sustainCC) >= region.sustainThreshold;
|
||||
impl.sustainState_ =
|
||||
sustainPressed ? Impl::SustainState::Sustaining : Impl::SustainState::Up;
|
||||
}
|
||||
|
||||
if (region.checkSostenuto) {
|
||||
const bool sostenutoPressed =
|
||||
resources.midiState.getCCValue(region.sostenutoCC) >= region.sostenutoThreshold;
|
||||
midiState.getCCValue(region.sostenutoCC) >= region.sostenutoThreshold;
|
||||
impl.sostenutoState_ =
|
||||
sostenutoPressed ? Impl::SostenutoState::PreviouslyDown : Impl::SostenutoState::Up;
|
||||
}
|
||||
|
|
@ -524,7 +535,7 @@ bool Voice::startVoice(Layer* layer, int delay, const TriggerEvent& event) noexc
|
|||
int Voice::Impl::getCurrentSampleQuality() const noexcept
|
||||
{
|
||||
return (region_ && region_->sampleQuality) ?
|
||||
*region_->sampleQuality : resources_.synthConfig.currentSampleQuality();
|
||||
*region_->sampleQuality : resources_.getSynthConfig().currentSampleQuality();
|
||||
}
|
||||
|
||||
int Voice::getCurrentSampleQuality() const noexcept
|
||||
|
|
@ -536,7 +547,7 @@ int Voice::getCurrentSampleQuality() const noexcept
|
|||
int Voice::Impl::getCurrentOscillatorQuality() const noexcept
|
||||
{
|
||||
return (region_ && region_->oscillatorQuality) ?
|
||||
*region_->oscillatorQuality : resources_.synthConfig.currentOscillatorQuality();
|
||||
*region_->oscillatorQuality : resources_.getSynthConfig().currentOscillatorQuality();
|
||||
}
|
||||
|
||||
int Voice::getCurrentOscillatorQuality() const noexcept
|
||||
|
|
@ -571,7 +582,8 @@ void Voice::Impl::release(int delay) noexcept
|
|||
switchState(State::cleanMeUp);
|
||||
}
|
||||
|
||||
resources_.modMatrix.releaseVoice(id_, region_->getId(), delay);
|
||||
ModMatrix& modMatrix = resources_.getModMatrix();
|
||||
modMatrix.releaseVoice(id_, region_->getId(), delay);
|
||||
}
|
||||
|
||||
void Voice::off(int delay, bool fast) noexcept
|
||||
|
|
@ -805,13 +817,15 @@ void Voice::Impl::resetCrossfades() noexcept
|
|||
float xfadeValue { 1.0f };
|
||||
const auto xfCurve = region_->crossfadeCCCurve;
|
||||
|
||||
MidiState& midiState = resources_.getMidiState();
|
||||
|
||||
for (const auto& mod : region_->crossfadeCCInRange) {
|
||||
const auto value = resources_.midiState.getCCValue(mod.cc);
|
||||
const auto value = midiState.getCCValue(mod.cc);
|
||||
xfadeValue *= crossfadeIn(mod.data, value, xfCurve);
|
||||
}
|
||||
|
||||
for (const auto& mod : region_->crossfadeCCOutRange) {
|
||||
const auto value = resources_.midiState.getCCValue(mod.cc);
|
||||
const auto value = midiState.getCCValue(mod.cc);
|
||||
xfadeValue *= crossfadeOut(mod.data, value, xfCurve);
|
||||
}
|
||||
|
||||
|
|
@ -823,8 +837,11 @@ void Voice::Impl::applyCrossfades(absl::Span<float> modulationSpan) noexcept
|
|||
const auto numSamples = modulationSpan.size();
|
||||
const auto xfCurve = region_->crossfadeCCCurve;
|
||||
|
||||
auto tempSpan = resources_.bufferPool.getBuffer(numSamples);
|
||||
auto xfadeSpan = resources_.bufferPool.getBuffer(numSamples);
|
||||
MidiState& midiState = resources_.getMidiState();
|
||||
BufferPool& bufferPool = resources_.getBufferPool();
|
||||
|
||||
auto tempSpan = bufferPool.getBuffer(numSamples);
|
||||
auto xfadeSpan = bufferPool.getBuffer(numSamples);
|
||||
|
||||
if (!tempSpan || !xfadeSpan)
|
||||
return;
|
||||
|
|
@ -833,7 +850,7 @@ void Voice::Impl::applyCrossfades(absl::Span<float> modulationSpan) noexcept
|
|||
|
||||
bool canShortcut = true;
|
||||
for (const auto& mod : region_->crossfadeCCInRange) {
|
||||
const auto& events = resources_.midiState.getCCEvents(mod.cc);
|
||||
const auto& events = midiState.getCCEvents(mod.cc);
|
||||
canShortcut &= (events.size() == 1);
|
||||
linearEnvelope(events, *tempSpan, [&](float x) {
|
||||
return crossfadeIn(mod.data, x, xfCurve);
|
||||
|
|
@ -842,7 +859,7 @@ void Voice::Impl::applyCrossfades(absl::Span<float> modulationSpan) noexcept
|
|||
}
|
||||
|
||||
for (const auto& mod : region_->crossfadeCCOutRange) {
|
||||
const auto& events = resources_.midiState.getCCEvents(mod.cc);
|
||||
const auto& events = midiState.getCCEvents(mod.cc);
|
||||
canShortcut &= (events.size() == 1);
|
||||
linearEnvelope(events, *tempSpan, [&](float x) {
|
||||
return crossfadeOut(mod.data, x, xfCurve);
|
||||
|
|
@ -859,7 +876,7 @@ void Voice::Impl::amplitudeEnvelope(absl::Span<float> modulationSpan) noexcept
|
|||
{
|
||||
const auto numSamples = modulationSpan.size();
|
||||
|
||||
ModMatrix& mm = resources_.modMatrix;
|
||||
ModMatrix& mm = resources_.getModMatrix();
|
||||
|
||||
// Amplitude EG
|
||||
absl::Span<const float> ampegOut(mm.getModulation(masterAmplitudeTarget_), numSamples);
|
||||
|
|
@ -891,7 +908,9 @@ void Voice::Impl::ampStageMono(AudioSpan<float> buffer) noexcept
|
|||
const auto numSamples = buffer.getNumFrames();
|
||||
const auto leftBuffer = buffer.getSpan(0);
|
||||
|
||||
auto modulationSpan = resources_.bufferPool.getBuffer(numSamples);
|
||||
BufferPool& bufferPool = resources_.getBufferPool();
|
||||
|
||||
auto modulationSpan = bufferPool.getBuffer(numSamples);
|
||||
if (!modulationSpan)
|
||||
return;
|
||||
|
||||
|
|
@ -904,8 +923,10 @@ void Voice::Impl::ampStageStereo(AudioSpan<float> buffer) noexcept
|
|||
{
|
||||
ScopedTiming logger { amplitudeDuration_ };
|
||||
|
||||
BufferPool& bufferPool = resources_.getBufferPool();
|
||||
|
||||
const auto numSamples = buffer.getNumFrames();
|
||||
auto modulationSpan = resources_.bufferPool.getBuffer(numSamples);
|
||||
auto modulationSpan = bufferPool.getBuffer(numSamples);
|
||||
if (!modulationSpan)
|
||||
return;
|
||||
|
||||
|
|
@ -922,11 +943,13 @@ void Voice::Impl::panStageMono(AudioSpan<float> buffer) noexcept
|
|||
const auto leftBuffer = buffer.getSpan(0);
|
||||
const auto rightBuffer = buffer.getSpan(1);
|
||||
|
||||
auto modulationSpan = resources_.bufferPool.getBuffer(numSamples);
|
||||
BufferPool& bufferPool = resources_.getBufferPool();
|
||||
|
||||
auto modulationSpan = bufferPool.getBuffer(numSamples);
|
||||
if (!modulationSpan)
|
||||
return;
|
||||
|
||||
ModMatrix& mm = resources_.modMatrix;
|
||||
ModMatrix& mm = resources_.getModMatrix();
|
||||
|
||||
// Prepare for stereo output
|
||||
copy<float>(leftBuffer, rightBuffer);
|
||||
|
|
@ -947,11 +970,13 @@ void Voice::Impl::panStageStereo(AudioSpan<float> buffer) noexcept
|
|||
const auto leftBuffer = buffer.getSpan(0);
|
||||
const auto rightBuffer = buffer.getSpan(1);
|
||||
|
||||
auto modulationSpan = resources_.bufferPool.getBuffer(numSamples);
|
||||
BufferPool& bufferPool = resources_.getBufferPool();
|
||||
|
||||
auto modulationSpan = bufferPool.getBuffer(numSamples);
|
||||
if (!modulationSpan)
|
||||
return;
|
||||
|
||||
ModMatrix& mm = resources_.modMatrix;
|
||||
ModMatrix& mm = resources_.getModMatrix();
|
||||
|
||||
// Apply panning
|
||||
fill(*modulationSpan, region_->pan);
|
||||
|
|
@ -1029,15 +1054,18 @@ void Voice::Impl::fillWithData(AudioSpan<float> buffer) noexcept
|
|||
|
||||
auto source = currentPromise_->getData();
|
||||
|
||||
BufferPool& bufferPool = resources_.getBufferPool();
|
||||
const CurveSet& curves = resources_.getCurves();
|
||||
|
||||
// calculate interpolation data
|
||||
// indices: integral position in the source audio
|
||||
// coeffs: fractional position normalized 0-1
|
||||
auto coeffs = resources_.bufferPool.getBuffer(numSamples);
|
||||
auto indices = resources_.bufferPool.getIndexBuffer(numSamples);
|
||||
auto coeffs = bufferPool.getBuffer(numSamples);
|
||||
auto indices = bufferPool.getIndexBuffer(numSamples);
|
||||
if (!indices || !coeffs)
|
||||
return;
|
||||
{
|
||||
auto jumps = resources_.bufferPool.getBuffer(numSamples);
|
||||
auto jumps = bufferPool.getBuffer(numSamples);
|
||||
if (!jumps)
|
||||
return;
|
||||
|
||||
|
|
@ -1091,7 +1119,7 @@ void Voice::Impl::fillWithData(AudioSpan<float> buffer) noexcept
|
|||
SpanHolder<absl::Span<int>> partitionBuffers[2];
|
||||
if (shouldLoop) {
|
||||
for (auto& buf : partitionBuffers) {
|
||||
buf = resources_.bufferPool.getIndexBuffer(numSamples);
|
||||
buf = bufferPool.getIndexBuffer(numSamples);
|
||||
if (!buf)
|
||||
return;
|
||||
}
|
||||
|
|
@ -1198,9 +1226,9 @@ void Voice::Impl::fillWithData(AudioSpan<float> buffer) noexcept
|
|||
source, ptBuffer, ptIndices, ptCoeffs, {}, quality);
|
||||
|
||||
if (ptType == kPartitionLoopXfade) {
|
||||
auto xfTemp1 = resources_.bufferPool.getBuffer(numSamples);
|
||||
auto xfTemp2 = resources_.bufferPool.getBuffer(numSamples);
|
||||
auto xfIndicesTemp = resources_.bufferPool.getIndexBuffer(numSamples);
|
||||
auto xfTemp1 = bufferPool.getBuffer(numSamples);
|
||||
auto xfTemp2 = bufferPool.getBuffer(numSamples);
|
||||
auto xfIndicesTemp = bufferPool.getIndexBuffer(numSamples);
|
||||
if (!xfTemp1 || !xfTemp2 || !xfIndicesTemp)
|
||||
return;
|
||||
|
||||
|
|
@ -1224,7 +1252,7 @@ void Voice::Impl::fillWithData(AudioSpan<float> buffer) noexcept
|
|||
xfCurve[i] = xfIn.evalNormalized(1.0f - xfCurvePos[i]);
|
||||
}
|
||||
else IF_CONSTEXPR (config::loopXfadeCurve == 1) {
|
||||
const Curve& xfOut = resources_.curves.getCurve(6);
|
||||
const Curve& xfOut = curves.getCurve(6);
|
||||
for (unsigned i = 0; i < ptSize; ++i)
|
||||
xfCurve[i] = xfOut.evalNormalized(xfCurvePos[i]);
|
||||
}
|
||||
|
|
@ -1274,7 +1302,7 @@ void Voice::Impl::fillWithData(AudioSpan<float> buffer) noexcept
|
|||
xfCurve[i] = xfIn.evalNormalized(xfInCurvePos[i]);
|
||||
}
|
||||
else IF_CONSTEXPR (config::loopXfadeCurve == 1) {
|
||||
const Curve& xfIn = resources_.curves.getCurve(5);
|
||||
const Curve& xfIn = curves.getCurve(5);
|
||||
for (unsigned i = 0; i < applySize; ++i)
|
||||
xfCurve[i] = xfIn.evalNormalized(xfInCurvePos[i]);
|
||||
}
|
||||
|
|
@ -1462,7 +1490,10 @@ void Voice::Impl::fillWithGenerator(AudioSpan<float> buffer) noexcept
|
|||
} else {
|
||||
const size_t numFrames = buffer.getNumFrames();
|
||||
|
||||
auto frequencies = resources_.bufferPool.getBuffer(numFrames);
|
||||
BufferPool& bufferPool = resources_.getBufferPool();
|
||||
ModMatrix& modMatrix = resources_.getModMatrix();
|
||||
|
||||
auto frequencies = bufferPool.getBuffer(numFrames);
|
||||
if (!frequencies)
|
||||
return;
|
||||
|
||||
|
|
@ -1475,7 +1506,7 @@ void Voice::Impl::fillWithGenerator(AudioSpan<float> buffer) noexcept
|
|||
for (size_t i = 0; i < numFrames; ++i)
|
||||
(*frequencies)[i] = baseRatio * centsFactor(pitch[i]);
|
||||
|
||||
auto detuneSpan = resources_.bufferPool.getBuffer(numFrames);
|
||||
auto detuneSpan = bufferPool.getBuffer(numFrames);
|
||||
if (!detuneSpan)
|
||||
return;
|
||||
|
||||
|
|
@ -1485,7 +1516,7 @@ void Voice::Impl::fillWithGenerator(AudioSpan<float> buffer) noexcept
|
|||
|
||||
if (oscillatorMode <= 0 && oscillatorMulti < 2) {
|
||||
// single oscillator
|
||||
auto tempSpan = resources_.bufferPool.getBuffer(numFrames);
|
||||
auto tempSpan = bufferPool.getBuffer(numFrames);
|
||||
if (!tempSpan)
|
||||
return;
|
||||
|
||||
|
|
@ -1498,13 +1529,13 @@ void Voice::Impl::fillWithGenerator(AudioSpan<float> buffer) noexcept
|
|||
}
|
||||
else if (oscillatorMode <= 0 && oscillatorMulti >= 3) {
|
||||
// unison oscillator
|
||||
auto tempSpan = resources_.bufferPool.getBuffer(numFrames);
|
||||
auto tempLeftSpan = resources_.bufferPool.getBuffer(numFrames);
|
||||
auto tempRightSpan = resources_.bufferPool.getBuffer(numFrames);
|
||||
auto tempSpan = bufferPool.getBuffer(numFrames);
|
||||
auto tempLeftSpan = bufferPool.getBuffer(numFrames);
|
||||
auto tempRightSpan = bufferPool.getBuffer(numFrames);
|
||||
if (!tempSpan || !tempLeftSpan || !tempRightSpan)
|
||||
return;
|
||||
|
||||
const float* detuneMod = resources_.modMatrix.getModulation(oscillatorDetuneTarget_);
|
||||
const float* detuneMod = modMatrix.getModulation(oscillatorDetuneTarget_);
|
||||
for (unsigned u = 0, uSize = waveUnisonSize_; u < uSize; ++u) {
|
||||
WavetableOscillator& osc = waveOscillators_[u];
|
||||
osc.setQuality(quality);
|
||||
|
|
@ -1531,7 +1562,7 @@ void Voice::Impl::fillWithGenerator(AudioSpan<float> buffer) noexcept
|
|||
}
|
||||
else {
|
||||
// modulated oscillator
|
||||
auto tempSpan = resources_.bufferPool.getBuffer(numFrames);
|
||||
auto tempSpan = bufferPool.getBuffer(numFrames);
|
||||
if (!tempSpan)
|
||||
return;
|
||||
|
||||
|
|
@ -1541,11 +1572,11 @@ void Voice::Impl::fillWithGenerator(AudioSpan<float> buffer) noexcept
|
|||
oscMod.setQuality(quality);
|
||||
|
||||
// compute the modulator
|
||||
auto modulatorSpan = resources_.bufferPool.getBuffer(numFrames);
|
||||
auto modulatorSpan = bufferPool.getBuffer(numFrames);
|
||||
if (!modulatorSpan)
|
||||
return;
|
||||
|
||||
const float* detuneMod = resources_.modMatrix.getModulation(oscillatorDetuneTarget_);
|
||||
const float* detuneMod = modMatrix.getModulation(oscillatorDetuneTarget_);
|
||||
if (!detuneMod)
|
||||
fill(*detuneSpan, waveDetuneRatio_[1]);
|
||||
else {
|
||||
|
|
@ -1560,7 +1591,7 @@ void Voice::Impl::fillWithGenerator(AudioSpan<float> buffer) noexcept
|
|||
const float oscillatorModDepth = region_->oscillatorModDepth;
|
||||
if (oscillatorModDepth != 1.0f)
|
||||
applyGain1(oscillatorModDepth, *modulatorSpan);
|
||||
const float* modDepthMod = resources_.modMatrix.getModulation(oscillatorModDepthTarget_);
|
||||
const float* modDepthMod = modMatrix.getModulation(oscillatorModDepthTarget_);
|
||||
if (modDepthMod)
|
||||
applyGain(absl::MakeConstSpan(modDepthMod, numFrames), *modulatorSpan);
|
||||
|
||||
|
|
@ -1672,12 +1703,12 @@ void Voice::Impl::updateLoopInformation() noexcept
|
|||
if (!region_->shouldLoop())
|
||||
return;
|
||||
|
||||
Resources& resources = resources_;
|
||||
MidiState& midiState = resources_.getMidiState();
|
||||
const FileInformation& info = currentPromise_->information;
|
||||
const double rate = info.sampleRate;
|
||||
|
||||
loop_.start = static_cast<int>(region_->loopStart(resources.midiState));
|
||||
loop_.end = max(static_cast<int>(region_->loopEnd(resources.midiState)), loop_.start);
|
||||
loop_.start = static_cast<int>(region_->loopStart(midiState));
|
||||
loop_.end = max(static_cast<int>(region_->loopEnd(midiState)), loop_.start);
|
||||
loop_.size = loop_.end + 1 - loop_.start;
|
||||
loop_.xfSize = static_cast<int>(lroundPositive(region_->loopCrossfade * rate));
|
||||
// Clamp the crossfade to the part available before the loop starts
|
||||
|
|
@ -1906,7 +1937,8 @@ void Voice::Impl::pitchEnvelope(absl::Span<float> pitchSpan) noexcept
|
|||
{
|
||||
const size_t numFrames = pitchSpan.size();
|
||||
|
||||
const EventVector& events = resources_.midiState.getPitchEvents();
|
||||
const MidiState& midiState = resources_.getMidiState();
|
||||
const EventVector& events = midiState.getPitchEvents();
|
||||
const auto bendLambda = [this](float bend) {
|
||||
return region_->getBendInCents(bend);
|
||||
};
|
||||
|
|
@ -1917,7 +1949,7 @@ void Voice::Impl::pitchEnvelope(absl::Span<float> pitchSpan) noexcept
|
|||
linearEnvelope(events, pitchSpan, bendLambda);
|
||||
bendSmoother_.process(pitchSpan, pitchSpan);
|
||||
|
||||
ModMatrix& mm = resources_.modMatrix;
|
||||
ModMatrix& mm = resources_.getModMatrix();
|
||||
|
||||
if (float* mod = mm.getModulation(pitchTarget_))
|
||||
add<float>(absl::MakeSpan(mod, numFrames), pitchSpan);
|
||||
|
|
@ -1931,7 +1963,7 @@ void Voice::Impl::resetSmoothers() noexcept
|
|||
|
||||
void Voice::Impl::saveModulationTargets(const Region* region) noexcept
|
||||
{
|
||||
ModMatrix& mm = resources_.modMatrix;
|
||||
ModMatrix& mm = resources_.getModMatrix();
|
||||
masterAmplitudeTarget_ = mm.findTarget(ModKey::createNXYZ(ModId::MasterAmplitude, region->getId()));
|
||||
amplitudeTarget_ = mm.findTarget(ModKey::createNXYZ(ModId::Amplitude, region->getId()));
|
||||
volumeTarget_ = mm.findTarget(ModKey::createNXYZ(ModId::Volume, region->getId()));
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
#include "Region.h"
|
||||
#include "Resources.h"
|
||||
#include "AudioSpan.h"
|
||||
#include "Logger.h"
|
||||
#include "utility/NumericId.h"
|
||||
#include "utility/LeakDetector.h"
|
||||
#include <memory>
|
||||
|
|
|
|||
|
|
@ -37,8 +37,8 @@ ControllerSource::~ControllerSource()
|
|||
float ControllerSource::Impl::getLastTransformedValue(uint16_t cc, uint8_t curveIndex) const noexcept
|
||||
{
|
||||
ASSERT(res_);
|
||||
const Curve& curve = res_->curves.getCurve(curveIndex);
|
||||
const auto lastCCValue = res_->midiState.getCCValue(cc);
|
||||
const Curve& curve = res_->getCurves().getCurve(curveIndex);
|
||||
const auto lastCCValue = res_->getMidiState().getCCValue(cc);
|
||||
return curve.evalNormalized(lastCCValue);
|
||||
}
|
||||
|
||||
|
|
@ -89,8 +89,8 @@ void ControllerSource::generate(const ModKey& sourceKey, NumericId<Voice> voiceI
|
|||
{
|
||||
const ModKey::Parameters p = sourceKey.parameters();
|
||||
const Resources& res = *impl_->res_;
|
||||
const Curve& curve = res.curves.getCurve(p.curve);
|
||||
const MidiState& ms = res.midiState;
|
||||
const Curve& curve = res.getCurves().getCurve(p.curve);
|
||||
const MidiState& ms = res.getMidiState();
|
||||
bool canShortcut = false;
|
||||
|
||||
auto transformValue = [p, &curve](float x) {
|
||||
|
|
@ -110,7 +110,7 @@ void ControllerSource::generate(const ModKey& sourceKey, NumericId<Voice> voiceI
|
|||
const auto voice = impl_->voiceManager_->getVoiceById(voiceId);
|
||||
const float fillValue =
|
||||
voice && voice->getTriggerEvent().type == TriggerEventType::NoteOn ?
|
||||
impl_->res_->midiState.getPolyAftertouch(voice->getTriggerEvent().number) : 0.0f;
|
||||
impl_->res_->getMidiState().getPolyAftertouch(voice->getTriggerEvent().number) : 0.0f;
|
||||
|
||||
sfz::fill(buffer, quantize(fillValue));
|
||||
canShortcut = true;
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
namespace sfz {
|
||||
|
||||
struct Resources;
|
||||
class Resources;
|
||||
|
||||
class ControllerSource : public ModGenerator {
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -421,7 +421,7 @@ TEST_CASE("[Files] Default path is ignored for generators")
|
|||
TEST_CASE("[Files] Set CC applies properly")
|
||||
{
|
||||
Synth synth;
|
||||
const auto& midiState = synth.getResources().midiState;
|
||||
const MidiState& midiState = synth.getResources().getMidiState();
|
||||
synth.loadSfzFile(fs::current_path() / "tests/TestFiles/set_cc.sfz");
|
||||
REQUIRE(midiState.getCCValue(142) == 63_norm);
|
||||
REQUIRE(midiState.getCCValue(61) == 122_norm);
|
||||
|
|
@ -430,7 +430,7 @@ TEST_CASE("[Files] Set CC applies properly")
|
|||
TEST_CASE("[Files] Set HDCC applies properly")
|
||||
{
|
||||
sfz::Synth synth;
|
||||
const auto& midiState = synth.getResources().midiState;
|
||||
const MidiState& midiState = synth.getResources().getMidiState();
|
||||
synth.loadSfzFile(fs::current_path() / "tests/TestFiles/set_hdcc.sfz");
|
||||
REQUIRE(midiState.getCCValue(142) == Approx(0.5678));
|
||||
REQUIRE(midiState.getCCValue(61) == Approx(0.1234));
|
||||
|
|
@ -439,7 +439,7 @@ TEST_CASE("[Files] Set HDCC applies properly")
|
|||
TEST_CASE("[Files] Set RealCC applies properly")
|
||||
{
|
||||
sfz::Synth synth;
|
||||
const auto& midiState = synth.getResources().midiState;
|
||||
const MidiState& midiState = synth.getResources().getMidiState();
|
||||
synth.loadSfzFile(fs::current_path() / "tests/TestFiles/set_realcc.sfz");
|
||||
REQUIRE(midiState.getCCValue(142) == Approx(0.5678));
|
||||
REQUIRE(midiState.getCCValue(61) == Approx(0.1234));
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
#include "sfizz/Synth.h"
|
||||
#include "sfizz/AudioBuffer.h"
|
||||
#include "sfizz/FlexEnvelope.h"
|
||||
#include "sfizz/modulations/ModMatrix.h"
|
||||
#include "catch2/catch.hpp"
|
||||
#include "TestHelpers.h"
|
||||
#include <array>
|
||||
|
|
@ -42,7 +43,7 @@ TEST_CASE("[FlexEG] Values")
|
|||
REQUIRE( egDescription.points[4].time == .4_a );
|
||||
REQUIRE( egDescription.points[4].level == 1.0_a );
|
||||
REQUIRE( egDescription.sustain == 3 );
|
||||
REQUIRE(synth.getResources().modMatrix.toDotGraph() == createDefaultGraph({
|
||||
REQUIRE(synth.getResources().getModMatrix().toDotGraph() == createDefaultGraph({
|
||||
R"("EG 1 {0}" -> "Amplitude {0}")",
|
||||
}));
|
||||
}
|
||||
|
|
@ -68,7 +69,7 @@ TEST_CASE("[FlexEG] Default values")
|
|||
REQUIRE( egDescription.points[1].level == 0.0_a );
|
||||
REQUIRE( egDescription.points[2].time == .1_a );
|
||||
REQUIRE( egDescription.points[2].level == .25_a );
|
||||
REQUIRE( synth.getResources().modMatrix.toDotGraph() == createDefaultGraph({}) );
|
||||
REQUIRE( synth.getResources().getModMatrix().toDotGraph() == createDefaultGraph({}) );
|
||||
}
|
||||
|
||||
TEST_CASE("[FlexEG] Connections")
|
||||
|
|
@ -86,7 +87,7 @@ TEST_CASE("[FlexEG] Connections")
|
|||
REQUIRE(synth.getNumRegions() == 6);
|
||||
REQUIRE( synth.getRegionView(0)->flexEGs.size() == 1 );
|
||||
REQUIRE( synth.getRegionView(0)->flexEGs[0].points.size() == 2 );
|
||||
REQUIRE( synth.getResources().modMatrix.toDotGraph() == createDefaultGraph({
|
||||
REQUIRE( synth.getResources().getModMatrix().toDotGraph() == createDefaultGraph({
|
||||
R"("EG 1 {0}" -> "Amplitude {0}")",
|
||||
R"("EG 1 {1}" -> "Pan {1}")",
|
||||
R"("EG 1 {2}" -> "Width {2}")",
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
// license. You should have receive a LICENSE.md file along with the code.
|
||||
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
|
||||
|
||||
#include "sfizz/modulations/ModMatrix.h"
|
||||
#include "sfizz/modulations/ModId.h"
|
||||
#include "sfizz/modulations/ModKey.h"
|
||||
#include "sfizz/Synth.h"
|
||||
|
|
@ -89,7 +90,7 @@ pan_oncc36=12.5 pan_stepcc36=0.5
|
|||
width_oncc425=29
|
||||
)");
|
||||
|
||||
const std::string graph = synth.getResources().modMatrix.toDotGraph();
|
||||
const std::string graph = synth.getResources().getModMatrix().toDotGraph();
|
||||
REQUIRE(graph == createDefaultGraph({
|
||||
R"("Controller 20 {curve=3, smooth=0, step=0}" -> "Amplitude {0}")",
|
||||
R"("Controller 42 {curve=0, smooth=32, step=0}" -> "Pitch {0}")",
|
||||
|
|
@ -108,7 +109,7 @@ TEST_CASE("[Modulations] Filter CC connections")
|
|||
resonance3=-1 resonance3_oncc1=2 resonance3_smoothcc1=10
|
||||
)");
|
||||
|
||||
const std::string graph = synth.getResources().modMatrix.toDotGraph();
|
||||
const std::string graph = synth.getResources().getModMatrix().toDotGraph();
|
||||
REQUIRE(graph == createDefaultGraph({
|
||||
R"("Controller 1 {curve=0, smooth=10, step=0}" -> "FilterResonance {0, N=3}")",
|
||||
R"("Controller 2 {curve=2, smooth=0, step=0}" -> "FilterCutoff {0, N=2}")",
|
||||
|
|
@ -126,7 +127,7 @@ TEST_CASE("[Modulations] EQ CC connections")
|
|||
eq3_bw_oncc1=2 eq3_bw_smoothcc1=10
|
||||
)");
|
||||
|
||||
const std::string graph = synth.getResources().modMatrix.toDotGraph();
|
||||
const std::string graph = synth.getResources().getModMatrix().toDotGraph();
|
||||
REQUIRE(graph == createDefaultGraph({
|
||||
R"("Controller 1 {curve=0, smooth=10, step=0}" -> "EqBandwidth {0, N=3}")",
|
||||
R"("Controller 2 {curve=0, smooth=0, step=0.1}" -> "EqGain {0, N=1}")",
|
||||
|
|
@ -147,7 +148,7 @@ TEST_CASE("[Modulations] LFO Filter connections")
|
|||
lfo6_freq=3 lfo6_fil1gain=-1
|
||||
)");
|
||||
|
||||
const std::string graph = synth.getResources().modMatrix.toDotGraph();
|
||||
const std::string graph = synth.getResources().getModMatrix().toDotGraph();
|
||||
REQUIRE(graph == createDefaultGraph({
|
||||
R"("LFO 1 {0}" -> "FilterCutoff {0, N=1}")",
|
||||
R"("LFO 2 {0}" -> "FilterCutoff {0, N=1}")",
|
||||
|
|
@ -171,7 +172,7 @@ TEST_CASE("[Modulations] EG Filter connections")
|
|||
eg6_time1=3 eg6_fil1gain=-1
|
||||
)");
|
||||
|
||||
const std::string graph = synth.getResources().modMatrix.toDotGraph();
|
||||
const std::string graph = synth.getResources().getModMatrix().toDotGraph();
|
||||
REQUIRE(graph == createDefaultGraph({
|
||||
R"("EG 1 {0}" -> "FilterCutoff {0, N=1}")",
|
||||
R"("EG 2 {0}" -> "FilterCutoff {0, N=1}")",
|
||||
|
|
@ -195,7 +196,7 @@ TEST_CASE("[Modulations] LFO EQ connections")
|
|||
lfo6_freq=3 lfo6_eq1freq=-1
|
||||
)");
|
||||
|
||||
const std::string graph = synth.getResources().modMatrix.toDotGraph();
|
||||
const std::string graph = synth.getResources().getModMatrix().toDotGraph();
|
||||
REQUIRE(graph == createDefaultGraph({
|
||||
R"("LFO 1 {0}" -> "EqBandwidth {0, N=1}")",
|
||||
R"("LFO 2 {0}" -> "EqFrequency {0, N=2}")",
|
||||
|
|
@ -219,7 +220,7 @@ TEST_CASE("[Modulations] EG EQ connections")
|
|||
eg6_freq=3 eg6_eq1freq=-1
|
||||
)");
|
||||
|
||||
const std::string graph = synth.getResources().modMatrix.toDotGraph();
|
||||
const std::string graph = synth.getResources().getModMatrix().toDotGraph();
|
||||
REQUIRE(graph == createDefaultGraph({
|
||||
R"("EG 1 {0}" -> "EqBandwidth {0, N=1}")",
|
||||
R"("EG 2 {0}" -> "EqFrequency {0, N=2}")",
|
||||
|
|
@ -244,7 +245,7 @@ TEST_CASE("[Modulations] FlexEG Ampeg target")
|
|||
eg1_ampeg=1
|
||||
)");
|
||||
|
||||
const std::string graph = synth.getResources().modMatrix.toDotGraph();
|
||||
const std::string graph = synth.getResources().getModMatrix().toDotGraph();
|
||||
REQUIRE(graph == createModulationDotGraph({
|
||||
R"("Controller 10 {curve=1, smooth=10, step=0}" -> "Pan {0}")",
|
||||
R"("Controller 11 {curve=4, smooth=10, step=0}" -> "Amplitude {0}")",
|
||||
|
|
@ -269,7 +270,7 @@ TEST_CASE("[Modulations] FlexEG Ampeg target with 2 FlexEGs")
|
|||
eg2_ampeg=1
|
||||
)");
|
||||
|
||||
const std::string graph = synth.getResources().modMatrix.toDotGraph();
|
||||
const std::string graph = synth.getResources().getModMatrix().toDotGraph();
|
||||
REQUIRE(graph == createModulationDotGraph({
|
||||
R"("Controller 10 {curve=1, smooth=10, step=0}" -> "Pan {0}")",
|
||||
R"("Controller 11 {curve=4, smooth=10, step=0}" -> "Amplitude {0}")",
|
||||
|
|
@ -296,7 +297,7 @@ TEST_CASE("[Modulations] FlexEG Ampeg target with multiple EGs targeting ampeg")
|
|||
eg2_ampeg=1
|
||||
)");
|
||||
|
||||
const std::string graph = synth.getResources().modMatrix.toDotGraph();
|
||||
const std::string graph = synth.getResources().getModMatrix().toDotGraph();
|
||||
REQUIRE(graph == createModulationDotGraph({
|
||||
R"("Controller 10 {curve=1, smooth=10, step=0}" -> "Pan {0}")",
|
||||
R"("Controller 11 {curve=4, smooth=10, step=0}" -> "Amplitude {0}")",
|
||||
|
|
@ -313,7 +314,7 @@ TEST_CASE("[Modulations] Override the default volume controller")
|
|||
<region> sample=*sine tune_oncc7=1200
|
||||
)");
|
||||
|
||||
const std::string graph = synth.getResources().modMatrix.toDotGraph();
|
||||
const std::string graph = synth.getResources().getModMatrix().toDotGraph();
|
||||
REQUIRE(graph == createModulationDotGraph({
|
||||
R"("AmplitudeEG {0}" -> "MasterAmplitude {0}")",
|
||||
R"("Controller 10 {curve=1, smooth=10, step=0}" -> "Pan {0}")",
|
||||
|
|
@ -330,7 +331,7 @@ TEST_CASE("[Modulations] Override the default pan controller")
|
|||
<region> sample=*sine on_locc10=127 on_hicc10=127
|
||||
)");
|
||||
|
||||
const std::string graph = synth.getResources().modMatrix.toDotGraph();
|
||||
const std::string graph = synth.getResources().getModMatrix().toDotGraph();
|
||||
REQUIRE(graph == createModulationDotGraph({
|
||||
R"("AmplitudeEG {0}" -> "MasterAmplitude {0}")",
|
||||
R"("Controller 11 {curve=4, smooth=10, step=0}" -> "Amplitude {0}")",
|
||||
|
|
@ -346,7 +347,7 @@ TEST_CASE("[Modulations] Aftertouch connections")
|
|||
<region> sample=*sine cutoff2_chanaft=1000
|
||||
)");
|
||||
|
||||
const std::string graph = synth.getResources().modMatrix.toDotGraph();
|
||||
const std::string graph = synth.getResources().getModMatrix().toDotGraph();
|
||||
REQUIRE(graph == createDefaultGraph({
|
||||
R"("ChannelAftertouch" -> "FilterCutoff {0, N=1}")",
|
||||
R"("ChannelAftertouch" -> "FilterCutoff {1, N=2}")",
|
||||
|
|
@ -362,7 +363,7 @@ TEST_CASE("[Modulations] LFO v1 connections")
|
|||
<region> sample=*sine fillfo_freq=1.0
|
||||
)");
|
||||
|
||||
const std::string graph = synth.getResources().modMatrix.toDotGraph();
|
||||
const std::string graph = synth.getResources().getModMatrix().toDotGraph();
|
||||
REQUIRE(graph == createDefaultGraph({
|
||||
R"("AmplitudeLFO {0}" -> "Volume {0}")",
|
||||
R"("PitchLFO {1}" -> "Pitch {1}")",
|
||||
|
|
@ -379,7 +380,7 @@ TEST_CASE("[Modulations] LFO v1 CC connections")
|
|||
<region> sample=*sine fillfo_depth_oncc3=-3600
|
||||
)");
|
||||
|
||||
const std::string graph = synth.getResources().modMatrix.toDotGraph();
|
||||
const std::string graph = synth.getResources().getModMatrix().toDotGraph();
|
||||
REQUIRE(graph == createDefaultGraph({
|
||||
R"("Controller 1 {curve=0, smooth=0, step=0}" -> "AmplitudeLFODepth {0}")",
|
||||
R"("Controller 2 {curve=0, smooth=0, step=0}" -> "PitchLFODepth {1}")",
|
||||
|
|
@ -399,7 +400,7 @@ TEST_CASE("[Modulations] LFO v1 CC frequency connections")
|
|||
<region> sample=*sine fillfo_freqcc3=-3600
|
||||
)");
|
||||
|
||||
const std::string graph = synth.getResources().modMatrix.toDotGraph();
|
||||
const std::string graph = synth.getResources().getModMatrix().toDotGraph();
|
||||
REQUIRE(graph == createDefaultGraph({
|
||||
R"("Controller 1 {curve=0, smooth=0, step=0}" -> "AmplitudeLFOFrequency {0}")",
|
||||
R"("Controller 2 {curve=0, smooth=0, step=0}" -> "PitchLFOFrequency {1}")",
|
||||
|
|
@ -419,7 +420,7 @@ TEST_CASE("[Modulations] LFO v1 aftertouch connections")
|
|||
<region> sample=*sine fillfo_depthchanaft=-3600
|
||||
)");
|
||||
|
||||
const std::string graph = synth.getResources().modMatrix.toDotGraph();
|
||||
const std::string graph = synth.getResources().getModMatrix().toDotGraph();
|
||||
REQUIRE(graph == createDefaultGraph({
|
||||
R"("ChannelAftertouch" -> "AmplitudeLFODepth {0}")",
|
||||
R"("ChannelAftertouch" -> "PitchLFODepth {1}")",
|
||||
|
|
@ -439,7 +440,7 @@ TEST_CASE("[Modulations] LFO v1 aftertouch frequency connections")
|
|||
<region> sample=*sine fillfo_freqchanaft=-3600
|
||||
)");
|
||||
|
||||
const std::string graph = synth.getResources().modMatrix.toDotGraph();
|
||||
const std::string graph = synth.getResources().getModMatrix().toDotGraph();
|
||||
REQUIRE(graph == createDefaultGraph({
|
||||
R"("ChannelAftertouch" -> "AmplitudeLFOFrequency {0}")",
|
||||
R"("ChannelAftertouch" -> "PitchLFOFrequency {1}")",
|
||||
|
|
@ -459,7 +460,7 @@ TEST_CASE("[Modulations] LFO v1 poly aftertouch connections")
|
|||
<region> sample=*sine fillfo_depthpolyaft=-3600
|
||||
)");
|
||||
|
||||
const std::string graph = synth.getResources().modMatrix.toDotGraph();
|
||||
const std::string graph = synth.getResources().getModMatrix().toDotGraph();
|
||||
REQUIRE(graph == createDefaultGraph({
|
||||
R"("PolyAftertouch" -> "AmplitudeLFODepth {0}")",
|
||||
R"("PolyAftertouch" -> "PitchLFODepth {1}")",
|
||||
|
|
@ -479,7 +480,7 @@ TEST_CASE("[Modulations] LFO v1 poly aftertouch frequency connections")
|
|||
<region> sample=*sine fillfo_freqpolyaft=-3600
|
||||
)");
|
||||
|
||||
const std::string graph = synth.getResources().modMatrix.toDotGraph();
|
||||
const std::string graph = synth.getResources().getModMatrix().toDotGraph();
|
||||
REQUIRE(graph == createDefaultGraph({
|
||||
R"("PolyAftertouch" -> "AmplitudeLFOFrequency {0}")",
|
||||
R"("PolyAftertouch" -> "PitchLFOFrequency {1}")",
|
||||
|
|
@ -498,7 +499,7 @@ TEST_CASE("[Modulations] EG v1 CC connections")
|
|||
<region> sample=*sine fileg_depth_oncc3=-3600
|
||||
)");
|
||||
|
||||
const std::string graph = synth.getResources().modMatrix.toDotGraph();
|
||||
const std::string graph = synth.getResources().getModMatrix().toDotGraph();
|
||||
REQUIRE(graph == createDefaultGraph({
|
||||
R"("Controller 2 {curve=0, smooth=0, step=0}" -> "PitchEGDepth {0}")",
|
||||
R"("Controller 3 {curve=0, smooth=0, step=0}" -> "FilterEGDepth {1}")",
|
||||
|
|
@ -523,7 +524,7 @@ TEST_CASE("[Modulations] LFO CC connections")
|
|||
pitch_oncc137=1200
|
||||
)");
|
||||
|
||||
const std::string graph = synth.getResources().modMatrix.toDotGraph();
|
||||
const std::string graph = synth.getResources().getModMatrix().toDotGraph();
|
||||
REQUIRE(graph == createDefaultGraph({
|
||||
R"("Controller 128 {curve=0, smooth=0, step=0}" -> "Pitch {0}")",
|
||||
R"("Controller 129 {curve=0, smooth=0, step=0}" -> "Pitch {0}")",
|
||||
|
|
@ -547,7 +548,7 @@ TEST_CASE("[Modulations] Extended CCs connections")
|
|||
lfo3_freq=0.1 lfo3_phase_cc1=2 lfo3_phase_smoothcc1=10 lfo3_phase_stepcc1=0.2 lfo3_phase_curvecc1=1 lfo3_amplitude=50
|
||||
)");
|
||||
|
||||
const std::string graph = synth.getResources().modMatrix.toDotGraph();
|
||||
const std::string graph = synth.getResources().getModMatrix().toDotGraph();
|
||||
REQUIRE(graph == createDefaultGraph({
|
||||
R"("LFO 1 {0}" -> "Volume {0}")",
|
||||
R"("LFO 2 {0}" -> "Pitch {0}")",
|
||||
|
|
|
|||
|
|
@ -141,7 +141,7 @@ TEST_CASE("[Synth] Reset all controllers")
|
|||
{
|
||||
sfz::Synth synth;
|
||||
sfz::AudioBuffer<float> buffer { 2, static_cast<unsigned>(synth.getSamplesPerBlock()) };
|
||||
const auto& midiState = synth.getResources().midiState;
|
||||
const sfz::MidiState& midiState = synth.getResources().getMidiState();
|
||||
synth.cc(0, 12, 64);
|
||||
synth.renderBlock(buffer);
|
||||
REQUIRE(midiState.getCCValue(12) == 64_norm);
|
||||
|
|
@ -401,7 +401,7 @@ TEST_CASE("[Synth] Gain to mix")
|
|||
TEST_CASE("[Synth] Basic curves")
|
||||
{
|
||||
sfz::Synth synth;
|
||||
const auto& curves = synth.getResources().curves;
|
||||
const sfz::CurveSet& curves = synth.getResources().getCurves();
|
||||
synth.loadSfzString(fs::current_path() / "tests/TestFiles/curves.sfz", R"(
|
||||
<region> sample=*sine
|
||||
<curve>curve_index=18 v000=0 v095=0.5 v127=1
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue