Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 6 of 6

Thread: Teensy 4 send multiple MIDI notes at once through USB.

  1. #1
    Senior Member
    Join Date
    Jan 2020
    Posts
    129

    Teensy 4 send multiple MIDI notes at once through USB.

    Hello!

    I'm wondering if it's possible to send multiple MIDI notes at once through USB midi.

    As far as I understand MIDI works sequencially sending one message at a time but I'm wondering if it's possible to send multiple notes and have them played at the same time without any delay between them.

    Thanks.

  2. #2
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    22,767
    The simple answer is yes, you can send multiple MIDI messages at once.

    The actual MIDI communication is done at 480 Mbit using a complicated protocol which communicates in packets. A single packet can hold up to 128 MIDI messages, so unless you are transmitting a pretty incredible number of messages very quickly, typically the messages you transmitted at once will all end packed into the same packet. Even though the individual bits are sent 1 at a time, the host controller in your PC receives the entire packet into a memory buffer and verifies its CRC check before passing the data on to any MIDI software. The end result is all the MIDI messages within 1 packet are indeed received at once by the software on your PC. Or at least the operating system & drivers make them all available to the software at the same instant.

    Even if multiple USB packets are used, the timing is incredibly fast relative to the pace of musical events. So even though a large burst MIDI messages spanning multiple USB packets aren't technically received simultaneously, the delay is so short that it's not worth any worry.

    Something you might consider on the Teensy side is the usbMIDI.send_now() function. If you have sent less than 128 messages, this function tells Teensy's USB code not to wait for any more, to transmit a USB packet as soon as possible with only the messages it currently has buffered. If you care deeply about performance, this can reduce latency by up to 125 microseconds. But it does use the USB bandwidth less efficiently, so only call usbMIDI.send_now() after you've completed a group of messages and you do not expect to send any more immediately.
    Last edited by PaulStoffregen; 09-23-2020 at 12:17 PM.

  3. #3
    Senior Member
    Join Date
    Jan 2020
    Posts
    129
    Quote Originally Posted by PaulStoffregen View Post
    The simple answer is yes, you can send multiple MIDI messages at once.

    The actual MIDI communication is done at 480 Mbit using a complicated protocol which communicates in packets. A single packet can hold up to 128 MIDI messages, so unless you are transmitting a pretty incredible number of messages very quickly, typically the messages you transmitted at once will all end packed into the same packet. Even though the individual bits are sent 1 at a time, the host controller in your PC receives the entire packet into a memory buffer and verifies its CRC check before passing the data on to any MIDI software. The end result is all the MIDI messages within 1 packet are indeed received at once by the software on your PC. Or at least the operating system & drivers make them all available to the software at the same instant.

    Even if multiple USB packets are used, the timing is incredibly fast relative to the pace of musical events. So even though a large burst MIDI messages spanning multiple USB packets aren't technically received simultaneously, the delay is so short that it's not worth any worry.

    Something you might consider on the Teensy side is the usbMIDI.send_now() function. If you have sent less than 128 messages, this function tells Teensy's USB code not to wait for any more, to transmit a USB packet as soon as possible with only the messages it currently has buffered. If you care deeply about performance, this can reduce latency by up to 125 microseconds. But it does use the USB bandwidth less efficiently, so only call usbMIDI.send_now() after you've completed a group of messages and you do not expect to send any more immediately.
    Thanks paul, very helpful as always.

    I'm using usbMIDI.send_now(). Ok so if I send three notes every time and I use send now it should always send them in the same package right?

    The timing may be fast but what I'm doing is a special case where phase cancellation will be a problem so it needs to be pretty much instantaneous.

  4. #4
    Senior Member
    Join Date
    Jul 2020
    Posts
    406
    MIDI isn't designed for timing that accurate. You'd expect MIDI latencies to be measured in milliseconds, not microseconds.
    You'd be at the mercy of the receiving software as to what happens, but its entirely plausible a whole packet is processed
    as if simultaneous, and its entirely plausible that it isn't - you'd need to experiment.

  5. #5
    Senior Member
    Join Date
    Jan 2020
    Posts
    129
    Quote Originally Posted by MarkT View Post
    MIDI isn't designed for timing that accurate. You'd expect MIDI latencies to be measured in milliseconds, not microseconds.
    You'd be at the mercy of the receiving software as to what happens, but its entirely plausible a whole packet is processed
    as if simultaneous, and its entirely plausible that it isn't - you'd need to experiment.
    Yeah I'm aware of that and it's not something I can control. All I can do is to try send them at once and cross my fingers that the recieving side will process it as three simultaneous hits.

  6. #6
    Junior Member
    Join Date
    Mar 2017
    Posts
    3
    Hi Paul,

    I'm working on a project that requires sending a large number of midi messages quickly and I just wanted to check something about the information you provide below.

    I've uncommented #define USBHOST_PRINT_DEBUG in USBHost_t36.h and I can see that when I send 64 MIDI messages in quick succession, they are sent as 64 buffers each of which contains a single midi message and 127x4 '00's

    When I check the MIDIDeviceBase::write_packed() function in the midi.cpp file I can see the following:

    Code:
    else {
        // TODO: start a timer, rather than sending the buffer
        // before it's full, to make best use of bandwidth
        tx1_count = tx_max;
        queue_Data_Transfer(txpipe, tx_buffer1, tx_max*4, this);
    }
    I would make a massive difference to my project to be able to send midi messages packed into a single buffer so I'm just wondering if I'm missing something to make this buffer packing work?

    Many thanks in advance,
    Dennis




    Quote Originally Posted by PaulStoffregen View Post
    The simple answer is yes, you can send multiple MIDI messages at once.

    The actual MIDI communication is done at 480 Mbit using a complicated protocol which communicates in packets. A single packet can hold up to 128 MIDI messages, so unless you are transmitting a pretty incredible number of messages very quickly, typically the messages you transmitted at once will all end packed into the same packet. Even though the individual bits are sent 1 at a time, the host controller in your PC receives the entire packet into a memory buffer and verifies its CRC check before passing the data on to any MIDI software. The end result is all the MIDI messages within 1 packet are indeed received at once by the software on your PC. Or at least the operating system & drivers make them all available to the software at the same instant.

    Even if multiple USB packets are used, the timing is incredibly fast relative to the pace of musical events. So even though a large burst MIDI messages spanning multiple USB packets aren't technically received simultaneously, the delay is so short that it's not worth any worry.

    Something you might consider on the Teensy side is the usbMIDI.send_now() function. If you have sent less than 128 messages, this function tells Teensy's USB code not to wait for any more, to transmit a USB packet as soon as possible with only the messages it currently has buffered. If you care deeply about performance, this can reduce latency by up to 125 microseconds. But it does use the USB bandwidth less efficiently, so only call usbMIDI.send_now() after you've completed a group of messages and you do not expect to send any more immediately.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •