Browse Source

Implement midi channel filtering in host midi

Signed-off-by: falkTX <falktx@falktx.com>
tags/22.02
falkTX 3 years ago
parent
commit
e3b9858994
Signed by: falkTX <falktx@falktx.com> GPG Key ID: CDBAA37ABC74FBA0
4 changed files with 93 additions and 52 deletions
  1. +86
    -21
      plugins/Cardinal/src/HostMIDI.cpp
  2. +1
    -1
      plugins/Cardinal/src/plugincontext.hpp
  3. +5
    -29
      src/CardinalPlugin.cpp
  4. +1
    -1
      src/PluginContext.hpp

+ 86
- 21
plugins/Cardinal/src/HostMIDI.cpp View File

@@ -82,6 +82,7 @@ struct HostMIDI : Module {
uint32_t midiEventFrame;
int64_t lastBlockFrame;
bool wasPlaying;
uint8_t channel;

// stuff from Rack
bool smooth;
@@ -138,6 +139,7 @@ struct HostMIDI : Module {
midiEventFrame = 0;
lastBlockFrame = -1;
wasPlaying = false;
channel = 0;
smooth = true;
channels = 1;
polyMode = ROTATE_MODE;
@@ -194,7 +196,7 @@ struct HostMIDI : Module {
}
}

for (uint32_t i=0; i<midiEventsLeft; ++i)
while (midiEventsLeft != 0)
{
const MidiEvent& midiEvent(*midiEvents);

@@ -216,6 +218,12 @@ struct HostMIDI : Module {
data = midiEvent.data;
}

if (channel != 0 && data[0] < 0xF0)
{
if ((data[0] & 0x0F) != (channel - 1))
continue;
}

converterMsg.frame = midiEventFrame;
std::memcpy(converterMsg.bytes.data(), data, midiEvent.size);

@@ -509,6 +517,7 @@ struct HostMIDI : Module {

struct MidiOutput : dsp::MidiGenerator<PORT_MAX_CHANNELS> {
CardinalPluginContext* const pcontext;
uint8_t channel = 0;
dsp::Timer rateLimiterTimer;

MidiOutput(CardinalPluginContext* const pc)
@@ -516,7 +525,7 @@ struct HostMIDI : Module {

void onMessage(const midi::Message& message) override
{
pcontext->writeMidiMessage(message);
pcontext->writeMidiMessage(message, channel);
}
} midiOutput;

@@ -555,6 +564,13 @@ struct HostMIDI : Module {
configOutput(CONTINUE_OUTPUT, "Continue trigger");
}

void onReset() override
{
midiInput.reset();
midiOutput.reset();
midiOutput.channel = 0;
}

void process(const ProcessArgs& args) override
{
if (midiInput.process(args, outputs))
@@ -622,39 +638,48 @@ struct HostMIDI : Module {

json_t* dataToJson() override
{
json_t* rootJ = json_object();
json_t* const rootJ = json_object();
DISTRHO_SAFE_ASSERT_RETURN(rootJ != nullptr, nullptr);

json_object_set_new(rootJ, "smooth", json_boolean(midiInput.smooth));
json_object_set_new(rootJ, "channels", json_integer(midiInput.channels));
json_object_set_new(rootJ, "polyMode", json_integer(midiInput.polyMode));

// Saving/restoring pitch and mod doesn't make much sense for MPE.
if (midiInput.polyMode != MidiInput::MPE_MODE) {
if (midiInput.polyMode != MidiInput::MPE_MODE)
{
json_object_set_new(rootJ, "lastPitch", json_integer(midiInput.pws[0]));
json_object_set_new(rootJ, "lastMod", json_integer(midiInput.mods[0]));
}

json_object_set_new(rootJ, "inputChannel", json_integer(midiInput.channel));
json_object_set_new(rootJ, "outputChannel", json_integer(midiOutput.channel));

return rootJ;
}

void dataFromJson(json_t* rootJ) override
{
json_t* smoothJ = json_object_get(rootJ, "smooth");
if (smoothJ)
if (json_t* const smoothJ = json_object_get(rootJ, "smooth"))
midiInput.smooth = json_boolean_value(smoothJ);

json_t* channelsJ = json_object_get(rootJ, "channels");
if (channelsJ)
if (json_t* const channelsJ = json_object_get(rootJ, "channels"))
midiInput.setChannels(json_integer_value(channelsJ));

json_t* polyModeJ = json_object_get(rootJ, "polyMode");
if (polyModeJ)
if (json_t* const polyModeJ = json_object_get(rootJ, "polyMode"))
midiInput.polyMode = (MidiInput::PolyMode) json_integer_value(polyModeJ);

json_t* lastPitchJ = json_object_get(rootJ, "lastPitch");
if (lastPitchJ)
if (json_t* const lastPitchJ = json_object_get(rootJ, "lastPitch"))
midiInput.pws[0] = json_integer_value(lastPitchJ);

json_t* lastModJ = json_object_get(rootJ, "lastMod");
if (lastModJ)
if (json_t* const lastModJ = json_object_get(rootJ, "lastMod"))
midiInput.mods[0] = json_integer_value(lastModJ);

if (json_t* const inputChannelJ = json_object_get(rootJ, "inputChannel"))
midiInput.channel = json_integer_value(inputChannelJ);

if (json_t* const outputChannelJ = json_object_get(rootJ, "outputChannel"))
midiOutput.channel = json_integer_value(outputChannelJ) & 0x0F;
}
};

@@ -742,12 +767,31 @@ struct HostMIDIWidget : ModuleWidget {
void appendContextMenu(Menu* const menu) override
{
menu->addChild(new MenuSeparator);

menu->addChild(createMenuLabel("MIDI Input"));

menu->addChild(createBoolPtrMenuItem("Smooth pitch/mod wheel", "", &module->midiInput.smooth));

struct ChannelItem : MenuItem {
struct InputChannelItem : MenuItem {
HostMIDI* module;
Menu* createChildMenu() override {
Menu* menu = new Menu;
for (int c = 0; c <= 16; c++) {
menu->addChild(createCheckMenuItem((c == 0) ? "All" : string::f("%d", c), "",
[=]() {return module->midiInput.channel == c;},
[=]() {module->midiInput.channel = c;}
));
}
return menu;
}
};
InputChannelItem* const inputChannelItem = new InputChannelItem;
inputChannelItem->text = "MIDI channel";
inputChannelItem->rightText = (module->midiInput.channel ? string::f("%d", module->midiInput.channel) : "All")
+ " " + RIGHT_ARROW;
inputChannelItem->module = module;
menu->addChild(inputChannelItem);

struct PolyphonyChannelItem : MenuItem {
HostMIDI* module;
Menu* createChildMenu() override {
Menu* menu = new Menu;
@@ -760,11 +804,11 @@ struct HostMIDIWidget : ModuleWidget {
return menu;
}
};
ChannelItem* channelItem = new ChannelItem;
channelItem->text = "Polyphony channels";
channelItem->rightText = string::f("%d", module->midiInput.channels) + " " + RIGHT_ARROW;
channelItem->module = module;
menu->addChild(channelItem);
PolyphonyChannelItem* const polyphonyChannelItem = new PolyphonyChannelItem;
polyphonyChannelItem->text = "Polyphony channels";
polyphonyChannelItem->rightText = string::f("%d", module->midiInput.channels) + " " + RIGHT_ARROW;
polyphonyChannelItem->module = module;
menu->addChild(polyphonyChannelItem);

menu->addChild(createIndexPtrSubmenuItem("Polyphony mode", {
"Rotate",
@@ -774,7 +818,28 @@ struct HostMIDIWidget : ModuleWidget {
}, &module->midiInput.polyMode));

menu->addChild(new MenuSeparator);
menu->addChild(createMenuLabel("MIDI Output"));

struct OutputChannelItem : MenuItem {
HostMIDI* module;
Menu* createChildMenu() override {
Menu* menu = new Menu;
for (uint8_t c = 0; c < 15; c++) {
menu->addChild(createCheckMenuItem(string::f("%d", c+1), "",
[=]() {return module->midiOutput.channel == c;},
[=]() {module->midiOutput.channel = c;}
));
}
return menu;
}
};
OutputChannelItem* const outputChannelItem = new OutputChannelItem;
outputChannelItem->text = "MIDI channel";
outputChannelItem->rightText = string::f("%d", module->midiOutput.channel+1) + " " + RIGHT_ARROW;
outputChannelItem->module = module;
menu->addChild(outputChannelItem);

menu->addChild(new MenuSeparator);
menu->addChild(createMenuLabel("MIDI Input & Output"));

menu->addChild(createMenuItem("Panic", "",


+ 1
- 1
plugins/Cardinal/src/plugincontext.hpp View File

@@ -70,7 +70,7 @@ struct CardinalPluginContext : rack::Context {
UI* ui;
#endif
CardinalPluginContext(Plugin* const p);
void writeMidiMessage(const rack::midi::Message& message);
void writeMidiMessage(const rack::midi::Message& message, uint8_t channel);
#ifndef HEADLESS
bool addIdleCallback(IdleCallback* cb) const;
void removeIdleCallback(IdleCallback* cb) const;


+ 5
- 29
src/CardinalPlugin.cpp View File

@@ -312,7 +312,7 @@ struct Initializer
// -----------------------------------------------------------------------------------------------------------
void CardinalPluginContext::writeMidiMessage(const rack::midi::Message& message)
void CardinalPluginContext::writeMidiMessage(const rack::midi::Message& message, const uint8_t channel)
{
const size_t size = message.bytes.size();
DISTRHO_SAFE_ASSERT_RETURN(size > 0,);
@@ -367,6 +367,9 @@ void CardinalPluginContext::writeMidiMessage(const rack::midi::Message& message)
std::memcpy(event.data, message.bytes.data(), event.size);
if (channel != 0 && event.data[0] < 0xF0)
event.data[0] |= channel & 0x0F;
plugin->writeMidiEvent(event);
}
@@ -831,34 +834,7 @@ protected:
{
const TimePosition& timePos(getTimePosition());
bool reset = false;
if (timePos.playing)
{
if (timePos.frame == 0 || fPreviousFrame + frames != timePos.frame)
reset = true;
/*
if (! context->playing)
{
if (timePos.frame == 0)
{
singleTimeMidiEvent.data[0] = 0xFA; // start
sendSingleSimpleMidiMessage(singleTimeMidiEvent);
}
singleTimeMidiEvent.data[0] = 0xFB; // continue
sendSingleSimpleMidiMessage(singleTimeMidiEvent);
}
*/
}
else if (context->playing)
{
/*
singleTimeMidiEvent.data[0] = 0xFC; // stop
sendSingleSimpleMidiMessage(singleTimeMidiEvent);
*/
}
const bool reset = timePos.playing && (timePos.frame == 0 || fPreviousFrame + frames != timePos.frame);
context->playing = timePos.playing;
context->bbtValid = timePos.bbt.valid;


+ 1
- 1
src/PluginContext.hpp View File

@@ -107,7 +107,7 @@ struct CardinalPluginContext : rack::Context {
std::memset(parameters, 0, sizeof(parameters));
}

void writeMidiMessage(const rack::midi::Message& message);
void writeMidiMessage(const rack::midi::Message& message, uint8_t channel);

#ifndef HEADLESS
bool addIdleCallback(IdleCallback* cb) const;


Loading…
Cancel
Save