-
Notifications
You must be signed in to change notification settings - Fork 12
/
DelayLineByFreq.h
153 lines (127 loc) · 4.45 KB
/
DelayLineByFreq.h
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
/*
* SurgeXT for VCV Rack - a Surge Synth Team product
*
* A set of modules expressing Surge XT into the VCV Rack Module Ecosystem
*
* Copyright 2019 - 2024, Various authors, as described in the github
* transaction log.
*
* Surge XT for VCV Rack is released under the GNU General Public License
* 3.0 or later (GPL-3.0-or-later). A copy of the license is in this
* repository in the file "LICENSE" or at:
*
* or at https://www.gnu.org/licenses/gpl-3.0.en.html
*
* All source for Surge XT for VCV Rack is available at
* https://github.com/surge-synthesizer/surge-rack/
*/
#ifndef SURGE_XT_RACK_SRC_DELAYLINEBYFREQ_H
#define SURGE_XT_RACK_SRC_DELAYLINEBYFREQ_H
#include "SurgeXT.h"
#include "XTModule.h"
#include "rack.hpp"
#include <cstring>
#include "DebugHelpers.h"
#include "globals.h"
#include <memory>
#include <array>
#include <sst/rackhelpers/neighbor_connectable.h>
#include "dsp/utilities/SSESincDelayLine.h"
namespace sst::surgext_rack::delay
{
struct DelayLineByFreq : modules::XTModule,
sst::rackhelpers::module_connector::NeighborConnectable_V1
{
enum ParamIds
{
VOCT,
CORRECTION,
NUM_PARAMS
};
enum InputIds
{
INPUT_L,
INPUT_R,
INPUT_VOCT,
NUM_INPUTS
};
enum OutputIds
{
OUTPUT_L,
OUTPUT_R,
NUM_OUTPUTS
};
enum LightIds
{
NUM_LIGHTS
};
DelayLineByFreq() : XTModule()
{
setupSurgeCommon(NUM_PARAMS, false, false);
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS);
configParam(VOCT, -5, 5, 0, "V/Oct Center");
auto pq = configParam(CORRECTION, 0, 20, 0, "Sample Correction");
pq->snapEnabled = true;
for (int i = 0; i < MAX_POLY; ++i)
{
lineL[i] = std::make_unique<SSESincDelayLine<delayLineLength>>(storage->sinctable);
lineR[i] = std::make_unique<SSESincDelayLine<delayLineLength>>(storage->sinctable);
}
configInput(INPUT_L, "In Left");
configInput(INPUT_R, "In Right");
configInput(INPUT_VOCT, "Delay Time as Frequency in v/oct");
configOutput(OUTPUT_L, "Out Left");
configOutput(OUTPUT_R, "Out Right");
configBypass(INPUT_L, OUTPUT_L);
configBypass(INPUT_R, OUTPUT_R);
}
std::string getName() override { return "DelayLineByFreq"; }
static constexpr size_t delayLineLength = 1 << 14;
std::array<std::unique_ptr<SSESincDelayLine<delayLineLength>>, MAX_POLY> lineL, lineR;
bool isBipolar(int paramId) override
{
if (paramId == VOCT)
return true;
return false;
}
void process(const ProcessArgs &args) override
{
// auto fpuguard = sst::plugininfra::cpufeatures::FPUStateGuard();
int lc = inputs[INPUT_L].getChannels();
int rc = inputs[INPUT_R].getChannels();
int cc = std::max({lc, rc, inputs[INPUT_VOCT].getChannels(), 1});
// If LC or RC are 1 we want to braodcast that input to all poly channels
// so set up a multiplier for channel in the get below
auto lm = (lc == 1 ? 0 : 1);
auto rm = (rc == 1 ? 0 : 1);
outputs[OUTPUT_L].setChannels(cc);
outputs[OUTPUT_R].setChannels(cc);
auto rInp = inputs[INPUT_R].isConnected() ? INPUT_R : INPUT_L;
for (int i = 0; i < cc; ++i)
{
auto il = inputs[INPUT_L].getVoltage(lm * i);
auto ir = inputs[rInp].getVoltage(rm * i);
float pitch0 =
(params[VOCT].getValue() + 5) * 12 + inputs[INPUT_VOCT].getVoltage(i) * 12;
auto n2p = storage->note_to_pitch_ignoring_tuning(pitch0) * Tunings::MIDI_0_FREQ;
float tm = storage->samplerate / n2p - params[CORRECTION].getValue();
tm = std::clamp(tm, FIRipol_N * 1.f, delayLineLength * 1.f);
auto dl = lineL[i]->read(tm);
auto dr = lineR[i]->read(tm);
lineL[i]->write(il);
lineR[i]->write(ir);
outputs[INPUT_L].setVoltage(dl, i);
outputs[INPUT_R].setVoltage(dr, i);
}
}
std::optional<std::vector<labeledStereoPort_t>> getPrimaryInputs() override
{
return {{std::make_pair("Input", std::make_pair(INPUT_L, INPUT_R))}};
}
std::optional<std::vector<labeledStereoPort_t>> getPrimaryOutputs() override
{
return {{std::make_pair("Output", std::make_pair(OUTPUT_L, OUTPUT_R))}};
}
};
} // namespace sst::surgext_rack::delay
#endif