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