Skip to content

Commit

Permalink
MPE Support
Browse files Browse the repository at this point in the history
  • Loading branch information
baconpaul committed Dec 29, 2024
1 parent a61d665 commit 30a5342
Show file tree
Hide file tree
Showing 11 changed files with 116 additions and 45 deletions.
5 changes: 0 additions & 5 deletions doc/design.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,11 @@ MODULATION:
- main
- Unison Sources

MPE Support
- An MPE-switch in main panel toggles voice manager
- MPE sources hooked up in mod matrix

PATCH SELECTOR:
- Jog Buttons for next/prev

MAIN/PLAY MODE:
- Global Transpose and Global in-semitone-tuning with LFO routable to tuning
- It also occurs to me that the main AEG feels totally dumb in voice mode. default moves to gate

CLAP
- An output per OP wher each output is just the solo OP * Main ADSR (and zero if the OP is off)
Expand Down
5 changes: 1 addition & 4 deletions src/clap/six-sines-clap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -162,10 +162,7 @@ struct SixSinesClap : public plugHelper_t, sst::clap_juce_shim::EditorProvider
return CLAP_PROCESS_CONTINUE;
}

void reset() noexcept override
{
engine->voiceManager->allSoundsOff();
}
void reset() noexcept override { engine->voiceManager->allSoundsOff(); }

bool handleEvent(const clap_event_header_t *nextEvent)
{
Expand Down
6 changes: 5 additions & 1 deletion src/dsp/node_support.h
Original file line number Diff line number Diff line change
Expand Up @@ -281,9 +281,13 @@ template <typename T> struct ModulationSupport
break;

case ModMatrixConfig::Source::MPE_PRESSURE:
sourcePointers[which] = &voiceValues.mpePressure;
break;
case ModMatrixConfig::Source::MPE_TIMBRE:
sourcePointers[which] = &voiceValues.mpeTimbre;
break;
case ModMatrixConfig::Source::MPE_PITCHBEND:
SXSNLOG("Unimplemented source " << sv);
sourcePointers[which] = &voiceValues.mpeBendInSemis;
break;

default:
Expand Down
22 changes: 17 additions & 5 deletions src/synth/patch.h
Original file line number Diff line number Diff line change
Expand Up @@ -733,7 +733,18 @@ struct Patch
.withName(name() + " Unison Phase Randomized")
.withGroupName(name())
.withDefault(true)
.withID(id(32)))
.withID(id(32))),
mpeActive(boolMd()
.withName(name() + " MPE Active")
.withGroupName(name())
.withDefault(false)
.withID(id(33))),
mpeBendRange(intMd()
.withName(name() + " MPE Bend Range")
.withGroupName(name())
.withRange(1, 96)
.withDefault(24)
.withID(id(34)))
{
defaultTrigger.adhocFeatures = Param::AdHocFeatureValues::TRIGGERMODE;
}
Expand All @@ -744,13 +755,14 @@ struct Patch
Param level, velSensitivity, playMode;
Param bendUp, bendDown, polyLimit, defaultTrigger, portaTime, pianoModeActive;
Param unisonCount, unisonSpread, uniPhaseRand;
Param mpeActive, mpeBendRange;

std::vector<Param *> params()
{
std::vector<Param *> res{&level, &velSensitivity, &playMode,
&bendUp, &bendDown, &polyLimit,
&defaultTrigger, &portaTime, &pianoModeActive,
&unisonCount, &unisonSpread, &uniPhaseRand};
std::vector<Param *> res{
&level, &velSensitivity, &playMode, &bendUp, &bendDown,
&polyLimit, &defaultTrigger, &portaTime, &pianoModeActive, &unisonCount,
&unisonSpread, &uniPhaseRand, &mpeActive, &mpeBendRange};
appendDAHDSRParams(res);
return res;
}
Expand Down
13 changes: 12 additions & 1 deletion src/synth/synth.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,8 @@ void Synth::processUIQueue(const clap_output_events_t *outq)
*/
if (dest->meta.id == patch.output.playMode.meta.id ||
dest->meta.id == patch.output.polyLimit.meta.id ||
dest->meta.id == patch.output.pianoModeActive.meta.id)
dest->meta.id == patch.output.pianoModeActive.meta.id ||
dest->meta.id == patch.output.mpeActive.meta.id)
{
resetPlaymode();
}
Expand Down Expand Up @@ -285,6 +286,16 @@ void Synth::resetPlaymode()
auto lim = (int)std::round(patch.output.polyLimit.value);
lim = std::clamp(lim, 1, (int)maxVoices);
voiceManager->setPolyphonyGroupVoiceLimit(0, lim);

auto mpe = (bool)std::round(patch.output.mpeActive.value);
if (mpe)
{
voiceManager->dialect = voiceManager_t::MIDI1Dialect::MIDI1_MPE;
}
else
{
voiceManager->dialect = voiceManager_t::MIDI1Dialect::MIDI1;
}
}

void Synth::handleParamValue(Param *p, uint32_t pid, float value)
Expand Down
15 changes: 12 additions & 3 deletions src/synth/synth.h
Original file line number Diff line number Diff line change
Expand Up @@ -186,9 +186,18 @@ struct Synth
void setVoicePolyphonicParameterModulation(Voice *, uint32_t, double) {}
void setPolyphonicAftertouch(Voice *v, int8_t a) { v->voiceValues.polyAt = a / 127.0; }

void setVoiceMIDIMPEChannelPitchBend(Voice *, uint16_t) {}
void setVoiceMIDIMPEChannelPressure(Voice *, int8_t) {}
void setVoiceMIDIMPETimbre(Voice *, int8_t) {}
void setVoiceMIDIMPEChannelPitchBend(Voice *v, uint16_t b)
{
auto stb = (b - 8192) * 1.0 / 8192;
v->voiceValues.mpeBendNormalized = stb;
v->voiceValues.mpeBendInSemis = stb * synth.patch.output.mpeBendRange.value;
;
}
void setVoiceMIDIMPEChannelPressure(Voice *v, int8_t p)
{
v->voiceValues.mpePressure = p / 127.0;
}
void setVoiceMIDIMPETimbre(Voice *v, int8_t t) { v->voiceValues.mpeTimbre = t / 127.0; }
};
struct VMMonoResponder
{
Expand Down
3 changes: 2 additions & 1 deletion src/synth/voice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ void Voice::renderBlock()
MTS_RetuningInSemitones(monoValues.mtsClient, voiceValues.key, voiceValues.channel);
}
retuneKey += ((monoValues.pitchBend >= 0) ? out.bendUp : out.bendDown) * monoValues.pitchBend;
retuneKey += voiceValues.portaDiff * voiceValues.portaSign;
retuneKey += voiceValues.portaDiff * voiceValues.portaSign + voiceValues.mpeBendInSemis;

if (voiceValues.portaDiff > 1e-5)
voiceValues.portaDiff -= voiceValues.dPorta;
Expand Down Expand Up @@ -190,6 +190,7 @@ void Voice::cleanup()
voiceValues.portaDiff = 0;
voiceValues.portaSign = 0;
voiceValues.dPorta = 0;
voiceValues.mpeBendInSemis = 0;

for (auto &s : src)
{
Expand Down
2 changes: 2 additions & 0 deletions src/synth/voice_values.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ struct VoiceValues
float portaDiff{0}, dPorta{0};
int portaSign{0};

float mpeBendInSemis{0}, mpeBendNormalized{0}, mpeTimbre{0}, mpePressure{0};

float uniRatioMul{1.0};
float uniPanShift{0.0};
int uniIndex{0};
Expand Down
66 changes: 49 additions & 17 deletions src/ui/main-sub-panel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,11 @@ namespace baconpaul::six_sines::ui
{
MainSubPanel::MainSubPanel(SixSinesEditor &e) : HasEditor(e), DAHDSRComponents()
{
auto &on = editor.patchCopy.output;
voiceTrigerAllowed = false;
setupDAHDSR(e, e.patchCopy.output);
setupDAHDSR(e, on);

createComponent(editor, *this, e.patchCopy.output.velSensitivity, velSen, velSenD);
createComponent(editor, *this, on.velSensitivity, velSen, velSenD);
addAndMakeVisible(*velSen);
velSenL = std::make_unique<jcmp::Label>();
velSenL->setText("Amp");
Expand All @@ -33,8 +34,8 @@ MainSubPanel::MainSubPanel(SixSinesEditor &e) : HasEditor(e), DAHDSRComponents()
velTitle->setText("Sens");
addAndMakeVisible(*velTitle);

createComponent(editor, *this, e.patchCopy.output.bendUp, bUp, bUpD);
createComponent(editor, *this, e.patchCopy.output.bendDown, bDn, bDnD);
createComponent(editor, *this, on.bendUp, bUp, bUpD);
createComponent(editor, *this, on.bendDown, bDn, bDnD);
bUpL = std::make_unique<jcmp::Label>();
bUpL->setText("+");
bDnL = std::make_unique<jcmp::Label>();
Expand All @@ -52,11 +53,11 @@ MainSubPanel::MainSubPanel(SixSinesEditor &e) : HasEditor(e), DAHDSRComponents()
playTitle->setText("Play");
addAndMakeVisible(*playTitle);

createComponent(editor, *this, e.patchCopy.output.playMode, playMode, playModeD);
createComponent(editor, *this, on.playMode, playMode, playModeD);
playMode->direction = sst::jucegui::components::MultiSwitch::VERTICAL;
addAndMakeVisible(*playMode);

createComponent(editor, *this, e.patchCopy.output.portaTime, portaTime, portaTimeD);
createComponent(editor, *this, on.portaTime, portaTime, portaTimeD);
addAndMakeVisible(*portaTime);
portaL = std::make_unique<jcmp::Label>();
portaL->setText("Porta");
Expand All @@ -70,7 +71,7 @@ MainSubPanel::MainSubPanel(SixSinesEditor &e) : HasEditor(e), DAHDSRComponents()
w->setEnabledState();
};

editor.componentRefreshByID[e.patchCopy.output.playMode.meta.id] = op;
editor.componentRefreshByID[on.playMode.meta.id] = op;
playModeD->onGuiSetValue = op;

triggerButton = std::make_unique<jcmp::TextPushButton>();
Expand All @@ -83,7 +84,7 @@ MainSubPanel::MainSubPanel(SixSinesEditor &e) : HasEditor(e), DAHDSRComponents()
}
});
setTriggerButtonLabel();
editor.componentRefreshByID[e.patchCopy.output.defaultTrigger.meta.id] =
editor.componentRefreshByID[on.defaultTrigger.meta.id] =
[w = juce::Component::SafePointer(this)]()
{
if (w)
Expand All @@ -93,23 +94,22 @@ MainSubPanel::MainSubPanel(SixSinesEditor &e) : HasEditor(e), DAHDSRComponents()
};
addAndMakeVisible(*triggerButton);

createComponent(editor, *this, e.patchCopy.output.pianoModeActive, pianoModeButton,
pianoModeButtonD);
createComponent(editor, *this, on.pianoModeActive, pianoModeButton, pianoModeButtonD);
addAndMakeVisible(*pianoModeButton);

createComponent(editor, *this, e.patchCopy.output.unisonCount, uniCt, uniCtD);
createComponent(editor, *this, on.unisonCount, uniCt, uniCtD);
addAndMakeVisible(*uniCt);
uniCtD->onGuiSetValue = op;

uniCtL = std::make_unique<jcmp::Label>();
uniCtL->setText("Voice");
addAndMakeVisible(*uniCtL);

createComponent(editor, *this, e.patchCopy.output.uniPhaseRand, uniRPhase, uniRPhaseDD);
createComponent(editor, *this, on.uniPhaseRand, uniRPhase, uniRPhaseDD);
uniRPhase->setLabel("Rand Phase");
addAndMakeVisible(*uniRPhase);

createComponent(editor, *this, e.patchCopy.output.unisonSpread, uniSpread, uniSpreadD);
createComponent(editor, *this, on.unisonSpread, uniSpread, uniSpreadD);
addAndMakeVisible(*uniSpread);
uniSpreadL = std::make_unique<jcmp::Label>();
uniSpreadL->setText("Spread");
Expand All @@ -118,7 +118,24 @@ MainSubPanel::MainSubPanel(SixSinesEditor &e) : HasEditor(e), DAHDSRComponents()
uniTitle = std::make_unique<RuledLabel>();
uniTitle->setText("Unison");
addAndMakeVisible(*uniTitle);
editor.componentRefreshByID[e.patchCopy.output.unisonCount.meta.id] = op;
editor.componentRefreshByID[on.unisonCount.meta.id] = op;

mpeTitle = std::make_unique<RuledLabel>();
mpeTitle->setText("MPE");
addAndMakeVisible(*mpeTitle);

createComponent(editor, *this, on.mpeActive, mpeActiveButton, mpeActiveButtonD);
addAndMakeVisible(*mpeActiveButton);
mpeActiveButton->setLabel("MPE Active");
mpeActiveButtonD->onGuiSetValue = op;
editor.componentRefreshByID[on.mpeActive.meta.id] = op;

createComponent(editor, *this, on.mpeBendRange, mpeRange, mpeRangeD);
addAndMakeVisible(*mpeRange);

mpeRangeL = std::make_unique<jcmp::Label>();
mpeRangeL->setText("Bend");
addAndMakeVisible(*mpeRangeL);

setEnabledState();
};
Expand All @@ -139,14 +156,14 @@ void MainSubPanel::resized()
positionKnobAndLabel(depx + xtraW, depy, velSen, velSenL);

depy += uicLabeledKnobHeight + uicMargin;
auto pmw{14};
positionTitleLabelAt(depx, depy, uicKnobSize + 2 * xtraW, bendTitle);
auto bbx = juce::Rectangle<int>(depx, depy + uicTitleLabelHeight, uicKnobSize + 2 * xtraW,
uicLabelHeight);
bUpL->setBounds(bbx.withWidth(18));
bUp->setBounds(bbx.withTrimmedLeft(18 + uicMargin));
bUpL->setBounds(bbx.withWidth(pmw));
bUp->setBounds(bbx.withTrimmedLeft(pmw + uicMargin));
bbx = bbx.translated(0, uicLabelHeight + uicMargin);

auto pmw{14};
bDnL->setBounds(bbx.withWidth(pmw));
bDn->setBounds(bbx.withTrimmedLeft(pmw + uicMargin));

Expand Down Expand Up @@ -174,6 +191,16 @@ void MainSubPanel::resized()
bbx = bbx.translated(0, uicMargin + uicLabelHeight);
uniRPhase->setBounds(bbx.withHeight(uicLabelHeight));
positionKnobAndLabel(bbx.getX() + xtraW, portaTime->getY(), uniSpread, uniSpreadL);

depx += bbx.getWidth() + uicMargin;
depy = r.getY();
positionTitleLabelAt(depx, depy, bbx.getWidth(), mpeTitle);
bbx = juce::Rectangle<int>(depx, depy + uicTitleLabelHeight, bbx.getWidth(), uicLabelHeight);
mpeActiveButton->setBounds(bbx.withHeight(uicLabelHeight));
bbx = bbx.translated(0, uicMargin + uicLabelHeight);
mpeRange->setBounds(bbx.withHeight(uicLabelHeight));
bbx = bbx.translated(0, uicMargin + uicLabelHeight);
mpeRangeL->setBounds(bbx.withHeight(uicLabelHeight));
}

void MainSubPanel::setTriggerButtonLabel()
Expand Down Expand Up @@ -238,6 +265,11 @@ void MainSubPanel::setEnabledState()
uniCtL->setText("Voice");
else
uniCtL->setText("Voices");

auto me = editor.patchCopy.output.mpeActive.value > 0.5;
mpeRange->setEnabled(me);
mpeRangeL->setEnabled(me);

repaint();
}

Expand Down
9 changes: 8 additions & 1 deletion src/ui/main-sub-panel.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ struct MainSubPanel : juce::Component, HasEditor, DAHDSRComponents<MainSubPanel,
std::unique_ptr<jcmp::MultiSwitch> playMode;
std::unique_ptr<PatchDiscrete> playModeD;

std::unique_ptr<RuledLabel> velTitle, bendTitle, uniTitle;
std::unique_ptr<RuledLabel> velTitle, bendTitle, uniTitle, mpeTitle;

std::unique_ptr<jcmp::Label> bUpL, bDnL;
std::unique_ptr<PatchContinuous> bUpD, bDnD;
Expand Down Expand Up @@ -73,6 +73,13 @@ struct MainSubPanel : juce::Component, HasEditor, DAHDSRComponents<MainSubPanel,
std::unique_ptr<jcmp::Knob> uniSpread;
std::unique_ptr<PatchContinuous> uniSpreadD;
std::unique_ptr<jcmp::Label> uniSpreadL;

std::unique_ptr<jcmp::ToggleButton> mpeActiveButton;
std::unique_ptr<PatchDiscrete> mpeActiveButtonD;

std::unique_ptr<jcmp::JogUpDownButton> mpeRange;
std::unique_ptr<PatchDiscrete> mpeRangeD;
std::unique_ptr<jcmp::Label> mpeRangeL;
};
} // namespace baconpaul::six_sines::ui
#endif // MAIN_SUB_PANEL_H
15 changes: 8 additions & 7 deletions src/ui/six-sines-editor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,14 @@ SixSinesEditor::SixSinesEditor(Synth::audioToUIQueue_t &atou, Synth::uiToAudioQu
style()
->getFont(jcmp::MenuButton::Styles::styleClass, jcmp::MenuButton::Styles::labelfont)
.withHeight(18));
auto bg = style()->getColour(jcmp::base_styles::Base::styleClass, jcmp::base_styles::Base::background);
style()->setColour(jcmp::base_styles::PushButton::styleClass, jcmp::base_styles::PushButton::fill,
bg.brighter(0.1));
style()->setColour(jcmp::base_styles::PushButton::styleClass, jcmp::base_styles::PushButton::fill_hover, bg.brighter(0.2));
style()->setColour(jcmp::base_styles::PushButton::styleClass, jcmp::base_styles::PushButton::fill_pressed,
bg.brighter(0.3));

auto bg = style()->getColour(jcmp::base_styles::Base::styleClass,
jcmp::base_styles::Base::background);
style()->setColour(jcmp::base_styles::PushButton::styleClass,
jcmp::base_styles::PushButton::fill, bg.brighter(0.1));
style()->setColour(jcmp::base_styles::PushButton::styleClass,
jcmp::base_styles::PushButton::fill_hover, bg.brighter(0.2));
style()->setColour(jcmp::base_styles::PushButton::styleClass,
jcmp::base_styles::PushButton::fill_pressed, bg.brighter(0.3));

matrixPanel = std::make_unique<MatrixPanel>(*this);
mixerPanel = std::make_unique<MixerPanel>(*this);
Expand Down

0 comments on commit 30a5342

Please sign in to comment.