Skip to content

Enlarge Ethernet buffer size to avoid dropping UDP packages

lathoub edited this page Jul 22, 2022 · 9 revisions

Windows

When using AppleMIDI on Windows, the 'Out of the Box' Ethernet Library could potentially drop packages (and therefor MIDI messages), because the rtpMIDI application does not put multiple MIDI message in a single package when send at the same time - rather it sends them 1 by 1 (Unlike on MacOS, where they are packed together). When playing a MIDI-file, the player will often reset effects on all channel before playing the MIDI messages from the file. This reset operation can send more than 100 messages at the same time:

ControlChange 1 123 0
ControlChange 1 121 0
ControlChange 2 123 0
ControlChange 2 121 0
...
ControlChange 16 123 0
ControlChange 16 121 0
PitchBend 1 0
ProgramChange 1 25
ProgramChange 2 25
...

With each packet 58 bytes (for ControlChange) and the total size quickly goes over 2048 bytes.

The Ethernet Library, by default, has a buffer size of 2048 bytes (for W5*00) based Ethernet controllers. https://github.com/arduino-libraries/Ethernet/blob/75a3c37b5e513305b82e926ca6a4f8190f536c9d/src/utility/w5100.cpp#L177

So with that burst of MIDI messages at the start of a song, the allocated buffer is too small and messages will be dropped. This behaviour is not acceptable.

Unfortunately, this buffer size can only be changed by changing the Ethernet code itself (buffer size](https://github.com/arduino-libraries/Ethernet/issues/70)). The issue is with the MAX_SOCK_NUM and ETHERNET_LARGE_BUFFERS MACROS. By default, MAX_SOCK_NUM is set to 4 for W5100 and 8 for W5200 and W5500

https://github.com/arduino-libraries/Ethernet/blob/75a3c37b5e513305b82e926ca6a4f8190f536c9d/src/Ethernet.h#L32-L40

2 options to resolve the issue:

Modify Ethernet Library

/*
// Configure the maximum number of sockets to support.  W5100 chips can have
// up to 4 sockets.  W5200 & W5500 can have up to 8 sockets.  Several bytes
// of RAM are used for each socket.  Reducing the maximum can save RAM, but
// you are limited to fewer simultaneous connections.
#if defined(RAMEND) && defined(RAMSTART) && ((RAMEND - RAMSTART) <= 2048)
#define MAX_SOCK_NUM 4
#else
#define MAX_SOCK_NUM 8
#endif
*/
#define MAX_SOCK_NUM 4

// By default, each socket uses 2K buffers inside the Wiznet chip.  If
// MAX_SOCK_NUM is set to fewer than the chip's maximum, uncommenting
// this will use larger buffers within the Wiznet chip.  Large buffers
// can really help with UDP protocols like Artnet.  In theory larger
// buffers should allow faster TCP over high-latency links, but this
// does not always seem to work in practice (maybe Wiznet bugs?)
#define ETHERNET_LARGE_BUFFERS

It is important to also uncomment ETHERNET_LARGE_BUFFERS By setting MAX_SOCK_NUM to 4 and ETHERNET_LARGE_BUFFERS, a larger buffer is available at the cost of the number of available sockets.

Use the Ethernet3 Library (W5500 only)

The Ethernet3 Library has fixed this issue and lets you set the maxSockets.

Ethernet.init(4); // maxSockNum = 4 Socket 0...3 -> RX/TX Buffer 4k

Logging errors (Windows only)

rtpMIDi allows logging of Errors to a file.

LogErrors

When the logfile is created, it indicates an error occured caused by buffer overruns or SPI transfer issues. Modify Ethernet.h as described here or use Ethernet3 (W5500). If the error persist, consider creating an issue.

[   172768.600] rtpMIDI_1_1_14_247 [ DIAG_ERROR   ]: Controller: We don't understand this command: 6172

Apple

On MacOS, multiple MIDI command are combined in 1 rtpMIDI message, as per the RFC6295 spec. The chance for buffer overruns is less likely, but can still happen.

The above modification is also recommended for MacOS users.


Conclusion

Clone the Ethernet Library or use the newer Ethernet3 library.

See here how this issue was discovered and fixed (thanks to @bjoernbau)