Skip to content

Commit

Permalink
Lift bus effects to voice (#1293)
Browse files Browse the repository at this point in the history
this commit allows bus-to-voice effects to be used
on group processors. It also introduces an api for
group-only processors. It brings in R1, R2, Delay and
Flanger. It updates the memory pool API

It does not support temposync, and it usese the
underlying tail apis, which for delay at least is
incorrect. I'll open a new issue for those. But this
can close a couple of others

Closes #1280
Closes #1281
  • Loading branch information
baconpaul authored Sep 10, 2024
1 parent 2c3d82e commit 0c0cee3
Show file tree
Hide file tree
Showing 17 changed files with 194 additions and 55 deletions.
4 changes: 2 additions & 2 deletions src-ui/app/edit-screen/components/MacroMappingVariantPane.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@
* https://github.com/surge-synthesizer/shortcircuit-xt
*/

#ifndef SCXT_SRC_UI_APP_EDIT_SCREEN_COMPONENTS_MAPPINGPANE_H
#define SCXT_SRC_UI_APP_EDIT_SCREEN_COMPONENTS_MAPPINGPANE_H
#ifndef SCXT_SRC_UI_APP_EDIT_SCREEN_COMPONENTS_MACROMAPPINGVARIANTPANE_H
#define SCXT_SRC_UI_APP_EDIT_SCREEN_COMPONENTS_MACROMAPPINGVARIANTPANE_H

#include "sst/jucegui/components/NamedPanel.h"
#include "app/HasEditor.h"
Expand Down
3 changes: 3 additions & 0 deletions src-ui/app/edit-screen/components/ProcessorPane.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@ void ProcessorPane::showHamburgerMenu()
std::string priorGroup = "none";
for (const auto &pd : editor->allProcessors)
{
if (pd.groupOnly && forZone)
continue;

if (pd.displayGroup != priorGroup && priorGroup != "none")
{
p.addSubMenu(priorGroup, subMenu);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@
* https://github.com/surge-synthesizer/shortcircuit-xt
*/

#ifndef SCXT_SRC_UI_APP_EDIT_SCREEN_COMPONENTS_MAPPING_PANE_SAMPLEDISPLAY_H
#define SCXT_SRC_UI_APP_EDIT_SCREEN_COMPONENTS_MAPPING_PANE_SAMPLEDISPLAY_H
#ifndef SCXT_SRC_UI_APP_EDIT_SCREEN_COMPONENTS_MAPPING_PANE_VARIANTDISPLAY_H
#define SCXT_SRC_UI_APP_EDIT_SCREEN_COMPONENTS_MAPPING_PANE_VARIANTDISPLAY_H

#include <juce_gui_basics/juce_gui_basics.h>
#include "sst/jucegui/components/ZoomContainer.h"
Expand Down
1 change: 1 addition & 0 deletions src/configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ namespace log
static constexpr bool selection{false};
static constexpr bool uiStructure{false};
static constexpr bool groupZoneMutation{false};
static constexpr bool memoryPool{false};
} // namespace log

} // namespace scxt
Expand Down
6 changes: 6 additions & 0 deletions src/dsp/processor/definition_helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,4 +76,10 @@
static constexpr float defaultMix{mix}; \
};

#define PROC_FOR_GROUP_ONLY(proct) \
template <> struct ProcessorForGroupOnly<proct> \
{ \
static constexpr bool isGroupOnly{true}; \
};

#endif // SHORTCIRCUITXT_DEFINITION_HELPERS_H
20 changes: 19 additions & 1 deletion src/dsp/processor/processor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,11 @@ template <size_t I> float implGetProcessorDefaultMix()
return ProcessorDefaultMix<(ProcessorType)I>::defaultMix;
}

template <size_t I> bool implGetForGroupOnly()
{
return ProcessorForGroupOnly<(ProcessorType)I>::isGroupOnly;
}

template <size_t... Is> auto getProcessorDisplayGroup(size_t ft, std::index_sequence<Is...>)
{
constexpr constCharOp_t fnc[] = {detail::implGetProcessorDisplayGroup<Is>...};
Expand All @@ -132,6 +137,13 @@ template <size_t... Is> auto getProcessorDefaultMix(size_t ft, std::index_sequen
constexpr floatOp_t fnc[] = {detail::implGetProcessorDefaultMix<Is>...};
return fnc[ft]();
}

template <size_t... Is> auto getForGroupOnly(size_t ft, std::index_sequence<Is...>)
{
constexpr boolOp_t fnc[] = {detail::implGetForGroupOnly<Is>...};
return fnc[ft]();
}

template <size_t I>
Processor *returnSpawnOnto(uint8_t *m, engine::MemoryPool *mp, const ProcessorStorage &ps, float *f,
int *i, bool needsMetadata)
Expand Down Expand Up @@ -222,6 +234,12 @@ float getProcessorDefaultMix(ProcessorType id)
id, std::make_index_sequence<(size_t)ProcessorType::proct_num_types>());
}

bool getProcessorGroupOnly(ProcessorType id)
{
return detail::getForGroupOnly(
id, std::make_index_sequence<(size_t)ProcessorType::proct_num_types>());
}

std::optional<ProcessorType> fromProcessorStreamingName(const std::string &s)
{
// A bit gross but hey
Expand All @@ -242,7 +260,7 @@ processorList_t getAllProcessorDescriptions()
if (isProcessorImplemented(pt))
{
res.push_back({pt, getProcessorStreamingName(pt), getProcessorName(pt),
getProcessorDisplayGroup(pt)});
getProcessorDisplayGroup(pt), getProcessorGroupOnly(pt)});
}
}
std::sort(res.begin(), res.end(), [](const auto &a, const auto &b) {
Expand Down
13 changes: 13 additions & 0 deletions src/dsp/processor/processor.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,11 @@ enum ProcessorType
proct_noise_am,
proct_osc_phasemod, // last part/fx

proct_lifted_reverb1,
proct_lifted_reverb2,
proct_lifted_delay,
proct_lifted_flanger,

proct_fx_treemonster,
proct_osc_VA,
proct_osc_tiltnoise,
Expand All @@ -161,12 +166,14 @@ const char *getProcessorName(ProcessorType id);
const char *getProcessorStreamingName(ProcessorType id);
const char *getProcessorDisplayGroup(ProcessorType id);
float getProcessorDefaultMix(ProcessorType id);
bool getProcessorGroupOnly(ProcessorType id);
std::optional<ProcessorType> fromProcessorStreamingName(const std::string &s);

struct ProcessorDescription
{
ProcessorType id;
std::string streamingName{"ERROR"}, displayName{"ERROR"}, displayGroup{"ERROR"};
bool groupOnly{false};
};

typedef std::vector<ProcessorDescription> processorList_t;
Expand Down Expand Up @@ -243,6 +250,7 @@ struct Processor : MoveableOnly<Processor>, SampleRateSupport

public:
size_t preReserveSize[16]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
size_t preReserveSingleInstanceSize[16]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};

ProcessorType getType() const { return myType; }
std::string getName() const { return getProcessorName(getType()); }
Expand Down Expand Up @@ -350,6 +358,11 @@ template <ProcessorType ft> struct ProcessorDefaultMix
static constexpr float defaultMix{1.0};
};

template <ProcessorType ft> struct ProcessorForGroupOnly
{
static constexpr bool isGroupOnly{false};
};

} // namespace scxt::dsp::processor

SC_DESCRIBE(scxt::dsp::processor::ProcessorStorage,
Expand Down
28 changes: 28 additions & 0 deletions src/dsp/processor/processor_defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,11 @@
#include "sst/voice-effects/dynamics/Compressor.h"
#include "sst/voice-effects/dynamics/AutoWah.h"

#include "sst/voice-effects/lifted_bus_effects/LiftedReverb1.h"
#include "sst/voice-effects/lifted_bus_effects/LiftedReverb2.h"
#include "sst/voice-effects/lifted_bus_effects/LiftedDelay.h"
#include "sst/voice-effects/lifted_bus_effects/LiftedFlanger.h"

namespace scxt::dsp::processor
{
// Just don't change the id or streaming name, basically
Expand Down Expand Up @@ -215,6 +220,29 @@ DEFINE_PROC(Chorus, sst::voice_effects::delay::Chorus<SCXTVFXConfig<1>>,
sst::voice_effects::delay::Chorus<SCXTVFXConfig<2>>, proct_Chorus, "Chorus",
"Modulation", "voice-chorus", dsp::surgeSincTable);

DEFINE_PROC(LiftedReverb1, sst::voice_effects::liftbus::LiftedReverb1<SCXTVFXConfig<1>>,
sst::voice_effects::liftbus::LiftedReverb1<SCXTVFXConfig<2>>, proct_lifted_reverb1,
"Reverb1", "Reverb", "lifted-reverb1");
PROC_FOR_GROUP_ONLY(proct_lifted_reverb1);
PROC_DEFAULT_MIX(proct_lifted_reverb1, 0.333);

DEFINE_PROC(LiftedReverb2, sst::voice_effects::liftbus::LiftedReverb2<SCXTVFXConfig<1>>,
sst::voice_effects::liftbus::LiftedReverb2<SCXTVFXConfig<2>>, proct_lifted_reverb2,
"Reverb2", "Reverb", "lifted-reverb2");
PROC_FOR_GROUP_ONLY(proct_lifted_reverb2);
PROC_DEFAULT_MIX(proct_lifted_reverb2, 0.333);

DEFINE_PROC(LiftedDelay, sst::voice_effects::liftbus::LiftedDelay<SCXTVFXConfig<1>>,
sst::voice_effects::liftbus::LiftedDelay<SCXTVFXConfig<2>>, proct_lifted_delay,
"Dual Delay", "Delay", "lifted-delay");
PROC_FOR_GROUP_ONLY(proct_lifted_delay);
PROC_DEFAULT_MIX(proct_lifted_delay, 0.333);

DEFINE_PROC(LiftedFlanger, sst::voice_effects::liftbus::LiftedFlanger<SCXTVFXConfig<1>>,
sst::voice_effects::liftbus::LiftedFlanger<SCXTVFXConfig<2>>, proct_lifted_flanger,
"Flanger", "Modulation", "lifted-flanger");
PROC_FOR_GROUP_ONLY(proct_lifted_flanger);

} // namespace scxt::dsp::processor

#endif // __SCXT_PROCESSOR_DEFS_H
24 changes: 24 additions & 0 deletions src/dsp/processor/processor_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,25 @@ template <int OSFactor> struct SCXTVFXConfig
}
}

static void preReserveSingleInstancePool(BaseClass *b, size_t s)
{
if (b->memoryPool)
{
b->memoryPool->preReserveSingleInstancePool(s);
}
else
{
for (int i = 0; i < 16; ++i)
{
if (b->preReserveSingleInstanceSize[i] == 0)
{
b->preReserveSingleInstanceSize[i] = s;
break;
}
}
}
}

static uint8_t *checkoutBlock(BaseClass *b, size_t s)
{
assert(b->memoryPool);
Expand Down Expand Up @@ -351,6 +370,11 @@ void Processor::setupProcessor(T *that, ProcessorType t, engine::MemoryPool *mp,
assert(memoryPool);
memoryPool->preReservePool(preReserveSize[i]);
}
if (preReserveSingleInstanceSize[i] > 0)
{
assert(memoryPool);
memoryPool->preReserveSingleInstancePool(preReserveSingleInstanceSize[i]);
}
}
}

Expand Down
16 changes: 15 additions & 1 deletion src/engine/group.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,11 @@ void Group::setupOnUnstream(const engine::Engine &e)

for (int p = 0; p < processorCount; ++p)
{
if (processors[p])
{
dsp::processor::unspawnProcessor(processors[p]);
processors[p] = nullptr;
}
setupProcessorControlDescriptions(p, processorStorage[p].type);
onProcessorTypeChanged(p, processorStorage[p].type);
}
Expand Down Expand Up @@ -402,6 +407,8 @@ void Group::onProcessorTypeChanged(int w, dsp::processor::ProcessorType t)
processors[w]->setSampleRate(sampleRate * (outputInfo.oversample ? 2 : 1));
processors[w]->setTempoPointer(&(getEngine()->transport.tempo));

endpoints.processorTarget[w].snapValues();

processors[w]->init();
}
}
Expand Down Expand Up @@ -448,9 +455,16 @@ void Group::attack()

rePrepareAndBindGroupMatrix();

for (auto p : processors)
for (int i = 0; i < processorsPerZoneAndGroup; ++i)
{
auto *p = processors[i];
if (p)
{
endpoints.processorTarget[i].snapValues();

p->init();
}
}
}

void Group::resetLFOs(int whichLFO)
Expand Down
1 change: 0 additions & 1 deletion src/engine/group.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ struct Group : MoveableOnly<Group>,
{
if (p)
{
SCLOG("Group Destructor: Unspawning Processors");
dsp::processor::unspawnProcessor(p);
}
}
Expand Down
12 changes: 7 additions & 5 deletions src/engine/group_and_zone_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,15 +132,17 @@ HasGroupZoneProcessors<T>::spawnTempProcessor(int whichProcessor,
dsp::processor::ProcessorType type, uint8_t *mem,
float *pfp, int *ifp, bool initFromDefaults)
{
dsp::processor::Processor *tmpProcessor{nullptr};
auto &tc = asT()->getEngine()->getMessageController()->threadingChecker;

auto &ps = processorStorage[whichProcessor];
tmpProcessor = dsp::processor::spawnProcessorInPlace(
type, asT()->getEngine()->getMemoryPool().get(), mem,
dsp::processor::processorMemoryBufferSize, ps, pfp, ifp, false, true);
dsp::processor::Processor *tmpProcessor{nullptr};

if (type != dsp::processor::proct_none)
{
auto &ps = processorStorage[whichProcessor];
tmpProcessor = dsp::processor::spawnProcessorInPlace(
type, asT()->getEngine()->getMemoryPool().get(), mem,
dsp::processor::processorMemoryBufferSize, ps, pfp, ifp, false, true);

assert(tmpProcessor);
assert(asT()->getEngine());
if (asT()->getEngine()->isSampleRateSet())
Expand Down
Loading

0 comments on commit 0c0cee3

Please sign in to comment.