-
Notifications
You must be signed in to change notification settings - Fork 43
/
ctagSoundProcessor.hpp
194 lines (151 loc) · 7.53 KB
/
ctagSoundProcessor.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
/***************
CTAG TBD >>to be determined<< is an open source eurorack synthesizer module.
A project conceived within the Creative Technologies Arbeitsgruppe of
Kiel University of Applied Sciences: https://www.creative-technologies.de
(c) 2020 by Robert Manzke. All rights reserved.
The CTAG TBD software is licensed under the GNU General Public License
(GPL 3.0), available here: https://www.gnu.org/licenses/gpl-3.0.txt
The CTAG TBD hardware design is released under the Creative Commons
Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0).
Details here: https://creativecommons.org/licenses/by-nc-sa/4.0/
CTAG TBD is provided "as is" without any express or implied warranties.
License and copyright details for specific submodules are included in their
respective component folders / files if different from this license.
***************/
// Base class for sound processors + interface
#pragma once
#define MK_BOOL_PAR(outname, inname) \
bool outname = inname;\
if(trig_##inname != -1) outname = data.trig[trig_##inname] == 1 ? false : true;
#define MK_FLT_PAR_ABS(outname, inname, norm, scale) \
float outname = inname / norm * scale;\
if(cv_##inname != -1) outname = fabsf(data.cv[cv_##inname]) * scale;
#define MK_FLT_PAR_ABS_ADD(outname, inname, norm, scale) \
float outname = inname / norm * scale;\
if(cv_##inname != -1) outname += fabsf(data.cv[cv_##inname]) * scale;
#define MK_FLT_PAR_ABS_SFT(outname, inname, norm, scale) \
float outname = inname / norm * scale;\
if(cv_##inname != -1) outname = (fabsf(data.cv[cv_##inname]) - 0.5f) * 2.f * scale;
#define MK_FLT_PAR(outname, inname, norm, scale) \
float outname = inname / norm * scale;\
if(cv_##inname != -1) outname = data.cv[cv_##inname] * scale;
#define MK_INT_PAR_ABS(outname, inname, scale) \
int outname = inname;\
if(cv_##inname != -1) outname = static_cast<int>(fabsf(data.cv[cv_##inname]) * scale);
#define MK_INT_PAR(outname, inname, scale) \
int outname = inname;\
if(cv_##inname != -1) outname = static_cast<int>(data.cv[cv_##inname] * scale);
#define MK_FLT_PAR_ABS_MIN_MAX(outname, inname, norm, out_min, out_max) \
float outname = inname/norm * (out_max-out_min)+out_min; \
if(cv_##inname != -1) outname = fabsf(data.cv[cv_##inname]) * (out_max-out_min)+out_min;
#define MK_FLT_PAR_ABS_PAN(outname, inname, norm, scale) \
float outname = (inname/norm+1.f)/2.f * scale; \
if(cv_##inname != -1) outname = fabsf(data.cv[cv_##inname]) * scale;
#include <stdint.h>
#include <string>
#include <memory>
#include <map>
#include <functional>
#include "ctagSPDataModel.hpp"
#include "ctagSPAllocator.hpp"
using namespace std;
namespace CTAG {
namespace SP {
struct ProcessData {
float *buf;
float *cv;
uint8_t *trig;
};
class ctagSoundProcessor {
public:
virtual void Process(const ProcessData &) = 0; // pure virtual --> must be implemented by derived
// plugins will need to make sure not to use more than blocksize bytes of data
virtual void Init(std::size_t blockSize, void *blockPtr) = 0;
virtual ~ctagSoundProcessor() {};
void* operator new (std::size_t size) {
return ctagSPAllocator::Allocate(size);
}
void operator delete (void *ptr) noexcept {
// arena allocator will just reset the arena
}
void* operator new[] (std::size_t size) = delete;
void* operator new[] (std::size_t size, const std::nothrow_t& tag) = delete;
void operator delete[] (void *ptr) noexcept = delete;
int GetAudioBufferSize() { return bufSz; }
void SetProcessChannel(int ch) { processCh = ch; }
const char *GetCStrJSONParamSpecs() const { return model->GetCStrJSONParams(); }
virtual const char *GetCStrID() { return id.c_str(); }
virtual const string& GetID() { return id; }
void SetParamValue(const string &id, const string &key, const int val) {
setParamValueInternal(id, key, val); // as immediate as possible
model->SetParamValue(id, key, val);
}
const char *GetCStrJSONPresets() { return model->GetCStrJSONPresets(); }
const char *GetCStrJSONAllPresetData() { return model->GetCStrJSONAllPresetData(); }
bool GetIsStereo() const { return isStereo; }
void SavePreset(const string &name, const int number) { model->SavePreset(name, number); }
void LoadPreset(const int number) {
model->LoadPreset(number); // first get the data into the model
loadPresetInternal();
}
std::string GetActivePluginParameters() { return model->GetActivePluginParameters(); }
void SetActivePluginParameters(std::string const& p) {
model->SetActivePluginParameters(p);
loadPresetInternal();
}
protected:
virtual void knowYourself() = 0;
virtual void setParamValueInternal(const string &id, const string &key, const int val) {
//printf("%s, %s, %d\n", id.c_str(), key.c_str(), val);
if (key.compare("current") == 0) {
auto it = pMapPar.find(id);
if (it != pMapPar.end()) {
(it->second)(val);
}
return;
}
if (key.compare("cv") == 0) {
if (val >= -1 && val < N_CVS) {
auto it = pMapCv.find(id);
if (it != pMapCv.end()) {
(it->second)(val);
}
}
return;
}
if (key.compare("trig") == 0) {
if (val >= -1 && val < N_TRIGS) {
auto it = pMapTrig.find(id);
if (it != pMapTrig.end()) {
(it->second)(val);
}
}
return;
}
};
virtual void loadPresetInternal() {
// iterate all parameters, take names from parameter map (first element)
for (const auto &kv: pMapPar) {
setParamValueInternal(kv.first, "current", model->GetParamValue(kv.first, "current"));
// check if cv and trig are set in preset, if so set in processor param
if (model->IsParamCV(kv.first)) {
//ESP_LOGW("MOdel", "IntParam %s, %d", name.c_str(), model->GetParamValue(name, "cv"));
setParamValueInternal(kv.first, "cv", model->GetParamValue(kv.first, "cv"));
} else if (model->IsParamTrig(kv.first)) {
//ESP_LOGW("MOdel", "BoolParam %s, %d", name.c_str(), model->GetParamValue(name, "trig"));
setParamValueInternal(kv.first, "trig", model->GetParamValue(kv.first, "trig"));
}
}
};
bool isStereo = false;
int const bufSz = 32;
int processCh = 0;
int instance {0};
std::unique_ptr<ctagSPDataModel> model = nullptr;
string id = "";
map<string, function<void(const int)>> pMapPar;
map<string, function<void(const int)>> pMapCv;
map<string, function<void(const int)>> pMapTrig;
};
}
}