xref: /minix/sys/sys/midiio.h (revision 6c8f7fc3)
1 /*	$NetBSD: midiio.h,v 1.15 2008/04/28 20:24:11 martin Exp $	*/
2 
3 /*-
4  * Copyright (c) 1998 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Lennart Augustsson (augustss@NetBSD.org) and (native API structures
9  * and macros) Chapman Flack (chap@NetBSD.org).
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 #ifndef _SYS_MIDIIO_H_
34 #define _SYS_MIDIIO_H_
35 
36 /*
37  * The API defined here produces events compatible with the OSS MIDI API at
38  * the binary level.
39  */
40 
41 #include <machine/endian_machdep.h>
42 
43 /*
44  * ioctl() commands for /dev/midi##
45  * XXX is directly frobbing an MPU401 even supported? isn't it just run
46  * in UART mode?
47  */
48 typedef struct {
49 	unsigned	char cmd;
50 	char		nr_args, nr_returns;
51 	unsigned char	data[30];
52 } mpu_command_rec;
53 
54 #define MIDI_PRETIME		_IOWR('m', 0, int)
55 #define MIDI_MPUMODE		_IOWR('m', 1, int)
56 #define MIDI_MPUCMD		_IOWR('m', 2, mpu_command_rec)
57 
58 
59 /* The MPU401 command acknowledge and active sense command */
60 #define MIDI_ACK	0xfe
61 
62 
63 /* Sequencer */
64 #define SEQUENCER_RESET			_IO  ('Q', 0)
65 #define SEQUENCER_SYNC			_IO  ('Q', 1)
66 #define SEQUENCER_INFO			_IOWR('Q', 2, struct synth_info)
67 #define SEQUENCER_CTRLRATE		_IOWR('Q', 3, int)
68 #define SEQUENCER_GETOUTCOUNT		_IOR ('Q', 4, int)
69 #define SEQUENCER_GETINCOUNT		_IOR ('Q', 5, int)
70 /*#define SEQUENCER_PERCMODE		_IOW ('Q', 6, int)*/
71 /*#define SEQUENCER_TESTMIDI		_IOW ('Q', 8, int)*/
72 #define SEQUENCER_RESETSAMPLES		_IOW ('Q', 9, int)
73 /*
74  * The sequencer at present makes no distinction between a 'synth' and a 'midi'.
75  * This is actually a cleaner layering than OSS: devices that are onboard
76  * synths just attach midi(4) via midisyn and present an ordinary MIDI face to
77  * the system. At present the same number is returned for NRSYNTHS and NRMIDIS
78  * but don't believe both, or you'll think you have twice as many devices as
79  * you really have. The MIDI_INFO ioctl isn't implemented; use SEQUENCER_INFO
80  * (which corresponds to OSS's SYNTH_INFO) to get information on any kind of
81  * device, though the struct synth_info it uses has some members that only
82  * pertain to synths (and get filled in with fixed, probably wrong values,
83  * anyway).
84  */
85 #define SEQUENCER_NRSYNTHS		_IOR ('Q',10, int)
86 #define SEQUENCER_NRMIDIS		_IOR ('Q',11, int)
87 /*#define SEQUENCER_MIDI_INFO		_IOWR('Q',12, struct midi_info)*/
88 #define SEQUENCER_THRESHOLD		_IOW ('Q',13, int)
89 #define SEQUENCER_MEMAVL		_IOWR('Q',14, int)
90 /*#define SEQUENCER_FM_4OP_ENABLE		_IOW ('Q',15, int)*/
91 #define SEQUENCER_PANIC			_IO  ('Q',17)
92 #define SEQUENCER_OUTOFBAND		_IOW ('Q',18, struct seq_event_rec)
93 #define SEQUENCER_GETTIME		_IOR ('Q',19, int)
94 /*#define SEQUENCER_ID			_IOWR('Q',20, struct synth_info)*/
95 /*#define SEQUENCER_CONTROL		_IOWR('Q',21, struct synth_control)*/
96 /*#define SEQUENCER_REMOVESAMPLE		_IOWR('Q',22, struct remove_sample)*/
97 
98 #if 0
99 typedef struct synth_control {
100 	int	devno;		/* Synthesizer # */
101 	char	data[4000];	/* Device specific command/data record */
102 } synth_control;
103 
104 typedef struct remove_sample {
105 	int	devno;		/* Synthesizer # */
106 	int	bankno;		/* MIDI bank # (0=General MIDI) */
107 	int	instrno;	/* MIDI instrument number */
108 } remove_sample;
109 #endif
110 
111 #define CMDSIZE 8
112 typedef struct seq_event_rec {
113 	u_char	arr[CMDSIZE];
114 } seq_event_rec;
115 
116 struct synth_info {
117 	char	name[30];
118 	int	device;
119 	int	synth_type;
120 #define SYNTH_TYPE_FM			0
121 #define SYNTH_TYPE_SAMPLE		1
122 #define SYNTH_TYPE_MIDI			2
123 
124 	int	synth_subtype;
125 #define SYNTH_SUB_FM_TYPE_ADLIB		0x00
126 #define SYNTH_SUB_FM_TYPE_OPL3		0x01
127 #define SYNTH_SUB_MIDI_TYPE_MPU401	0x401
128 
129 #define SYNTH_SUB_SAMPLE_TYPE_BASIC	0x10
130 #define SYNTH_SUB_SAMPLE_TYPE_GUS	SAMPLE_TYPE_BASIC
131 
132 	int	nr_voices;
133 	int	instr_bank_size;
134 	u_int	capabilities;
135 #define SYNTH_CAP_OPL3			0x00000002
136 #define SYNTH_CAP_INPUT			0x00000004
137 };
138 
139 /* Sequencer timer */
140 #define SEQUENCER_TMR_TIMEBASE		_IOWR('T', 1, int)
141 #define SEQUENCER_TMR_START		_IO  ('T', 2)
142 #define SEQUENCER_TMR_STOP		_IO  ('T', 3)
143 #define SEQUENCER_TMR_CONTINUE		_IO  ('T', 4)
144 #define SEQUENCER_TMR_TEMPO		_IOWR('T', 5, int)
145 #define SEQUENCER_TMR_SOURCE		_IOWR('T', 6, int)
146 #  define SEQUENCER_TMR_INTERNAL	0x00000001
147 #if 0
148 #  define SEQUENCER_TMR_EXTERNAL	0x00000002
149 #  define SEQUENCER_TMR_MODE_MIDI	0x00000010
150 #  define SEQUENCER_TMR_MODE_FSK	0x00000020
151 #  define SEQUENCER_TMR_MODE_CLS	0x00000040
152 #  define SEQUENCER_TMR_MODE_SMPTE	0x00000080
153 #endif
154 #define SEQUENCER_TMR_METRONOME		_IOW ('T', 7, int)
155 #define SEQUENCER_TMR_SELECT		_IOW ('T', 8, int)
156 
157 
158 #define MIDI_CTRL_BANK_SELECT_MSB	0
159 #define MIDI_CTRL_MODULATION_MSB	1
160 #define MIDI_CTRL_BREATH_MSB		2
161 #define MIDI_CTRL_FOOT_MSB		4
162 #define MIDI_CTRL_PORTAMENTO_TIME_MSB	5
163 #define MIDI_CTRL_DATA_ENTRY_MSB	6
164 #define MIDI_CTRL_CHANNEL_VOLUME_MSB	7
165 #define MIDI_CTRL_BALANCE_MSB		8
166 #define MIDI_CTRL_PAN_MSB		10
167 #define MIDI_CTRL_EXPRESSION_MSB	11
168 #define MIDI_CTRL_EFFECT_1_MSB		12
169 #define MIDI_CTRL_EFFECT_2_MSB		13
170 #define MIDI_CTRL_GENERAL_PURPOSE_1_MSB	16
171 #define MIDI_CTRL_GENERAL_PURPOSE_2_MSB	17
172 #define MIDI_CTRL_GENERAL_PURPOSE_3_MSB	18
173 #define MIDI_CTRL_GENERAL_PURPOSE_4_MSB	19
174 #define MIDI_CTRL_BANK_SELECT_LSB	32
175 #define MIDI_CTRL_MODULATION_LSB	33
176 #define MIDI_CTRL_BREATH_LSB		34
177 #define MIDI_CTRL_FOOT_LSB		36
178 #define MIDI_CTRL_PORTAMENTO_TIME_LSB	37
179 #define MIDI_CTRL_DATA_ENTRY_LSB	38
180 #define MIDI_CTRL_CHANNEL_VOLUME_LSB	39
181 #define MIDI_CTRL_BALANCE_LSB		40
182 #define MIDI_CTRL_PAN_LSB		42
183 #define MIDI_CTRL_EXPRESSION_LSB	43
184 #define MIDI_CTRL_EFFECT_1_LSB		44
185 #define MIDI_CTRL_EFFECT_2_LSB		45
186 #define MIDI_CTRL_GENERAL_PURPOSE_1_LSB	48
187 #define MIDI_CTRL_GENERAL_PURPOSE_2_LSB	49
188 #define MIDI_CTRL_GENERAL_PURPOSE_3_LSB	50
189 #define MIDI_CTRL_GENERAL_PURPOSE_4_LSB	51
190 #define MIDI_CTRL_HOLD_1		64
191 #define MIDI_CTRL_PORTAMENTO		65
192 #define MIDI_CTRL_SOSTENUTO		66
193 #define MIDI_CTRL_SOFT_PEDAL		67
194 #define MIDI_CTRL_LEGATO		68
195 #define MIDI_CTRL_HOLD_2		69
196 #define MIDI_CTRL_SOUND_VARIATION	70
197 #define MIDI_CTRL_HARMONIC_INTENSITY	71
198 #define MIDI_CTRL_RELEASE_TIME		72
199 #define MIDI_CTRL_ATTACK_TIME		73
200 #define MIDI_CTRL_BRIGHTNESS		74
201 #define MIDI_CTRL_DECAY_TIME		75
202 #define MIDI_CTRL_VIBRATO_RATE		76
203 #define MIDI_CTRL_VIBRATO_DEPTH		77
204 #define MIDI_CTRL_VIBRATO_DELAY		78
205 #define MIDI_CTRL_VIBRATO_DECAY		MIDI_CTRL_VIBRATO_DELAY /*deprecated*/
206 #define MIDI_CTRL_SOUND_10		79
207 #define MIDI_CTRL_GENERAL_PURPOSE_5	80
208 #define MIDI_CTRL_GENERAL_PURPOSE_6	81
209 #define MIDI_CTRL_GENERAL_PURPOSE_7	82
210 #define MIDI_CTRL_GENERAL_PURPOSE_8	83
211 #define MIDI_CTRL_PORTAMENTO_CONTROL	84
212 #define MIDI_CTRL_EFFECT_DEPTH_1	91
213 #define MIDI_CTRL_EFFECT_DEPTH_2	92
214 #define MIDI_CTRL_EFFECT_DEPTH_3	93
215 #define MIDI_CTRL_EFFECT_DEPTH_4	94
216 #define MIDI_CTRL_EFFECT_DEPTH_5	95
217 #define MIDI_CTRL_RPN_INCREMENT		96
218 #define MIDI_CTRL_RPN_DECREMENT		97
219 #define MIDI_CTRL_NRPN_LSB		98
220 #define MIDI_CTRL_NRPN_MSB		99
221 #define MIDI_CTRL_RPN_LSB		100
222 #define MIDI_CTRL_RPN_MSB		101
223 #define MIDI_CTRL_SOUND_OFF		120
224 #define MIDI_CTRL_RESET			121
225 #define MIDI_CTRL_LOCAL			122
226 #define MIDI_CTRL_NOTES_OFF		123
227 #define MIDI_CTRL_ALLOFF		MIDI_CTRL_NOTES_OFF /*deprecated*/
228 #define MIDI_CTRL_OMNI_OFF		124
229 #define MIDI_CTRL_OMNI_ON		125
230 #define MIDI_CTRL_POLY_OFF		126
231 #define MIDI_CTRL_POLY_ON		127
232 
233 #define MIDI_BEND_NEUTRAL	(1<<13)
234 
235 #define MIDI_RPN_PITCH_BEND_SENSITIVITY	0
236 #define MIDI_RPN_CHANNEL_FINE_TUNING	1
237 #define MIDI_RPN_CHANNEL_COARSE_TUNING	2
238 #define MIDI_RPN_TUNING_PROGRAM_CHANGE	3
239 #define MIDI_RPN_TUNING_BANK_SELECT	4
240 #define MIDI_RPN_MODULATION_DEPTH_RANGE	5
241 
242 #define MIDI_NOTEOFF		0x80
243 #define MIDI_NOTEON		0x90
244 #define MIDI_KEY_PRESSURE	0xA0
245 #define MIDI_CTL_CHANGE		0xB0
246 #define MIDI_PGM_CHANGE		0xC0
247 #define MIDI_CHN_PRESSURE	0xD0
248 #define MIDI_PITCH_BEND		0xE0
249 #define MIDI_SYSTEM_PREFIX	0xF0
250 
251 #define MIDI_IS_STATUS(d) ((d) >= 0x80)
252 #define MIDI_IS_COMMON(d) ((d) >= 0xf0)
253 
254 #define MIDI_SYSEX_START	0xF0
255 #define MIDI_SYSEX_END		0xF7
256 
257 #define MIDI_GET_STATUS(d) ((d) & 0xf0)
258 #define MIDI_GET_CHAN(d) ((d) & 0x0f)
259 
260 #define MIDI_HALF_VEL 64
261 
262 #define SEQ_LOCAL		0x80
263 #define SEQ_TIMING		0x81
264 #define SEQ_CHN_COMMON		0x92
265 #define SEQ_CHN_VOICE		0x93
266 #define SEQ_SYSEX		0x94
267 #define SEQ_FULLSIZE		0xfd
268 
269 #define SEQ_MK_CHN_VOICE(e, unit, cmd, chan, key, vel) (\
270     (e)->arr[0] = SEQ_CHN_VOICE, (e)->arr[1] = (unit), (e)->arr[2] = (cmd),\
271     (e)->arr[3] = (chan), (e)->arr[4] = (key), (e)->arr[5] = (vel),\
272     (e)->arr[6] = 0, (e)->arr[7] = 0)
273 #define SEQ_MK_CHN_COMMON(e, unit, cmd, chan, p1, p2, w14) (\
274     (e)->arr[0] = SEQ_CHN_COMMON, (e)->arr[1] = (unit), (e)->arr[2] = (cmd),\
275     (e)->arr[3] = (chan), (e)->arr[4] = (p1), (e)->arr[5] = (p2),\
276     *(short*)&(e)->arr[6] = (w14))
277 
278 #if _BYTE_ORDER == _BIG_ENDIAN
279 /* big endian */
280 #define SEQ_PATCHKEY(id) (0xfd00|id)
281 #else
282 /* little endian */
283 #define SEQ_PATCHKEY(id) ((id<<8)|0xfd)
284 #endif
285 struct sysex_info {
286 	uint16_t	key;	/* Use SYSEX_PATCH or MAUI_PATCH here */
287 #define SEQ_SYSEX_PATCH	SEQ_PATCHKEY(0x05)
288 #define SEQ_MAUI_PATCH	SEQ_PATCHKEY(0x06)
289 	int16_t	device_no;	/* Synthesizer number */
290 	int32_t	len;		/* Size of the sysex data in bytes */
291 	u_char	data[1];	/* Sysex data starts here */
292 };
293 #define SEQ_SYSEX_HDRSIZE ((u_long)((struct sysex_info *)0)->data)
294 
295 typedef unsigned char sbi_instr_data[32];
296 struct sbi_instrument {
297 	uint16_t key;	/* FM_PATCH or OPL3_PATCH */
298 #define SBI_FM_PATCH	SEQ_PATCHKEY(0x01)
299 #define SBI_OPL3_PATCH	SEQ_PATCHKEY(0x03)
300 	int16_t		device;
301 	int32_t		channel;
302 	sbi_instr_data	operators;
303 };
304 
305 #define TMR_RESET		0	/* beware: not an OSS event */
306 #define TMR_WAIT_REL		1	/* Time relative to the prev time */
307 #define TMR_WAIT_ABS		2	/* Absolute time since TMR_START */
308 #define TMR_STOP		3
309 #define TMR_START		4
310 #define TMR_CONTINUE		5
311 #define TMR_TEMPO		6
312 #define TMR_ECHO		8
313 #define TMR_CLOCK		9	/* MIDI clock */
314 #define TMR_SPP			10	/* Song position pointer */
315 #define TMR_TIMESIG		11	/* Time signature */
316 
317 /* Old sequencer definitions */
318 #define SEQOLD_CMDSIZE 4
319 
320 #define SEQOLD_NOTEOFF		0
321 #define SEQOLD_NOTEON		1
322 #define SEQOLD_WAIT		TMR_WAIT_ABS
323 #define SEQOLD_PGMCHANGE	3
324 #define SEQOLD_SYNCTIMER	TMR_START
325 #define SEQOLD_MIDIPUTC		5
326 #define SEQOLD_ECHO		TMR_ECHO
327 #define SEQOLD_AFTERTOUCH	9
328 #define SEQOLD_CONTROLLER	10
329 #define SEQOLD_PRIVATE		0xfe
330 #define SEQOLD_EXTENDED		0xff
331 
332 /*
333  * The 'midipitch' data type, used in the kernel between the midisyn layer and
334  * onboard synth drivers, and in userland as parameters to the MIDI Tuning Spec
335  * (RP-012) universal-system-exclusive messages. It is a MIDI key number shifted
336  * left to accommodate 14 bit sub-semitone resolution. In this representation,
337  * tuning and bending adjustments are simple addition and subtraction.
338  */
339 typedef int32_t midipitch_t;
340 
341 /*
342  * Nominal conversions between midipitches and key numbers. (Beware that these
343  * are the nominal, standard correspondences, but whole point of the MIDI Tuning
344  * Spec is that you can set things up so the hardware might render key N at
345  * actual pitch MIDIPITCH_FROM_KEY(N)+c for some correction c.)
346  */
347 #define MIDIPITCH_FROM_KEY(k) ((k)<<14)
348 #define MIDIPITCH_TO_KEY(mp) (((mp)+(1<<13))>>14)
349 
350 #define MIDIPITCH_MAX (MIDIPITCH_FROM_KEY(128)-2) /* ...(128)-1 is reserved */
351 #define MIDIPITCH_OCTAVE  196608
352 #define MIDIPITCH_SEMITONE 16384
353 #define MIDIPITCH_CENT       164 /* this, regrettably, is inexact. */
354 
355 /*
356  * For rendering, convert a midipitch (after all tuning adjustments) to Hz.
357  * The conversion is DEFINED as MIDI key 69.00000 (A) === 440 Hz equal tempered
358  * always. Alternate tunings are obtained by adjusting midipitches.
359  *
360  * The midihz18_t (Hz shifted left for 18-bit sub-Hz resolution) covers the
361  * full midipitch range without losing 21-bit precision, as the lowest midipitch
362  * is ~8 Hz (~3 bits left of radix point, 18 right) and for the highest the
363  * result still fits in a uint32.
364  */
365 typedef uint32_t midihz18_t;
366 
367 #define MIDIHZ18_TO_HZ(h18) ((h18)>>18) /* truncates! ok for dbg msgs maybe */
368 
369 #ifndef _KERNEL
370 /*
371  * With floating point in userland, can also manipulate midipitches as
372  * floating-point fractional MIDI key numbers (tuning adjustments are still
373  * additive), and hz18 as fractional Hz (adjustments don't add in this form).
374  */
375 #include <math.h>
376 #define MIDIPITCH_TO_FRKEY(mp) (scalbn((mp),-14))
377 #define MIDIPITCH_FROM_FRKEY(frk) ((midipitch_t)round(scalbn((frk),14)))
378 #define MIDIHZ18_TO_FRHZ(h18) (scalbn((h18),-18))
379 #define MIDIHZ18_FROM_FRHZ(frh) ((midihz18_t)round(scalbn((frh),18)))
380 
381 #define MIDIPITCH_TO_FRHZ(mp) (440*pow(2,(MIDIPITCH_TO_FRKEY((mp))-69)/12))
382 #define MIDIPITCH_FROM_FRHZ(fhz) \
383                                MIDIPITCH_FROM_FRKEY(69+12*log((fhz)/440)/log(2))
384 #define MIDIPITCH_TO_HZ18(mp) MIDIHZ18_FROM_FRHZ(MIDIPITCH_TO_FRHZ((mp)))
385 #define MIDIPITCH_FROM_HZ18(h18) MIDIPITCH_FROM_FRHZ(MIDIHZ18_TO_FRHZ((h18)))
386 
387 #else /* no fp in kernel; only an accurate to-hz18 conversion is implemented */
388 
389 extern midihz18_t midisyn_mp2hz18(midipitch_t);
390 #define MIDIPITCH_TO_HZ18(mp) (midisyn_mp2hz18((mp)))
391 
392 #endif /* _KERNEL */
393 
394 
395 /*
396  * A native API for the /dev/music sequencer device follows. The event
397  * structures are OSS events at the level of bytes, but for developing or
398  * porting applications some macros and documentation are needed to generate
399  * and dissect the events; here they are. For porting existing OSS applications,
400  * sys/soundcard.h can be extended to supply the usual OSS macros, defining them
401  * in terms of these.
402  */
403 
404 /*
405  * TODO: determine OSS compatible structures for TMR_RESET and TMR_CLOCK,
406  *       OSS values of EV_SYSTEM, SNDCTL_SEQ_ACTSENSE_ENABLE,
407  *       SNDCTL_SEQ_TIMING_ENABLE, and SNDCTL_SEQ_RT_ENABLE.
408  * (TMR_RESET may be a NetBSD extension: it is generated in sequencer.c and
409  * has no args. To be corrected if a different definition is found anywhere.)
410  */
411 typedef union {
412 
413 #define _EVT_HDR \
414 	uint8_t tag
415 
416 	_EVT_HDR;
417 
418 #define _LOCAL_HDR \
419 	_EVT_HDR; \
420 	uint8_t op
421 
422 	struct { _LOCAL_HDR; } local;
423 
424 	struct {
425 		_LOCAL_HDR;
426 		uint16_t _zero;
427 		uint32_t devmask;
428 	} l_startaudio;
429 
430 /* define a constructor for local evts - someday when we support any */
431 
432 #define _TIMING_HDR \
433 	_LOCAL_HDR; \
434 	uint16_t _zeroh
435 	struct { _TIMING_HDR; } timing;
436 
437 	struct {
438 		_TIMING_HDR;
439 		uint32_t divisions;
440 	} t_WAIT_REL, t_WAIT_ABS;
441 
442 	struct {
443 		_TIMING_HDR;
444 		uint32_t _zero;
445 	} t_STOP, t_START, t_CONTINUE, t_RESET;
446 
447 	struct {
448 		_TIMING_HDR;
449 		uint32_t bpm; /* unambiguously, (MIDI clocks/minute)/24 */
450 	} t_TEMPO;
451 
452 	struct {
453 		_TIMING_HDR;
454 		uint32_t cookie;
455 	} t_ECHO;
456 
457 	struct {
458 		_TIMING_HDR;
459 		uint32_t midibeat; /* in low 14 bits; midibeat: 6 MIDI clocks */
460 	} t_SPP;
461 
462 	struct {
463 		_TIMING_HDR;
464 #if _BYTE_ORDER == _BIG_ENDIAN
465 		uint8_t numerator;
466 		uint8_t lg2denom;
467 		uint8_t clks_per_click;
468 		uint8_t dsq_per_24clks;
469 #elif _BYTE_ORDER == _LITTLE_ENDIAN
470 		uint8_t dsq_per_24clks;
471 		uint8_t clks_per_click;
472 		uint8_t lg2denom;
473 		uint8_t numerator;
474 #else
475 #error "unexpected _BYTE_ORDER"
476 #endif
477 	} t_TIMESIG;
478 
479 	struct { /* use this only to implement OSS compatibility macro */
480 		_TIMING_HDR;
481 		uint32_t signature;
482 	} t_osscompat_timesig;
483 
484 
485 #define _COMMON_HDR \
486 	_EVT_HDR; \
487 	uint8_t device; \
488 	uint8_t op; \
489 	uint8_t channel
490 
491 	struct { _COMMON_HDR; } common;
492 
493 	struct {
494 		_COMMON_HDR;
495 		uint8_t controller;
496 		uint8_t _zero;
497 		uint16_t value;
498 	} c_CTL_CHANGE;
499 
500 	struct {
501 		_COMMON_HDR;
502 		uint8_t program;
503 		uint8_t _zero0;
504 		uint16_t _zero1;
505 	} c_PGM_CHANGE;
506 
507 	struct {
508 		_COMMON_HDR;
509 		uint8_t pressure;
510 		uint8_t _zero0;
511 		uint16_t _zero1;
512 	} c_CHN_PRESSURE;
513 
514 	struct {
515 		_COMMON_HDR;
516 		uint8_t _zero0;
517 		uint8_t _zero1;
518 		uint16_t value;
519 	} c_PITCH_BEND;
520 
521 #define _VOICE_HDR \
522 	_COMMON_HDR; \
523 	uint8_t key
524 
525 	struct { _VOICE_HDR; }  voice;
526 
527 	struct {
528 		_VOICE_HDR;
529 		uint8_t velocity;
530 		uint16_t _zero;
531 	} c_NOTEOFF, c_NOTEON;
532 
533 	struct {
534 		_VOICE_HDR;
535 		uint8_t pressure;
536 		uint16_t _zero;
537 	} c_KEY_PRESSURE;
538 
539 	struct {
540 		_EVT_HDR;
541 		uint8_t device;
542 		uint8_t buffer[6];
543 	} sysex;
544 
545 	struct {
546 		_EVT_HDR;
547 		uint8_t device;
548 		uint8_t status;
549 		uint8_t data[2];
550 	} system;
551 
552 	struct {
553 		_EVT_HDR;
554 		uint8_t byte;
555 		uint8_t device;
556 		uint8_t _zero0;
557 		uint32_t _zero1;
558 	} putc; /* a seqold event that's still needed at times, ugly as 'tis */
559 
560 	struct {
561 		_EVT_HDR;
562 		uint8_t byte[7];
563 	} unknown; /* for debug/display */
564 
565 #undef _VOICE_HDR
566 #undef _COMMON_HDR
567 #undef _TIMING_HDR
568 #undef _LOCAL_HDR
569 #undef _EVT_HDR
570 
571 } __packed seq_event_t;
572 
573 #define _SEQ_TAG_NOTEOFF	SEQ_CHN_VOICE
574 #define _SEQ_TAG_NOTEON 	SEQ_CHN_VOICE
575 #define _SEQ_TAG_KEY_PRESSURE	SEQ_CHN_VOICE
576 
577 #define _SEQ_TAG_CTL_CHANGE	SEQ_CHN_COMMON
578 #define _SEQ_TAG_PGM_CHANGE	SEQ_CHN_COMMON
579 #define _SEQ_TAG_CHN_PRESSURE	SEQ_CHN_COMMON
580 #define _SEQ_TAG_PITCH_BEND	SEQ_CHN_COMMON
581 
582 #if __STDC_VERSION__ >= 199901L
583 
584 #define SEQ_MK_EVENT(_member,_tag,...)					\
585 (seq_event_t){ ._member = { .tag = (_tag), __VA_ARGS__ } }
586 
587 #define SEQ_MK_TIMING(_op,...)						\
588 SEQ_MK_EVENT(t_##_op, SEQ_TIMING, .op = TMR_##_op, __VA_ARGS__)
589 
590 #define SEQ_MK_CHN(_op,...)						\
591 SEQ_MK_EVENT(c_##_op, _SEQ_TAG_##_op, .op = MIDI_##_op, __VA_ARGS__)
592 
593 #define SEQ_MK_SYSEX(_dev,...)						\
594 SEQ_MK_EVENT(sysex, 0x94, .device=(_dev), 				\
595              .buffer={0xff, 0xff, 0xff, 0xff, 0xff, 0xff, __VA_ARGS__})
596 
597 #else /* assume gcc 2.95.3 */
598 
599 #define SEQ_MK_EVENT(_member,_tag,_args...)				\
600 (seq_event_t){ ._member = { .tag = (_tag), _args } }
601 
602 #define SEQ_MK_TIMING(_op,_args...)						\
603 SEQ_MK_EVENT(t_##_op, SEQ_TIMING, .op = TMR_##_op, _args)
604 
605 #define SEQ_MK_CHN(_op,_args...)					\
606 SEQ_MK_EVENT(c_##_op, _SEQ_TAG_##_op, .op = MIDI_##_op, _args)
607 
608 #define SEQ_MK_SYSEX(_dev,_args...)						\
609 SEQ_MK_EVENT(sysex, 0x94, .device=(_dev), 				\
610              .buffer={0xff, 0xff, 0xff, 0xff, 0xff, 0xff, _args})
611 
612 #endif /* c99 vs. gcc 2.95.3 */
613 
614 #if 0
615 #include <fcntl.h>
616 #include <stdio.h>
617 int
618 main(int argc, char **argv)
619 {
620 	int i;
621 	int fd;
622 	seq_event_t e;
623 
624 	/* simple usage example (add a buffer to reduce syscall overhead) */
625 	fd = open("/dev/music", O_RDWR);
626 	write(fd, &SEQ_MK_TIMING(START), sizeof (seq_event_t));
627 
628 	read(fd, &e, sizeof e);
629 	switch ( e.tag ) {
630 	case SEQ_CHN_VOICE:
631 		switch ( e.voice.op ) {
632 		case MIDI_NOTEON:
633 			printf("Note on, dev=%d chn=%d key=%d vel=%d\n",
634 			    e.c_NOTEON.device, e.c_NOTEON.channel,
635 			    e.c_NOTEON.key, e.c_NOTEON.velocity);
636 		}
637 	}
638 
639 	/* all the macros: */
640 	e = SEQ_MK_TIMING(START);
641 	e = SEQ_MK_TIMING(STOP);
642 	e = SEQ_MK_TIMING(CONTINUE);
643 	/*
644 	 * Wait until the specified number of divisions from the timer start
645 	 * (abs) or the preceding event (rel). The number of divisions to a
646 	 * beat or to a MIDI clock is determined by the timebase (set by
647 	 * ioctl). The tempo is expressed in beats per minute, where a beat
648 	 * is always 24 MIDI clocks (and usually equated to a quarter note,
649 	 * but that can be changed with timesig)--that is, tempo is
650 	 * (MIDI clocks per minute)/24. The timebase is the number of divisions
651 	 * in a beat--that is, the number of divisions that make up 24 MIDI
652 	 * clocks--so the timebase is 24*(divisions per MIDI clock). The MThd
653 	 * header in a SMF gives the 'natural' timebase for the file; if the
654 	 * timebase is set accordingly, then the delay values appearing in the
655 	 * tracks are in terms of divisions, and can be used as WAIT_REL
656 	 * arguments without modification.
657 	 */
658 	e = SEQ_MK_TIMING(WAIT_ABS, .divisions=192);
659 	e = SEQ_MK_TIMING(WAIT_REL, .divisions=192);
660 	/*
661 	 * The 'beat' in bpm is 24 MIDI clocks (usually a quarter note but
662 	 * changeable with timesig).
663 	 */
664 	e = SEQ_MK_TIMING(TEMPO, .bpm=84);
665 	/*
666 	 * An ECHO event on output appears on input at the appointed time; the
667 	 * cookie can be anything of interest to the application. Can be used
668 	 * in schemes to get some control over latency.
669 	 */
670 	e = SEQ_MK_TIMING(ECHO, .cookie=0xfeedface);
671 	/*
672 	 * A midibeat is smaller than a beat. It is six MIDI clocks, or a fourth
673 	 * of a beat, or a sixteenth note if the beat is a quarter. SPP is a
674 	 * request to position at the requested midibeat from the start of the
675 	 * sequence. [sequencer does not at present implement SPP]
676 	 */
677 	e = SEQ_MK_TIMING(SPP, .midibeat=128);
678 	/*
679 	 * numerator and lg2denom describe the time signature as it would
680 	 * appear on a staff, where lg2denom of 0,1,2,3... corresponds to
681 	 * denominator of 1,2,4,8... respectively. So the example below
682 	 * corresponds to 4/4. dsq_per_24clks defines the relationship of
683 	 * MIDI clocks to note values, by specifying the number of
684 	 * demisemiquavers (32nd notes) represented by 24 MIDI clocks.
685 	 * The default is 8 demisemiquavers, or a quarter note.
686 	 * clks_per_click can configure a metronome (for example, the MPU401
687 	 * had such a feature in intelligent mode) to click every so many
688 	 * MIDI clocks. The 24 in this example would give a click every quarter
689 	 * note. [sequencer does not at present implement TIMESIG]
690 	 */
691 	e = SEQ_MK_TIMING(TIMESIG, .numerator=4, .lg2denom=2,
692 	                           .clks_per_click=24, .dsq_per_24clks=8);
693 	/*
694 	 * This example declares 6/8 time where the beat (24 clocks) is the
695 	 * eighth note, but the metronome clicks every dotted quarter (twice
696 	 * per measure):
697 	 */
698 	e = SEQ_MK_TIMING(TIMESIG, .numerator=6, .lg2denom=3,
699 	                           .clks_per_click=72, .dsq_per_24clks=4);
700 	/*
701 	 * An alternate declaration for 6/8 where the beat (24 clocks) is now
702 	 * the dotted quarter and corresponds to the metronome click:
703 	 */
704 	e = SEQ_MK_TIMING(TIMESIG, .numerator=6, .lg2denom=3,
705 	                           .clks_per_click=24, .dsq_per_24clks=12);
706 	/*
707 	 * It would also be possible to keep the default correspondence of
708 	 * 24 clocks to the quarter note (8 dsq), and still click the metronome
709 	 * each dotted quarter:
710 	 */
711 	e = SEQ_MK_TIMING(TIMESIG, .numerator=6, .lg2denom=3,
712 	                           .clks_per_click=36, .dsq_per_24clks=8);
713 
714 	e = SEQ_MK_CHN(NOTEON,  .device=1, .channel=0, .key=60, .velocity=64);
715 	e = SEQ_MK_CHN(NOTEOFF, .device=1, .channel=0, .key=60, .velocity=64);
716 	e = SEQ_MK_CHN(KEY_PRESSURE, .device=1, .channel=0, .key=60,
717 	                             .pressure=64);
718 
719 	/*
720 	 * sequencer does not at present implement CTL_CHANGE well. The API
721 	 * provides for a 14-bit value where you give the controller index
722 	 * of the controller MSB and sequencer will split the 14-bit value to
723 	 * the controller MSB and LSB for you--but it doesn't; it ignores the
724 	 * high bits of value and writes the low bits whether you have specified
725 	 * MSB or LSB. That would not be hard to fix but for the fact that OSS
726 	 * itself seems to suffer from the same mixup (and its behavior differs
727 	 * with whether the underlying device is an onboard synth or a MIDI
728 	 * link!) so there is surely a lot of code that relies on it being
729 	 * broken :(.
730 	 * (Note: as the OSS developers have ceased development of the
731 	 * /dev/music API as of OSS4, it would be possible given a complete
732 	 * list of the events defined in OSS4 to add some new ones for native
733 	 * use without fear of future conflict, such as a better ctl_change.)
734 	 */
735 	e = SEQ_MK_CHN(CTL_CHANGE, .device=1, .channel=0,
736 	               .controller=MIDI_CTRL_EXPRESSION_MSB, .value=8192);/*XX*/
737 	/*
738 	 * The way you really have to do it:
739 	 */
740 	e = SEQ_MK_CHN(CTL_CHANGE, .device=1, .channel=0,
741 	               .controller=MIDI_CTRL_EXPRESSION_MSB, .value=8192>>7);
742 	e = SEQ_MK_CHN(CTL_CHANGE, .device=1, .channel=0,
743 	               .controller=MIDI_CTRL_EXPRESSION_LSB, .value=8192&0x7f);
744 
745 	e = SEQ_MK_CHN(PGM_CHANGE,   .device=1, .channel=0, .program=51);
746 	e = SEQ_MK_CHN(CHN_PRESSURE, .device=1, .channel=0, .pressure=64);
747 	e = SEQ_MK_CHN(PITCH_BEND,   .device=1, .channel=0, .value=8192);
748 
749 	/*
750 	 * A SYSEX event carries up to six bytes of a system exclusive message.
751 	 * The first such message must begin with MIDI_SYSEX_START (0xf0), the
752 	 * last must end with MIDI_SYSEX_END (0xf7), and only the last may carry
753 	 * fewer than 6 bytes. To supply message bytes in the macro, you must
754 	 * prefix the first with [0]= as shown. The macro's first argument is
755 	 * the device.
756 	 */
757 	e = SEQ_MK_SYSEX(1,[0]=MIDI_SYSEX_START,1,2,MIDI_SYSEX_END);
758 	/*
759 	 * In some cases it may be easier to use the macro only to initialize
760 	 * the event, and fill in the message bytes later. The code that fills
761 	 * in the message does not need to store 0xff following the SYSEX_END.
762 	 */
763 	e = SEQ_MK_SYSEX(1);
764 	for ( i = 0; i < 3; ++ i )
765 		e.sysex.buffer[i] = i;
766 	/*
767 	 * It would be nice to think the old /dev/sequencer MIDIPUTC event
768 	 * obsolete, but it is still needed (absent any better API) by any MIDI
769 	 * file player that will implement the ESCAPED events that may occur in
770 	 * SMF. Sorry. Here's how to use it:
771 	 */
772 	e = SEQ_MK_EVENT(putc, SEQOLD_MIDIPUTC, .device=1, .byte=42);
773 
774 	printf("confirm event size: %d (should be 8)\n", sizeof (seq_event_t));
775 	return 0;
776 }
777 #endif /* 0 */
778 
779 #endif /* !_SYS_MIDIIO_H_ */
780