Skip to content

Commit

Permalink
Improved dsp chain setup
Browse files Browse the repository at this point in the history
  • Loading branch information
ffAudio committed Apr 17, 2024
1 parent 929e485 commit 6fcef1e
Show file tree
Hide file tree
Showing 15 changed files with 168 additions and 55 deletions.
24 changes: 12 additions & 12 deletions modules/foleys_dsp_magic/DSP/foleys_BuiltinNodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ class MagicDspBuilder;
class AudioInput : public DspNode
{
public:
AudioInput (MagicDspBuilder& builder, const juce::ValueTree& node) : DspNode (builder, node) { }
AudioInput (DspProgram& program, const juce::ValueTree& node) : DspNode (program, node) { }
[[nodiscard]] juce::String getCategory() const override { return Category::Audio; }

void prepare (juce::dsp::ProcessSpec spec) override { }
void process (juce::dsp::AudioBlock<float>& buffer, juce::MidiBuffer& midi) override { }
void prepare ([[maybe_unused]] juce::dsp::ProcessSpec spec) override { }
void process ([[maybe_unused]] juce::dsp::AudioBlock<float>& buffer, [[maybe_unused]] juce::MidiBuffer& midi) override { }
void release() override { }

FOLEYS_DECLARE_DSP_FACTORY (AudioInput)
Expand All @@ -30,11 +30,11 @@ class AudioInput : public DspNode
class AudioOutput : public DspNode
{
public:
AudioOutput (MagicDspBuilder& builder, const juce::ValueTree& node) : DspNode (builder, node) { }
AudioOutput (DspProgram& program, const juce::ValueTree& node) : DspNode (program, node) { }
[[nodiscard]] juce::String getCategory() const override { return Category::Audio; }

void prepare (juce::dsp::ProcessSpec spec) override { }
void process (juce::dsp::AudioBlock<float>& buffer, juce::MidiBuffer& midi) override { }
void prepare ([[maybe_unused]] juce::dsp::ProcessSpec spec) override { }
void process ([[maybe_unused]] juce::dsp::AudioBlock<float>& buffer, [[maybe_unused]] juce::MidiBuffer& midi) override { }
void release() override { }

FOLEYS_DECLARE_DSP_FACTORY (AudioOutput)
Expand All @@ -45,11 +45,11 @@ class AudioOutput : public DspNode
class MidiInput : public DspNode
{
public:
MidiInput (MagicDspBuilder& builder, const juce::ValueTree& node) : DspNode (builder, node) { }
MidiInput (DspProgram& program, const juce::ValueTree& node) : DspNode (program, node) { }
[[nodiscard]] juce::String getCategory() const override { return Category::Audio; }

void prepare (juce::dsp::ProcessSpec spec) override { }
void process (juce::dsp::AudioBlock<float>& buffer, juce::MidiBuffer& midi) override { }
void prepare ([[maybe_unused]] juce::dsp::ProcessSpec spec) override { }
void process ([[maybe_unused]] juce::dsp::AudioBlock<float>& buffer, [[maybe_unused]] juce::MidiBuffer& midi) override { }
void release() override { }

FOLEYS_DECLARE_DSP_FACTORY (MidiInput)
Expand All @@ -60,11 +60,11 @@ class MidiInput : public DspNode
class MidiOutput : public DspNode
{
public:
MidiOutput (MagicDspBuilder& builder, const juce::ValueTree& node) : DspNode (builder, node) { }
MidiOutput (DspProgram& program, const juce::ValueTree& node) : DspNode (program, node) { }
[[nodiscard]] juce::String getCategory() const override { return Category::Audio; }

void prepare (juce::dsp::ProcessSpec spec) override { }
void process (juce::dsp::AudioBlock<float>& buffer, juce::MidiBuffer& midi) override { }
void prepare ([[maybe_unused]] juce::dsp::ProcessSpec spec) override { }
void process ([[maybe_unused]] juce::dsp::AudioBlock<float>& buffer, [[maybe_unused]] juce::MidiBuffer& midi) override { }
void release() override { }

FOLEYS_DECLARE_DSP_FACTORY (MidiOutput)
Expand Down
41 changes: 28 additions & 13 deletions modules/foleys_dsp_magic/DSP/foleys_DspNode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,28 +11,43 @@ namespace NodeIDs
{
DECLARE_ID (name)
DECLARE_ID (uid)
}
} // namespace NodeIDs

DspNode::DspNode (MagicDspBuilder& builder, const juce::ValueTree& node) : config (node)
DspNode::DspNode (DspProgram& program, const juce::ValueTree& node) : config (node)
{
nodeName = node.getProperty (NodeIDs::name, "noname");
nodeType = node.getType().toString();
if (config.hasProperty(NodeIDs::uid))
{
uid = config.getProperty(NodeIDs::uid);
builder.setNextUID(uid);
}
else
{
uid = builder.nextUID();
config.setProperty(NodeIDs::uid, uid, nullptr);
}
}

DspNode::~DspNode()
{
masterReference.clear();
}

/* static */
int DspNode::getUID (const juce::ValueTree& tree)
{
return tree.getProperty (NodeIDs::uid, 0);
}

juce::String DspNode::getName() const
{
return config.getProperty (NodeIDs::name, "unnamed").toString();
}

int DspNode::getUID() const
{
return config.getProperty (NodeIDs::uid, 0);
}

void DspNode::setName (const juce::String& newName)
{
config.setProperty (NodeIDs::name, newName, nullptr);
}

void DspNode::setUID (int newUID)
{
config.setProperty (NodeIDs::uid, newUID, nullptr);
}


} // namespace foleys::dsp
36 changes: 28 additions & 8 deletions modules/foleys_dsp_magic/DSP/foleys_DspNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
namespace foleys::dsp
{

class MagicDspBuilder;
class DspProgram;

namespace Category
{
Expand All @@ -19,38 +19,58 @@ static constexpr auto Filters = "Filters";
static constexpr auto Scripts = "Scripts";
}


class DspNode
{
public:
explicit DspNode (MagicDspBuilder& builder, const juce::ValueTree& node);
enum ConnectionType
{
Invalid = 0,
Audio,
MIDI,
Parameter
};

explicit DspNode (DspProgram& program, const juce::ValueTree& node);
virtual ~DspNode();

[[nodiscard]] virtual juce::String getCategory() const = 0;

[[nodiscard]] juce::String getName() const { return nodeName; }
[[nodiscard]] juce::String getType() const { return nodeType; }
[[nodiscard]] int getUID() const { return uid; }
[[nodiscard]] juce::String getName() const;
[[nodiscard]] int getUID() const;

void setName (const juce::String& newName);
void setUID (int newUID);

virtual void prepare (juce::dsp::ProcessSpec spec) = 0;
virtual void process (juce::dsp::AudioBlock<float>& buffer, juce::MidiBuffer& midi) = 0;
virtual void release() = 0;

// throw-away default implementation, make pure virtual
virtual int getNumAudioInputs() { return 1; }
virtual int getNumAudioOutputs() { return 1; }
virtual int getNumParameterInputs() { return 5; }
virtual int getNumParameterOutputs() { return 1; }
virtual bool hasMidiInput() { return true; }
virtual bool hasMidiOutput() { return true; }

[[nodiscard]] const juce::ValueTree& getConfig() const { return config; }

static int getUID (const juce::ValueTree& tree);

private:
juce::ValueTree config;
juce::String nodeName;
juce::String nodeType;
int uid = 0;

JUCE_DECLARE_WEAK_REFERENCEABLE (DspNode)
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DspNode)
};

#define FOLEYS_DECLARE_DSP_FACTORY(itemName) \
static inline std::unique_ptr<DspNode> factory (foleys::dsp::MagicDspBuilder& builder, const juce::ValueTree& node) \
static inline std::unique_ptr<DspNode> factory (foleys::dsp::DspProgram& program, const juce::ValueTree& node) \
{ \
return std::make_unique<itemName> (builder, node); \
return std::make_unique<itemName> (program, node); \
} \
static constexpr auto ID = #itemName;

Expand Down
67 changes: 60 additions & 7 deletions modules/foleys_dsp_magic/DSP/foleys_DspProgram.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,13 @@
namespace foleys::dsp
{

DspProgram::DspProgram (MagicDspBuilder& builder, const juce::ValueTree& tree)
DspProgram::DspProgram (MagicDspBuilder& builder) : dspBuilder (builder) { }

DspProgram::DspProgram (MagicDspBuilder& builder, const juce::ValueTree& tree) : dspBuilder (builder), dspConfig (tree)
{
for (auto node: tree)
{
auto child = builder.createNode (node);
if (child)
{
nodeLookup[child->getUID()] = child.get();
nodes.push_back (std::move (child));
}
createNode (node);
}

for (const auto& node: nodes)
Expand All @@ -33,6 +30,53 @@ DspProgram::DspProgram (MagicDspBuilder& builder, const juce::ValueTree& tree)
}
}

bool DspProgram::addNode (const juce::ValueTree& newNode)
{
auto success = createNode (newNode);
if (success)
dspConfig.appendChild (newNode, nullptr);

return success;
}

bool DspProgram::createNode (const juce::ValueTree& newNode)
{
auto child = dspBuilder.createNode (*this, newNode);
if (child)
{
auto uid = child->getUID();
if (uid > 0)
{
if (nodeLookup.find (uid) != nodeLookup.cend())
{
/*
* This uid already exists!
*/
jassertfalse;
return false;
}
}
else
{
uid = uidCounter + 1;
child->setUID (uid);
}
uidCounter = std::max (uidCounter, uid);

nodeLookup[child->getUID()] = child.get();
nodes.push_back (std::move (child));

return true;
}
return false;
}

bool DspProgram::connectNodes (DspNode::ConnectionType connectionType, int sourceUID, int sourceIndex, int targetUID, int targetIndex)
{

}


void DspProgram::prepareToPlay (double sampleRate, int expectedNumSamples)
{
juce::dsp::ProcessSpec spec { sampleRate, static_cast<juce::uint32> (expectedNumSamples), 2 };
Expand All @@ -49,5 +93,14 @@ void DspProgram::releaseResources()
node->release();
}

DspNode* DspProgram::getNodeWithUID (int uid)
{
const auto& it = std::find_if (nodes.begin(), nodes.end(), [uid] (const auto& node) { return node->getUID() == uid; });
if (it != nodes.end())
return it->get();

return nullptr;
}


} // namespace foleys::dsp
19 changes: 18 additions & 1 deletion modules/foleys_dsp_magic/DSP/foleys_DspProgram.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,13 @@ namespace foleys::dsp
class DspProgram
{
public:
explicit DspProgram (MagicDspBuilder& builder, const juce::ValueTree& tree);
explicit DspProgram (MagicDspBuilder& builder);
DspProgram (MagicDspBuilder& builder, const juce::ValueTree& tree);

bool addNode (const juce::ValueTree& newNode);
bool createNode (const juce::ValueTree& newNode);

bool connectNodes (DspNode::ConnectionType connectionType, int sourceUID, int sourceIndex, int targetUID, int targetIndex);

void prepareToPlay (double sampleRate, int expectedNumSamples);
void processBlock (juce::AudioBuffer<float>& buffer, juce::MidiBuffer& midi);
Expand All @@ -24,9 +30,20 @@ class DspProgram
bool producesMidi() const { return midiOutput != nullptr; }
bool isMidiEffect() const { return acceptsMidi() && producesMidi(); }

DspNode* getNodeWithUID (int uid);

std::vector<std::unique_ptr<DspNode>>::const_iterator begin() { return nodes.cbegin(); }
std::vector<std::unique_ptr<DspNode>>::const_iterator end() { return nodes.cend(); }

juce::ValueTree getConfig() const { return dspConfig; }

private:
MagicDspBuilder& dspBuilder;
juce::ValueTree dspConfig { "Program" };

std::vector<std::unique_ptr<DspNode>> nodes;
std::map<int, DspNode*> nodeLookup;
int uidCounter = 0;

juce::WeakReference<DspNode> midiInput;
juce::WeakReference<DspNode> midiOutput;
Expand Down
10 changes: 8 additions & 2 deletions modules/foleys_dsp_magic/DSP/foleys_MagicDspBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,19 +46,25 @@ std::unique_ptr<DspProgram> MagicDspBuilder::createProgram (const juce::ValueTre
return std::make_unique<DspProgram> (*this, tree);
}

std::unique_ptr<DspNode> MagicDspBuilder::createNode (const juce::ValueTree& node)
std::unique_ptr<DspNode> MagicDspBuilder::createNode (DspProgram& program, const juce::ValueTree& node)
{
auto factory = factories.find (node.getType());
if (factory != factories.end())
{
auto item = factory->second (*this, node);
auto item = factory->second (program, node);
return item;
}

DBG ("No DSP factory for: " << node.getType().toString());
return {};
}

bool MagicDspBuilder::canCreate (const juce::ValueTree& node) const
{
auto factory = factories.find (node.getType());
return (factory != factories.end());
}

MagicGUIState& MagicDspBuilder::getMagicState()
{
return magicState;
Expand Down
10 changes: 6 additions & 4 deletions modules/foleys_dsp_magic/DSP/foleys_MagicDspBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ namespace foleys::dsp
class MagicDspBuilder
{
public:
using DspFactory = std::function<std::unique_ptr<DspNode> (MagicDspBuilder& builder, const juce::ValueTree& node)>;
using DspFactory = std::function<std::unique_ptr<DspNode> (DspProgram& program, const juce::ValueTree& node)>;

explicit MagicDspBuilder (MagicGUIState& magicState);

Expand All @@ -23,15 +23,17 @@ class MagicDspBuilder

std::unique_ptr<DspProgram> createProgram (const juce::ValueTree& tree);

std::unique_ptr<DspNode> createNode (const juce::ValueTree& node);
std::unique_ptr<DspNode> createNode (DspProgram& program, const juce::ValueTree& node);

bool canCreate (const juce::ValueTree& node) const;

MagicGUIState& getMagicState();

[[nodiscard]] int nextUID();
void setNextUID (int uid);

std::map<juce::Identifier, DspFactory>::iterator begin() {return factories.begin();}
std::map<juce::Identifier, DspFactory>::iterator end() {return factories.end();}
std::map<juce::Identifier, DspFactory>::iterator begin() { return factories.begin(); }
std::map<juce::Identifier, DspFactory>::iterator end() { return factories.end(); }

private:
MagicGUIState& magicState;
Expand Down
2 changes: 1 addition & 1 deletion modules/foleys_dsp_magic/Nodes/foleys_Analyser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
namespace foleys::dsp
{

Analyser::Analyser (MagicDspBuilder& builder, const juce::ValueTree& config) : DspNode (builder, config) { }
Analyser::Analyser (DspProgram& program, const juce::ValueTree& config) : DspNode (program, config) { }


} // namespace foleys::dsp
2 changes: 1 addition & 1 deletion modules/foleys_dsp_magic/Nodes/foleys_Analyser.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace foleys::dsp
class Analyser : public DspNode
{
public:
Analyser (MagicDspBuilder& builder, const juce::ValueTree& config);
Analyser (DspProgram& program, const juce::ValueTree& config);
[[nodiscard]] juce::String getCategory() const override { return Category::Visualisers; }

void prepare (juce::dsp::ProcessSpec spec) override { }
Expand Down
Loading

0 comments on commit 6fcef1e

Please sign in to comment.