Skip to content

Commit 18885aa

Browse files
committed
Merge branch 'dev'
2 parents 05fde13 + 8ad77c9 commit 18885aa

104 files changed

Lines changed: 3788 additions & 620 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

PatchCore/build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ android {
6969
}
7070
}
7171

72-
val artifactVersion = "0.1.5"
72+
val artifactVersion = libs.versions.artifacts.patchCore.get()
7373

7474
mavenPublishing {
7575
publishToMavenCentral(SonatypeHost.CENTRAL_PORTAL, automaticRelease = false)

PatchCore/src/main/cpp/CMakeLists.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@ add_library(
1414
patchcore/module/PatchModule.cpp
1515
patchcore/module/PolyModule.cpp
1616
patchcore/module/PolyProxyModule.cpp
17-
patchcore/module/Router.cpp
17+
patchcore/module/PolyProxyPatchModule.cpp
18+
patchcore/module/router/Router.cpp
19+
patchcore/module/router/GraphRouter.cpp
1820

1921
patchcore/module/ModuleParameter.cpp
2022

PatchCore/src/main/cpp/include/patchcore/module/Module.hpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@ class Module: public OnStartBuffer {
6565

6666
int getSampleRate() const;
6767

68+
public:
69+
void onProxyOutputCreated(ModuleOutput* output, const std::string& withName);
70+
bool hasProxyOutputs() const;
71+
6872
protected:
6973

7074
virtual void registerInput(ModuleInput& input, const std::string& withName = "") final {
@@ -92,10 +96,9 @@ class Module: public OnStartBuffer {
9296
userInputs[input.getName()] = &input;
9397
}
9498
if (auto floatInput = dynamic_cast<FloatUserInput *>(&input)) {
95-
printf("Registering FloatUserInput: %s\n", floatInput->getName().c_str());
9699
interpolatedInputs.push_back(floatInput);
97100
} else {
98-
printf("Registering UserInput: %s\n", input.getName().c_str());
101+
// Do nothing
99102
}
100103
input.setModule(this);
101104
}
@@ -144,6 +147,9 @@ class Module: public OnStartBuffer {
144147

145148
int sampleRate;
146149
std::string name;
150+
151+
private:
152+
bool _hasProxyOutputs = false;
147153
};
148154

149155
#endif //PATCHCORE_MODULE_HPP

PatchCore/src/main/cpp/include/patchcore/module/PatchModule.hpp

Lines changed: 21 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -25,37 +25,40 @@
2525

2626
#include "patchcore/module/factory/ModuleFactory.hpp"
2727
#include "patchcore/module/Module.hpp"
28-
#include "patchcore/module/Router.hpp"
28+
#include "patchcore/module/router/Router.hpp"
29+
#include "patchcore/module/router/GraphRouter.hpp"
2930
#include "patchcore/module/output/ProxyModuleOutput.hpp"
3031
#include "patchcore/module/input/ProxyModuleInput.hpp"
3132
#include "patchcore/module/input/ProxyModuleUserInput.hpp"
3233

3334
#include <string>
3435
#include <vector>
3536

36-
// PatchModule can be used to create subModule with multiple modules inside, connections between them and inputs/outputs
37-
// outward facing inputs/outputs should be exposed manually by calling addInput/addOutput
38-
// userInputs are available througth getModule("module_name")->getUserInput("input_name") or
39-
// exposed by addUserInput
40-
// the main usecase is to create a module dynamically
37+
/*
38+
* PatchModule can be used to create subModule with multiple modules inside, connections between them and inputs/outputs
39+
* outward facing inputs/outputs should be exposed manually by calling addInput/addOutput
40+
* userInputs are available througth getModule("module_name")->getUserInput("input_name") or
41+
* exposed by addUserInput
42+
* the main usecase is to create a module dynamically
43+
*/
4144

4245
class PatchModule : public Module {
4346
public:
4447
PatchModule(ModuleFactory *factory, std::string name, int sampleRate);
45-
PatchModule(const PatchModule &other);
48+
PatchModule(const PatchModule &other); // copy constructor for clone
49+
public:
4650
std::unique_ptr<Module> clone() const override;
4751
virtual ~PatchModule() override;
48-
52+
protected:
53+
PatchModule();
4954
//Module interface
5055
public:
5156
void onStartBuffer(int size) override;
5257
void envelope() override;
53-
protected:
54-
void envelopeModules();
55-
5658
//PatchModule specific
5759
//creates a new input/output from existing ModuleInput/ModuleOutput
5860
public:
61+
//TODO rename to createProxyInput/Output/UserInput
5962
virtual ProxyModuleInput* addInput(ModuleInput* input, const std::string& withName);
6063
virtual ProxyModuleOutput* addOutput(ModuleOutput* output, const std::string& withName);
6164
virtual UserInput* addUserInput(UserInput* input, const std::string& withName);
@@ -66,9 +69,6 @@ class PatchModule : public Module {
6669
private:
6770
ModuleInput* findInputByClone(const ModuleInput &input) const;
6871
ModuleOutput* findOutputByClone(const ModuleOutput &output) const;
69-
protected:
70-
void addModuleToEnvelope(Module* module);
71-
void clearModulesToEnvelope();
7272

7373
//PatchModule specific
7474
public:
@@ -85,34 +85,26 @@ class PatchModule : public Module {
8585

8686
//PatchModule Router specific
8787
public:
88-
virtual void addPatch(ModuleOutput* output, ModuleInput* input);
89-
//TODO add method to remove a single patch
9088
virtual void resetPatch();
89+
virtual void addPatch(ModuleOutput* output, ModuleInput* input);
90+
virtual void removePatch(ModuleOutput* output, ModuleInput* input);
9191
private:
92-
void clonePatches(const Router &router);
92+
void clonePatches(const AbstractRouter &router);
9393

9494
//Module copy and poly module creation
9595
public:
9696
virtual std::unique_ptr<PolyProxyModule> createPolyModuleProxy(PolyModule* polyModule) const override;
9797

98-
private:
98+
protected:
9999
std::mutex _mutex;
100+
private:
100101
ModuleFactory* _factory;
101102

102103
std::mutex routerMutex;
103-
Router _router = Router();
104+
// Router _router = Router(this);
105+
GraphRouter _router = GraphRouter(this);
104106

105107
std::vector<std::unique_ptr<Module>> _modules = std::vector<std::unique_ptr<Module>>();
106-
//all FloatUserInputs of all modules in this PatchModule
107-
std::vector<FloatUserInput *> _inputs = std::vector<FloatUserInput *>();
108-
109-
//TODO make a better name for this
110-
// this is used to envelope modules that are not connected to the router
111-
std::vector<Module *> _modulesToAlwaysEnvelope = std::vector<Module *>();
112-
std::vector<Module *> _modulesToEnvelope = std::vector<Module *>();
113-
114-
std::vector<FloatUserInput *> _interpolatedInputsToAlwaysEnvelope = std::vector<FloatUserInput *>();
115-
std::vector<FloatUserInput *> _interpolatedInputsToEnvelope = std::vector<FloatUserInput *>();
116108

117109
std::vector<ProxyModuleOutput *> _proxyModuleOutputs;
118110
std::vector<ProxyModuleInput *> _proxyModuleInputs;

PatchCore/src/main/cpp/include/patchcore/module/PolyModule.hpp

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,11 @@
2929
#include <string>
3030

3131

32-
//the main idea behind this class is to provide an PatchModule interface for polyphonic modules
33-
//it's acts like a container for multiple PatchModule instances, each representing a voice and proxies
34-
//methods to all voices
32+
/*
33+
* The main idea behind this class is to provide an PatchModule interface for polyphonic modules
34+
* it's acts like a container for multiple PatchModule instances, each representing a voice and proxies
35+
* methods to all voices
36+
*/
3537
class PolyModule : public PatchModule {
3638
public:
3739
PolyModule(ModuleFactory *factory, std::string name, int sampleRate, int voiceCount);
@@ -47,6 +49,7 @@ class PolyModule : public PatchModule {
4749
public:
4850
ProxyModuleInput* addInput(ModuleInput* input, const std::string& withName) override;
4951
ProxyModuleOutput* addOutput(ModuleOutput* output, const std::string& withName) override;
52+
virtual ProxyModuleOutput* addDemuxOutput(ModuleOutput* output, const std::string& withName, const int defaultVoiceIndex);
5053
//don't know in what case this is useful, but it is here for consistency
5154
UserInput* addUserInput(UserInput* input, const std::string& withName) override;
5255
//PatchModule specific
@@ -57,27 +60,23 @@ class PolyModule : public PatchModule {
5760
virtual Module* getModule(const std::string& moduleName) const override;
5861
//PatchModule Router specific
5962
public:
60-
virtual void addPatch(ModuleOutput* output, ModuleInput* input) override;
6163
virtual void resetPatch() override;
62-
63-
64+
virtual void addPatch(ModuleOutput* output, ModuleInput* input) override;
65+
virtual void removePatch(ModuleOutput* output, ModuleInput* input) override;
6466
// polyphony support
67+
public:
6568
size_t getVoiceCount() const;
66-
6769
PatchModule* getVoice(size_t index);
6870

6971
size_t getActiveVoiceCount() const;
7072
void setActiveVoiceCount(size_t count);
7173

7274
protected:
73-
std::vector<std::unique_ptr<PatchModule>> voices;
75+
std::vector<std::unique_ptr<PatchModule>> _voices;
76+
std::vector<PatchModule*> voices;
7477
size_t voiceCount;
7578
size_t activeVoiceCount;
7679

77-
// std::unordered_map<std::string, ModuleInput *> inputs;
78-
// std::unordered_map<std::string, ModuleOutput *> outputs;
79-
// std::unordered_map<std::string, UserInput *> userInputs;
80-
8180
std::vector<std::unique_ptr<PolyProxyModule>> polyProxies;
8281
std::vector<PolyProxyOutput *> proxyOutputs;
8382
std::vector<PolyProxyInput *> proxyInputs;

PatchCore/src/main/cpp/include/patchcore/module/PolyProxyModule.hpp

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -30,27 +30,35 @@
3030

3131
class PolyModule;
3232

33+
/*
34+
* PolyProxyModule is a proxy for a Module inside a PolyModule.
35+
* The main purpose for this class is to pass interface calls to the proxied modules.
36+
* Default implementation has only Module get Inputs/Outputs/UserInputs functionality.
37+
*/
38+
3339
class PolyProxyModule : public Module {
3440
public:
3541
PolyProxyModule(const Module* module, PolyModule* polyModule);
42+
protected:
43+
PolyProxyModule(const Module* module);
44+
public:
45+
std::unique_ptr<Module> clone() const override; // throw runtime_error
3646
virtual ~PolyProxyModule() override = default;
37-
38-
void envelope() override {
39-
throw std::runtime_error("PolyProxyModule does not implement envelope method");
40-
}
41-
42-
std::unique_ptr<Module> clone() const override {
43-
throw std::runtime_error("PolyProxyModule does not implement clone method");
44-
}
45-
46-
//TODO test it!!! maybe it shouldn't throw an error
47-
std::unique_ptr<PolyProxyModule> createPolyModuleProxy(PolyModule *polyModule) const override {
48-
throw std::runtime_error("PolyProxyModule does not implement createPolyModuleProxy method");
49-
}
47+
// module interface
48+
public:
49+
void envelope() override; // throw runtime_error
50+
void onStartBuffer(int size) override; // throw runtime_error
51+
//for test
52+
public:
53+
// poly module creation
54+
public:
55+
std::unique_ptr<PolyProxyModule> createPolyModuleProxy(PolyModule *polyModule) const override; // throw runtime_error
5056

5157
protected:
58+
// needed for derived classes to pass calls to the voices
5259
std::vector<Module *> modulesToProxy;
5360

61+
// not needed for now, but kept for consistency and future use
5462
std::vector<std::unique_ptr<PolyProxyInput>> polyProxyInputs;
5563
std::vector<std::unique_ptr<PolyProxyOutput>> polyProxyOutputs;
5664
std::vector<std::unique_ptr<PolyProxyUserInput>> polyProxyUserInputs;
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/*
2+
* PatchCore — Modular Synthesizer Engine
3+
* Copyright (c) 2025 Evgenii Petrov
4+
*
5+
* This file is part of PatchCore.
6+
*
7+
* PatchCore is free software: you can redistribute it and/or modify
8+
* it under the terms of the GNU Affero General Public License as published by
9+
* the Free Software Foundation, either version 3 of the License, or
10+
* (at your option) any later version.
11+
*
12+
* PatchCore is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU Affero General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU AGPL License
18+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
19+
*
20+
* Commercial licensing available: contact sillydevices@gmail.com
21+
*/
22+
23+
#ifndef PATCHCORE_POLYPROXYPATCHMODULE_HPP
24+
#define PATCHCORE_POLYPROXYPATCHMODULE_HPP
25+
26+
#include "PolyProxyModule.hpp"
27+
#include "PatchModule.hpp"
28+
#include "PolyModule.hpp"
29+
30+
/*
31+
* PolyProxyPatchModule is a proxy for a PatchModule inside a PolyModule.
32+
* it must have an methods from PatchModule, but PolyModule do almost the same and derives from PatchModule.
33+
* So to avoid code duplication PolyProxyPatchModule derives from PolyModule
34+
* It doesn't use any PolyProxyModule methods, but it's needed to be used as a PolyProxyModule
35+
*/
36+
37+
class PolyProxyPatchModule: public PolyProxyModule, public PolyModule {
38+
public:
39+
PolyProxyPatchModule(ModuleFactory *factory, const PatchModule* module, PolyModule* polyModule);
40+
~PolyProxyPatchModule() override = default;
41+
public:
42+
void envelope() override {
43+
throw std::runtime_error("PolyProxyPatchModule does not implement envelope method");
44+
}
45+
// Module interface
46+
// all methods below just call PolyModule versions
47+
public:
48+
const std::unordered_map<std::string, ModuleInput *>& getModuleInputs() const override;
49+
ModuleInput* getModuleInput(const std::string& moduleName) override;
50+
51+
const std::unordered_map<std::string, ModuleOutput *>& getModuleOutputs() const override;
52+
ModuleOutput * getModuleOutput(const std::string& outputName) override;
53+
54+
const std::unordered_map<std::string, UserInput *>& getUserInputs() const override;
55+
UserInput *getUserInput(const std::string& inputName) override;
56+
};
57+
58+
#endif //PATCHCORE_POLYPROXYPATCHMODULE_HPP

PatchCore/src/main/cpp/include/patchcore/module/input/PolyProxyInput.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ class PolyProxyInput : public ModuleInput {
4444
}
4545
virtual ~PolyProxyInput() = default;
4646
public:
47+
//TODO this is a hack to update voiceOutput from PolyModule::addInput
48+
void setVoiceInput(int voiceIndex, ModuleInput *voiceInput) {
49+
voiceInputs[voiceIndex] = voiceInput;
50+
}
4751
void setCompositeVoiceInput(int voiceIndex, ProxyModuleInput *compositeInput) {
4852
voiceProxyInputs[voiceIndex] = compositeInput;
4953
}

PatchCore/src/main/cpp/include/patchcore/module/input/PolyProxyUserInput.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ class PolyProxyUserInput {
3636

3737
public:
3838
virtual UserInput* getVoice(int voiceIndex) = 0;
39+
////TODO this is a hack to update voiceOutput from PolyModule::addUserInput
40+
virtual void setVoiceInput(int voiceIndex, ProxyModuleUserInput* voiceInput) = 0;
3941
virtual void setProxyVoiceInput(int voiceIndex, ProxyModuleUserInput* proxyInput) = 0;
4042

4143
protected:

PatchCore/src/main/cpp/include/patchcore/module/input/user/poly/PolyProxyBoolUserInput.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,11 @@ class PolyProxyBoolUserInput : public PolyProxyUserInput, public BoolUserInput {
4949
}
5050
virtual ~PolyProxyBoolUserInput() = default;
5151
public:
52+
void setVoiceInput(int voiceIndex, ProxyModuleUserInput *voiceInput) override {
53+
auto casted = dynamic_cast<ProxyModuleBoolUserInput *>(voiceInput);
54+
if (casted == nullptr) throw std::runtime_error("PolyProxyBoolUserInput: Composite input is not a CompositeModuleBoolUserInput");
55+
voiceInputs[voiceIndex] = casted;
56+
}
5257
void setProxyVoiceInput(int voiceIndex, ProxyModuleUserInput *compositeInput) override {
5358
auto casted = dynamic_cast<ProxyModuleBoolUserInput *>(compositeInput);
5459
if (casted == nullptr) throw std::runtime_error("PolyProxyBoolUserInput: Composite input is not a CompositeModuleBoolUserInput");

0 commit comments

Comments
 (0)