diff options
Diffstat (limited to 'sys/i386/isa/sound/midi_synth.c')
-rw-r--r-- | sys/i386/isa/sound/midi_synth.c | 675 |
1 files changed, 0 insertions, 675 deletions
diff --git a/sys/i386/isa/sound/midi_synth.c b/sys/i386/isa/sound/midi_synth.c deleted file mode 100644 index e63b24a..0000000 --- a/sys/i386/isa/sound/midi_synth.c +++ /dev/null @@ -1,675 +0,0 @@ -/* - * sound/midi_synth.c - * - * High level midi sequencer manager for dumb MIDI interfaces. - * - * Copyright by Hannu Savolainen 1993 - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. 2. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ - -#define USE_SEQ_MACROS -#define USE_SIMPLE_MACROS - -#include <stddef.h> - -#include <i386/isa/sound/sound_config.h> - -#if defined(CONFIGURE_SOUNDCARD) /* && defined(CONFIG_MIDI) */ - -#define _MIDI_SYNTH_C_ - -static int *sysex_sleeper = NULL; -static volatile struct snd_wait sysex_sleep_flag = {0}; - -#include <i386/isa/sound/midi_synth.h> - -static int midi2synth[MAX_MIDI_DEV]; -static int sysex_state[MAX_MIDI_DEV] = -{0}; -static unsigned char prev_out_status[MAX_MIDI_DEV]; - -#ifndef CONFIG_SEQUENCER -#define STORE(cmd) -#else -#define STORE(cmd) { \ - int len; \ - unsigned char obuf[8]; \ - cmd; \ - seq_input_event(obuf, len); \ -} -#endif - -#define _seqbuf obuf -#define _seqbufptr 0 -#define _SEQ_ADVBUF(x) len=x - -void -do_midi_msg(int synthno, unsigned char *msg, int mlen) -{ - switch (msg[0] & 0xf0) { - case 0x90: - if (msg[2] != 0) { - STORE(SEQ_START_NOTE(synthno, msg[0] & 0x0f, msg[1], msg[2])); - break; - } - msg[2] = 64; - - case 0x80: - STORE(SEQ_STOP_NOTE(synthno, msg[0] & 0x0f, msg[1], msg[2])); - break; - - case 0xA0: - STORE(SEQ_KEY_PRESSURE(synthno, msg[0] & 0x0f, msg[1], msg[2])); - break; - - case 0xB0: - STORE(SEQ_CONTROL(synthno, msg[0] & 0x0f, msg[1], msg[2])); - break; - - case 0xC0: - STORE(SEQ_SET_PATCH(synthno, msg[0] & 0x0f, msg[1])); - break; - - case 0xD0: - STORE(SEQ_CHN_PRESSURE(synthno, msg[0] & 0x0f, msg[1])); - break; - - case 0xE0: - STORE(SEQ_BENDER(synthno, msg[0] & 0x0f, - (msg[1] % 0x7f) | ((msg[2] & 0x7f) << 7))); - break; - - default: - /* - * printf ("MPU: Unknown midi channel message %02x\n", - * msg[0]); - */ - ; - } -} - -static void -midi_outc(int midi_dev, int data) -{ - int timeout; - - for (timeout = 0; timeout < 32000; timeout++) - if (midi_devs[midi_dev]->putc(midi_dev, (unsigned char) (data & 0xff))) { - if (data & 0x80) /* Status byte */ - prev_out_status[midi_dev] = - (unsigned char) (data & 0xff); /* Store for running - * status */ - return; /* Mission complete */ - } - /* - * Sorry! No space on buffers. - */ - printf("Midi send timed out\n"); -} - -static int -prefix_cmd(int midi_dev, unsigned char status) -{ - if ((char *) midi_devs[midi_dev]->prefix_cmd == NULL) - return 1; - - return midi_devs[midi_dev]->prefix_cmd(midi_dev, status); -} - -static void -midi_synth_input(int orig_dev, unsigned char data) -{ - int dev; - struct midi_input_info *inc; - - static unsigned char len_tab[] = /* # of data bytes following a status */ - { - 2, /* 8x */ - 2, /* 9x */ - 2, /* Ax */ - 2, /* Bx */ - 1, /* Cx */ - 1, /* Dx */ - 2, /* Ex */ - 0 /* Fx */ - }; - - if (orig_dev < 0 || orig_dev > num_midis) - return; - - if (data == 0xfe) /* Ignore active sensing */ - return; - - dev = midi2synth[orig_dev]; - inc = &midi_devs[orig_dev]->in_info; - - switch (inc->m_state) { - case MST_INIT: - if (data & 0x80) { /* MIDI status byte */ - if ((data & 0xf0) == 0xf0) { /* Common message */ - switch (data) { - case 0xf0: /* Sysex */ - inc->m_state = MST_SYSEX; - break; /* Sysex */ - - case 0xf1: /* MTC quarter frame */ - case 0xf3: /* Song select */ - inc->m_state = MST_DATA; - inc->m_ptr = 1; - inc->m_left = 1; - inc->m_buf[0] = data; - break; - - case 0xf2: /* Song position pointer */ - inc->m_state = MST_DATA; - inc->m_ptr = 1; - inc->m_left = 2; - inc->m_buf[0] = data; - break; - - default: - inc->m_buf[0] = data; - inc->m_ptr = 1; - do_midi_msg(dev, inc->m_buf, inc->m_ptr); - inc->m_ptr = 0; - inc->m_left = 0; - } - } else { - inc->m_state = MST_DATA; - inc->m_ptr = 1; - inc->m_left = len_tab[(data >> 4) - 8]; - inc->m_buf[0] = inc->m_prev_status = data; - } - } else if (inc->m_prev_status & 0x80) { /* Ignore if no previous - * status (yet) *//* Data byte (use running status) */ - inc->m_state = MST_DATA; - inc->m_ptr = 2; - inc->m_left = len_tab[(data >> 4) - 8] - 1; - inc->m_buf[0] = inc->m_prev_status; - inc->m_buf[1] = data; - } - break; /* MST_INIT */ - - case MST_DATA: - inc->m_buf[inc->m_ptr++] = data; - if (--inc->m_left <= 0) { - inc->m_state = MST_INIT; - do_midi_msg(dev, inc->m_buf, inc->m_ptr); - inc->m_ptr = 0; - } - break; /* MST_DATA */ - - case MST_SYSEX: - if (data == 0xf7) { /* Sysex end */ - inc->m_state = MST_INIT; - inc->m_left = 0; - inc->m_ptr = 0; - } - break; /* MST_SYSEX */ - - default: - printf("MIDI%d: Unexpected state %d (%02x)\n", orig_dev, inc->m_state, - (int) data); - inc->m_state = MST_INIT; - } -} - -static void -leave_sysex(int dev) -{ - int orig_dev = synth_devs[dev]->midi_dev; - int timeout = 0; - - if (!sysex_state[dev]) - return; - - sysex_state[dev] = 0; - - while (!midi_devs[orig_dev]->putc(orig_dev, 0xf7) && timeout < 1000) - timeout++; - - sysex_state[dev] = 0; -} - -static void -midi_synth_output(int dev) -{ - /* - * Currently NOP - */ -} - -int -midi_synth_ioctl(int dev, unsigned int cmd, ioctl_arg arg) -{ - /* - * int orig_dev = synth_devs[dev]->midi_dev; - */ - - switch (cmd) { - - case SNDCTL_SYNTH_INFO: - bcopy(synth_devs[dev]->info, &(((char *) arg)[0]), sizeof(struct synth_info)); - return 0; - break; - - case SNDCTL_SYNTH_MEMAVL: - return 0x7fffffff; - break; - - default: - return -(EINVAL); - } -} - -int -midi_synth_kill_note(int dev, int channel, int note, int velocity) -{ - int orig_dev = synth_devs[dev]->midi_dev; - int msg, chn; - - if (note < 0 || note > 127) - return 0; - if (channel < 0 || channel > 15) - return 0; - RANGE (velocity, 0, 127 ) ; - leave_sysex(dev); - - msg = prev_out_status[orig_dev] & 0xf0; - chn = prev_out_status[orig_dev] & 0x0f; - - if (chn == channel && ((msg == 0x90 && velocity == 64) || msg == 0x80)) { /* Use running status */ - if (!prefix_cmd(orig_dev, note)) - return 0; - - midi_outc(orig_dev, note); - - if (msg == 0x90)/* Running status = Note on */ - midi_outc(orig_dev, 0); /* Note on with velocity 0 == note off */ - else - midi_outc(orig_dev, velocity); - } else { - if (velocity == 64) { - if (!prefix_cmd(orig_dev, 0x90 | (channel & 0x0f))) - return 0; - midi_outc(orig_dev, 0x90 | (channel & 0x0f)); /* Note on */ - midi_outc(orig_dev, note); - midi_outc(orig_dev, 0); /* Zero G */ - } else { - if (!prefix_cmd(orig_dev, 0x80 | (channel & 0x0f))) - return 0; - midi_outc(orig_dev, 0x80 | (channel & 0x0f)); /* Note off */ - midi_outc(orig_dev, note); - midi_outc(orig_dev, velocity); - } - } - - return 0; -} - -int -midi_synth_set_instr(int dev, int channel, int instr_no) -{ - int orig_dev = synth_devs[dev]->midi_dev; - - if (instr_no < 0 || instr_no > 127) - return 0; - if (channel < 0 || channel > 15) - return 0; - - leave_sysex(dev); - - if (!prefix_cmd(orig_dev, 0xc0 | (channel & 0x0f))) - return 0; - midi_outc(orig_dev, 0xc0 | (channel & 0x0f)); /* Program change */ - midi_outc(orig_dev, instr_no); - - return 0; -} - -int -midi_synth_start_note(int dev, int channel, int note, int velocity) -{ - int orig_dev = synth_devs[dev]->midi_dev; - int msg, chn; - - if (note < 0 || note > 127) - return 0; - if (channel < 0 || channel > 15) - return 0; - RANGE (velocity, 0, 127 ); - leave_sysex(dev); - - msg = prev_out_status[orig_dev] & 0xf0; - chn = prev_out_status[orig_dev] & 0x0f; - - if (chn == channel && msg == 0x90) { /* Use running status */ - if (!prefix_cmd(orig_dev, note)) - return 0; - midi_outc(orig_dev, note); - midi_outc(orig_dev, velocity); - } else { - if (!prefix_cmd(orig_dev, 0x90 | (channel & 0x0f))) - return 0; - midi_outc(orig_dev, 0x90 | (channel & 0x0f)); /* Note on */ - midi_outc(orig_dev, note); - midi_outc(orig_dev, velocity); - } - return 0; -} - -void -midi_synth_reset(int dev) -{ - - leave_sysex(dev); -} - -int -midi_synth_open(int dev, int mode) -{ - int orig_dev = synth_devs[dev]->midi_dev; - int err; - unsigned long flags; - struct midi_input_info *inc; - - if (orig_dev < 0 || orig_dev > num_midis) - return -(ENXIO); - - midi2synth[orig_dev] = dev; - sysex_state[dev] = 0; - prev_out_status[orig_dev] = 0; - - if ((err = midi_devs[orig_dev]->open(orig_dev, mode, - midi_synth_input, midi_synth_output)) < 0) - return err; - - inc = &midi_devs[orig_dev]->in_info; - - flags = splhigh(); - inc->m_busy = 0; - inc->m_state = MST_INIT; - inc->m_ptr = 0; - inc->m_left = 0; - inc->m_prev_status = 0x00; - splx(flags); - - sysex_sleep_flag.aborting = 0; - sysex_sleep_flag.mode = WK_NONE; - - return 1; -} - -void -midi_synth_close(int dev) -{ - int orig_dev = synth_devs[dev]->midi_dev; - - leave_sysex(dev); - - /* - * Shut up the synths by sending just single active sensing message. - */ - midi_devs[orig_dev]->putc(orig_dev, 0xfe); - - midi_devs[orig_dev]->close(orig_dev); -} - -void -midi_synth_hw_control(int dev, unsigned char *event) -{ -} - -int -midi_synth_load_patch(int dev, int format, snd_rw_buf * addr, - int offs, int count, int pmgr_flag) -{ - int orig_dev = synth_devs[dev]->midi_dev; - - struct sysex_info sysex; - int i; - unsigned long left, src_offs, eox_seen = 0; - int first_byte = 1; - int hdr_size = offsetof(struct sysex_info, data); - - leave_sysex(dev); - - if (!prefix_cmd(orig_dev, 0xf0)) - return 0; - - if (format != SYSEX_PATCH) { - printf("MIDI Error: Invalid patch format (key) 0x%x\n", format); - return -(EINVAL); - } - if (count < hdr_size) { - printf("MIDI Error: Patch header too short\n"); - return -(EINVAL); - } - count -= hdr_size; - - /* - * Copy the header from user space but ignore the first bytes which - * have been transferred already. - */ - - - if (uiomove(&((char *) &sysex)[offs], hdr_size - offs, addr)) { - printf("sb: Bad copyin()!\n"); - }; - - if (count < sysex.len) { - printf("MIDI Warning: Sysex record too short (%d<%d)\n", - count, (int) sysex.len); - sysex.len = count; - } - left = sysex.len; - src_offs = 0; - - sysex_sleep_flag.aborting = 0; - sysex_sleep_flag.mode = WK_NONE; - - for (i = 0; i < left && !(sysex_sleep_flag.aborting); i++) { - unsigned char data; - - uiomove((char *) &(data), 1, addr); - - eox_seen = (i > 0 && data & 0x80); /* End of sysex */ - - if (eox_seen && data != 0xf7) - data = 0xf7; - - if (i == 0) { - if (data != 0xf0) { - printf("Error: Sysex start missing\n"); - return -(EINVAL); - } - } - while (!midi_devs[orig_dev]->putc(orig_dev, - (unsigned char) (data & 0xff)) && - !(sysex_sleep_flag.aborting)) { - int chn; - - - sysex_sleeper = &chn; - DO_SLEEP(chn, sysex_sleep_flag, 1); - - }; /* Wait for timeout */ - - if (!first_byte && data & 0x80) - return 0; - first_byte = 0; - } - - if (!eox_seen) - midi_outc(orig_dev, 0xf7); - return 0; -} - -void -midi_synth_panning(int dev, int channel, int pressure) -{ -} - -void -midi_synth_aftertouch(int dev, int channel, int pressure) -{ - int orig_dev = synth_devs[dev]->midi_dev; - int msg, chn; - - if (pressure < 0 || pressure > 127) - return; - if (channel < 0 || channel > 15) - return; - - leave_sysex(dev); - - msg = prev_out_status[orig_dev] & 0xf0; - chn = prev_out_status[orig_dev] & 0x0f; - - if (msg != 0xd0 || chn != channel) { /* Test for running status */ - if (!prefix_cmd(orig_dev, 0xd0 | (channel & 0x0f))) - return; - midi_outc(orig_dev, 0xd0 | (channel & 0x0f)); /* Channel pressure */ - } else if (!prefix_cmd(orig_dev, pressure)) - return; - - midi_outc(orig_dev, pressure); -} - -void -midi_synth_controller(int dev, int channel, int ctrl_num, int value) -{ - int orig_dev = synth_devs[dev]->midi_dev; - int chn, msg; - - if (ctrl_num < 1 || ctrl_num > 127) - return; /* NOTE! Controller # 0 ignored */ - if (channel < 0 || channel > 15) - return; - - leave_sysex(dev); - - msg = prev_out_status[orig_dev] & 0xf0; - chn = prev_out_status[orig_dev] & 0x0f; - - if (msg != 0xb0 || chn != channel) { - if (!prefix_cmd(orig_dev, 0xb0 | (channel & 0x0f))) - return; - midi_outc(orig_dev, 0xb0 | (channel & 0x0f)); - } else if (!prefix_cmd(orig_dev, ctrl_num)) - return; - - midi_outc(orig_dev, ctrl_num); - midi_outc(orig_dev, value & 0x7f); -} - -int -midi_synth_patchmgr(int dev, struct patmgr_info * rec) -{ - return -(EINVAL); -} - -void -midi_synth_bender(int dev, int channel, int value) -{ - int orig_dev = synth_devs[dev]->midi_dev; - int msg, prev_chn; - - if (channel < 0 || channel > 15) - return; - - if (value < 0 || value > 16383) - return; - - leave_sysex(dev); - - msg = prev_out_status[orig_dev] & 0xf0; - prev_chn = prev_out_status[orig_dev] & 0x0f; - - if (msg != 0xd0 || prev_chn != channel) { /* Test for running status */ - if (!prefix_cmd(orig_dev, 0xe0 | (channel & 0x0f))) - return; - midi_outc(orig_dev, 0xe0 | (channel & 0x0f)); - } else if (!prefix_cmd(orig_dev, value & 0x7f)) - return; - - midi_outc(orig_dev, value & 0x7f); - midi_outc(orig_dev, (value >> 7) & 0x7f); -} - -void -midi_synth_setup_voice(int dev, int voice, int channel) -{ -} - -int -midi_synth_send_sysex(int dev, unsigned char *bytes, int len) -{ - int orig_dev = synth_devs[dev]->midi_dev; - int i; - - for (i = 0; i < len; i++) { - switch (bytes[i]) { - case 0xf0: /* Start sysex */ - if (!prefix_cmd(orig_dev, 0xf0)) - return 0; - sysex_state[dev] = 1; - break; - - case 0xf7: /* End sysex */ - if (!sysex_state[dev]) /* Orphan sysex end */ - return 0; - sysex_state[dev] = 0; - break; - - default: - if (!sysex_state[dev]) - return 0; - - if (bytes[i] & 0x80) { /* Error. Another message before sysex end */ - bytes[i] = 0xf7; /* Sysex end */ - sysex_state[dev] = 0; - } - } - - if (!midi_devs[orig_dev]->putc(orig_dev, bytes[i])) { - /* - * Hardware leve buffer is full. Abort the sysex message. - */ - - int timeout = 0; - - bytes[i] = 0xf7; - sysex_state[dev] = 0; - - while (!midi_devs[orig_dev]->putc(orig_dev, bytes[i]) && - timeout < 1000) - timeout++; - } - if (!sysex_state[dev]) - return 0; - } - - return 0; -} -#endif |