Skip to content

Commit 1444364

Browse files
committed
Stop buttons MIDI control.
1 parent c28144a commit 1444364

File tree

4 files changed

+103
-11
lines changed

4 files changed

+103
-11
lines changed

README.md

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,23 @@ The rest and the most of the code (including voicing, spatialisation, reverb, et
2323
The convolution reverb uses impulse responses from the [Open AIR](https://www.openair.hosted.york.ac.uk/) project database.
2424

2525
## MIDI Control
26-
Sequencer steps are controlled via the program change messages sent on the control MIDI channel (program 0 corresponds to the first step of the sequencer, 1 - to the second and so on).
27-
> In a DAW use `Program` parameter to control the sequencer steps.
28-
29-
Control MIDI channel:
30-
- `CC 1` modulation wheel enables/disables tremulant;
31-
- `CC 7` controls the global volume and the volume of each division which has `swell` enabled;
32-
- `CC 91` controls the reverb output level;
26+
Sequencer steps are controlled via the program change messages sent on the control MIDI channel (program `0 `corresponds to the first step of the sequencer, `1` - to the second and so on).
27+
> In a DAW you may use `Program` parameter to control the sequencer steps.
28+
29+
MIDI controllers (CCs):
30+
- `CC 1` modulation wheel enables/disables tremulant
31+
- `CC 7` controls the global volume (on the control MIDI channel) and the volume of each division which has `swell` config flag enabled (on the swell MIDI channel)
32+
- `CC 91` controls the reverb output level
33+
- `CC 98` Stops control
34+
35+
> :point_right: The stops control follows the original Aeolus convention. The control mode is set by the message `01mm0ggg`, where `mm` is the control mode, and `ggg` is the control group (division number, counter from the top starting from `0`).
36+
> Control modes are:
37+
> - `00` Disable the division (all stops are off)
38+
> - `01` Set stop off
39+
> - `10` Set stop on
40+
> - `11` Toggle
41+
>
42+
> Once the control message is received the value of the format `000bbbbb` will execute the selected control mode action on specified stop buton `bbbbb`, counted from `0`.
3343
3444
## Custom organ configuration
3545
Custom organ configuration will be loaded by the plugin if found at `Documents/Aeolus/organ_config.json` location.

Source/aeolus/engine.cpp

Lines changed: 68 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -863,9 +863,9 @@ void Engine::applyVolume(float* outL, float* outR, int numFrames)
863863

864864
void Engine::processControlMIDIMessage(const MidiMessage& message)
865865
{
866-
// NOTE: VST3 will not pass the program change MIDI messages through.
867-
// Instead program change must be handled at the processor level
868-
// via the setCurrentProgram() method.
866+
// @note VST3 will not pass the program change MIDI messages through.
867+
// Instead program change must be handled at the processor level
868+
// via the setCurrentProgram() method.
869869

870870
// Here we handle the program change message nevertheless
871871
// in case of a non-VST3 or stand-alone plugin.
@@ -874,6 +874,71 @@ void Engine::processControlMIDIMessage(const MidiMessage& message)
874874

875875
if (step >= 0 && step < _sequencer->getStepsCount())
876876
_sequencer->setStep(step);
877+
} else if (message.isController() && message.getControllerNumber() == CC_STOP_BUTTONS) {
878+
const auto value{ message.getControllerValue() };
879+
880+
if (value & 0xC8 == 0x40) {
881+
// 01mm0ggg
882+
StopControlMode mode { StopControlMode::Disabled };
883+
884+
const int modeValue{ (value >> 4) & 0x03 >> 4 };
885+
switch (modeValue) {
886+
case 0: mode = StopControlMode::Disabled; break;
887+
case 1: mode = StopControlMode::SetOff; break;
888+
case 2: mode = StopControlMode::SetOn; break;
889+
case 3: mode = StopControlMode::Toggle; break;
890+
default: break;
891+
}
892+
893+
_stopControlMode = mode;
894+
_stopControlGroup = value & 0x07;
895+
896+
if (_stopControlMode == StopControlMode::Disabled) {
897+
// Disable message does not require a 2nd part and can be processed immeditely.
898+
processStopControlMessage();
899+
900+
_stopControlMode.reset();
901+
}
902+
} else if (value & 0xE0 == 0) {
903+
// 000bbbbb
904+
if (_stopControlMode.has_value()) {
905+
_stopControlButton = value & 0x1F;
906+
907+
processStopControlMessage();
908+
}
909+
} else {
910+
_stopControlMode.reset();
911+
}
912+
}
913+
}
914+
915+
void Engine::processStopControlMessage()
916+
{
917+
if (!_stopControlMode.has_value())
918+
return;
919+
920+
if (!juce::isPositiveAndBelow(_stopControlGroup, _divisions.size()))
921+
return;
922+
923+
auto* division{ _divisions.getUnchecked(_stopControlGroup) };
924+
925+
const auto mode{ *_stopControlMode };
926+
927+
switch (mode) {
928+
case StopControlMode::Disabled:
929+
division->disableAllStops();
930+
break;
931+
case StopControlMode::SetOff:
932+
division->enableStop(_stopControlButton, false);
933+
break;
934+
case StopControlMode::SetOn:
935+
division->enableStop(_stopControlButton, true);
936+
break;
937+
case StopControlMode::Toggle:
938+
division->enableStop(_stopControlButton, !division->isStopEnabled(_stopControlButton));
939+
break;
940+
default:
941+
break;
877942
}
878943
}
879944

Source/aeolus/engine.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include "aeolus/dsp/convolver.h"
3333
#include "aeolus/dsp/interpolator.h"
3434

35+
#include <optional>
3536
#include <vector>
3637

3738
AEOLUS_NAMESPACE_BEGIN
@@ -304,8 +305,12 @@ class Engine
304305
void applyVolume(juce::AudioBuffer<float>& out);
305306
void applyVolume(float* outL, float* outR, int numFrames);
306307

308+
/// Process control MIDI messages: program change (sequencer) and stop buttons CC.
307309
void processControlMIDIMessage(const juce::MidiMessage& message);
308310

311+
/// Process stop buttons MIDI controls.
312+
void processStopControlMessage();
313+
309314
float _sampleRate;
310315

311316
RingBuffer<NoteEvent, 1024> _pendingNoteEvents;
@@ -314,6 +319,10 @@ class Engine
314319

315320
AudioParameterPool _params; ///< Internal parameters.
316321

322+
std::optional<StopControlMode> _stopControlMode{};
323+
int _stopControlGroup{};
324+
int _stopControlButton{};
325+
317326
/// List of all divisions
318327
juce::OwnedArray<Division> _divisions;
319328

Source/aeolus/globals.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,15 @@ constexpr static float TUNING_FREQUENCY_DEFAULT = 440.0f;
103103
enum {
104104
CC_MODULATION = 1,
105105
CC_VOLUME = 7,
106-
CC_REVERB = 91
106+
CC_REVERB = 91,
107+
CC_STOP_BUTTONS = 98
108+
};
109+
110+
enum class StopControlMode {
111+
Disabled, // 0b00
112+
SetOff, // 0b01
113+
SetOn, // 0b10
114+
Toggle // 0b11
107115
};
108116

109117
//==============================================================================

0 commit comments

Comments
 (0)