MiniDexed
MiniDexed copied to clipboard
Supporting RTP-MIDI
RTP-MIDI (also known as AppleMIDI) is a protocol to transport MIDI messages within RTP (Real-time Protocol) packets over Ethernet and WiFi networks. It is completely open and free (no license is needed), and is compatible both with LAN and WAN application fields.
I imagine this could be quite useful to, e.g., send sysex from a computer to the Raspberry Pi and to have the Raspberry Pi driven by sequencers on a computer, phone, or tablet, especially since USB gadget mode is not available on Circle (although a Raspberry Pi PIco could probably be used to act as a USB MIDI to serial converter).
The AppleMIDI library contains C++ code for Arduino. It compiles on Arduino, MacOS (XCode) and Windows (MSVS).
I wonder how much effort it would be to port it to Circle.
In case the effort is prohibitive, we might want to use an ESP8266 as a WLAN-RTP-MIDI-to-Serial-MIDI bridge, but using wired Ethernet would be better to reduce latency.
although a Raspberry Pi PIco could probably be used to act as a USB MIDI to serial converter
Guess who has had this idea before! @rsta2: https://github.com/rsta2/pico/tree/main/midi_adapter
If someone wants to try it, I can provide an .uf2 file of midi_adapter for the Pico.
Me! :)
Hello Everyone,
I was able to compile Arduino's MIDI library for aarch64 which is a dependency for AppleMidi (RTP). But after dealing with cmake for 4 hours I gave up linking those two 😓
Any cmake guru to help?
Here is the toolchain configuration for cmake:
set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_PROCESSOR ARM)
set(TOOLCHAIN_PREFIX aarch64-none-elf-)
find_program(BINUTILS_PATH ${TOOLCHAIN_PREFIX}gcc NO_CACHE)
if (NOT BINUTILS_PATH)
message(FATAL_ERROR "ARM GCC toolchain not found")
endif ()
get_filename_component(ARM_TOOLCHAIN_DIR ${BINUTILS_PATH} DIRECTORY)
# Without that flag CMake is not able to pass test compilation check
if (${CMAKE_VERSION} VERSION_EQUAL "3.6.0" OR ${CMAKE_VERSION} VERSION_GREATER "3.6")
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
else ()
set(CMAKE_EXE_LINKER_FLAGS_INIT "--specs=nosys.specs")
endif ()
set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}gcc)
set(CMAKE_ASM_COMPILER ${CMAKE_C_COMPILER})
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}g++)
set(CMAKE_AR ${TOOLCHAIN_PREFIX}gcc-ar)
set(CMAKE_RANLIB ${TOOLCHAIN_PREFIX}gcc-ranlib)
execute_process(COMMAND ${CMAKE_C_COMPILER} -print-sysroot
OUTPUT_VARIABLE ARM_GCC_SYSROOT OUTPUT_STRIP_TRAILING_WHITESPACE)
# Default C compiler flags
set(CMAKE_C_FLAGS_DEBUG_INIT "-g3 -Og -Wall -pedantic -DDEBUG")
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG_INIT}" CACHE STRING "" FORCE)
set(CMAKE_C_FLAGS_RELEASE_INIT "-O3 -Wall")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE_INIT}" CACHE STRING "" FORCE)
set(CMAKE_C_FLAGS_MINSIZEREL_INIT "-Os -Wall")
set(CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS_MINSIZEREL_INIT}" CACHE STRING "" FORCE)
set(CMAKE_C_FLAGS_RELWITHDEBINFO_INIT "-O2 -g -Wall")
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO_INIT}" CACHE STRING "" FORCE)
# Default C++ compiler flags
set(CMAKE_CXX_FLAGS_DEBUG_INIT "-g3 -Og -Wall -pedantic -DDEBUG")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG_INIT}" CACHE STRING "" FORCE)
set(CMAKE_CXX_FLAGS_RELEASE_INIT "-O3 -Wall")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE_INIT}" CACHE STRING "" FORCE)
set(CMAKE_CXX_FLAGS_MINSIZEREL_INIT "-Os -Wall")
set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL_INIT}" CACHE STRING "" FORCE)
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT "-O2 -g -Wall")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT}" CACHE STRING "" FORCE)
set(CMAKE_OBJCOPY ${ARM_TOOLCHAIN_DIR}/${TOOLCHAIN_PREFIX}objcopy CACHE INTERNAL "objcopy tool")
set(CMAKE_SIZE_UTIL ${ARM_TOOLCHAIN_DIR}/${TOOLCHAIN_PREFIX}size CACHE INTERNAL "size tool")
set(CMAKE_SYSROOT ${ARM_GCC_SYSROOT})
set(CMAKE_FIND_ROOT_PATH ${BINUTILS_PATH})
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
Just for the PoC I have created this sketch for ESP8266 and it works great in terms of latency. Next I am going to try SysEx messages from Dexed.
#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <WiFiClient.h>
#include <WiFiUdp.h>
#define SerialMon Serial
#include <AppleMIDI.h>
char ssid[] = ""; // your network SSID (name)
char pass[] = ""; // your network password (use for WPA, or use as key for WEP)
unsigned long t0 = millis();
int8_t isConnected = 0;
APPLEMIDI_CREATE_DEFAULTSESSION_INSTANCE();
MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, MIDI2);
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
void setup()
{
Serial1.begin(31250);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, pass);
// Set up mDNS responder:
if (!MDNS.begin(AppleMIDI.getName()))
MDNS.addService("apple-midi", "udp", AppleMIDI.getPort());
MIDI.begin();
MIDI.turnThruOff();
MIDI2.begin(MIDI_CHANNEL_OMNI);
MIDI2.turnThruOff();
AppleMIDI.setHandleConnected([](const APPLEMIDI_NAMESPACE::ssrc_t & ssrc, const char* name) {
isConnected++;
});
AppleMIDI.setHandleDisconnected([](const APPLEMIDI_NAMESPACE::ssrc_t & ssrc) {
isConnected--;
});
MIDI.setHandleNoteOn([](byte channel, byte note, byte velocity) {
});
MIDI.setHandleNoteOff([](byte channel, byte note, byte velocity) {
});
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
void loop()
{
MDNS.update();
// Listen to incoming notes
if (MIDI.read()){
MIDI2.send(MIDI.getType(), MIDI.getData1(), MIDI.getData2(), MIDI.getChannel());
}
}
Okay confirmed with HDMI and Sysex arrives at MiniDexed from synthmata but voices are not changing
Also no message emitted to HDMI from here: https://github.com/probonopd/MiniDexed/blob/2024-01-16/src/mididevice.cpp#L395
Also WiFi support from does not work for my Pi3 A+, image boots up then after USB initialization, it freezes. circle-stdlib @ 61cf3a4
I'd love to see this implemented.
Oh nice, did not realise that everything packaged nicely with mt32 and License allow me to copy it. Let me try porting it.
@omersiar let us know how it goes - I think many people would appreciate RTP-MIDI.
Wireless connection with my RPi3 A+ is working, also the RTP socket is created but could not able to override the function that passes MIDI data.
https://github.com/rsta2/circle/discussions/493
Okay everything is now working on RPi 3A+, the FTP functionality is nice actually, one can also send the kernel images. Apart from RTP new UDP receiver should also work, which can enable some SysEx utility to send configuration to it.
rtpMIDI software reports 3-4ms latency for my setup which is a 5Ghz Wi-Fi network
PoC code is here -> https://github.com/omersiar/MiniDexed/tree/network