Midi Patchbay / Router (Software)

aliced25

0x7F6990 & 0xFFEF
gibt es eine Software bzw. eine Funktion in MidiOX oder MidiTrix mit der ich ähnlich flexibel Midi Daten routen kann, wie mit Ableton Live? Prinzipiell funktionieren MidiOX & MidiTrix ziemlich gut aber ich finde dort keine Funktion mit der ich die Kanalnummer ändern kann (Data mapping (MidiOX) führt auch nicht zum Erfolg)...

[midiInA ch1] --> [midiOutB ch7]
[midiInA ch2] --> [midiOutB ch6]
[midiInA ch3] --> [midiOutC ch1]
[midiInA ch4] --> [midiOutD ch1] ... mit Ableton kein Problem

mit MidiOX oder MidiTrix geht leider nur folgendes mit Hilfe der Filterfunktionen:

[midiInA ch1] -Filter-> [midiOutB ch1]
[midiInA ch2] -Filter-> [midiOutC ch2]
[midiInA ch3] -Filter-> [midiOutD ch3] ...
 
Lösung
recliq
@aliced25
Eigentlich ist es ganz einfach, aber ich kann dich verstehen, MidiOX ist nicht sehr intuitiv...

Hier mal eine Step bei Step Anleitung für MidiA Ch1 => Midib Ch2:
  1. Options/MIDI Devices öffen, den Haken unten setzen (Automatically attach Inputs to Outputs during selection) und MidiA bei Input und MidiB bei Output anwählen
  2. Input Monitor öffnen (View/Input Monitor) und Output Monitor
  3. Sicherstellen das unten in der Statusleiste REC angewählt ist
    1645258720364.png
  4. Jetzt solltest du wenn du bei MidiA eine Note spielst die gleiche Note bei MidiB sehen, noch mit gleichem Channel
    1645258785548.png

  5. Jetzt kommt das Mapping: Options/Data Mapping, im Fenster auf Insert klicken
  6. Folgende Regel...
MidiOX kann das definitiv, guck mal unter Options/MidiMap...
Kann dir jetzt ausm Kopf nicht genau erklären wie, kann ich morgen mal machen...
 
hm, hab ich schon ausprobiert mit dem Data mapping... Klingt auch logisch, man kann Regeln festlegen und Daten transformieren, offensichtlich auch Eingangskanäle auf andere Ausgangskanäle legen, aber funktioniert irgendwie nicht so wie ich mir das denke... anscheinend mache ich da noch was falsch.
 
@aliced25
Eigentlich ist es ganz einfach, aber ich kann dich verstehen, MidiOX ist nicht sehr intuitiv...

Hier mal eine Step bei Step Anleitung für MidiA Ch1 => Midib Ch2:
  1. Options/MIDI Devices öffen, den Haken unten setzen (Automatically attach Inputs to Outputs during selection) und MidiA bei Input und MidiB bei Output anwählen
  2. Input Monitor öffnen (View/Input Monitor) und Output Monitor
  3. Sicherstellen das unten in der Statusleiste REC angewählt ist
    1645258720364.png
  4. Jetzt solltest du wenn du bei MidiA eine Note spielst die gleiche Note bei MidiB sehen, noch mit gleichem Channel
    1645258785548.png

  5. Jetzt kommt das Mapping: Options/Data Mapping, im Fenster auf Insert klicken
  6. Folgende Regel erstellen:
    1645259030706.png
  7. Wichtig (Stolperfalle!): Im Data Mappingfestern das Mapping aktivieren (Turn Map On after OK) und Fenster mit OK schließen:
    1645259112708.png
  8. Wieder auf MidiA Ch1 eine Note spielen und freuen:
    1645259184315.png
PS: Inder Statusleiste unten rechts siehst du nun das aktivierte Mapping, dort kannst du es auch ein/ausschalten:
1645259332214.png
 
Lösung
Danke für Deine Erklärung, hab den Denkfehler bei mir gefunden. Ich hatte den Kanalfilter in Verbindung mit den mappings falsch interpretiert und quasi Gegenteilig eingestellt.
 
ok, jetzt werden aber alle Geräte die auf Kanal 1 empfangen angespielt, wenn der Input von Kanal 1 kommt, da die Kanalfilterung jetzt nicht mehr greift...

[midiInA ch1] --> [midiOutB ch1] --> [midiOutC ch1] --> [midiOutD ch1]

die Umleitung funktioniert zwar wie gewollt, aber eben mit dem unerwünschten Nebeneffekt!
 
Zuletzt bearbeitet:
ok, jetzt werden aber alle Geräte die auf Kanal 1 empfangen angespielt, wenn der Input von Kanal 1 kommt, da die Kanalfilterung jetzt nicht mehr greift...

[midiInA ch1] --> [midiOutB ch1] --> [midiOutC ch1] --> [midiOutD ch1]

die Umleitung funktioniert zwar wie gewollt, aber eben mit dem unerwünschten Nebeneffekt!
Ich nehme an du willst dieses Setup erreichen:
[midiInA ch1] --> [midiOutB ch7]
[midiInA ch2] --> [midiOutB ch6]
[midiInA ch3] --> [midiOutC ch1]
[midiInA ch4] --> [midiOutD ch1]

Dann öffne View/Port Routings :
1645270450796.png
Wenn du dort auf das Kästchen auf der Linie zwischen Input Port und Output Port klickst, kannst du festlegen welche Channel du auf dem Output Port ausgeben willst...
 
@aliced25
Wahrscheinlich musst du sogar noch etwas mehr machen, da du auf MidiC und MidiD Ch1 mit verschiednen source channeln benutzen willst und mit dem oben genannten setup findet das channel mapping vor dem Routing statt.
Du kannst aber dein channel maps in einzelne Dateien speichern und diese dann im routing zuweisen...

PS: Dein Setup scheint wirklich etwas Problematisch... wenn du bei MidiA Ch5 statt Ch1 nimmst geht es...
1645272121190.png
 
Zuletzt bearbeitet:
Hatte ich auch genauso gemacht und für jede Verbindung eine eigenes Mapping erstellt. Ich könnte die Problematik umgehen, indem keiner der Klangerzeuger direkt über Kanal 1 vom Input angesprochen wird. Egal, ich hab mir überlegt selber ein kleines Programm zu schreiben, mit dem ich mein MidiSetup route...
 
so, vermutlich einfacher als MidiOX zu konfigurieren!
Das Programm ist sehr simpel, wer will kann sich den SourceCode für seine Gegebenheiten anpassen. Mit der Auskommentierten Funktion kann man seine eigenen Device Nummern ermitteln und entsprechend übertragen...

C++:
#include <stdio.h>
#include <windows.h>

#pragma comment(lib, "winmm.lib")

HMIDIIN hMidiIn_MidiTraC;

HMIDIOUT hMidiOut_NordModular;
HMIDIOUT hMidiOut_MicroFreak;
HMIDIOUT hMidiOut_Prophet;
HMIDIOUT hMidiOut_Iridium;
HMIDIOUT hMidiOut_Jupiter;
HMIDIOUT hMidiOut_JX3P;
HMIDIOUT hMidiOut_TC;

#define MIDITRAC 8

#define NORDMODULAR 12
#define MICROFREAK 11
#define PROPHET 7
#define IRIDIUM 8
#define JUPITER 4
#define JX3P 10
#define TC 11

//void show_MidiDevices() {
//    MIDIINCAPS inputCaps;
//    MIDIOUTCAPS outputCaps;
//    unsigned int inputDeviceNum = midiInGetNumDevs();
//    unsigned int outputDeviceNum = midiOutGetNumDevs();
//    printf("  Midi Input Devices:\n  -------------------\n");
//    if (inputDeviceNum > 0) {
//        for (unsigned int i = 0; i < inputDeviceNum; ++i) {
//            midiInGetDevCaps(i, &inputCaps, sizeof(MIDIINCAPS));
//            wprintf(L"  [%2i] %s\n", i, inputCaps.szPname);
//        }
//    }
//    else {
//        fprintf(stderr, "  no Midi-In Device");
//    }
//    printf("\n  Midi Output Devices:\n  --------------------\n");
//    if (outputDeviceNum > 0) {
//        for (unsigned int i = 0; i < outputDeviceNum; ++i) {
//            midiOutGetDevCaps(i, &outputCaps, sizeof(MIDIOUTCAPS));
//            wprintf(L"  [%2i] %s\n", i, outputCaps.szPname);
//        }
//    }
//    else {
//        fprintf(stderr, "  no Midi-Out Device");
//    }
//    printf("\n  press [SPACE]\n");
//    while (!(GetAsyncKeyState(VK_SPACE) & 0x8000)) {}
//}

void CALLBACK MidiInProc(HMIDIIN hmidiIN, unsigned int wMsg, long dwInstance, unsigned int dwParam1, unsigned int dwParam2) {
    if (dwParam1 == 0xf8 || dwParam1 == 0xfa || dwParam1 == 0xfc) { // handle MidiRealTimeMessages
        midiOutShortMsg(hMidiOut_NordModular, dwParam1);
        midiOutShortMsg(hMidiOut_MicroFreak, dwParam1);
        midiOutShortMsg(hMidiOut_Prophet, dwParam1);
        midiOutShortMsg(hMidiOut_Iridium, dwParam1);
        midiOutShortMsg(hMidiOut_Jupiter, dwParam1);
        midiOutShortMsg(hMidiOut_TC, dwParam1);
    }
    switch (dwParam1 & 0xf) {
        case 0: // MidiIputKanal 1 -> NordModular Slot 1 Kanal 1
            midiOutShortMsg(hMidiOut_NordModular, dwParam1);
            break;
        case 1: // MidiIputKanal 2 -> NordModular Slot 2 Kanal 2
            midiOutShortMsg(hMidiOut_NordModular, dwParam1);
            break;
        case 2: // MidiIputKanal 3 -> NordModular Slot 3 Kanal 3
            midiOutShortMsg(hMidiOut_NordModular, dwParam1);
            break;
        case 3: // MidiIputKanal 4 -> NordModular Slot 4 Kanal 4
            midiOutShortMsg(hMidiOut_NordModular, dwParam1);
            break;
        case 4: // MidiIputKanal 5 -> JX3P (all Channels)
            midiOutShortMsg(hMidiOut_JX3P, dwParam1);
            break;
        case 5: // MidiIputKanal 6 -> MicroFreak Kanal 1
            dwParam1 -= 5;
            midiOutShortMsg(hMidiOut_MicroFreak, dwParam1);
            break;
        case 6: // MidiIputKanal 7 -> Prophet Kanal 1
            dwParam1 -= 6;
            midiOutShortMsg(hMidiOut_Prophet, dwParam1);
            break;
        case 7: // MidiIputKanal 8 -> Iridium Layer 1 Kanal 1
            dwParam1 -= 7;
            midiOutShortMsg(hMidiOut_Iridium, dwParam1);
            break;
        case 8: // MidiIputKanal 9 -> Iridium Layer 2 Kanal 2
            dwParam1 -= 7;
            midiOutShortMsg(hMidiOut_Iridium, dwParam1);
            break;
        case 9: // Jupiter Part 1 Kanal 1
            dwParam1 -= 9;
            midiOutShortMsg(hMidiOut_Jupiter, dwParam1);
            break;
        case 10: // Jupiter Part 2 Kanal 2
            dwParam1 -= 9;
            midiOutShortMsg(hMidiOut_Jupiter, dwParam1);
            break;
        case 11: // Jupiter Part 3 Kanal 3
            dwParam1 -= 9;
            midiOutShortMsg(hMidiOut_Jupiter, dwParam1);
            break;
        case 12: // Jupiter Part 4 Kanal 4
            dwParam1 -= 9;
            midiOutShortMsg(hMidiOut_Jupiter, dwParam1);
            break;
        case 13: // Jupiter Part Drums Kanal 5
            dwParam1 -= 9;
            midiOutShortMsg(hMidiOut_Jupiter, dwParam1);
            break;
        case 14: // Roland Sh01a Kanal 6
            dwParam1 -= 9;
            midiOutShortMsg(hMidiOut_Jupiter, dwParam1);
            break;
        case 15: // MachineDrum Kanal 16
            midiOutShortMsg(hMidiOut_NordModular, dwParam1);
            break;
        default:
            break;
    }
}


int main() {
    //show_MidiDevices();
    //system("CLS");

    midiOutOpen(&hMidiOut_NordModular, NORDMODULAR, 0, 0, 0);
    midiOutOpen(&hMidiOut_MicroFreak, MICROFREAK, 0, 0, 0);
    midiOutOpen(&hMidiOut_Prophet, PROPHET, 0, 0, 0);
    midiOutOpen(&hMidiOut_Iridium, IRIDIUM, 0, 0, 0);
    midiOutOpen(&hMidiOut_Jupiter, JUPITER, 0, 0, 0);
    midiOutOpen(&hMidiOut_JX3P, JX3P, 0, 0, 0);
    midiOutOpen(&hMidiOut_TC, TC, 0, 0, 0);

    midiInOpen(&hMidiIn_MidiTraC, MIDITRAC, (DWORD_PTR)(void*)MidiInProc, 0, CALLBACK_FUNCTION);
    midiInStart(hMidiIn_MidiTraC);

    printf("Route666 by @liceD25...\n"
            "\nNordModular:\t01|02|03|04"
            "\nRoland JX3P:\t05"
            "\nMicroFreak:\t06"
            "\nProphet:\t07"
            "\nIridium:\t08|09"
            "\nJupiter:\t10|11|12|13|14"
            "\nRoland Sh01:\t15"
            "\nMachineDrum:\t16\n\n[ESC]");
    while (!(GetAsyncKeyState(VK_ESCAPE) &0x8000)){}

    midiInStop(hMidiIn_MidiTraC);

    midiOutReset(hMidiOut_NordModular);
    midiOutReset(hMidiOut_MicroFreak);
    midiOutReset(hMidiOut_Prophet);
    midiOutReset(hMidiOut_Iridium);
    midiOutReset(hMidiOut_Jupiter);
    midiOutReset(hMidiOut_JX3P);
    return 0;
}
 
Zuletzt bearbeitet:
ist es wirklich... und schon gar nicht "rocksolid" programmiert. Vielleicht setze ich mich noch mal dran und mache das Ganze konfigurierbar, so dass es jeder nutzen kann...
 
vielleicht sollte ich doch mal C++ lernen. in max muss ich schon für ein einzelnes GUI-element mehr code schreiben.^^

andererseits ginge die bloße zuweisung von port zu port unter MacOS auch einfach im betriebssystem. meine matrix kann einzelne datenarten zuordnen, splitten, oder rausfiltern... da kämpfst du erst mal mit dem platz auf dem bildschirm und sich das konzept auszudenken ist mehr arbeit wie es umzusetzen.

midiosx kann sehr viel. wirklich benutzbar finde ich die oberfläche aber auch nicht. die steuersoftware der "midihub" device ist da schöner.
 
Zuletzt bearbeitet:
@aliced25
Ich wollte dir auch nicht zu nahe treten, wusste nicht, dass das von dir kommt. Bei solchen Gewohnheiten sollte man achtsam deren Sichverfestigung beobachten, früher oder später beisst schlechter Code immer zurück, es sei denn, man benutzt ihn nicht. Aber dann muss man ihn auch nicht schreiben. Und manchmal beisst er auch andere Leute, die nichts dafür können. Das beschreibt eigentlich schon die letzten 30 Jahre fast aller Software. ;-)
 
vielleicht sollte ich doch mal C++ lernen. in max muss ich schon für ein einzelnes GUI-element mehr code schreiben.^^
mit GUI ist da nix, außer ein paar Ausgaben auf der Konsole...

der "midihub" device ist da schöner.

Tausche ESI M4U gegen midihub... hab das ESI nur geholt, weil der Midihub damals nicht verfügbar war.

@aliced25
Ich wollte dir auch nicht zu nahe treten, wusste nicht, dass das von dir kommt. Bei solchen Gewohnheiten sollte man achtsam deren Sichverfestigung beobachten, früher oder später beisst schlechter Code immer zurück, es sei denn, man benutzt ihn nicht. Aber dann muss man ihn auch nicht schreiben. Und manchmal beisst er auch andere Leute, die nichts dafür können. Das beschreibt eigentlich schon die letzten 30 Jahre fast aller Software. ;-)
Natürlich ist das kein literarisches Meisterwerk und nur so dahin gerotzt, aber es funktioniert (solange sich bloß nichts an der Zuordnung ändert und windoof nicht hustet, dann fällt mir der schlechte Code natürlich vor die Füße... auf der anderen Seite ist das Ganze so einfach gestrickt, dass man nur die defines anpassen muss und der Rummel läuft wieder)
 
Ich geh mal davon aus, dass die Win32-API auch hier die MIDI-Ports zur Laufzeit für alle anderen Anwendungen blockiert?

Das hängt vom Treiber ab, sofern es einen gibt - wenn der multiclientfähig ist, gibt es da keine Probleme. Um virtualMidi kommt man aber spätestens nicht herum, wenn man zwischen den Anwendungen Mididaten routen möchte.
 


News

Zurück
Oben