It does work.
Thanks!
Can you also use multiple midi controler, via the USB-A midi host, with the Meta?
usb hubs
no support at this time
(usb) midi hubs
hmm, I cannot remember status on this one.
Im pretty sure you cannot target/select a particular āportā , as discussed in this topic.
Iāve a suspicion it may merge the inputs of all ports, and only send to the first port?
that said, I may have missed progress on this one⦠@danngreen ?
Id hope we can get full support (input and output) on midi hubs, even if itās initially just at the sdk level, as per my feedback on sdk 2.1.
this would be really useful for some modules Im working on for MPE , as an MPE device uses all 16 channels, so plug one in, and thats all you get.
(ok, you could use global channel for other uses ;))
I started a branch for USB hubs, but didnāt get it stable enough. I could give it another go sometime, but I think āMIDI hubsā (aka USB-MIDI cables), is probably going to offer more benefit. Also it should be easier to add since itās not at the driver level (Iām not sure why I tried to do USB hubs first, I thought it would be easier than it was)
Iām still thinking to add an API for a MIDI browser similar to the File Browser. For backwards compatibility you could choose one as the default in the main settings/prefs. Then there would be an api to let the user select a MIDI device/cable id, in case a module wants to offer that (or if a module can connect to multiple devices).
Thank you @danngreen, the API would be great and very useful!
If the H4MIDI appears to the host as a single USB-MIDI device with one or more endpoints, would the META be able to communicate with it under the current implementation?
Or should I wait for the MIDI Browser API to be implemented for multi-port devices?
This will help me know whether I can integrate the H4MIDI now, or whether I should plan for future firmware support.
Thanks again for the constant updates on META ā the module is absolutely fantastic ! ![]()
yeah, per previous topic, using the usb cable id approach hopefully shouldnāt be too much of an upheaval.
these cables/virtual ports are also used for things other than midi hubs, many (usb) midi devices also use them.
e.g Haken, Osmose, Embodme, Push, Electra One, Squarp Hapax⦠are just the ones sitting on my desk ![]()
and for some of these , which (virtual) port you use is very important - Haken/Osmose you must send midi data on port 2 (not port 1).
it be nice to have a browser / selector, but thats more a nice to have than required - Im so used to devices not show the device name, Im used to select ports purely by their number.
With the H4MIDI you can connect up to 8 USB-Midi devices directly to the MM. Perhaps need to power the H4MIDI.
Hi,
You made it work with more then 2 devices on the midi hub with META or are you relating to the general specs of the H4MIDI?
Ok Iām doing this now. I realized backwards compatibility is going to be an issue here, since this changes the size of the midi message. But I think I can squeeze the cable number in the top 4 bits of the rack::midi::Message::size byte, since that can only be 0-3 anyways.
You should be able to use it like:
rack::midi::InputQueue midiInput;
void read_midi() {
rack::midi::Message msg;
if (midiInput.tryPop(&msg, args.frame)) {
if (msg.usb_cable == 2) // respond to cable 2
...
So the data is getting passed to modules, but itās still āblindā ā thereās no way to know if the attached device has a cable 2, etc.
In lieu of a MIDI browser, I could just add some API calls like int get_num_usb_midi_in_jacks() and std::string get_usb_midi_in_jack_name(int id) so you could at least check if your desired midi device is attached and/or if a particular jack/cable id is valid.
And I need to do the same for MIDI outputs now, tooā¦
sounds, like a good solution - midi is all bit masking ![]()
descriptors would be useful,
that said, I found often the descriptors themselves are little more than port 1 / port 2. - but still better than nothing.
(probably better for a different topic, but ā¦)
I wonder , how does VCV handle this? does it just generate a different midi device for each port?
EDIT: yeah, vcv just creates a Midi Device for each port, so I get āOsmose - Port 1ā, āOsmose - Port 2ā
you may want to bare this in mind for the āmid termā, if you plan to add this as part of VCV Wrapper ācompatibilityā - but its not something, I worry about at present, the midi stuff is currently MM specific when I use it.
btw: while you are in this āareaā, did you look at the sysex suggestions I made on the other topic, again following the usb midi protocol, which uses (multiple) fixed 4 byte packets.
Ive a couple of use-cases Iād like to mess with in this area - in particular the way Embody Erae Touch has a (sysex) API to control ācustom surfacesā - could be fun with the MM to give a dynamic surface to play with e.g. a physical sequence surface with bi-directional feedback.
Yeah, right now Iām just pausing the MIDI RX when it sees an 0xF0 in the status byte, and then resumes when it sees an 0xF7 in any status or data bytes (but not the usb header). Iām a little unsure if in practice actual devices use the USB MIDI Sysex start/stop and packet size indicatorsā¦
So I could turn this filter off easily, and it would work if all packets in the SysEx field contained a USB header conforming to the spec (the Table 4-1 on p16 of https://www.usb.org/sites/default/files/midi10.pdf), that is, if all packets in the Sysex stream had a CIN set to 0x4-0x7.
But it wonāt work if just raw data is sent as 4 x bytes per packet (using 0xF7 anywhere to mark the end of the stream). That is, the raw data needs to be split up into 3-byte packets, with a USB MIDI header (CN/CIN) pre-pended. Iām not sure if any MIDI devices do this? It would mean losing the concept of USB ācable/jackā since that header would be hijacked for the raw data.
yeah, so the way it works isā¦
you get 0x4 to start, then all subsequent message are 0x4 (hence the start and continue) , until you get 0x5-7 which indicates the end. - put another way it was a usb midi āhackā, to say at the end of the message how many bytes are valid.
its a very simple system ![]()
the key here is⦠the CIN always determines the message⦠since you can actually receive other messages (e.g. note on/off/cc) whilst sysex is active. hence you cannot just have āraw bytesā, the CIN always indicates message type including still part of the sysex
note: you can only have one sysex active at at time.
its all quite transparent⦠I think last time I read up on this was when doing sysex for axoloti ![]()
Ok, excellent, thatās how I understood it too. Then I wonāt have to hack it so hard to not break backwards API compatibility. I should be able to just turn off the SysEx filter and dump the 1-3 byte packets into the midi message data.
I might have to use another bit to indicate this is a sysex packet so a module can query if the data is sysex.
I donāt have the H4MIDI but scrolling through the docs, it looks like you can configure it extensively in terms of how it merges multiple streams.
So the current MM firmware would work with it if you did something like routing each device to a different channel. Then you could have various MIDI modules in your patch listening in different channels.
Or configure it to keep the channels intact but just merge all the streams together (the MM wouldnāt be able to tell which source a given message came from, but it would get all the messages including channel data OK)
cool, Iāll keep an eye out for a test firmware.
Iāve got a a test vcv module(somewhere
) I wrote for the Erae Touch which uses sysex that I can test with.
iirc, itāll also need to use the 2nd midi port, so will test that at the same time.
note: vcv does not support sysex, so my module had to connect directly to the device, rather than use the vcv api - so hopefully can adapt that fairly easily.
Iād expect , like this module, modules using sysex will be quite specific to devices - nature of the beast.
This doesnāt quite conform to the midi spec. If any non-realitime status byte is received while a port is receiving sysex then that effectively ends the message.
Here is the relevant quote from the midi-spec
interesting point⦠but is that not superseded by usb midi spec?
i.e. you could make it such that usb-usb midi would allow for interleaving but still allow for backwards compatibility for traditional serial devices.
(bare in mind any din ā usb midi converter is already having to do some translation, so would not be ādifficultā to do this)
usb midi spec, basically has extra redundancy that the serial midi did not have, which is what (could) allow for interleaving.
all that said, Id have to dig thru the usb midi spec to look for where it says this is possible - I could also check it out in practice to see.
I implemented this to what I think is the standard-compliant, and just passing non-compliant situations to module to deal with if it cares to. In the way I did it for incoming MIDI, the situation @audiobird youāre bringing up (a USB MIDI device ending a SysEx stream with an 0xF7 in the payload, without setting CIN to 0x5, 0x6 or 0x7) would need to be caught by the module thatās interpreting the sysex data. In the way I have it, the module just gets a struct with this:
struct rack::Message {
std::array<uint8_t, 3> bytes{};
uint8_t usb_cable : 4 = 0;
uint8_t usb_code : 4 = 0;
///...
int getUsbCable() const {
return usb_cable;
}
int getUsbCIN() const {
return usb_code;
}
So if a module is getting SysEx over these messages, it would need to check usb_code if it was sure the sender was compliant with the USB MIDI standard, or check bytes[] for 0xF7 if the sender is not compliant with the USB MIDI spec (which I imagine might happen with DIN5->USB adapters)
I have a similar structure setup for native module MIDI (not using the rack layer), but I havenāt opened any API functions for it yet.
For outgoing MIDI, I made a little bit more of an interface for sending SysEx. Example:
midi::Output midiOutput;
midi::Message msg;
// Send 3 bytes of sysex payload:
msg.startSysEx(0x01, 0x02);
midiOutput.onMessage(msg); // sends [04] 0xF0 0x01 0x02
msg.endSysEx(0x03);
midiOutput.onMessage(msg); // sends [06] 0x03 0xF7 0x00
// Send 8 bytes of sysex payload over USB cable 9
msg.setUsbCable(9);
msg.startSysEx(0x04, 0x05);
midiOutput.onMessage(msg); // sends [94] 0xF0 0x04 0x05
msg.continueSysEx(0x06, 0x07, 0x08);
midiOutput.onMessage(msg); // sends [94] 0x06 0x07 0x08
msg.continueSysEx(0x09, 0x0a, 0x0b);
midiOutput.onMessage(msg); // sends [94] 0x09 0x0a 0x0b
msg.endSysEx();
midiOutput.onMessage(msg); // sends [95] 0xF7 0x00 0x00
// Where [p#] is the USB header (p=cable)
Hereās the dev firmware:
https://github.com/4ms/metamodule/releases/download/firmware-v2.2.0-usb-cablenum-02/metamodule-firmware-v2.2.0-usb-cablenum-02-firmware-assets.zip
I havenāt checked if any of my controllers can send/receive SysEx yet so I only have tested this by mocking up data going in and out.
I can report that the Breakout box by SOMA LABORATORY works fine with the MM. ![]()
It features:
1 USB-C
1 DIN MIDI IN
1 DIN MIDI OUT
AND 11 more CV OUT ![]()
CV interface:
PC/MAC first voice channel . . . . . 1
PC/MAC second voice channel. . . . 2
PC/MAC CC channel . . . . . . . . . 0
PC/MAC output CC:
1st lower socket . . . . . . . . .CC20
2nd lower socket . . . . . . . . . CC21
3d lower socket. . . . . . . . . .CC22
1st upper socket . . . . . . . . . CC23
2nd upper socket. . . . . . . . CC24
3d upper socket . . . . . . . . . CC25
Tilt . . . . . . . . . . . . . . . . CC26
CC range 0ā127 maps to ā5 to 5 volts
with zero volts at 64.
MPE mode
can be turned on by pressing the button,
the XYZ LED will light up in MPE mode.
Behringer X-Control working great with Meta module.
It has a USB Mini port and it worked fine with the lead that comes with the X-Control Mini via an Amazon USB-C/USB-A converter, and with a USB-C to USB Mini cable.
No issues found at all.