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