unixdev.net


Switch to SpeakEasy.net DSL

The Modular Manual Browser

Home Page
Manual: (OpenBSD-5.7)
Page:
Section:
Apropos / Subsearch:
optional field

MIDI(4)                  BSD Kernel Interfaces Manual                  MIDI(4)

NAME
     midi -- raw device independent interface to MIDI ports

SYNOPSIS
     midi* at autri?
     midi* at eap?
     midi* at envy?
     midi* at mpu?
     midi* at sb?
     midi* at umidi?
     midi* at ym?

DESCRIPTION
     The midi driver makes MIDI ports available to user applications.  A midi
     device corresponds to 2 MIDI ports: one input port and one output port.
     Data received on the input port is not interpreted and is passed to the
     user program as-is.  Similarly, data issued by the user program is sent
     as-is to the output port.

     Only one process may hold open a midi device at a given time, although
     file descriptors may be shared between processes once the first open com-
     pletes.  If it is opened read-only (write-only) only the input (output)
     MIDI port is available.

   Writing to the device
     A process can send raw MIDI data to the output port by using the write(2)
     system call.  Data is queued and the system call returns immediately; the
     data is sent as fast as possible to the output MIDI port.  However, if
     the in-kernel buffer is full or the requested amount is too large, then
     write(2) may block.  The current size of the in-kernel buffer is 1024
     bytes, which ensures that write(2) isn't blocking in most situations.

   Reading from the device
     Data received from the input MIDI port is stored into the in-kernel buf-
     fer.  A process can retrieve its contents by using the read(2) system
     call.  If there is less data than the amount requested for reading, then
     a shorter amount is returned.  If no data is available, then the read(2)
     system call will block until data is received, and then return immedi-
     ately.

     The MIDI protocol has been designed for real-time performance and doesn't
     support flow control.  An application must be able to read the incoming
     data fast enough (the MIDI standard's maximum rate is 3125 bytes per sec-
     ond).  The kernel can buffer up to 1024 bytes; once the buffer is full
     input will be silently discarded.

   Polling the device
     A process can use the poll(2) system call to poll for the following
     events:

     POLLIN   The in-kernel input buffer isn't empty, i.e. at least one byte
              is available for reading.  A subsequent call to read(2) will not
              be blocking.

     POLLOUT  The in-kernel output buffer is empty, thus a subsequent call to
              write(2) will not be blocking if a reasonable amount of data is
              written (currently less that 1024 bytes).

     Using the poll(2) system call is the recommended way to handle multiple
     midi devices in a real-time MIDI application.

   Non-blocking I/O
     If the midi device is opened with the O_NONBLOCK flag (see open(2)), then
     subsequent calls to read(2) or write(2) will never block.  The write(2)
     system call may write less bytes than requested, or may return EAGAIN if
     no data could be sent or queued.  Similarly, the read(2) system call may
     return EAGAIN if no input is available.

     Note that even if non-blocking I/O is not selected, read(2) and write(2)
     system calls are non-blocking when the kernel buffers permit it.

FILES
     /dev/rmidi*  midi devices

EXAMPLES
     The following command could record the memory dump of a synthesizer in a
     file:

           $ cat -u /dev/rmidi2 >dumpfile

     A MIDI keyboard could be connected to a synthesizer by the command:

           $ cat -u /dev/rmidi1 >/dev/rmidi2

     The input port could be connected to the output port by the command:

           $ cat -u <>/dev/rmidi1 >&0

     The following example reads MIDI timing events from an input device, MIDI
     common and voice events from another input device, and sends the result
     to a third (output) device.

           #define BUFSIZE         0x100
           #define ISTIMING(c)     ((c) == 0xf8 || (c) == 0xfa || (c) == 0xfc)
           #define ISCOMMON(c)     ((c) < 0xf8)

           int ofd;
           struct pollfd ifd[2];
           unsigned char ibuf[BUFSIZE], obuf[2 * BUFSIZE];
           ssize_t iused, oused, i;

           ifd[0].events = ifd[1].events = POLLIN;
           for (;;) {
                   oused = 0;
                   if (poll(ifd, 2, -1) == -1)
                           errx(1, "poll");
                   if (ifd[0].revents & POLLIN) {
                           if ((iused = read(ifd[0].fd, ibuf, BUFSIZE)) == -1)
                                   errx(1, "read");
                           for (i = 0; i < iused; i++)
                                   if (ISTIMING(ibuf[i]))
                                           obuf[oused++] = ibuf[i];
                   }
                   if (ifd[1].revents & POLLIN) {
                           if ((iused = read(ifd[1].fd, ibuf, BUFSIZE)) == -1)
                                   errx(1, "read");
                           for (i = 0; i < iused; i++)
                                   if (ISCOMMON(ibuf[i]))
                                           obuf[oused++] = ibuf[i];
                   }
                   if (write(ofd, obuf, oused) == -1)
                           errx(1, "write");
           }

     In the above example, unless kernel buffers are full, processing is done
     in real-time without any noticeable latency; as expected, the only block-
     ing system call is poll(2).

ERRORS
     If open(2), read(2), write(2), or poll(2) fail then errno(2) may be set
     to one of:

     [ENXIO]            The device is opened read-only (write-only) but
                        write(2) (read(2)) was called.

     [EIO]              The device is being detached while a process has been
                        trying to read or write (for instance an umidi(4)
                        device has been unplugged).

     [EAGAIN]           Non-blocking I/O was selected and the output buffer is
                        full (on writing) or the input buffer is empty (on
                        reading).

     [EBUSY]            The device is already open by another process.

SEE ALSO
     autri(4), eap(4), envy(4), mpu(4), sb(4), umidi(4), ym(4)

HISTORY
     The midi driver first appeared in OpenBSD 2.5.

AUTHORS
     The midi driver was originally written by Lennart Augustsson and later
     largely rewritten by Alexandre Ratchov.

CAVEATS
     MIDI hardware was designed for real time performance and software using
     such hardware must be able to process MIDI events without any noticeable
     latency (typically no more than 5ms, which is the time it takes for sound
     to propagate 1.75 meters).

     The OpenBSD midi driver processes data fast enough, however if a MIDI
     application tries to write data faster than the hardware is able to
     process it (typically 3125 bytes per second), then kernel buffers may
     become full and the application may be blocked.

     The other common reason for MIDI data being delayed is the system load.
     Processes cannot be preempted while running in kernel mode.  If there are
     too much processes running concurrently (especially if they are running a
     lot of expensive system calls) then the scheduling of a real-time MIDI
     application may be delayed.  Even on low-end machines this delay hardly
     reaches a few milliseconds provided that the system load is reasonable.

     A real-time MIDI application can avoid being swapped by locking its mem-
     ory (see mlock(2) and mlockall(2)).

BUGS
     For a given device, even if the physical MIDI input and output ports are
     independent, there is no way for one process to use the input MIDI port
     and for another process to use the output MIDI port at the same time.

BSD                             April 30, 2017                             BSD