1*74422c2fSdholland /* $NetBSD: midiio.h,v 1.16 2015/09/06 06:01:02 dholland Exp $ */ 248bae9eeSaugustss 367dbe5edSchristos /*- 448bae9eeSaugustss * Copyright (c) 1998 The NetBSD Foundation, Inc. 548bae9eeSaugustss * All rights reserved. 648bae9eeSaugustss * 767dbe5edSchristos * This code is derived from software contributed to The NetBSD Foundation 8710af634Schap * by Lennart Augustsson (augustss@NetBSD.org) and (native API structures 9710af634Schap * and macros) Chapman Flack (chap@NetBSD.org). 1048bae9eeSaugustss * 1148bae9eeSaugustss * Redistribution and use in source and binary forms, with or without 1248bae9eeSaugustss * modification, are permitted provided that the following conditions 1348bae9eeSaugustss * are met: 1448bae9eeSaugustss * 1. Redistributions of source code must retain the above copyright 1548bae9eeSaugustss * notice, this list of conditions and the following disclaimer. 1648bae9eeSaugustss * 2. Redistributions in binary form must reproduce the above copyright 1748bae9eeSaugustss * notice, this list of conditions and the following disclaimer in the 1848bae9eeSaugustss * documentation and/or other materials provided with the distribution. 1948bae9eeSaugustss * 2048bae9eeSaugustss * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 2148bae9eeSaugustss * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 2248bae9eeSaugustss * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 2367dbe5edSchristos * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 2467dbe5edSchristos * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2548bae9eeSaugustss * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2648bae9eeSaugustss * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2748bae9eeSaugustss * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2848bae9eeSaugustss * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2948bae9eeSaugustss * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 3048bae9eeSaugustss * POSSIBILITY OF SUCH DAMAGE. 3148bae9eeSaugustss */ 3248bae9eeSaugustss 3348bae9eeSaugustss #ifndef _SYS_MIDIIO_H_ 3448bae9eeSaugustss #define _SYS_MIDIIO_H_ 3548bae9eeSaugustss 3648bae9eeSaugustss /* 37710af634Schap * The API defined here produces events compatible with the OSS MIDI API at 38710af634Schap * the binary level. 3948bae9eeSaugustss */ 4048bae9eeSaugustss 414c58d3d9Sbjh21 #include <machine/endian_machdep.h> 42*74422c2fSdholland #include <sys/ioccom.h> 4348bae9eeSaugustss 4448bae9eeSaugustss /* 4548bae9eeSaugustss * ioctl() commands for /dev/midi## 46710af634Schap * XXX is directly frobbing an MPU401 even supported? isn't it just run 47710af634Schap * in UART mode? 4848bae9eeSaugustss */ 4948bae9eeSaugustss typedef struct { 5048bae9eeSaugustss unsigned char cmd; 5148bae9eeSaugustss char nr_args, nr_returns; 5248bae9eeSaugustss unsigned char data[30]; 5348bae9eeSaugustss } mpu_command_rec; 5448bae9eeSaugustss 5548bae9eeSaugustss #define MIDI_PRETIME _IOWR('m', 0, int) 5648bae9eeSaugustss #define MIDI_MPUMODE _IOWR('m', 1, int) 5748bae9eeSaugustss #define MIDI_MPUCMD _IOWR('m', 2, mpu_command_rec) 5848bae9eeSaugustss 5948bae9eeSaugustss 6048bae9eeSaugustss /* The MPU401 command acknowledge and active sense command */ 6148bae9eeSaugustss #define MIDI_ACK 0xfe 6248bae9eeSaugustss 6348bae9eeSaugustss 6448bae9eeSaugustss /* Sequencer */ 6548bae9eeSaugustss #define SEQUENCER_RESET _IO ('Q', 0) 6648bae9eeSaugustss #define SEQUENCER_SYNC _IO ('Q', 1) 6748bae9eeSaugustss #define SEQUENCER_INFO _IOWR('Q', 2, struct synth_info) 6848bae9eeSaugustss #define SEQUENCER_CTRLRATE _IOWR('Q', 3, int) 6948bae9eeSaugustss #define SEQUENCER_GETOUTCOUNT _IOR ('Q', 4, int) 7048bae9eeSaugustss #define SEQUENCER_GETINCOUNT _IOR ('Q', 5, int) 7148bae9eeSaugustss /*#define SEQUENCER_PERCMODE _IOW ('Q', 6, int)*/ 7248bae9eeSaugustss /*#define SEQUENCER_TESTMIDI _IOW ('Q', 8, int)*/ 7327c5df27Saugustss #define SEQUENCER_RESETSAMPLES _IOW ('Q', 9, int) 74710af634Schap /* 75710af634Schap * The sequencer at present makes no distinction between a 'synth' and a 'midi'. 76710af634Schap * This is actually a cleaner layering than OSS: devices that are onboard 77710af634Schap * synths just attach midi(4) via midisyn and present an ordinary MIDI face to 78710af634Schap * the system. At present the same number is returned for NRSYNTHS and NRMIDIS 79710af634Schap * but don't believe both, or you'll think you have twice as many devices as 80710af634Schap * you really have. The MIDI_INFO ioctl isn't implemented; use SEQUENCER_INFO 81710af634Schap * (which corresponds to OSS's SYNTH_INFO) to get information on any kind of 82710af634Schap * device, though the struct synth_info it uses has some members that only 83710af634Schap * pertain to synths (and get filled in with fixed, probably wrong values, 84710af634Schap * anyway). 85710af634Schap */ 8648bae9eeSaugustss #define SEQUENCER_NRSYNTHS _IOR ('Q',10, int) 8748bae9eeSaugustss #define SEQUENCER_NRMIDIS _IOR ('Q',11, int) 8848bae9eeSaugustss /*#define SEQUENCER_MIDI_INFO _IOWR('Q',12, struct midi_info)*/ 8948bae9eeSaugustss #define SEQUENCER_THRESHOLD _IOW ('Q',13, int) 9048bae9eeSaugustss #define SEQUENCER_MEMAVL _IOWR('Q',14, int) 9148bae9eeSaugustss /*#define SEQUENCER_FM_4OP_ENABLE _IOW ('Q',15, int)*/ 9248bae9eeSaugustss #define SEQUENCER_PANIC _IO ('Q',17) 9348bae9eeSaugustss #define SEQUENCER_OUTOFBAND _IOW ('Q',18, struct seq_event_rec) 9448bae9eeSaugustss #define SEQUENCER_GETTIME _IOR ('Q',19, int) 9548bae9eeSaugustss /*#define SEQUENCER_ID _IOWR('Q',20, struct synth_info)*/ 9648bae9eeSaugustss /*#define SEQUENCER_CONTROL _IOWR('Q',21, struct synth_control)*/ 9748bae9eeSaugustss /*#define SEQUENCER_REMOVESAMPLE _IOWR('Q',22, struct remove_sample)*/ 9848bae9eeSaugustss 9948bae9eeSaugustss #if 0 10048bae9eeSaugustss typedef struct synth_control { 10148bae9eeSaugustss int devno; /* Synthesizer # */ 10248bae9eeSaugustss char data[4000]; /* Device specific command/data record */ 10348bae9eeSaugustss } synth_control; 10448bae9eeSaugustss 10548bae9eeSaugustss typedef struct remove_sample { 10648bae9eeSaugustss int devno; /* Synthesizer # */ 10748bae9eeSaugustss int bankno; /* MIDI bank # (0=General MIDI) */ 10848bae9eeSaugustss int instrno; /* MIDI instrument number */ 10948bae9eeSaugustss } remove_sample; 11048bae9eeSaugustss #endif 11148bae9eeSaugustss 11248bae9eeSaugustss #define CMDSIZE 8 11348bae9eeSaugustss typedef struct seq_event_rec { 11448bae9eeSaugustss u_char arr[CMDSIZE]; 11548bae9eeSaugustss } seq_event_rec; 11648bae9eeSaugustss 11748bae9eeSaugustss struct synth_info { 11848bae9eeSaugustss char name[30]; 11948bae9eeSaugustss int device; 12048bae9eeSaugustss int synth_type; 12148bae9eeSaugustss #define SYNTH_TYPE_FM 0 12248bae9eeSaugustss #define SYNTH_TYPE_SAMPLE 1 12348bae9eeSaugustss #define SYNTH_TYPE_MIDI 2 12448bae9eeSaugustss 12548bae9eeSaugustss int synth_subtype; 12648bae9eeSaugustss #define SYNTH_SUB_FM_TYPE_ADLIB 0x00 12748bae9eeSaugustss #define SYNTH_SUB_FM_TYPE_OPL3 0x01 12848bae9eeSaugustss #define SYNTH_SUB_MIDI_TYPE_MPU401 0x401 12948bae9eeSaugustss 13048bae9eeSaugustss #define SYNTH_SUB_SAMPLE_TYPE_BASIC 0x10 13148bae9eeSaugustss #define SYNTH_SUB_SAMPLE_TYPE_GUS SAMPLE_TYPE_BASIC 13248bae9eeSaugustss 13348bae9eeSaugustss int nr_voices; 13448bae9eeSaugustss int instr_bank_size; 13548bae9eeSaugustss u_int capabilities; 13648bae9eeSaugustss #define SYNTH_CAP_OPL3 0x00000002 13748bae9eeSaugustss #define SYNTH_CAP_INPUT 0x00000004 13848bae9eeSaugustss }; 13948bae9eeSaugustss 14048bae9eeSaugustss /* Sequencer timer */ 14148bae9eeSaugustss #define SEQUENCER_TMR_TIMEBASE _IOWR('T', 1, int) 14248bae9eeSaugustss #define SEQUENCER_TMR_START _IO ('T', 2) 14348bae9eeSaugustss #define SEQUENCER_TMR_STOP _IO ('T', 3) 14448bae9eeSaugustss #define SEQUENCER_TMR_CONTINUE _IO ('T', 4) 14548bae9eeSaugustss #define SEQUENCER_TMR_TEMPO _IOWR('T', 5, int) 14648bae9eeSaugustss #define SEQUENCER_TMR_SOURCE _IOWR('T', 6, int) 14748bae9eeSaugustss # define SEQUENCER_TMR_INTERNAL 0x00000001 14848bae9eeSaugustss #if 0 14948bae9eeSaugustss # define SEQUENCER_TMR_EXTERNAL 0x00000002 15048bae9eeSaugustss # define SEQUENCER_TMR_MODE_MIDI 0x00000010 15148bae9eeSaugustss # define SEQUENCER_TMR_MODE_FSK 0x00000020 15248bae9eeSaugustss # define SEQUENCER_TMR_MODE_CLS 0x00000040 15348bae9eeSaugustss # define SEQUENCER_TMR_MODE_SMPTE 0x00000080 15448bae9eeSaugustss #endif 15548bae9eeSaugustss #define SEQUENCER_TMR_METRONOME _IOW ('T', 7, int) 15648bae9eeSaugustss #define SEQUENCER_TMR_SELECT _IOW ('T', 8, int) 15748bae9eeSaugustss 15848bae9eeSaugustss 1594ad7b15dSitohy #define MIDI_CTRL_BANK_SELECT_MSB 0 1604ad7b15dSitohy #define MIDI_CTRL_MODULATION_MSB 1 1614ad7b15dSitohy #define MIDI_CTRL_BREATH_MSB 2 1624ad7b15dSitohy #define MIDI_CTRL_FOOT_MSB 4 1634ad7b15dSitohy #define MIDI_CTRL_PORTAMENTO_TIME_MSB 5 1644ad7b15dSitohy #define MIDI_CTRL_DATA_ENTRY_MSB 6 1654ad7b15dSitohy #define MIDI_CTRL_CHANNEL_VOLUME_MSB 7 1664ad7b15dSitohy #define MIDI_CTRL_BALANCE_MSB 8 1674ad7b15dSitohy #define MIDI_CTRL_PAN_MSB 10 1684ad7b15dSitohy #define MIDI_CTRL_EXPRESSION_MSB 11 169710af634Schap #define MIDI_CTRL_EFFECT_1_MSB 12 170710af634Schap #define MIDI_CTRL_EFFECT_2_MSB 13 1714ad7b15dSitohy #define MIDI_CTRL_GENERAL_PURPOSE_1_MSB 16 1724ad7b15dSitohy #define MIDI_CTRL_GENERAL_PURPOSE_2_MSB 17 1734ad7b15dSitohy #define MIDI_CTRL_GENERAL_PURPOSE_3_MSB 18 1744ad7b15dSitohy #define MIDI_CTRL_GENERAL_PURPOSE_4_MSB 19 1754ad7b15dSitohy #define MIDI_CTRL_BANK_SELECT_LSB 32 1764ad7b15dSitohy #define MIDI_CTRL_MODULATION_LSB 33 1774ad7b15dSitohy #define MIDI_CTRL_BREATH_LSB 34 1784ad7b15dSitohy #define MIDI_CTRL_FOOT_LSB 36 1794ad7b15dSitohy #define MIDI_CTRL_PORTAMENTO_TIME_LSB 37 1804ad7b15dSitohy #define MIDI_CTRL_DATA_ENTRY_LSB 38 1814ad7b15dSitohy #define MIDI_CTRL_CHANNEL_VOLUME_LSB 39 1824ad7b15dSitohy #define MIDI_CTRL_BALANCE_LSB 40 1834ad7b15dSitohy #define MIDI_CTRL_PAN_LSB 42 1844ad7b15dSitohy #define MIDI_CTRL_EXPRESSION_LSB 43 185710af634Schap #define MIDI_CTRL_EFFECT_1_LSB 44 186710af634Schap #define MIDI_CTRL_EFFECT_2_LSB 45 1874ad7b15dSitohy #define MIDI_CTRL_GENERAL_PURPOSE_1_LSB 48 1884ad7b15dSitohy #define MIDI_CTRL_GENERAL_PURPOSE_2_LSB 49 1894ad7b15dSitohy #define MIDI_CTRL_GENERAL_PURPOSE_3_LSB 50 1904ad7b15dSitohy #define MIDI_CTRL_GENERAL_PURPOSE_4_LSB 51 1914ad7b15dSitohy #define MIDI_CTRL_HOLD_1 64 1924ad7b15dSitohy #define MIDI_CTRL_PORTAMENTO 65 1934ad7b15dSitohy #define MIDI_CTRL_SOSTENUTO 66 1944ad7b15dSitohy #define MIDI_CTRL_SOFT_PEDAL 67 195710af634Schap #define MIDI_CTRL_LEGATO 68 1964ad7b15dSitohy #define MIDI_CTRL_HOLD_2 69 1974ad7b15dSitohy #define MIDI_CTRL_SOUND_VARIATION 70 1984ad7b15dSitohy #define MIDI_CTRL_HARMONIC_INTENSITY 71 1994ad7b15dSitohy #define MIDI_CTRL_RELEASE_TIME 72 2004ad7b15dSitohy #define MIDI_CTRL_ATTACK_TIME 73 2014ad7b15dSitohy #define MIDI_CTRL_BRIGHTNESS 74 2024ad7b15dSitohy #define MIDI_CTRL_DECAY_TIME 75 2034ad7b15dSitohy #define MIDI_CTRL_VIBRATO_RATE 76 2044ad7b15dSitohy #define MIDI_CTRL_VIBRATO_DEPTH 77 205710af634Schap #define MIDI_CTRL_VIBRATO_DELAY 78 206710af634Schap #define MIDI_CTRL_VIBRATO_DECAY MIDI_CTRL_VIBRATO_DELAY /*deprecated*/ 207710af634Schap #define MIDI_CTRL_SOUND_10 79 2084ad7b15dSitohy #define MIDI_CTRL_GENERAL_PURPOSE_5 80 2094ad7b15dSitohy #define MIDI_CTRL_GENERAL_PURPOSE_6 81 2104ad7b15dSitohy #define MIDI_CTRL_GENERAL_PURPOSE_7 82 2114ad7b15dSitohy #define MIDI_CTRL_GENERAL_PURPOSE_8 83 2124ad7b15dSitohy #define MIDI_CTRL_PORTAMENTO_CONTROL 84 2134ad7b15dSitohy #define MIDI_CTRL_EFFECT_DEPTH_1 91 2144ad7b15dSitohy #define MIDI_CTRL_EFFECT_DEPTH_2 92 2154ad7b15dSitohy #define MIDI_CTRL_EFFECT_DEPTH_3 93 2164ad7b15dSitohy #define MIDI_CTRL_EFFECT_DEPTH_4 94 2174ad7b15dSitohy #define MIDI_CTRL_EFFECT_DEPTH_5 95 2184ad7b15dSitohy #define MIDI_CTRL_RPN_INCREMENT 96 2194ad7b15dSitohy #define MIDI_CTRL_RPN_DECREMENT 97 2204ad7b15dSitohy #define MIDI_CTRL_NRPN_LSB 98 2214ad7b15dSitohy #define MIDI_CTRL_NRPN_MSB 99 2224ad7b15dSitohy #define MIDI_CTRL_RPN_LSB 100 2234ad7b15dSitohy #define MIDI_CTRL_RPN_MSB 101 2244ad7b15dSitohy #define MIDI_CTRL_SOUND_OFF 120 22548bae9eeSaugustss #define MIDI_CTRL_RESET 121 226710af634Schap #define MIDI_CTRL_LOCAL 122 227710af634Schap #define MIDI_CTRL_NOTES_OFF 123 228710af634Schap #define MIDI_CTRL_ALLOFF MIDI_CTRL_NOTES_OFF /*deprecated*/ 229710af634Schap #define MIDI_CTRL_OMNI_OFF 124 230710af634Schap #define MIDI_CTRL_OMNI_ON 125 231710af634Schap #define MIDI_CTRL_POLY_OFF 126 232710af634Schap #define MIDI_CTRL_POLY_ON 127 2334ad7b15dSitohy 23448bae9eeSaugustss #define MIDI_BEND_NEUTRAL (1<<13) 23548bae9eeSaugustss 236710af634Schap #define MIDI_RPN_PITCH_BEND_SENSITIVITY 0 237710af634Schap #define MIDI_RPN_CHANNEL_FINE_TUNING 1 238710af634Schap #define MIDI_RPN_CHANNEL_COARSE_TUNING 2 239710af634Schap #define MIDI_RPN_TUNING_PROGRAM_CHANGE 3 240710af634Schap #define MIDI_RPN_TUNING_BANK_SELECT 4 241710af634Schap #define MIDI_RPN_MODULATION_DEPTH_RANGE 5 242710af634Schap 24348bae9eeSaugustss #define MIDI_NOTEOFF 0x80 24448bae9eeSaugustss #define MIDI_NOTEON 0x90 24548bae9eeSaugustss #define MIDI_KEY_PRESSURE 0xA0 24648bae9eeSaugustss #define MIDI_CTL_CHANGE 0xB0 24748bae9eeSaugustss #define MIDI_PGM_CHANGE 0xC0 24848bae9eeSaugustss #define MIDI_CHN_PRESSURE 0xD0 24948bae9eeSaugustss #define MIDI_PITCH_BEND 0xE0 25048bae9eeSaugustss #define MIDI_SYSTEM_PREFIX 0xF0 25148bae9eeSaugustss 25248bae9eeSaugustss #define MIDI_IS_STATUS(d) ((d) >= 0x80) 25348bae9eeSaugustss #define MIDI_IS_COMMON(d) ((d) >= 0xf0) 25448bae9eeSaugustss 25548bae9eeSaugustss #define MIDI_SYSEX_START 0xF0 25648bae9eeSaugustss #define MIDI_SYSEX_END 0xF7 25748bae9eeSaugustss 25848bae9eeSaugustss #define MIDI_GET_STATUS(d) ((d) & 0xf0) 25948bae9eeSaugustss #define MIDI_GET_CHAN(d) ((d) & 0x0f) 26048bae9eeSaugustss 26148bae9eeSaugustss #define MIDI_HALF_VEL 64 26248bae9eeSaugustss 26348bae9eeSaugustss #define SEQ_LOCAL 0x80 26448bae9eeSaugustss #define SEQ_TIMING 0x81 26548bae9eeSaugustss #define SEQ_CHN_COMMON 0x92 26648bae9eeSaugustss #define SEQ_CHN_VOICE 0x93 267b7dab0b3Saugustss #define SEQ_SYSEX 0x94 26848bae9eeSaugustss #define SEQ_FULLSIZE 0xfd 26948bae9eeSaugustss 27048bae9eeSaugustss #define SEQ_MK_CHN_VOICE(e, unit, cmd, chan, key, vel) (\ 27148bae9eeSaugustss (e)->arr[0] = SEQ_CHN_VOICE, (e)->arr[1] = (unit), (e)->arr[2] = (cmd),\ 27248bae9eeSaugustss (e)->arr[3] = (chan), (e)->arr[4] = (key), (e)->arr[5] = (vel),\ 27348bae9eeSaugustss (e)->arr[6] = 0, (e)->arr[7] = 0) 27448bae9eeSaugustss #define SEQ_MK_CHN_COMMON(e, unit, cmd, chan, p1, p2, w14) (\ 27533a864eeSaugustss (e)->arr[0] = SEQ_CHN_COMMON, (e)->arr[1] = (unit), (e)->arr[2] = (cmd),\ 27648bae9eeSaugustss (e)->arr[3] = (chan), (e)->arr[4] = (p1), (e)->arr[5] = (p2),\ 27748bae9eeSaugustss *(short*)&(e)->arr[6] = (w14)) 27848bae9eeSaugustss 2794c58d3d9Sbjh21 #if _BYTE_ORDER == _BIG_ENDIAN 280331bfdf5Saugustss /* big endian */ 28148bae9eeSaugustss #define SEQ_PATCHKEY(id) (0xfd00|id) 282331bfdf5Saugustss #else 283331bfdf5Saugustss /* little endian */ 284331bfdf5Saugustss #define SEQ_PATCHKEY(id) ((id<<8)|0xfd) 28548bae9eeSaugustss #endif 28648bae9eeSaugustss struct sysex_info { 287144515ceSperry uint16_t key; /* Use SYSEX_PATCH or MAUI_PATCH here */ 28848bae9eeSaugustss #define SEQ_SYSEX_PATCH SEQ_PATCHKEY(0x05) 28948bae9eeSaugustss #define SEQ_MAUI_PATCH SEQ_PATCHKEY(0x06) 29048bae9eeSaugustss int16_t device_no; /* Synthesizer number */ 29148bae9eeSaugustss int32_t len; /* Size of the sysex data in bytes */ 29248bae9eeSaugustss u_char data[1]; /* Sysex data starts here */ 29348bae9eeSaugustss }; 29448bae9eeSaugustss #define SEQ_SYSEX_HDRSIZE ((u_long)((struct sysex_info *)0)->data) 29548bae9eeSaugustss 29648bae9eeSaugustss typedef unsigned char sbi_instr_data[32]; 29748bae9eeSaugustss struct sbi_instrument { 298144515ceSperry uint16_t key; /* FM_PATCH or OPL3_PATCH */ 29927c5df27Saugustss #define SBI_FM_PATCH SEQ_PATCHKEY(0x01) 30027c5df27Saugustss #define SBI_OPL3_PATCH SEQ_PATCHKEY(0x03) 30148bae9eeSaugustss int16_t device; 30248bae9eeSaugustss int32_t channel; 30348bae9eeSaugustss sbi_instr_data operators; 30448bae9eeSaugustss }; 30548bae9eeSaugustss 306710af634Schap #define TMR_RESET 0 /* beware: not an OSS event */ 30748bae9eeSaugustss #define TMR_WAIT_REL 1 /* Time relative to the prev time */ 30848bae9eeSaugustss #define TMR_WAIT_ABS 2 /* Absolute time since TMR_START */ 30948bae9eeSaugustss #define TMR_STOP 3 31048bae9eeSaugustss #define TMR_START 4 31148bae9eeSaugustss #define TMR_CONTINUE 5 31248bae9eeSaugustss #define TMR_TEMPO 6 31348bae9eeSaugustss #define TMR_ECHO 8 31448bae9eeSaugustss #define TMR_CLOCK 9 /* MIDI clock */ 31548bae9eeSaugustss #define TMR_SPP 10 /* Song position pointer */ 31648bae9eeSaugustss #define TMR_TIMESIG 11 /* Time signature */ 31748bae9eeSaugustss 31848bae9eeSaugustss /* Old sequencer definitions */ 31948bae9eeSaugustss #define SEQOLD_CMDSIZE 4 32048bae9eeSaugustss 32148bae9eeSaugustss #define SEQOLD_NOTEOFF 0 32248bae9eeSaugustss #define SEQOLD_NOTEON 1 32348bae9eeSaugustss #define SEQOLD_WAIT TMR_WAIT_ABS 32448bae9eeSaugustss #define SEQOLD_PGMCHANGE 3 32548bae9eeSaugustss #define SEQOLD_SYNCTIMER TMR_START 32648bae9eeSaugustss #define SEQOLD_MIDIPUTC 5 32748bae9eeSaugustss #define SEQOLD_ECHO TMR_ECHO 32848bae9eeSaugustss #define SEQOLD_AFTERTOUCH 9 32948bae9eeSaugustss #define SEQOLD_CONTROLLER 10 33048bae9eeSaugustss #define SEQOLD_PRIVATE 0xfe 33148bae9eeSaugustss #define SEQOLD_EXTENDED 0xff 33248bae9eeSaugustss 333710af634Schap /* 334710af634Schap * The 'midipitch' data type, used in the kernel between the midisyn layer and 335710af634Schap * onboard synth drivers, and in userland as parameters to the MIDI Tuning Spec 336710af634Schap * (RP-012) universal-system-exclusive messages. It is a MIDI key number shifted 337710af634Schap * left to accommodate 14 bit sub-semitone resolution. In this representation, 338710af634Schap * tuning and bending adjustments are simple addition and subtraction. 339710af634Schap */ 340710af634Schap typedef int32_t midipitch_t; 341710af634Schap 342710af634Schap /* 343710af634Schap * Nominal conversions between midipitches and key numbers. (Beware that these 344710af634Schap * are the nominal, standard correspondences, but whole point of the MIDI Tuning 345710af634Schap * Spec is that you can set things up so the hardware might render key N at 346710af634Schap * actual pitch MIDIPITCH_FROM_KEY(N)+c for some correction c.) 347710af634Schap */ 348710af634Schap #define MIDIPITCH_FROM_KEY(k) ((k)<<14) 349710af634Schap #define MIDIPITCH_TO_KEY(mp) (((mp)+(1<<13))>>14) 350710af634Schap 351710af634Schap #define MIDIPITCH_MAX (MIDIPITCH_FROM_KEY(128)-2) /* ...(128)-1 is reserved */ 352710af634Schap #define MIDIPITCH_OCTAVE 196608 353710af634Schap #define MIDIPITCH_SEMITONE 16384 354710af634Schap #define MIDIPITCH_CENT 164 /* this, regrettably, is inexact. */ 355710af634Schap 356710af634Schap /* 357710af634Schap * For rendering, convert a midipitch (after all tuning adjustments) to Hz. 358710af634Schap * The conversion is DEFINED as MIDI key 69.00000 (A) === 440 Hz equal tempered 359710af634Schap * always. Alternate tunings are obtained by adjusting midipitches. 360710af634Schap * 361710af634Schap * The midihz18_t (Hz shifted left for 18-bit sub-Hz resolution) covers the 362710af634Schap * full midipitch range without losing 21-bit precision, as the lowest midipitch 363710af634Schap * is ~8 Hz (~3 bits left of radix point, 18 right) and for the highest the 364710af634Schap * result still fits in a uint32. 365710af634Schap */ 366710af634Schap typedef uint32_t midihz18_t; 367710af634Schap 368710af634Schap #define MIDIHZ18_TO_HZ(h18) ((h18)>>18) /* truncates! ok for dbg msgs maybe */ 369710af634Schap 370710af634Schap #ifndef _KERNEL 371710af634Schap /* 372710af634Schap * With floating point in userland, can also manipulate midipitches as 373710af634Schap * floating-point fractional MIDI key numbers (tuning adjustments are still 374710af634Schap * additive), and hz18 as fractional Hz (adjustments don't add in this form). 375710af634Schap */ 376710af634Schap #include <math.h> 377710af634Schap #define MIDIPITCH_TO_FRKEY(mp) (scalbn((mp),-14)) 378710af634Schap #define MIDIPITCH_FROM_FRKEY(frk) ((midipitch_t)round(scalbn((frk),14))) 379710af634Schap #define MIDIHZ18_TO_FRHZ(h18) (scalbn((h18),-18)) 380710af634Schap #define MIDIHZ18_FROM_FRHZ(frh) ((midihz18_t)round(scalbn((frh),18))) 381710af634Schap 382710af634Schap #define MIDIPITCH_TO_FRHZ(mp) (440*pow(2,(MIDIPITCH_TO_FRKEY((mp))-69)/12)) 383710af634Schap #define MIDIPITCH_FROM_FRHZ(fhz) \ 384710af634Schap MIDIPITCH_FROM_FRKEY(69+12*log((fhz)/440)/log(2)) 385710af634Schap #define MIDIPITCH_TO_HZ18(mp) MIDIHZ18_FROM_FRHZ(MIDIPITCH_TO_FRHZ((mp))) 386710af634Schap #define MIDIPITCH_FROM_HZ18(h18) MIDIPITCH_FROM_FRHZ(MIDIHZ18_TO_FRHZ((h18))) 387710af634Schap 388710af634Schap #else /* no fp in kernel; only an accurate to-hz18 conversion is implemented */ 389710af634Schap 390710af634Schap extern midihz18_t midisyn_mp2hz18(midipitch_t); 391710af634Schap #define MIDIPITCH_TO_HZ18(mp) (midisyn_mp2hz18((mp))) 392710af634Schap 393710af634Schap #endif /* _KERNEL */ 394710af634Schap 395710af634Schap 396710af634Schap /* 397710af634Schap * A native API for the /dev/music sequencer device follows. The event 398710af634Schap * structures are OSS events at the level of bytes, but for developing or 399710af634Schap * porting applications some macros and documentation are needed to generate 400710af634Schap * and dissect the events; here they are. For porting existing OSS applications, 401710af634Schap * sys/soundcard.h can be extended to supply the usual OSS macros, defining them 402710af634Schap * in terms of these. 403710af634Schap */ 404710af634Schap 405710af634Schap /* 406710af634Schap * TODO: determine OSS compatible structures for TMR_RESET and TMR_CLOCK, 407710af634Schap * OSS values of EV_SYSTEM, SNDCTL_SEQ_ACTSENSE_ENABLE, 408710af634Schap * SNDCTL_SEQ_TIMING_ENABLE, and SNDCTL_SEQ_RT_ENABLE. 409710af634Schap * (TMR_RESET may be a NetBSD extension: it is generated in sequencer.c and 410710af634Schap * has no args. To be corrected if a different definition is found anywhere.) 411710af634Schap */ 412710af634Schap typedef union { 413710af634Schap 414710af634Schap #define _EVT_HDR \ 415710af634Schap uint8_t tag 416710af634Schap 417710af634Schap _EVT_HDR; 418710af634Schap 419710af634Schap #define _LOCAL_HDR \ 420710af634Schap _EVT_HDR; \ 421710af634Schap uint8_t op 422710af634Schap 423710af634Schap struct { _LOCAL_HDR; } local; 424710af634Schap 425710af634Schap struct { 426710af634Schap _LOCAL_HDR; 427710af634Schap uint16_t _zero; 428710af634Schap uint32_t devmask; 429710af634Schap } l_startaudio; 430710af634Schap 431710af634Schap /* define a constructor for local evts - someday when we support any */ 432710af634Schap 433710af634Schap #define _TIMING_HDR \ 434710af634Schap _LOCAL_HDR; \ 435710af634Schap uint16_t _zeroh 436710af634Schap struct { _TIMING_HDR; } timing; 437710af634Schap 438710af634Schap struct { 439710af634Schap _TIMING_HDR; 440710af634Schap uint32_t divisions; 441710af634Schap } t_WAIT_REL, t_WAIT_ABS; 442710af634Schap 443710af634Schap struct { 444710af634Schap _TIMING_HDR; 445710af634Schap uint32_t _zero; 446710af634Schap } t_STOP, t_START, t_CONTINUE, t_RESET; 447710af634Schap 448710af634Schap struct { 449710af634Schap _TIMING_HDR; 450710af634Schap uint32_t bpm; /* unambiguously, (MIDI clocks/minute)/24 */ 451710af634Schap } t_TEMPO; 452710af634Schap 453710af634Schap struct { 454710af634Schap _TIMING_HDR; 455710af634Schap uint32_t cookie; 456710af634Schap } t_ECHO; 457710af634Schap 458710af634Schap struct { 459710af634Schap _TIMING_HDR; 460710af634Schap uint32_t midibeat; /* in low 14 bits; midibeat: 6 MIDI clocks */ 461710af634Schap } t_SPP; 462710af634Schap 463710af634Schap struct { 464710af634Schap _TIMING_HDR; 465710af634Schap #if _BYTE_ORDER == _BIG_ENDIAN 466710af634Schap uint8_t numerator; 467710af634Schap uint8_t lg2denom; 468710af634Schap uint8_t clks_per_click; 469710af634Schap uint8_t dsq_per_24clks; 470710af634Schap #elif _BYTE_ORDER == _LITTLE_ENDIAN 471710af634Schap uint8_t dsq_per_24clks; 472710af634Schap uint8_t clks_per_click; 473710af634Schap uint8_t lg2denom; 474710af634Schap uint8_t numerator; 475710af634Schap #else 476710af634Schap #error "unexpected _BYTE_ORDER" 477710af634Schap #endif 478710af634Schap } t_TIMESIG; 479710af634Schap 480710af634Schap struct { /* use this only to implement OSS compatibility macro */ 481710af634Schap _TIMING_HDR; 482710af634Schap uint32_t signature; 483710af634Schap } t_osscompat_timesig; 484710af634Schap 485710af634Schap 486710af634Schap #define _COMMON_HDR \ 487710af634Schap _EVT_HDR; \ 488710af634Schap uint8_t device; \ 489710af634Schap uint8_t op; \ 490710af634Schap uint8_t channel 491710af634Schap 492710af634Schap struct { _COMMON_HDR; } common; 493710af634Schap 494710af634Schap struct { 495710af634Schap _COMMON_HDR; 496710af634Schap uint8_t controller; 497710af634Schap uint8_t _zero; 498710af634Schap uint16_t value; 499710af634Schap } c_CTL_CHANGE; 500710af634Schap 501710af634Schap struct { 502710af634Schap _COMMON_HDR; 503710af634Schap uint8_t program; 504710af634Schap uint8_t _zero0; 505710af634Schap uint16_t _zero1; 506710af634Schap } c_PGM_CHANGE; 507710af634Schap 508710af634Schap struct { 509710af634Schap _COMMON_HDR; 510710af634Schap uint8_t pressure; 511710af634Schap uint8_t _zero0; 512710af634Schap uint16_t _zero1; 513710af634Schap } c_CHN_PRESSURE; 514710af634Schap 515710af634Schap struct { 516710af634Schap _COMMON_HDR; 517710af634Schap uint8_t _zero0; 518710af634Schap uint8_t _zero1; 519710af634Schap uint16_t value; 520710af634Schap } c_PITCH_BEND; 521710af634Schap 522710af634Schap #define _VOICE_HDR \ 523710af634Schap _COMMON_HDR; \ 524710af634Schap uint8_t key 525710af634Schap 526710af634Schap struct { _VOICE_HDR; } voice; 527710af634Schap 528710af634Schap struct { 529710af634Schap _VOICE_HDR; 530710af634Schap uint8_t velocity; 531710af634Schap uint16_t _zero; 532710af634Schap } c_NOTEOFF, c_NOTEON; 533710af634Schap 534710af634Schap struct { 535710af634Schap _VOICE_HDR; 536710af634Schap uint8_t pressure; 537710af634Schap uint16_t _zero; 538710af634Schap } c_KEY_PRESSURE; 539710af634Schap 540710af634Schap struct { 541710af634Schap _EVT_HDR; 542710af634Schap uint8_t device; 543710af634Schap uint8_t buffer[6]; 544710af634Schap } sysex; 545710af634Schap 546710af634Schap struct { 547710af634Schap _EVT_HDR; 548710af634Schap uint8_t device; 549710af634Schap uint8_t status; 550710af634Schap uint8_t data[2]; 551710af634Schap } system; 552710af634Schap 553710af634Schap struct { 554710af634Schap _EVT_HDR; 555710af634Schap uint8_t byte; 556710af634Schap uint8_t device; 557710af634Schap uint8_t _zero0; 558710af634Schap uint32_t _zero1; 559710af634Schap } putc; /* a seqold event that's still needed at times, ugly as 'tis */ 560710af634Schap 561710af634Schap struct { 562710af634Schap _EVT_HDR; 563710af634Schap uint8_t byte[7]; 564710af634Schap } unknown; /* for debug/display */ 565710af634Schap 566710af634Schap #undef _VOICE_HDR 567710af634Schap #undef _COMMON_HDR 568710af634Schap #undef _TIMING_HDR 569710af634Schap #undef _LOCAL_HDR 570710af634Schap #undef _EVT_HDR 571710af634Schap 572710af634Schap } __packed seq_event_t; 573710af634Schap 574710af634Schap #define _SEQ_TAG_NOTEOFF SEQ_CHN_VOICE 575710af634Schap #define _SEQ_TAG_NOTEON SEQ_CHN_VOICE 576710af634Schap #define _SEQ_TAG_KEY_PRESSURE SEQ_CHN_VOICE 577710af634Schap 578710af634Schap #define _SEQ_TAG_CTL_CHANGE SEQ_CHN_COMMON 579710af634Schap #define _SEQ_TAG_PGM_CHANGE SEQ_CHN_COMMON 580710af634Schap #define _SEQ_TAG_CHN_PRESSURE SEQ_CHN_COMMON 581710af634Schap #define _SEQ_TAG_PITCH_BEND SEQ_CHN_COMMON 582710af634Schap 583710af634Schap #if __STDC_VERSION__ >= 199901L 584710af634Schap 585710af634Schap #define SEQ_MK_EVENT(_member,_tag,...) \ 586710af634Schap (seq_event_t){ ._member = { .tag = (_tag), __VA_ARGS__ } } 587710af634Schap 588710af634Schap #define SEQ_MK_TIMING(_op,...) \ 589710af634Schap SEQ_MK_EVENT(t_##_op, SEQ_TIMING, .op = TMR_##_op, __VA_ARGS__) 590710af634Schap 591710af634Schap #define SEQ_MK_CHN(_op,...) \ 592710af634Schap SEQ_MK_EVENT(c_##_op, _SEQ_TAG_##_op, .op = MIDI_##_op, __VA_ARGS__) 593710af634Schap 594710af634Schap #define SEQ_MK_SYSEX(_dev,...) \ 595710af634Schap SEQ_MK_EVENT(sysex, 0x94, .device=(_dev), \ 596710af634Schap .buffer={0xff, 0xff, 0xff, 0xff, 0xff, 0xff, __VA_ARGS__}) 597710af634Schap 598710af634Schap #else /* assume gcc 2.95.3 */ 599710af634Schap 600710af634Schap #define SEQ_MK_EVENT(_member,_tag,_args...) \ 601710af634Schap (seq_event_t){ ._member = { .tag = (_tag), _args } } 602710af634Schap 603710af634Schap #define SEQ_MK_TIMING(_op,_args...) \ 604710af634Schap SEQ_MK_EVENT(t_##_op, SEQ_TIMING, .op = TMR_##_op, _args) 605710af634Schap 606710af634Schap #define SEQ_MK_CHN(_op,_args...) \ 607710af634Schap SEQ_MK_EVENT(c_##_op, _SEQ_TAG_##_op, .op = MIDI_##_op, _args) 608710af634Schap 609710af634Schap #define SEQ_MK_SYSEX(_dev,_args...) \ 610710af634Schap SEQ_MK_EVENT(sysex, 0x94, .device=(_dev), \ 611710af634Schap .buffer={0xff, 0xff, 0xff, 0xff, 0xff, 0xff, _args}) 612710af634Schap 613710af634Schap #endif /* c99 vs. gcc 2.95.3 */ 614710af634Schap 615710af634Schap #if 0 616710af634Schap #include <fcntl.h> 617710af634Schap #include <stdio.h> 618710af634Schap int 619710af634Schap main(int argc, char **argv) 620710af634Schap { 621710af634Schap int i; 622710af634Schap int fd; 623710af634Schap seq_event_t e; 624710af634Schap 625710af634Schap /* simple usage example (add a buffer to reduce syscall overhead) */ 626710af634Schap fd = open("/dev/music", O_RDWR); 627710af634Schap write(fd, &SEQ_MK_TIMING(START), sizeof (seq_event_t)); 628710af634Schap 629710af634Schap read(fd, &e, sizeof e); 630710af634Schap switch ( e.tag ) { 631710af634Schap case SEQ_CHN_VOICE: 632710af634Schap switch ( e.voice.op ) { 633710af634Schap case MIDI_NOTEON: 634710af634Schap printf("Note on, dev=%d chn=%d key=%d vel=%d\n", 635710af634Schap e.c_NOTEON.device, e.c_NOTEON.channel, 636710af634Schap e.c_NOTEON.key, e.c_NOTEON.velocity); 637710af634Schap } 638710af634Schap } 639710af634Schap 640710af634Schap /* all the macros: */ 641710af634Schap e = SEQ_MK_TIMING(START); 642710af634Schap e = SEQ_MK_TIMING(STOP); 643710af634Schap e = SEQ_MK_TIMING(CONTINUE); 644710af634Schap /* 645710af634Schap * Wait until the specified number of divisions from the timer start 646710af634Schap * (abs) or the preceding event (rel). The number of divisions to a 647710af634Schap * beat or to a MIDI clock is determined by the timebase (set by 648710af634Schap * ioctl). The tempo is expressed in beats per minute, where a beat 649710af634Schap * is always 24 MIDI clocks (and usually equated to a quarter note, 650710af634Schap * but that can be changed with timesig)--that is, tempo is 651710af634Schap * (MIDI clocks per minute)/24. The timebase is the number of divisions 652710af634Schap * in a beat--that is, the number of divisions that make up 24 MIDI 653710af634Schap * clocks--so the timebase is 24*(divisions per MIDI clock). The MThd 654710af634Schap * header in a SMF gives the 'natural' timebase for the file; if the 655710af634Schap * timebase is set accordingly, then the delay values appearing in the 656710af634Schap * tracks are in terms of divisions, and can be used as WAIT_REL 657710af634Schap * arguments without modification. 658710af634Schap */ 659710af634Schap e = SEQ_MK_TIMING(WAIT_ABS, .divisions=192); 660710af634Schap e = SEQ_MK_TIMING(WAIT_REL, .divisions=192); 661710af634Schap /* 662710af634Schap * The 'beat' in bpm is 24 MIDI clocks (usually a quarter note but 663710af634Schap * changeable with timesig). 664710af634Schap */ 665710af634Schap e = SEQ_MK_TIMING(TEMPO, .bpm=84); 666710af634Schap /* 667710af634Schap * An ECHO event on output appears on input at the appointed time; the 668710af634Schap * cookie can be anything of interest to the application. Can be used 669710af634Schap * in schemes to get some control over latency. 670710af634Schap */ 671710af634Schap e = SEQ_MK_TIMING(ECHO, .cookie=0xfeedface); 672710af634Schap /* 673710af634Schap * A midibeat is smaller than a beat. It is six MIDI clocks, or a fourth 674710af634Schap * of a beat, or a sixteenth note if the beat is a quarter. SPP is a 675710af634Schap * request to position at the requested midibeat from the start of the 676710af634Schap * sequence. [sequencer does not at present implement SPP] 677710af634Schap */ 678710af634Schap e = SEQ_MK_TIMING(SPP, .midibeat=128); 679710af634Schap /* 680710af634Schap * numerator and lg2denom describe the time signature as it would 681710af634Schap * appear on a staff, where lg2denom of 0,1,2,3... corresponds to 682710af634Schap * denominator of 1,2,4,8... respectively. So the example below 683710af634Schap * corresponds to 4/4. dsq_per_24clks defines the relationship of 684710af634Schap * MIDI clocks to note values, by specifying the number of 685710af634Schap * demisemiquavers (32nd notes) represented by 24 MIDI clocks. 686710af634Schap * The default is 8 demisemiquavers, or a quarter note. 687710af634Schap * clks_per_click can configure a metronome (for example, the MPU401 688710af634Schap * had such a feature in intelligent mode) to click every so many 689710af634Schap * MIDI clocks. The 24 in this example would give a click every quarter 690710af634Schap * note. [sequencer does not at present implement TIMESIG] 691710af634Schap */ 692710af634Schap e = SEQ_MK_TIMING(TIMESIG, .numerator=4, .lg2denom=2, 693710af634Schap .clks_per_click=24, .dsq_per_24clks=8); 694710af634Schap /* 695710af634Schap * This example declares 6/8 time where the beat (24 clocks) is the 696710af634Schap * eighth note, but the metronome clicks every dotted quarter (twice 697710af634Schap * per measure): 698710af634Schap */ 699710af634Schap e = SEQ_MK_TIMING(TIMESIG, .numerator=6, .lg2denom=3, 700710af634Schap .clks_per_click=72, .dsq_per_24clks=4); 701710af634Schap /* 702710af634Schap * An alternate declaration for 6/8 where the beat (24 clocks) is now 703710af634Schap * the dotted quarter and corresponds to the metronome click: 704710af634Schap */ 705710af634Schap e = SEQ_MK_TIMING(TIMESIG, .numerator=6, .lg2denom=3, 706710af634Schap .clks_per_click=24, .dsq_per_24clks=12); 707710af634Schap /* 708710af634Schap * It would also be possible to keep the default correspondence of 709710af634Schap * 24 clocks to the quarter note (8 dsq), and still click the metronome 710710af634Schap * each dotted quarter: 711710af634Schap */ 712710af634Schap e = SEQ_MK_TIMING(TIMESIG, .numerator=6, .lg2denom=3, 713710af634Schap .clks_per_click=36, .dsq_per_24clks=8); 714710af634Schap 715710af634Schap e = SEQ_MK_CHN(NOTEON, .device=1, .channel=0, .key=60, .velocity=64); 716710af634Schap e = SEQ_MK_CHN(NOTEOFF, .device=1, .channel=0, .key=60, .velocity=64); 717710af634Schap e = SEQ_MK_CHN(KEY_PRESSURE, .device=1, .channel=0, .key=60, 718710af634Schap .pressure=64); 719710af634Schap 720710af634Schap /* 721710af634Schap * sequencer does not at present implement CTL_CHANGE well. The API 722710af634Schap * provides for a 14-bit value where you give the controller index 723710af634Schap * of the controller MSB and sequencer will split the 14-bit value to 724710af634Schap * the controller MSB and LSB for you--but it doesn't; it ignores the 725710af634Schap * high bits of value and writes the low bits whether you have specified 726710af634Schap * MSB or LSB. That would not be hard to fix but for the fact that OSS 727710af634Schap * itself seems to suffer from the same mixup (and its behavior differs 728710af634Schap * with whether the underlying device is an onboard synth or a MIDI 729710af634Schap * link!) so there is surely a lot of code that relies on it being 730710af634Schap * broken :(. 731710af634Schap * (Note: as the OSS developers have ceased development of the 732710af634Schap * /dev/music API as of OSS4, it would be possible given a complete 733710af634Schap * list of the events defined in OSS4 to add some new ones for native 734710af634Schap * use without fear of future conflict, such as a better ctl_change.) 735710af634Schap */ 736710af634Schap e = SEQ_MK_CHN(CTL_CHANGE, .device=1, .channel=0, 737710af634Schap .controller=MIDI_CTRL_EXPRESSION_MSB, .value=8192);/*XX*/ 738710af634Schap /* 739710af634Schap * The way you really have to do it: 740710af634Schap */ 741710af634Schap e = SEQ_MK_CHN(CTL_CHANGE, .device=1, .channel=0, 742710af634Schap .controller=MIDI_CTRL_EXPRESSION_MSB, .value=8192>>7); 743710af634Schap e = SEQ_MK_CHN(CTL_CHANGE, .device=1, .channel=0, 744710af634Schap .controller=MIDI_CTRL_EXPRESSION_LSB, .value=8192&0x7f); 745710af634Schap 746710af634Schap e = SEQ_MK_CHN(PGM_CHANGE, .device=1, .channel=0, .program=51); 747710af634Schap e = SEQ_MK_CHN(CHN_PRESSURE, .device=1, .channel=0, .pressure=64); 748710af634Schap e = SEQ_MK_CHN(PITCH_BEND, .device=1, .channel=0, .value=8192); 749710af634Schap 750710af634Schap /* 751710af634Schap * A SYSEX event carries up to six bytes of a system exclusive message. 752710af634Schap * The first such message must begin with MIDI_SYSEX_START (0xf0), the 753710af634Schap * last must end with MIDI_SYSEX_END (0xf7), and only the last may carry 754710af634Schap * fewer than 6 bytes. To supply message bytes in the macro, you must 755710af634Schap * prefix the first with [0]= as shown. The macro's first argument is 756710af634Schap * the device. 757710af634Schap */ 758710af634Schap e = SEQ_MK_SYSEX(1,[0]=MIDI_SYSEX_START,1,2,MIDI_SYSEX_END); 759710af634Schap /* 760710af634Schap * In some cases it may be easier to use the macro only to initialize 761710af634Schap * the event, and fill in the message bytes later. The code that fills 762710af634Schap * in the message does not need to store 0xff following the SYSEX_END. 763710af634Schap */ 764710af634Schap e = SEQ_MK_SYSEX(1); 765710af634Schap for ( i = 0; i < 3; ++ i ) 766710af634Schap e.sysex.buffer[i] = i; 767710af634Schap /* 768710af634Schap * It would be nice to think the old /dev/sequencer MIDIPUTC event 769710af634Schap * obsolete, but it is still needed (absent any better API) by any MIDI 770710af634Schap * file player that will implement the ESCAPED events that may occur in 771710af634Schap * SMF. Sorry. Here's how to use it: 772710af634Schap */ 773710af634Schap e = SEQ_MK_EVENT(putc, SEQOLD_MIDIPUTC, .device=1, .byte=42); 774710af634Schap 775710af634Schap printf("confirm event size: %d (should be 8)\n", sizeof (seq_event_t)); 776710af634Schap return 0; 777710af634Schap } 778710af634Schap #endif /* 0 */ 779710af634Schap 78048bae9eeSaugustss #endif /* !_SYS_MIDIIO_H_ */ 781