Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/dsp engine #105

Closed
wants to merge 25 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
dba079c
Initial commit for DSP engine
ffAudio Feb 4, 2024
48a48cf
Added a default constructor
ffAudio Apr 7, 2024
7892c73
Allow edit mode without toolbox
ffAudio Apr 8, 2024
3084200
Made MagicBuilder weakReferencable
ffAudio Apr 8, 2024
bb94b42
Cleaned up Parameter Serialisation
ffAudio Apr 11, 2024
5622b77
Fixed namespace in example
ffAudio Apr 11, 2024
1781c1e
Fixed wrong group XML
ffAudio Apr 11, 2024
7354ad6
Improved debug log
ffAudio Apr 11, 2024
c090016
Improved dsp chain setup
ffAudio Apr 17, 2024
967fa7b
Implemented Connections
ffAudio Apr 19, 2024
c7898f5
Implemented conections
ffAudio Apr 22, 2024
d4a8c5e
Implemented actual processing
ffAudio May 4, 2024
1a4df36
Send buffer size in process for generators
ffAudio May 6, 2024
9d72e5d
Renamed Connection to Input for consistency
ffAudio May 6, 2024
24123f2
Renamed Connection files to Input
ffAudio May 6, 2024
23274d9
Add undo pointer
ffAudio May 6, 2024
35d2108
Added range of output for no audio signals
ffAudio May 8, 2024
78a3ab7
Implemented sample wise oscillator
ffAudio May 10, 2024
8816c2b
Removed dc and amplitude from Oscillator, as it is redundand with Gain
ffAudio May 12, 2024
597c09f
Update to macos-14
ffAudio May 13, 2024
ba4f5ad
Added option to place builder into a rectangle
ffAudio May 21, 2024
cf24f1f
Fixed unhandled case warning
ffAudio May 22, 2024
44abaab
Added a multiplier for parameters
ffAudio May 23, 2024
d6dd586
Refactored connection/Input saving
ffAudio May 23, 2024
35a8213
Added range mapping from output to input
ffAudio May 24, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .clang-format
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ PenaltyExcessCharacter: '1'
PenaltyReturnTypeOnItsOwnLine: '20'
PointerAlignment: Left
ReflowComments: 'false'
SortIncludes: 'true'
SortIncludes: 'false'
SortUsingDeclarations: 'true'
SpaceAfterCStyleCast: 'true'
SpaceAfterLogicalNot: 'false'
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@ jobs:
name: ${{ matrix.os }} - ${{ matrix.build_type }}
strategy:
matrix:
os: [macos-13, windows-latest]
os: [macos-14-arm64, windows-latest]
build_type: [Debug, Release]
fail-fast: false

steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
with:
submodules: recursive

Expand Down
1 change: 1 addition & 0 deletions Examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ elseif(WIN32)
set(COPY_FOLDER ${CMAKE_SOURCE_DIR}/Builds/VisualStudio2019)
endif()

add_subdirectory(NoCodeExample)
add_subdirectory(APVTS_Tutorial)
add_subdirectory(EqualizerExample)
add_subdirectory(ExtendingExample)
Expand Down
63 changes: 63 additions & 0 deletions Examples/NoCodeExample/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
cmake_minimum_required(VERSION 3.13.0)

project("NoCodeExample" VERSION ${FGM_VERSION})

# add the plugin targets
juce_add_plugin(${PROJECT_NAME}
VERSION "${version}"
COMPANY_NAME "Foleys Finest Audio"
PLUGIN_MANUFACTURER_CODE "FFAU"
PLUGIN_CODE "NoCd"
IS_SYNTH yes
FORMATS ${FORMATS}
VST3_CATEGORIES "Fx" "Analyser" "EQ"
AAX_CATEGORY "AAX_ePlugInCategory_SWGenerators"
AU_MAIN_TYPE "kAudioUnitType_Generator"
COMPANY_WEBSITE "https://foleysfinest.com"
COMPANY_EMAIL "[email protected]"
BUNDLE_ID "com.foleysfinest.NoCodeExample"
PLUGIN_NAME "NoCodeExample"
PRODUCT_NAME "NoCodeExample")

juce_add_binary_data(${PROJECT_NAME}_data
SOURCES
Resources/magic.xml)

juce_generate_juce_header(${PROJECT_NAME})

target_sources(${PROJECT_NAME}
PRIVATE
NoCodeExample.cpp)

# add required flags
target_link_libraries(${PROJECT_NAME}
PRIVATE
${PROJECT_NAME}_data
foleys_dsp_magic
foleys_gui_magic
juce::juce_audio_basics
juce::juce_audio_plugin_client
juce::juce_audio_processors
juce::juce_audio_utils
juce::juce_dsp
juce::juce_cryptography
juce::juce_gui_extra
juce::juce_opengl
juce::juce_recommended_warning_flags
juce::juce_recommended_config_flags
juce::juce_recommended_lto_flags)

target_compile_definitions(${PROJECT_NAME}
PUBLIC
# switch the following off in the product to hide editor
FOLEYS_SHOW_GUI_EDITOR_PALLETTE=0
FOLEYS_SAVE_EDITED_GUI_IN_PLUGIN_STATE=0
JUCE_VST3_CAN_REPLACE_VST2=0
JUCE_WEB_BROWSER=0)

foreach (FORMAT ${FORMATS})
get_target_property(ARTEFACTS_DIR ${PROJECT_NAME}_${FORMAT} LIBRARY_OUTPUT_DIRECTORY)
add_custom_command(TARGET ${PROJECT_NAME}_${FORMAT} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory ${ARTEFACTS_DIR} ${COPY_FOLDER})
endforeach ()

__pgm_internal_add_pluginval_tests(${PROJECT_NAME})
8 changes: 8 additions & 0 deletions Examples/NoCodeExample/NoCodeExample.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@

#include "BinaryData.h"
#include <foleys_dsp_magic/foleys_dsp_magic.h>

juce::AudioProcessor* JUCE_CALLTYPE createPluginFilter()
{
return new foleys::dsp::PluginProcessor (BinaryData::magic_xml, BinaryData::magic_xmlSize);
}
404 changes: 404 additions & 0 deletions Examples/NoCodeExample/Resources/magic.xml

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion Examples/PlayerExample/Source/MainComponent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,5 +184,5 @@ void MainComponent::paint (juce::Graphics& g)

void MainComponent::resized()
{
magicBuilder.updateLayout();
magicBuilder.updateLayout (getLocalBounds());
}
5 changes: 4 additions & 1 deletion modules/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@

# add modules to juce. You need to list it in `target_link_libraries` too
juce_add_modules (foleys_gui_magic ALIAS_NAMESPACE foleys)
juce_add_modules(
foleys_gui_magic
foleys_dsp_magic
ALIAS_NAMESPACE foleys)
238 changes: 238 additions & 0 deletions modules/foleys_dsp_magic/DSP/foleys_DspNode.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,238 @@
//
// Created by Daniel Walz on 04.02.24.
//

#include "foleys_DspNode.h"

namespace foleys::dsp
{

namespace NodeIDs
{
DECLARE_ID (name)
DECLARE_ID (uid)
} // namespace NodeIDs

DspNode::DspNode (DspProgram& owningProgram, const juce::ValueTree& node) : program (owningProgram), config (node)
{
nodeType = node.getType().toString();
}

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

void DspNode::addAudioInput (const juce::String& name)
{
audioInputs.emplace_back (*this, ConnectionType::Audio, name, static_cast<int> (audioInputs.size()));
}

void DspNode::addParameterInput (const juce::String& name, float defaultValue, float minValue, float maxValue)
{
auto& newInput = parameterInputs.emplace_back (*this, ConnectionType::Parameter, name, static_cast<int> (parameterInputs.size()));
newInput.defaultValue = defaultValue;
newInput.minValue = minValue;
newInput.maxValue = maxValue;
}

void DspNode::addAudioOutput (const juce::String& name)
{
audioOutputs.emplace_back (*this, name);
}

void DspNode::addParameterOutput (const juce::String& name)
{
parameterOutputs.emplace_back (*this, name);
}

Output* DspNode::getOutput (ConnectionType type, int index)
{
if (type == ConnectionType::Audio && juce::isPositiveAndBelow (index, audioOutputs.size()))
return &audioOutputs[static_cast<size_t> (index)];

if (type == ConnectionType::Parameter && juce::isPositiveAndBelow (index, parameterOutputs.size()))
return &parameterOutputs[static_cast<size_t> (index)];

return nullptr;
}

void DspNode::updateConnections()
{
for (auto& audioInput: getAudioInputs())
audioInput.restore();
for (auto& parameterInput: getParameterInputs())
parameterInput.restore();

midiInput.restore();
}

Output* DspNode::getConnectedOutput (ConnectionType type, int inputIndex)
{
if (auto* connection = getInput (type, inputIndex))
{
jassert (inputIndex == connection->targetIndex);

if (connection->isConnected())
return connection->sourceNode->getOutput (type, connection->sourceIndex);
}

return nullptr;
}

/* 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);
}

Input* DspNode::getInput (ConnectionType type, int index)
{
switch (type)
{
case ConnectionType::MIDI: return &midiInput;
case ConnectionType::Audio: return &audioInputs[static_cast<size_t> (index)];
case ConnectionType::Parameter: return &parameterInputs[static_cast<size_t> (index)];
case ConnectionType::Invalid: return nullptr;
default: jassertfalse; return nullptr;
}
}

Input* DspNode::getInputChecked (ConnectionType type, int idx)
{
auto index = static_cast<size_t> (idx);
switch (type)
{
case ConnectionType::MIDI: return (hasMidiInput() ? &midiInput : nullptr);
case ConnectionType::Audio: return (juce::isPositiveAndBelow (index, audioInputs.size()) ? &audioInputs[index] : nullptr);
case ConnectionType::Parameter: return (juce::isPositiveAndBelow (index, parameterInputs.size()) ? &parameterInputs[index] : nullptr);
case ConnectionType::Invalid: return nullptr;
default: jassertfalse; return nullptr;
}
}

int DspNode::getNumAudioInputs() const
{
return static_cast<int> (audioInputs.size());
}

int DspNode::getNumParameterInputs() const
{
return static_cast<int> (parameterInputs.size());
}

int DspNode::getNumAudioOutputs() const
{
return static_cast<int> (audioOutputs.size());
}

int DspNode::getNumParameterOutputs() const
{
return static_cast<int> (parameterOutputs.size());
}

juce::String DspNode::getAudioInputName (int index) const
{
if (juce::isPositiveAndBelow (index, audioInputs.size()))
return audioInputs[static_cast<size_t> (index)].inputName;

jassertfalse;
return TRANS ("Audio ") + juce::String (index);
}

juce::String DspNode::getParameterInputName (int index) const
{
if (juce::isPositiveAndBelow (index, parameterInputs.size()))
return parameterInputs[static_cast<size_t> (index)].inputName;

jassertfalse;
return TRANS ("Parameter ") + juce::String (index);
}

juce::String DspNode::getAudioOutputName (int index) const
{
if (juce::isPositiveAndBelow (index, audioOutputs.size()))
return audioOutputs[static_cast<size_t> (index)].name;

jassertfalse;
return TRANS ("Audio ") + juce::String (index);
}

juce::String DspNode::getParameterOutputName (int index) const
{
if (juce::isPositiveAndBelow (index, parameterOutputs.size()))
return parameterOutputs[static_cast<size_t> (index)].name;

jassertfalse;
return TRANS ("Parameter ") + juce::String (index);
}

juce::String DspNode::getMidiOutputName() const
{
return TRANS ("Midi Out");
}

juce::String DspNode::getMidiInputName() const
{
return TRANS ("Midi In");
}

void DspNode::clearInputs (ConnectionType type)
{
switch (type)
{
case ConnectionType::Audio: audioInputs.clear(); break;
case ConnectionType::Parameter: parameterInputs.clear(); break;
default: break;
}
}

void DspNode::clearOutputs (ConnectionType type)
{
switch (type)
{
case ConnectionType::Audio: audioOutputs.clear(); break;
case ConnectionType::Parameter: parameterOutputs.clear(); break;
default: break;
}
}

std::vector<DspNode*> DspNode::getNodesToDependOn()
{
std::vector<DspNode*> sources;
for (const auto& audio: audioInputs)
if (audio.isConnected())
sources.push_back (audio.sourceNode);

for (const auto& parameter: parameterInputs)
if (parameter.isConnected())
sources.push_back (parameter.sourceNode);

if (midiInput.isConnected())
sources.push_back (midiInput.sourceNode);

return sources;
}


} // namespace foleys::dsp
Loading
Loading