| 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 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 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_ */ |
| 781 | |