778 lines
22 KiB
Groff
778 lines
22 KiB
Groff
.\" $NetBSD: midi.4,v 1.27 2006/07/02 01:34:33 wiz Exp $
|
|
.\"
|
|
.\" Copyright (c) 1999-2006 The NetBSD Foundation, Inc.
|
|
.\" All rights reserved.
|
|
.\"
|
|
.\" This code is derived from software contributed to The NetBSD Foundation
|
|
.\" by Lennart Augustsson and Chapman Flack.
|
|
.\"
|
|
.\" Redistribution and use in source and binary forms, with or without
|
|
.\" modification, are permitted provided that the following conditions
|
|
.\" are met:
|
|
.\" 1. Redistributions of source code must retain the above copyright
|
|
.\" notice, this list of conditions and the following disclaimer.
|
|
.\" 2. Redistributions in binary form must reproduce the above copyright
|
|
.\" notice, this list of conditions and the following disclaimer in the
|
|
.\" documentation and/or other materials provided with the distribution.
|
|
.\" 3. All advertising materials mentioning features or use of this software
|
|
.\" must display the following acknowledgement:
|
|
.\" This product includes software developed by the NetBSD
|
|
.\" Foundation, Inc. and its contributors.
|
|
.\" 4. Neither the name of The NetBSD Foundation nor the names of its
|
|
.\" contributors may be used to endorse or promote products derived
|
|
.\" from this software without specific prior written permission.
|
|
.\"
|
|
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
|
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
|
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
.\" POSSIBILITY OF SUCH DAMAGE.
|
|
.\"
|
|
.Dd May 6, 2006
|
|
.Dt MIDI 4
|
|
.Os
|
|
.Sh NAME
|
|
.Nm midi
|
|
.Nd device-independent MIDI driver layer
|
|
.Sh SYNOPSIS
|
|
.Cd "midi* at midibus?"
|
|
.Cd "midi* at pcppi?"
|
|
.Cd "pseudo-device sequencer"
|
|
.Pp
|
|
.In sys/types.h
|
|
.In sys/midiio.h
|
|
.Sh DESCRIPTION
|
|
The
|
|
.Nm
|
|
driver is the machine independent layer over anything that can
|
|
source or sink a
|
|
.Tn MIDI
|
|
data stream, whether a physical
|
|
.Tn "MIDI IN"
|
|
or
|
|
.Tn "MIDI OUT"
|
|
jack on a soundcard, cabled to some external synthesizer or input controller,
|
|
an on-board programmable tone generator, or a single jack, synthesizer, or
|
|
controller component within a complex
|
|
.Tn USB
|
|
or
|
|
.Tn IEEE1394
|
|
.Tn MIDI
|
|
device that has several
|
|
such components and appears as several
|
|
.Tn MIDI
|
|
streams.
|
|
.Ss Concepts
|
|
One
|
|
.Tn MIDI
|
|
data stream is a unidirectional stream of
|
|
.Tn MIDI
|
|
messages, as could be carried over one
|
|
.Tn MIDI
|
|
cable in the
|
|
.Tn "MIDI 1.0"
|
|
specification.
|
|
Many
|
|
.Tn MIDI
|
|
messages
|
|
carry a four-bit channel number, creating up to 16
|
|
.Tn MIDI
|
|
channels within a single
|
|
.Tn MIDI
|
|
stream.
|
|
There may be multiple consumers of a
|
|
.Tn MIDI
|
|
stream, each configured
|
|
to react only to messages on specific channels; the sets of channels different
|
|
consumers react to need not be disjoint.
|
|
Many modern devices such as multitimbral keyboards and tone generators
|
|
listen on all 16 channels, or may be viewed as collections of 16
|
|
independent consumers each listening on one channel.
|
|
.Tn MIDI
|
|
defines some messages that take no channel number, and
|
|
apply to all consumers of the
|
|
stream on which they are sent.
|
|
For an inbound stream,
|
|
.Nm
|
|
is a promiscuous
|
|
receiver, capturing all messages regardless of channel number.
|
|
For an outbound stream, the writer can specify a channel number
|
|
per message; there is no notion of binding the stream to one
|
|
destination channel in advance.
|
|
.Pp
|
|
A single
|
|
.Nm
|
|
device instance is the endpoint of one outbound stream, one
|
|
inbound stream, or one of each.
|
|
In the third case, the write and read sides are independent
|
|
.Tn MIDI
|
|
streams.
|
|
For example, a soundcard driver may map its
|
|
.Tn "MIDI OUT"
|
|
and
|
|
.Tn "MIDI IN"
|
|
jacks to the write and read sides of a single device instance, but
|
|
those jacks can be cabled to completely different pieces of gear.
|
|
Information from
|
|
.Xr dmesg 8 ,
|
|
and a diagram of any external
|
|
.Tn MIDI
|
|
cabling, will help clarify the mapping.
|
|
.Ss "Underlying drivers and MIDI protocol"
|
|
Drivers
|
|
.Nm
|
|
can attach include soundcard drivers, many of
|
|
which support a
|
|
.Tn UART
|
|
resembling Roland's
|
|
.Tn MPU401
|
|
and handled by
|
|
.Xr mpu 4 ,
|
|
.Tn "USB MIDI"
|
|
devices via
|
|
.Xr umidi 4 ,
|
|
and on-board devices that can make sounds,
|
|
whether a lowly
|
|
.Tn PC
|
|
speaker or a Yamaha
|
|
.Tn OPL .
|
|
Serial port and
|
|
.Tn IEEE1394
|
|
connections are currently science fiction.
|
|
.Pp
|
|
The
|
|
.Tn MIDI
|
|
protocol permits some forms of message compression such as running
|
|
status and hidden note-off.
|
|
Received messages on inbound streams are always canonicalized by
|
|
.Nm
|
|
before presentation to higher layers.
|
|
Messages for transmission are accepted by
|
|
.Nm
|
|
in any valid form.
|
|
.Ss "Device access"
|
|
Access to
|
|
.Nm
|
|
device instances can be through the raw device nodes,
|
|
.Pa /dev/rmidiN ,
|
|
or through the sequencer,
|
|
.Pa /dev/music .
|
|
.Ss "Raw MIDI access"
|
|
A
|
|
.Pa /dev/rmidiN
|
|
device supports
|
|
.Xr read 2 ,
|
|
.Xr write 2 ,
|
|
.Xr ioctl 2 ,
|
|
.Xr select 2 Ns / Ns
|
|
.Xr poll 2
|
|
and the corresponding
|
|
.Xr kevent 2
|
|
filters,
|
|
and may be opened
|
|
only when it is not already open.
|
|
It may be opened in
|
|
.Dv O_RDONLY ,
|
|
.Dv O_WRONLY ,
|
|
or
|
|
.Dv O_RDWR
|
|
mode, but a later
|
|
.Xr read 2
|
|
or
|
|
.Xr write 2
|
|
will return \-1 if the device has no associated
|
|
input or output stream, respectively.
|
|
.Pp
|
|
Bytes written are passed as quickly as possible to the underlying driver
|
|
as complete
|
|
.Tn MIDI
|
|
messages; a maximum of two bytes at the end of a
|
|
.Xr write 2
|
|
may remain buffered if they do not complete a message, until
|
|
completed by a following
|
|
.Xr write 2 .
|
|
.Pp
|
|
A
|
|
.Xr read 2
|
|
will not block or return
|
|
.Er EWOULDBLOCK
|
|
when it could immediately return any nonzero count, and
|
|
.Tn MIDI
|
|
messages received are available to
|
|
.Xr read 2
|
|
as soon as they are complete,
|
|
with a maximum of two received bytes remaining buffered if they do not
|
|
complete a message.
|
|
.Pp
|
|
As all
|
|
.Tn MIDI
|
|
messages are three bytes or fewer except for System Exclusive,
|
|
which can have arbitrary length, these rules imply that System Exclusive
|
|
messages are the only ones of which some bytes can be delivered before
|
|
all are available.
|
|
.Pp
|
|
System Realtime messages are passed with minimum delay in either direction,
|
|
ahead of any possible buffered incomplete message.
|
|
As a result, they will never interrupt any
|
|
.Tn MIDI
|
|
message except possibly System Exclusive.
|
|
.Pp
|
|
A
|
|
.Xr read 2
|
|
with a buffer large enough to accommodate the first complete
|
|
message available will be satisfied with as many complete messages as
|
|
will fit.
|
|
A buffer too small for the first complete
|
|
message will be filled to capacity.
|
|
Therefore, an application that reads from an
|
|
.Pa rmidi
|
|
device with buffers of three bytes or larger need never parse
|
|
across read boundaries to assemble a received message, except possibly in
|
|
the case of a System Exclusive message.
|
|
However, if the application reads through a buffering layer such as
|
|
.Xr fread 3 ,
|
|
this property will not be preserved.
|
|
.Pp
|
|
The
|
|
.Nm
|
|
driver itself supports the
|
|
.Xr ioctl 2
|
|
operations
|
|
.Dv FIOASYNC ,
|
|
.Dv FIONBIO ,
|
|
and
|
|
.Dv FIONREAD .
|
|
Underlying devices may support others.
|
|
The value returned for
|
|
.Dv FIONREAD
|
|
reflects the size in bytes of complete messages
|
|
(or System Exclusive chunks) ready to read.
|
|
If the
|
|
.Xr ioctl 2
|
|
returns
|
|
.Va n
|
|
and a
|
|
.Xr read 2
|
|
of size
|
|
.Va n
|
|
is issued,
|
|
.Va n
|
|
bytes will be read, but if a
|
|
.Xr read 2
|
|
of
|
|
size
|
|
.Va m
|
|
\*[Lt]
|
|
.Va n
|
|
is issued, fewer than
|
|
.Va m
|
|
bytes may be read if
|
|
.Va m
|
|
does not fall
|
|
on a message/chunk boundary.
|
|
.Pp
|
|
Raw
|
|
.Tn MIDI
|
|
access can be used to receive bulk dumps from synthesizers, download
|
|
bulk data to them, and so on.
|
|
Simple patching of one device to another can be
|
|
done at the command line, as with
|
|
.Dl $ cat -u 0\*[Lt]\*[Gt]/dev/rmidi0 1\*[Gt]\*[Am]0
|
|
which will loop all messages received on the input stream of
|
|
.Pa rmidi0
|
|
input stream back to its output
|
|
stream in real time.
|
|
However, an attempt to record and play back music with
|
|
.Dl $ cat /dev/rmidiN \*[Gt]foo; cat foo \*[Gt]/dev/rmidiN
|
|
will be disappointing.
|
|
The file
|
|
.Pa foo
|
|
will contain all of the notes that were played, but because
|
|
.Tn MIDI
|
|
messages carry
|
|
no explicit timing, the
|
|
.Sq "playback"
|
|
will reproduce them all at once, as fast as
|
|
they can be transmitted.
|
|
To preserve timing information, the sequencer device can be used.
|
|
.Ss "Active Sensing"
|
|
The
|
|
.Tn MIDI
|
|
protocol includes a keepalive function called Active Sensing.
|
|
In any receiver that has
|
|
.Em not
|
|
received at least one Active Sense
|
|
.Tn MIDI
|
|
message, the
|
|
feature is suppressed and no timeout applies.
|
|
If at least one such message has
|
|
been received, the lapse of any subsequent 300 ms interval without receipt of
|
|
any message reflects loss of communication, and the receiver should silence any
|
|
currently sounding notes and return to non-Active-Sensing behavior.
|
|
A sender using Active Sensing generally avoids 300 ms gaps in
|
|
transmission by sending Active Sense messages (which have no other
|
|
effect) as needed when there is no other traffic to send in the
|
|
interval.
|
|
This feature can be important for
|
|
.Tn MIDI ,
|
|
which relies on separate Note On and Note Off messages, to avoid notes stuck on
|
|
indefinitely if communication is interrupted before a Note Off
|
|
message arrives.
|
|
.Pp
|
|
This protocol is supported in
|
|
.Nm .
|
|
An outbound stream will be kept alive
|
|
by sending Active Sense messages as needed, beginning after any real
|
|
traffic is sent on the stream, and continuing until the stream is closed.
|
|
On an inbound stream, if any Active Sense has been received, then a process
|
|
reading an
|
|
.Pa rmidi
|
|
device will see an end-of-file indication if the input timeout elapses.
|
|
The stream remains open, the driver reverts to enforcing no timeout, and the
|
|
process may continue to read for more input.
|
|
Subsequent receipt of an
|
|
Active Sense message will re-arm the timeout.
|
|
As received Active Sense messages are handled by
|
|
.Nm ,
|
|
they are not included among messages read from the
|
|
.Pa /dev/rmidiN
|
|
device.
|
|
.Pp
|
|
These rules support end-to-end Active Sensing behavior in simple cases
|
|
without special action in an application.
|
|
For example, in
|
|
.Dl $ cat -u /dev/rmidi0 \*[Gt]/dev/rmidi1
|
|
if the input stream to
|
|
.Pa rmidi0
|
|
is lost, the
|
|
.Xr cat 1
|
|
command exits; on the
|
|
.Xr close 2
|
|
of
|
|
.Pa rmidi1 ,
|
|
.Nm
|
|
ceases to send Active Sense messages, and the receiving
|
|
device will detect the loss and silence any outstanding notes.
|
|
.Ss "Access through the sequencer"
|
|
To play music using the raw
|
|
.Tn MIDI
|
|
.Tn API
|
|
would require an application to
|
|
issue many small writes with very precise timing.
|
|
The sequencer device,
|
|
.Pa /dev/music ,
|
|
can manage the timing of
|
|
.Tn MIDI
|
|
data in the kernel, to avoid
|
|
such demanding real-time constraints on a user process.
|
|
.Pp
|
|
The
|
|
.Pa /dev/music
|
|
device can be opened only when it is not already open.
|
|
When opened, the sequencer internally opens all
|
|
.Tn MIDI
|
|
instances existing
|
|
in the system that are not already open at their raw nodes; any attempts
|
|
to open them at their raw nodes while the sequencer is open will fail.
|
|
All access to the corresponding
|
|
.Tn MIDI
|
|
streams will then be through the
|
|
sequencer.
|
|
.Pp
|
|
Reads and writes of
|
|
.Pa /dev/music
|
|
pass eight-byte event structures defined in
|
|
.Aq Pa sys/midiio.h
|
|
(which see for their documentation and examples of use).
|
|
Some events correspond to
|
|
.Tn MIDI
|
|
messages, and carry an integer
|
|
.Va device
|
|
field to identify one of the
|
|
.Tn MIDI
|
|
devices opened by the sequencer.
|
|
Other events carry timing information interpreted or generated by the
|
|
sequencer itself.
|
|
.Pp
|
|
A message received on an input stream is wrapped in a sequencer event
|
|
along with the device index of the stream it arrived on, and queued for
|
|
the reader of
|
|
.Pa /dev/music .
|
|
If a measurable time interval passed since the
|
|
last preceding message, a timing event that represents a delay for that interval
|
|
is queued ahead of the received event.
|
|
The sequencer handles output events by
|
|
interpreting any timing event, and routing any
|
|
.Tn MIDI
|
|
message event at the proper time to
|
|
an underlying output stream according to its
|
|
.Va device
|
|
index.
|
|
Therefore
|
|
.Dl $ cat /dev/music \*[Gt]foo; cat foo \*[Gt]/dev/music
|
|
can be expected to capture and reproduce an input performance including
|
|
timing.
|
|
.Pp
|
|
The process of playing back a complex
|
|
.Tn MIDI
|
|
file is illustrated below.
|
|
The file may contain several tracks\(emfour, in this example\(emof
|
|
.Tn MIDI
|
|
events, each marked with a device index and a time stamp, that may
|
|
overlap in time.
|
|
In the example,
|
|
.Va a ,
|
|
.Va b ,
|
|
and
|
|
.Va c
|
|
are device indices of
|
|
the three output
|
|
.Tn MIDI
|
|
streams; the left-hand digit in each input event represents a
|
|
.Tn MIDI
|
|
channel on the selected stream, and the right-hand digit represents
|
|
a time for the event's occurrence.
|
|
As illustrated, the input tracks are not firmly associated with
|
|
output streams; any track may contain events for any stream.
|
|
.Bd -literal
|
|
| | a2|4 |
|
|
a0|3 | c1|3 c0|3
|
|
| b0|2 b1|2 |
|
|
| b1|1 | c0|1
|
|
a0|0 | b0|0 |
|
|
v v v v
|
|
+---------------------------+
|
|
| merge to 1 ordered stream |
|
|
| user code, eg midiplay(1) |
|
|
+---------------------------+
|
|
b1|2
|
|
b0|2
|
|
c0|1
|
|
b1|1
|
|
b0|0
|
|
a0|0
|
|
v
|
|
_______+-------------+_______user
|
|
| /dev/music | kernel
|
|
| (sequencer) |
|
|
+-------------+
|
|
| 1 0
|
|
+-----' | '-----.
|
|
0 0 |
|
|
v v v
|
|
+-------+ +--------+ +---------+
|
|
|midi(4)| |midi(4) | |midi(4) |
|
|
|rmidia | |rmidib | |rmidic |
|
|
+-------+ +--------+ +---------+
|
|
| mpu(4)| |umidi(4)| |midisyn |
|
|
+-------+ +--------+ +---------+
|
|
| HW | | | opl(4) |
|
|
| MIDI | U +---------+
|
|
| UART | S | internal|
|
|
+-------+ B | tone |
|
|
| | |generator|
|
|
v | +---------+
|
|
external v
|
|
MIDI device external
|
|
MIDI device
|
|
.Ed
|
|
.Pp
|
|
A user process must merge the tracks into a single stream of sequencer
|
|
.Tn MIDI
|
|
and timing events in order by desired timing.
|
|
The sequencer obeys the timing events and distributes the
|
|
.Tn MIDI
|
|
events to the three destinations,
|
|
in this case two external devices connected to a sound card
|
|
.Tn UART
|
|
and a
|
|
.Tn USB
|
|
interface, and an
|
|
.Tn OPL
|
|
tone generator on a sound card.
|
|
.Sh NOTES
|
|
Use of
|
|
.Xr select 2 Ns / Ns
|
|
.Xr poll 2
|
|
with the sequencer is supported, however, there is no guarantee that a
|
|
.Xr write 2
|
|
will not block or return
|
|
.Er EWOULDBLOCK
|
|
if it begins with a timer-wait event, even if
|
|
.Xr select 2 Ns / Ns
|
|
.Xr poll 2
|
|
reported the sequencer writable.
|
|
.Pp
|
|
The delivery of a realtime message ahead of buffered bytes of an incomplete
|
|
message may cause the realtime message to seem, in a saved byte stream, to have
|
|
arrived up to 640 us earlier than it really did, at
|
|
.Tn MIDI
|
|
1.0 data rates.
|
|
Higher data rates make the effect less significant.
|
|
.Pp
|
|
Another sequencer device,
|
|
.Pa /dev/sequencer ,
|
|
is provided only for backward
|
|
compatibility with an obsolete
|
|
.Tn OSS
|
|
interface in which some sequencer events
|
|
were four-byte records.
|
|
It is not further documented here, and the
|
|
.Pa /dev/music
|
|
.Tn API
|
|
should be used in new code.
|
|
The
|
|
.Pa /dev/sequencer
|
|
emulation is implemented only for writing, and that might not be complete.
|
|
.Sh IMPLEMENTATION NOTES
|
|
Some hardware devices supporting
|
|
.Nm
|
|
lack transmit-ready interrupts, and some have the capability in
|
|
hardware but currently lack driver support.
|
|
They can be recognized by the annotation
|
|
.Li "(CPU-intensive output)"
|
|
in
|
|
.Xr dmesg 8 .
|
|
While suitable for music playback, they may have an objectionable impact on
|
|
system responsiveness during bulk transmission such as patch downloads, and
|
|
are best avoided for that purpose if other suitable devices are present.
|
|
.Pp
|
|
Buffer space in
|
|
.Nm
|
|
itself is adequate for about 200 ms of traffic at
|
|
.Tn "MIDI 1.0"
|
|
data rates, per stream.
|
|
.Pp
|
|
Event counters record bytes and messages discarded because of protocol
|
|
errors or buffer overruns, and can be viewed with
|
|
.Li "vmstat -e" .
|
|
They can be useful in diagnosing flaky cables and other communication
|
|
problems.
|
|
.Pp
|
|
.\" These two paragraphs really belong not here but in a midi(9) man page,
|
|
.\" which should one day exist.
|
|
A raw sound generator uses the
|
|
.Sy midisyn
|
|
layer to present a
|
|
.Tn MIDI
|
|
message-driven interface attachable by
|
|
.Nm .
|
|
.Pp
|
|
While
|
|
.Nm
|
|
accepts messages for transmission in any valid mixture of compressed
|
|
or canonical form, they are always presented to an underlying driver
|
|
in the form it prefers.
|
|
Drivers for simple
|
|
.Tn UART Ns -like
|
|
devices
|
|
register their preference for a compressed byte stream, while those like
|
|
.Xr umidi 4 ,
|
|
which uses a packet protocol, or
|
|
.Sy midisyn ,
|
|
which interprets complete
|
|
messages, register for intact canonical messages.
|
|
This design eliminates the
|
|
need for compression and canonicalization logic from all layers above and below
|
|
.Nm
|
|
itself.
|
|
.Sh FILES
|
|
.Bl -tag -width /dev/sequencer -compact
|
|
.It Pa /dev/rmidiN
|
|
.It Pa /dev/music
|
|
.It Pa /dev/sequencer
|
|
.El
|
|
.Sh ERRORS
|
|
In addition to other errors documented for the
|
|
.Xr write 2
|
|
family of system calls,
|
|
.Er EPROTO
|
|
can be returned if the bytes to be written on a raw
|
|
.Nm
|
|
device would violate
|
|
.Tn MIDI
|
|
protocol.
|
|
.Sh SEE ALSO
|
|
.Xr midiplay 1 ,
|
|
.Xr ioctl 2 ,
|
|
.Xr ossaudio 3 ,
|
|
.Xr audio 4 ,
|
|
.Xr mpu 4 ,
|
|
.Xr opl 4 ,
|
|
.Xr umidi 4
|
|
.br
|
|
For ports using the ISA bus:
|
|
.Xr cms 4 ,
|
|
.Xr pcppi 4 ,
|
|
.Xr sb 4
|
|
.br
|
|
For ports using the PCI bus:
|
|
.Xr autri 4 ,
|
|
.Xr clcs 4 ,
|
|
.Xr eap 4
|
|
.Sh HISTORY
|
|
The
|
|
.Nm
|
|
driver first appeared in
|
|
.Nx 1.4 .
|
|
It was overhauled and this manual page rewritten for
|
|
.Nx 4.0 .
|
|
.Sh BUGS
|
|
Some
|
|
.Tn OSS
|
|
sequencer events and
|
|
.Xr ioctl 2
|
|
operations are unimplemented, as
|
|
.Aq Pa sys/midiio.h
|
|
notes.
|
|
.Pp
|
|
.Tn OSS
|
|
source-compatible sequencer macros should be added to
|
|
.Aq Pa sys/soundcard.h ,
|
|
implemented with the
|
|
.Nx
|
|
ones in
|
|
.Aq Pa sys/midiio.h ,
|
|
so sources written for OSS can be easily compiled.
|
|
.Pp
|
|
The sequencer blocks (or returns
|
|
.Er EWOULDBLOCK )
|
|
only when its buffer physically fills, which can represent an arbitrary
|
|
latency because of buffered timing events.
|
|
As a result, interrupting a process writing the sequencer may not
|
|
interrupt music playback for a considerable time.
|
|
The sequencer could enforce a reasonable latency bound
|
|
by examining timing events as they are enqueued and blocking appropriately.
|
|
.Pp
|
|
.Dv FIOASYNC
|
|
enables signal delivery to the calling process only;
|
|
.Dv FIOSETOWN
|
|
is not supported.
|
|
.Pp
|
|
The sequencer can only be a timing master, but does not send timing messages
|
|
to synchronize any slave device; it cannot be slaved to timing messages
|
|
received on any interface (which would presumably require a PLL algorithm
|
|
similar to NTP's, and expertise in that area to implement it).
|
|
The sequencer ignores timing messages received on any interface
|
|
and does not pass them along to the reading process, and the OSS
|
|
operations to change that behavior are unimplemented.
|
|
.Pp
|
|
The
|
|
.Dv SEQUENCER_TMR_TIMEBASE
|
|
.Xr ioctl 2
|
|
will report successfully setting any
|
|
timebase up to ridiculously high resolutions, though the actual
|
|
resolution, and therefore jitter, is constrained by
|
|
.Xr hz 9 .
|
|
Comparable sequencer implementations typically allow a selection from available
|
|
sources of time interrupts that may be programmable.
|
|
.Pp
|
|
The device number in a sequencer event is treated on
|
|
.Xr write 2
|
|
as index into
|
|
the array of
|
|
.Tn MIDI
|
|
devices the sequencer has opened, but on
|
|
.Xr read 2
|
|
as the
|
|
unit number of the source
|
|
.Tn MIDI
|
|
device; these are usually the same if the
|
|
sequencer has opened all the
|
|
.Tn MIDI
|
|
devices (that is, none was already open
|
|
at its raw node when the sequencer was opened), but might not be the same
|
|
otherwise.
|
|
.Pp
|
|
There is at present no way to make reception nonpromiscuous,
|
|
should anyone have a reason to want to.
|
|
.Pp
|
|
There should be ways to override default Active Sense behavior.
|
|
As one obvious
|
|
case, if an application is seen to send Active Sense explicitly,
|
|
.Nm
|
|
should refrain
|
|
from adding its own.
|
|
On receive, there should be an option to pass Active Sense through
|
|
rather than interpreting it, for apps that wish to handle or ignore it
|
|
themselves and never see
|
|
.Dv EOF .
|
|
.Pp
|
|
When a
|
|
.Nm
|
|
stream is open by the sequencer, Active Sense messages received on the stream
|
|
are passed to the sequencer and not interpreted by
|
|
.Nm .
|
|
The sequencer at present neither does anything itself with Active Sense
|
|
messages received, nor supports the
|
|
.Tn OSS
|
|
.Tn API
|
|
for making them available to the user process.
|
|
.Pp
|
|
System Exclusive messages can be received by reading a raw device, but
|
|
not by reading the sequencer; they are discarded on receipt when the
|
|
stream is open by the sequencer, rather than being presented as the
|
|
OSS-defined sequencer events.
|
|
.Pp
|
|
.Sy midisyn
|
|
is too rudimentary at present to get satisfactory results from any
|
|
onboard synth.
|
|
It lacks the required special interpretation of the
|
|
General
|
|
.Tn MIDI
|
|
percussion channel in GM mode.
|
|
More devices should be supported; some sound cards with synthesis
|
|
capability have
|
|
.Nx
|
|
drivers that implement the
|
|
.Xr audio 4
|
|
but not the
|
|
.Sy midisyn
|
|
interface.
|
|
Voice stealing algorithm does not follow the General
|
|
.Tn MIDI
|
|
Developer Guidelines.
|
|
.Pp
|
|
.Tn ALSA
|
|
sequencer compatibility is lacking, but becoming important to applications.
|
|
It would require the function of merging multiple tracks into a single ordered
|
|
stream to be moved from user space into the sequencer.
|
|
Assuming the sequencer driven by periodic interrupts, timing wheels
|
|
could be used as in
|
|
.Xr hardclock 9
|
|
itself.
|
|
Similar functionality will be in OSS4; with the right infrastructure
|
|
it should be possible to support both.
|
|
When merging
|
|
.Tn MIDI
|
|
streams, a notion of transaction
|
|
is needed to group critical message sequences.
|
|
If
|
|
.Tn ALSA
|
|
or
|
|
.Tn OSS4
|
|
have no such notion, it should be provided as an upward-compatible
|
|
extension.
|
|
.Pp
|
|
I would rather have
|
|
.Xr open 2
|
|
itself return an error (by the POSIX description
|
|
.Er ENODEV
|
|
looks most appropriate) if a read or write mode
|
|
is requested that is not supported by the instance, rather than letting
|
|
.Xr open 2
|
|
succeed and
|
|
.Xr read 2
|
|
or
|
|
.Xr write 2
|
|
return \-1, but so help me, the latter seems
|
|
the more common
|
|
.Ux
|
|
practice.
|