Move the Synth p-impl to the header file SynthPrivate
This commit is contained in:
parent
bf4fd71ea6
commit
bb5cd652f5
4 changed files with 280 additions and 272 deletions
|
|
@ -107,6 +107,7 @@ set (SFIZZ_HEADERS
|
||||||
sfizz/SwapAndPop.h
|
sfizz/SwapAndPop.h
|
||||||
sfizz/Synth.h
|
sfizz/Synth.h
|
||||||
sfizz/SynthConfig.h
|
sfizz/SynthConfig.h
|
||||||
|
sfizz/SynthPrivate.h
|
||||||
sfizz/Tuning.h
|
sfizz/Tuning.h
|
||||||
sfizz/Voice.h
|
sfizz/Voice.h
|
||||||
sfizz/VoiceManager.h
|
sfizz/VoiceManager.h
|
||||||
|
|
|
||||||
|
|
@ -4,31 +4,23 @@
|
||||||
// license. You should have receive a LICENSE.md file along with the code.
|
// 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
|
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
|
||||||
|
|
||||||
#include "Synth.h"
|
#include "SynthPrivate.h"
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
#include "Debug.h"
|
#include "Debug.h"
|
||||||
#include "Effects.h"
|
|
||||||
#include "Macros.h"
|
#include "Macros.h"
|
||||||
#include "modulations/ModId.h"
|
#include "modulations/ModId.h"
|
||||||
#include "modulations/ModKey.h"
|
#include "modulations/ModKey.h"
|
||||||
#include "modulations/ModMatrix.h"
|
#include "modulations/ModMatrix.h"
|
||||||
#include "modulations/sources/ADSREnvelope.h"
|
|
||||||
#include "modulations/sources/Controller.h"
|
|
||||||
#include "modulations/sources/FlexEnvelope.h"
|
|
||||||
#include "modulations/sources/LFO.h"
|
|
||||||
#include "PolyphonyGroup.h"
|
#include "PolyphonyGroup.h"
|
||||||
#include "pugixml.hpp"
|
#include "pugixml.hpp"
|
||||||
#include "Region.h"
|
#include "Region.h"
|
||||||
#include "RegionSet.h"
|
#include "RegionSet.h"
|
||||||
#include "Resources.h"
|
#include "Resources.h"
|
||||||
#include "ScopedFTZ.h"
|
#include "ScopedFTZ.h"
|
||||||
#include "SisterVoiceRing.h"
|
|
||||||
#include "StringViewHelpers.h"
|
#include "StringViewHelpers.h"
|
||||||
#include "TriggerEvent.h"
|
|
||||||
#include "utility/SpinMutex.h"
|
#include "utility/SpinMutex.h"
|
||||||
#include "utility/XmlHelpers.h"
|
#include "utility/XmlHelpers.h"
|
||||||
#include "Voice.h"
|
#include "Voice.h"
|
||||||
#include "VoiceManager.h"
|
|
||||||
#include <absl/algorithm/container.h>
|
#include <absl/algorithm/container.h>
|
||||||
#include <absl/memory/memory.h>
|
#include <absl/memory/memory.h>
|
||||||
#include <absl/strings/str_replace.h>
|
#include <absl/strings/str_replace.h>
|
||||||
|
|
@ -42,268 +34,6 @@
|
||||||
|
|
||||||
namespace sfz {
|
namespace sfz {
|
||||||
|
|
||||||
struct Synth::Impl final: public Parser::Listener {
|
|
||||||
Impl();
|
|
||||||
~Impl();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief The parser callback; this is called by the parent object each time
|
|
||||||
* a new region, group, master, global, curve or control set of opcodes
|
|
||||||
* appears in the parser
|
|
||||||
*
|
|
||||||
* @param header the header for the set of opcodes
|
|
||||||
* @param members the opcode members
|
|
||||||
*/
|
|
||||||
void onParseFullBlock(const std::string& header, const std::vector<Opcode>& members) final;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief The parser callback when an error occurs.
|
|
||||||
*/
|
|
||||||
void onParseError(const SourceRange& range, const std::string& message) final;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief The parser callback when a warning occurs.
|
|
||||||
*/
|
|
||||||
void onParseWarning(const SourceRange& range, const std::string& message) final;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Reset all CCs; to be used on CC 121
|
|
||||||
*
|
|
||||||
* @param delay the delay for the controller reset
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void resetAllControllers(int delay) noexcept;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Remove all regions, resets all voices and clears everything
|
|
||||||
* to bring back the synth in its original state.
|
|
||||||
*
|
|
||||||
* The callback mutex should be taken to call this function.
|
|
||||||
*/
|
|
||||||
void clear();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Helper function to dispatch <global> opcodes
|
|
||||||
*
|
|
||||||
* @param members the opcodes of the <global> block
|
|
||||||
*/
|
|
||||||
void handleGlobalOpcodes(const std::vector<Opcode>& members);
|
|
||||||
/**
|
|
||||||
* @brief Helper function to dispatch <master> opcodes
|
|
||||||
*
|
|
||||||
* @param members the opcodes of the <master> block
|
|
||||||
*/
|
|
||||||
void handleMasterOpcodes(const std::vector<Opcode>& members);
|
|
||||||
/**
|
|
||||||
* @brief Helper function to dispatch <group> opcodes
|
|
||||||
*
|
|
||||||
* @param members the opcodes of the <group> block
|
|
||||||
*/
|
|
||||||
void handleGroupOpcodes(const std::vector<Opcode>& members, const std::vector<Opcode>& masterMembers);
|
|
||||||
/**
|
|
||||||
* @brief Helper function to dispatch <control> opcodes
|
|
||||||
*
|
|
||||||
* @param members the opcodes of the <control> block
|
|
||||||
*/
|
|
||||||
void handleControlOpcodes(const std::vector<Opcode>& members);
|
|
||||||
/**
|
|
||||||
* @brief Helper function to dispatch <effect> opcodes
|
|
||||||
*
|
|
||||||
* @param members the opcodes of the <effect> block
|
|
||||||
*/
|
|
||||||
void handleEffectOpcodes(const std::vector<Opcode>& members);
|
|
||||||
/**
|
|
||||||
* @brief Helper function to merge all the currently active opcodes
|
|
||||||
* as set by the successive callbacks and create a new region to store
|
|
||||||
* in the synth.
|
|
||||||
*
|
|
||||||
* @param regionOpcodes the opcodes that are specific to the region
|
|
||||||
*/
|
|
||||||
void buildRegion(const std::vector<Opcode>& regionOpcodes);
|
|
||||||
/**
|
|
||||||
* @brief Resets and possibly changes the number of voices (polyphony) in
|
|
||||||
* the synth.
|
|
||||||
*
|
|
||||||
* @param numVoices
|
|
||||||
*/
|
|
||||||
void resetVoices(int numVoices);
|
|
||||||
/**
|
|
||||||
* @brief Make the stored settings take effect in all the voices
|
|
||||||
*/
|
|
||||||
void applySettingsPerVoice();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Establish all connections of the modulation matrix.
|
|
||||||
*/
|
|
||||||
void setupModMatrix();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get the modification time of all included sfz files
|
|
||||||
*
|
|
||||||
* @return fs::file_time_type
|
|
||||||
*/
|
|
||||||
fs::file_time_type checkModificationTime();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Check all regions and start voices for note on events
|
|
||||||
*
|
|
||||||
* @param delay
|
|
||||||
* @param noteNumber
|
|
||||||
* @param velocity
|
|
||||||
*/
|
|
||||||
void noteOnDispatch(int delay, int noteNumber, float velocity) noexcept;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Check all regions and start voices for note off events
|
|
||||||
*
|
|
||||||
* @param delay
|
|
||||||
* @param noteNumber
|
|
||||||
* @param velocity
|
|
||||||
*/
|
|
||||||
void noteOffDispatch(int delay, int noteNumber, float velocity) noexcept;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Check all regions and start voices for cc events
|
|
||||||
*
|
|
||||||
* @param delay
|
|
||||||
* @param ccNumber
|
|
||||||
* @param value
|
|
||||||
*/
|
|
||||||
void ccDispatch(int delay, int ccNumber, float value) noexcept;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Start a voice for a specific region.
|
|
||||||
* This will do the needed polyphony checks and voice stealing.
|
|
||||||
*
|
|
||||||
* @param region
|
|
||||||
* @param delay
|
|
||||||
* @param triggerEvent
|
|
||||||
* @param ring
|
|
||||||
*/
|
|
||||||
void startVoice(Region* region, int delay, const TriggerEvent& triggerEvent, SisterVoiceRingBuilder& ring) noexcept;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Start all delayed release voices of the region if necessary
|
|
||||||
*
|
|
||||||
* @param region
|
|
||||||
* @param delay
|
|
||||||
* @param ring
|
|
||||||
*/
|
|
||||||
void startDelayedReleaseVoices(Region* region, int delay, SisterVoiceRingBuilder& ring) noexcept;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Finalize SFZ loading, following a successful execution of the
|
|
||||||
* parsing step.
|
|
||||||
*/
|
|
||||||
void finalizeSfzLoad();
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
static void updateUsedCCsFromCCMap(std::bitset<config::numCCs>& usedCCs, const CCMap<T> map) noexcept
|
|
||||||
{
|
|
||||||
for (auto& mod : map)
|
|
||||||
usedCCs[mod.cc] = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void updateUsedCCsFromRegion(std::bitset<config::numCCs>& usedCCs, const Region& region);
|
|
||||||
static void updateUsedCCsFromModulations(std::bitset<config::numCCs>& usedCCs, const ModMatrix& mm);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Set the default value for a CC
|
|
||||||
*
|
|
||||||
* @param ccNumber
|
|
||||||
* @param value
|
|
||||||
*/
|
|
||||||
void setDefaultHdcc(int ccNumber, float value);
|
|
||||||
|
|
||||||
int numGroups_ { 0 };
|
|
||||||
int numMasters_ { 0 };
|
|
||||||
|
|
||||||
// Opcode memory; these are used to build regions, as a new region
|
|
||||||
// will integrate opcodes from the group, master and global block
|
|
||||||
std::vector<Opcode> globalOpcodes_;
|
|
||||||
std::vector<Opcode> masterOpcodes_;
|
|
||||||
std::vector<Opcode> groupOpcodes_;
|
|
||||||
|
|
||||||
// Names for the CC and notes as set by label_cc and label_key
|
|
||||||
std::vector<CCNamePair> ccLabels_;
|
|
||||||
std::vector<NoteNamePair> keyLabels_;
|
|
||||||
std::vector<NoteNamePair> keyswitchLabels_;
|
|
||||||
|
|
||||||
// Set as sw_default if present in the file
|
|
||||||
absl::optional<uint8_t> currentSwitch_;
|
|
||||||
std::vector<std::string> unknownOpcodes_;
|
|
||||||
using RegionViewVector = std::vector<Region*>;
|
|
||||||
using VoiceViewVector = std::vector<Voice*>;
|
|
||||||
using RegionPtr = std::unique_ptr<Region>;
|
|
||||||
using RegionSetPtr = std::unique_ptr<RegionSet>;
|
|
||||||
std::vector<RegionPtr> regions_;
|
|
||||||
VoiceManager voiceManager_;
|
|
||||||
|
|
||||||
// These are more general "groups" than sfz and encapsulates the full hierarchy
|
|
||||||
RegionSet* currentSet_ { nullptr };
|
|
||||||
std::vector<RegionSetPtr> sets_;
|
|
||||||
|
|
||||||
std::array<RegionViewVector, 128> lastKeyswitchLists_;
|
|
||||||
std::array<RegionViewVector, 128> downKeyswitchLists_;
|
|
||||||
std::array<RegionViewVector, 128> upKeyswitchLists_;
|
|
||||||
RegionViewVector previousKeyswitchLists_;
|
|
||||||
std::array<RegionViewVector, 128> noteActivationLists_;
|
|
||||||
std::array<RegionViewVector, config::numCCs> ccActivationLists_;
|
|
||||||
|
|
||||||
// Effect factory and buses
|
|
||||||
EffectFactory effectFactory_;
|
|
||||||
typedef std::unique_ptr<EffectBus> EffectBusPtr;
|
|
||||||
std::vector<EffectBusPtr> effectBuses_; // 0 is "main", 1-N are "fx1"-"fxN"
|
|
||||||
|
|
||||||
int samplesPerBlock_ { config::defaultSamplesPerBlock };
|
|
||||||
float sampleRate_ { config::defaultSampleRate };
|
|
||||||
float volume_ { Default::globalVolume };
|
|
||||||
int numVoices_ { config::numVoices };
|
|
||||||
Oversampling oversamplingFactor_ { config::defaultOversamplingFactor };
|
|
||||||
|
|
||||||
// Distribution used to generate random value for the *rand opcodes
|
|
||||||
std::uniform_real_distribution<float> randNoteDistribution_ { 0, 1 };
|
|
||||||
|
|
||||||
SpinMutex callbackGuard_;
|
|
||||||
|
|
||||||
// Singletons passed as references to the voices
|
|
||||||
Resources resources_;
|
|
||||||
|
|
||||||
// Control opcodes
|
|
||||||
std::string defaultPath_ { "" };
|
|
||||||
int noteOffset_ { 0 };
|
|
||||||
int octaveOffset_ { 0 };
|
|
||||||
|
|
||||||
// Modulation source generators
|
|
||||||
std::unique_ptr<ControllerSource> genController_;
|
|
||||||
std::unique_ptr<LFOSource> genLFO_;
|
|
||||||
std::unique_ptr<FlexEnvelopeSource> genFlexEnvelope_;
|
|
||||||
std::unique_ptr<ADSREnvelopeSource> genADSREnvelope_;
|
|
||||||
|
|
||||||
// Settings per voice
|
|
||||||
struct {
|
|
||||||
size_t maxFilters { 0 };
|
|
||||||
size_t maxEQs { 0 };
|
|
||||||
size_t maxLFOs { 0 };
|
|
||||||
size_t maxFlexEGs { 0 };
|
|
||||||
bool havePitchEG { false };
|
|
||||||
bool haveFilterEG { false };
|
|
||||||
} settingsPerVoice_;
|
|
||||||
|
|
||||||
Duration dispatchDuration_ { 0 };
|
|
||||||
|
|
||||||
std::chrono::time_point<std::chrono::high_resolution_clock> lastGarbageCollection_;
|
|
||||||
|
|
||||||
Parser parser_;
|
|
||||||
fs::file_time_type modificationTime_ { };
|
|
||||||
|
|
||||||
std::array<float, config::numCCs> defaultCCValues_;
|
|
||||||
|
|
||||||
// Messaging
|
|
||||||
sfizz_receive_t* broadcastReceiver = nullptr;
|
|
||||||
void* broadcastData = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
Synth::Synth()
|
Synth::Synth()
|
||||||
: impl_(new Impl) // NOLINT: (paul) I don't get why clang-tidy complains here
|
: impl_(new Impl) // NOLINT: (paul) I don't get why clang-tidy complains here
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
// license. You should have receive a LICENSE.md file along with the code.
|
// 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
|
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
|
||||||
|
|
||||||
#include "Synth.h"
|
#include "SynthPrivate.h"
|
||||||
#include "StringViewHelpers.h"
|
#include "StringViewHelpers.h"
|
||||||
#include <absl/strings/ascii.h>
|
#include <absl/strings/ascii.h>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
|
||||||
277
src/sfizz/SynthPrivate.h
Normal file
277
src/sfizz/SynthPrivate.h
Normal file
|
|
@ -0,0 +1,277 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Synth.h"
|
||||||
|
#include "Effects.h"
|
||||||
|
#include "SisterVoiceRing.h"
|
||||||
|
#include "TriggerEvent.h"
|
||||||
|
#include "VoiceManager.h"
|
||||||
|
#include "modulations/sources/ADSREnvelope.h"
|
||||||
|
#include "modulations/sources/Controller.h"
|
||||||
|
#include "modulations/sources/FlexEnvelope.h"
|
||||||
|
#include "modulations/sources/LFO.h"
|
||||||
|
|
||||||
|
namespace sfz {
|
||||||
|
|
||||||
|
struct Synth::Impl final: public Parser::Listener {
|
||||||
|
Impl();
|
||||||
|
~Impl();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The parser callback; this is called by the parent object each time
|
||||||
|
* a new region, group, master, global, curve or control set of opcodes
|
||||||
|
* appears in the parser
|
||||||
|
*
|
||||||
|
* @param header the header for the set of opcodes
|
||||||
|
* @param members the opcode members
|
||||||
|
*/
|
||||||
|
void onParseFullBlock(const std::string& header, const std::vector<Opcode>& members) final;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The parser callback when an error occurs.
|
||||||
|
*/
|
||||||
|
void onParseError(const SourceRange& range, const std::string& message) final;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The parser callback when a warning occurs.
|
||||||
|
*/
|
||||||
|
void onParseWarning(const SourceRange& range, const std::string& message) final;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reset all CCs; to be used on CC 121
|
||||||
|
*
|
||||||
|
* @param delay the delay for the controller reset
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void resetAllControllers(int delay) noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Remove all regions, resets all voices and clears everything
|
||||||
|
* to bring back the synth in its original state.
|
||||||
|
*
|
||||||
|
* The callback mutex should be taken to call this function.
|
||||||
|
*/
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Helper function to dispatch <global> opcodes
|
||||||
|
*
|
||||||
|
* @param members the opcodes of the <global> block
|
||||||
|
*/
|
||||||
|
void handleGlobalOpcodes(const std::vector<Opcode>& members);
|
||||||
|
/**
|
||||||
|
* @brief Helper function to dispatch <master> opcodes
|
||||||
|
*
|
||||||
|
* @param members the opcodes of the <master> block
|
||||||
|
*/
|
||||||
|
void handleMasterOpcodes(const std::vector<Opcode>& members);
|
||||||
|
/**
|
||||||
|
* @brief Helper function to dispatch <group> opcodes
|
||||||
|
*
|
||||||
|
* @param members the opcodes of the <group> block
|
||||||
|
*/
|
||||||
|
void handleGroupOpcodes(const std::vector<Opcode>& members, const std::vector<Opcode>& masterMembers);
|
||||||
|
/**
|
||||||
|
* @brief Helper function to dispatch <control> opcodes
|
||||||
|
*
|
||||||
|
* @param members the opcodes of the <control> block
|
||||||
|
*/
|
||||||
|
void handleControlOpcodes(const std::vector<Opcode>& members);
|
||||||
|
/**
|
||||||
|
* @brief Helper function to dispatch <effect> opcodes
|
||||||
|
*
|
||||||
|
* @param members the opcodes of the <effect> block
|
||||||
|
*/
|
||||||
|
void handleEffectOpcodes(const std::vector<Opcode>& members);
|
||||||
|
/**
|
||||||
|
* @brief Helper function to merge all the currently active opcodes
|
||||||
|
* as set by the successive callbacks and create a new region to store
|
||||||
|
* in the synth.
|
||||||
|
*
|
||||||
|
* @param regionOpcodes the opcodes that are specific to the region
|
||||||
|
*/
|
||||||
|
void buildRegion(const std::vector<Opcode>& regionOpcodes);
|
||||||
|
/**
|
||||||
|
* @brief Resets and possibly changes the number of voices (polyphony) in
|
||||||
|
* the synth.
|
||||||
|
*
|
||||||
|
* @param numVoices
|
||||||
|
*/
|
||||||
|
void resetVoices(int numVoices);
|
||||||
|
/**
|
||||||
|
* @brief Make the stored settings take effect in all the voices
|
||||||
|
*/
|
||||||
|
void applySettingsPerVoice();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Establish all connections of the modulation matrix.
|
||||||
|
*/
|
||||||
|
void setupModMatrix();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the modification time of all included sfz files
|
||||||
|
*
|
||||||
|
* @return fs::file_time_type
|
||||||
|
*/
|
||||||
|
fs::file_time_type checkModificationTime();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Check all regions and start voices for note on events
|
||||||
|
*
|
||||||
|
* @param delay
|
||||||
|
* @param noteNumber
|
||||||
|
* @param velocity
|
||||||
|
*/
|
||||||
|
void noteOnDispatch(int delay, int noteNumber, float velocity) noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Check all regions and start voices for note off events
|
||||||
|
*
|
||||||
|
* @param delay
|
||||||
|
* @param noteNumber
|
||||||
|
* @param velocity
|
||||||
|
*/
|
||||||
|
void noteOffDispatch(int delay, int noteNumber, float velocity) noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Check all regions and start voices for cc events
|
||||||
|
*
|
||||||
|
* @param delay
|
||||||
|
* @param ccNumber
|
||||||
|
* @param value
|
||||||
|
*/
|
||||||
|
void ccDispatch(int delay, int ccNumber, float value) noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Start a voice for a specific region.
|
||||||
|
* This will do the needed polyphony checks and voice stealing.
|
||||||
|
*
|
||||||
|
* @param region
|
||||||
|
* @param delay
|
||||||
|
* @param triggerEvent
|
||||||
|
* @param ring
|
||||||
|
*/
|
||||||
|
void startVoice(Region* region, int delay, const TriggerEvent& triggerEvent, SisterVoiceRingBuilder& ring) noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Start all delayed release voices of the region if necessary
|
||||||
|
*
|
||||||
|
* @param region
|
||||||
|
* @param delay
|
||||||
|
* @param ring
|
||||||
|
*/
|
||||||
|
void startDelayedReleaseVoices(Region* region, int delay, SisterVoiceRingBuilder& ring) noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Finalize SFZ loading, following a successful execution of the
|
||||||
|
* parsing step.
|
||||||
|
*/
|
||||||
|
void finalizeSfzLoad();
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
static void updateUsedCCsFromCCMap(std::bitset<config::numCCs>& usedCCs, const CCMap<T> map) noexcept
|
||||||
|
{
|
||||||
|
for (auto& mod : map)
|
||||||
|
usedCCs[mod.cc] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void updateUsedCCsFromRegion(std::bitset<config::numCCs>& usedCCs, const Region& region);
|
||||||
|
static void updateUsedCCsFromModulations(std::bitset<config::numCCs>& usedCCs, const ModMatrix& mm);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the default value for a CC
|
||||||
|
*
|
||||||
|
* @param ccNumber
|
||||||
|
* @param value
|
||||||
|
*/
|
||||||
|
void setDefaultHdcc(int ccNumber, float value);
|
||||||
|
|
||||||
|
int numGroups_ { 0 };
|
||||||
|
int numMasters_ { 0 };
|
||||||
|
|
||||||
|
// Opcode memory; these are used to build regions, as a new region
|
||||||
|
// will integrate opcodes from the group, master and global block
|
||||||
|
std::vector<Opcode> globalOpcodes_;
|
||||||
|
std::vector<Opcode> masterOpcodes_;
|
||||||
|
std::vector<Opcode> groupOpcodes_;
|
||||||
|
|
||||||
|
// Names for the CC and notes as set by label_cc and label_key
|
||||||
|
std::vector<CCNamePair> ccLabels_;
|
||||||
|
std::vector<NoteNamePair> keyLabels_;
|
||||||
|
std::vector<NoteNamePair> keyswitchLabels_;
|
||||||
|
|
||||||
|
// Set as sw_default if present in the file
|
||||||
|
absl::optional<uint8_t> currentSwitch_;
|
||||||
|
std::vector<std::string> unknownOpcodes_;
|
||||||
|
using RegionViewVector = std::vector<Region*>;
|
||||||
|
using VoiceViewVector = std::vector<Voice*>;
|
||||||
|
using RegionPtr = std::unique_ptr<Region>;
|
||||||
|
using RegionSetPtr = std::unique_ptr<RegionSet>;
|
||||||
|
std::vector<RegionPtr> regions_;
|
||||||
|
VoiceManager voiceManager_;
|
||||||
|
|
||||||
|
// These are more general "groups" than sfz and encapsulates the full hierarchy
|
||||||
|
RegionSet* currentSet_ { nullptr };
|
||||||
|
std::vector<RegionSetPtr> sets_;
|
||||||
|
|
||||||
|
std::array<RegionViewVector, 128> lastKeyswitchLists_;
|
||||||
|
std::array<RegionViewVector, 128> downKeyswitchLists_;
|
||||||
|
std::array<RegionViewVector, 128> upKeyswitchLists_;
|
||||||
|
RegionViewVector previousKeyswitchLists_;
|
||||||
|
std::array<RegionViewVector, 128> noteActivationLists_;
|
||||||
|
std::array<RegionViewVector, config::numCCs> ccActivationLists_;
|
||||||
|
|
||||||
|
// Effect factory and buses
|
||||||
|
EffectFactory effectFactory_;
|
||||||
|
typedef std::unique_ptr<EffectBus> EffectBusPtr;
|
||||||
|
std::vector<EffectBusPtr> effectBuses_; // 0 is "main", 1-N are "fx1"-"fxN"
|
||||||
|
|
||||||
|
int samplesPerBlock_ { config::defaultSamplesPerBlock };
|
||||||
|
float sampleRate_ { config::defaultSampleRate };
|
||||||
|
float volume_ { Default::globalVolume };
|
||||||
|
int numVoices_ { config::numVoices };
|
||||||
|
Oversampling oversamplingFactor_ { config::defaultOversamplingFactor };
|
||||||
|
|
||||||
|
// Distribution used to generate random value for the *rand opcodes
|
||||||
|
std::uniform_real_distribution<float> randNoteDistribution_ { 0, 1 };
|
||||||
|
|
||||||
|
SpinMutex callbackGuard_;
|
||||||
|
|
||||||
|
// Singletons passed as references to the voices
|
||||||
|
Resources resources_;
|
||||||
|
|
||||||
|
// Control opcodes
|
||||||
|
std::string defaultPath_ { "" };
|
||||||
|
int noteOffset_ { 0 };
|
||||||
|
int octaveOffset_ { 0 };
|
||||||
|
|
||||||
|
// Modulation source generators
|
||||||
|
std::unique_ptr<ControllerSource> genController_;
|
||||||
|
std::unique_ptr<LFOSource> genLFO_;
|
||||||
|
std::unique_ptr<FlexEnvelopeSource> genFlexEnvelope_;
|
||||||
|
std::unique_ptr<ADSREnvelopeSource> genADSREnvelope_;
|
||||||
|
|
||||||
|
// Settings per voice
|
||||||
|
struct {
|
||||||
|
size_t maxFilters { 0 };
|
||||||
|
size_t maxEQs { 0 };
|
||||||
|
size_t maxLFOs { 0 };
|
||||||
|
size_t maxFlexEGs { 0 };
|
||||||
|
bool havePitchEG { false };
|
||||||
|
bool haveFilterEG { false };
|
||||||
|
} settingsPerVoice_;
|
||||||
|
|
||||||
|
Duration dispatchDuration_ { 0 };
|
||||||
|
|
||||||
|
std::chrono::time_point<std::chrono::high_resolution_clock> lastGarbageCollection_;
|
||||||
|
|
||||||
|
Parser parser_;
|
||||||
|
fs::file_time_type modificationTime_ { };
|
||||||
|
|
||||||
|
std::array<float, config::numCCs> defaultCCValues_;
|
||||||
|
|
||||||
|
// Messaging
|
||||||
|
sfizz_receive_t* broadcastReceiver = nullptr;
|
||||||
|
void* broadcastData = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace sfz
|
||||||
Loading…
Add table
Reference in a new issue