RtMidi Documentation

repository·master·Indexed 22 days ago

https://github.com/thestk/rtmidi

A C++ library providing a unified API for real-time MIDI input and output across Linux, macOS, Windows, iOS, and Android. It features core abstractions RtMidiIn for timestamped MIDI input and RtMidiOut for immediate MIDI output, supporting device enumeration and platform abstractions such as ALSA, JACK, CoreMIDI, and UWP. The library can be integrated as a module or used via Go bindings.

Tokens
2K
Snippets
7
Records
10
Agent score
79%

What's inside RtMidi

  1. Overview of RtMidi core classes and functionality

    master

    RtMidi provides a common C++ API for real-time MIDI input and output across multiple platforms (Linux, macOS, Windows, Web MIDI, iOS, and Android).

    Core Abstractions

    • RtMidiIn: Handles MIDI input. Each instance supports a single MIDI connection. Input messages are timestamped with delta times in seconds (as a double) and passed to the user as raw bytes using std::vector<unsigned char>.
    • RtMidiOut: Handles MIDI output. Each instance supports a single MIDI connection. Note that RtMidi does not provide timing functionality; output messages are sent immediately upon calling the API.

    Key Features

    • Object-oriented C++ design.
    • Single header and single source file for easy integration.
    • MIDI device enumeration.
    • Platform abstraction (ALSA/JACK on Linux, CoreMIDI/JACK on macOS, Multimedia Library/UWP on Windows).
  2. How to use RtMidi as a module

    master

    RtMidi can be used as a module. To enable this, build with the RTMIDI_BUILD_MODULES flag.

    When used as a module, you access the API using import rt.midi;. Namespaces are implicitly imported unless RTMIDI_USE_NAMESPACE is defined. You can access classes via the rt::midi namespace or the global namespace (e.g., rt::midi::MidiApi or ::MidiApi).

  3. Build and compile RtMidi test programs

    master

    Unix Systems (Linux/macOS)

    If you have checked out the code from git, first run ./autogen.sh. Then, follow these steps:

    1. Run ./configure in the top-level directory.
    2. Navigate to the tests/ directory.
    3. Run make to compile the test programs.

    Windows

    Open the Visual C++ workspace file located in the tests/ directory.

    # If using git
    ./autogen.sh
    
    # Configure and build tests
    ./configure
    cd tests
    make
  4. Build RtMidi into an Android app

    master

    To integrate RtMidi into an Android application, you must include the following core files from the main RtMidi project into your Android Studio project via symlinks or direct inclusion:

    • RtMidi.cpp
    • RtMidi.h (Note: The source refers to RdMidi.h, which is likely a typo for RtMidi.h)
    • MidiDeviceOpenedListener.java

    The example project demonstrates a basic implementation that:

    1. Lists available MIDI devices.
    2. Opens a selected MIDI port.
    3. Prints incoming MIDI packets to the console.
    # Example Android Studio project 
    
    Simple app using RtMidi. There are symlinks to 3 files in the main RtMidi project
    * RtMidi.cpp
    * RdMidi.h
    * MidiDeviceOpenedListener.java
  5. Windows-specific threading requirements

    master

    When using RtMidi on Windows (for example, when interacting with GS Synth), you may need to initialize and uninitialize the COM library on the thread that uses RtMidi. Call CoInitializeEx when the thread starts and CoUninitialize when the thread exits.

    // On Windows, call these on the thread using RtMidi
    CoInitializeEx(...);
    // ... use RtMidi ...
    CoUninitialize();
  6. Manage MIDI ports and connections

    master

    Both MIDIIn and MIDIOut implement the MIDI interface, which provides common port management functionality:

    • OpenPort(port int, name string): Opens a specific MIDI port by its enumeration index.
    • OpenVirtualPort(name string): Creates a virtual input port (supported on macOS, JACK, and ALSA) to allow software-to-software MIDI connections.
    • PortCount(): Returns the number of available MIDI ports.
    • PortName(port int): Returns the string name of the port at the specified index.
    • Close(): Closes the connection to the port.
    • Destroy(): Frees the underlying RtMidi resources.
  7. Use the MIDIOut interface for MIDI output

    master

    The MIDIOut interface allows you to send MIDI messages to an output port.

    To create an instance:

    • NewMIDIOutDefault(): Creates an instance using the default API.
    • NewMIDIOut(api API, name string): Creates an instance with a specific API and name.

    Key methods:

    • SendMessage([]byte): Immediately sends the provided byte slice over the open MIDI port.
    • API(): Returns the API constant currently being used by this instance.
    // Example: Sending a MIDI message
    out, err := rtmidi.NewMIDIOutDefault()
    if err != nil {
    	panic(err)
    }
    
    // Send a Note On message (example bytes)
    err = out.SendMessage([]byte{0x90, 0x3C, 0x7F})
    if err != nil {
    	panic(err)
    }
  8. Use the MIDIIn interface for MIDI input

    master

    The MIDIIn interface allows you to receive MIDI messages. You can either poll for messages using Message() or set up a real-time callback using SetCallback().

    To create an instance:

    • NewMIDIInDefault(): Creates an instance using the default API.
    • NewMIDIIn(api API, name string, queueSize int): Creates an instance with a specific API, a custom name, and a defined message queue size.

    Key methods:

    • SetCallback(func(MIDIIn, []byte, float64)): Registers a function to be called whenever a MIDI message arrives. The callback receives the MIDIIn instance, the message bytes, and the timestamp as a float64.
    • Message(): Returns the next available MIDI message as []byte and its delta-time as float64. Returns immediately if no message is available.
    • IgnoreTypes(midiSysex bool, midiTime bool, midiSense bool): Configures whether to ignore SysEx, timing, or active sensing messages. Setting a parameter to true means that type will be ignored.
    // Example: Using a callback for MIDI input
    in, err := rtmidi.NewMIDIInDefault()
    if err != nil {
    	panic(err)
    }
    
    err = in.SetCallback(func(m rtmidi.MIDIIn, msg []byte, ts float64) {
    	fmt.Printf("Received message: %v at %f\n", msg, ts)
    })
    
    // Keep the program running to receive messages
    select {}
  9. Get RtMidi version and available APIs

    master

    Use GetVersion() to retrieve the current RtMidi version string. To see which MIDI APIs are currently compiled and available on your system, use CompiledAPI(), which returns a slice of API constants.

    fmt.Println("Version:", rtmidi.GetVersion())
    
    apis := rtmidi.CompiledAPI()
    for _, api := range apis {
    	fmt.Println("Available API:", api.String())
    }
  10. Reference: API enumeration

    master

    The API type represents the underlying MIDI backend being used. Use these constants when calling NewMIDIIn or NewMIDIOut to specify a preferred backend.

    const (
    	APIUnspecified API = C.RTMIDI_API_UNSPECIFIED // Searches for a working compiled API
    	APIMacOSXCore API = C.RTMIDI_API_MACOSX_CORE  // Macintosh OS-X CoreMIDI
    	APILinuxALSA  API = C.RTMIDI_API_LINUX_ALSA   // Advanced Linux Sound Architecture
    	APIUnixJack   API = C.RTMIDI_API_UNIX_JACK    // JACK Low-Latency MIDI Server
    	APIWindowsMM  API = C.RTMIDI_API_WINDOWS_MM   // Microsoft Multimedia MIDI
    	APIDummy      API = C.RTMIDI_API_RTMIDI_DUMMY // Non-functional compilable API
    )