⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sequencer.c

📁 freebsd v4.4内核源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * sound/sequencer.c * * The sequencer personality manager. * * 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 SEQUENCER_C#include <i386/isa/sound/sound_config.h>#include <i386/isa/sound/midi_ctrl.h>extern void seq_drain_midi_queues __P((void));#ifdef CONFIGURE_SOUNDCARD#ifndef EXCLUDE_SEQUENCERstatic int      sequencer_ok = 0;static struct sound_timer_operations *tmr;static int      tmr_no = -1;	/* Currently selected timer */static int      pending_timer = -1;	/* For timer change operation *//* * Local counts for number of synth and MIDI devices. These are initialized * by the sequencer_open. */static int      max_mididev = 0;static int      max_synthdev = 0;/* * The seq_mode gives the operating mode of the sequencer: *      1 = level1 (the default) *      2 = level2 (extended capabilites) */#define SEQ_1	1#define SEQ_2	2static int      seq_mode = SEQ_1;DEFINE_WAIT_QUEUE (seq_sleeper, seq_sleep_flag);DEFINE_WAIT_QUEUE (midi_sleeper, midi_sleep_flag);static int      midi_opened[MAX_MIDI_DEV] ={0};static int      midi_written[MAX_MIDI_DEV] ={0};static unsigned long   prev_input_time = 0;static int             prev_event_time;static unsigned long   seq_time = 0;#include <i386/isa/sound/tuning.h>#define EV_SZ	8#define IEV_SZ	8static unsigned char *queue = NULL;static unsigned char *iqueue = NULL;static volatile int qhead = 0, qtail = 0, qlen = 0;static volatile int iqhead = 0, iqtail = 0, iqlen = 0;static volatile int seq_playing = 0;static int      sequencer_busy = 0;static int      output_treshold;static int      pre_event_timeout;static unsigned synth_open_mask;static int      seq_queue (unsigned char *note, char nonblock);static void     seq_startplay (void);static int      seq_sync (void);static void     seq_reset (void);static int      pmgr_present[MAX_SYNTH_DEV] ={0};#if MAX_SYNTH_DEV > 15#error Too many synthesizer devices enabled.#endifintsequencer_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count){  int             c = count, p = 0;  int             ev_len;  unsigned long   flags;  dev = dev >> 4;  ev_len = seq_mode == SEQ_1 ? 4 : 8;  if (dev)			/*				 * Patch manager device				 */    return pmgr_read (dev - 1, file, buf, count);  DISABLE_INTR (flags);  if (!iqlen)    {      if (ISSET_FILE_FLAG (file, O_NONBLOCK))	{	  RESTORE_INTR (flags);	  return RET_ERROR (EAGAIN);	}      DO_SLEEP (midi_sleeper, midi_sleep_flag, pre_event_timeout);      if (!iqlen)	{	  RESTORE_INTR (flags);	  return 0;	}    }  while (iqlen && c >= ev_len)    {      COPY_TO_USER (buf, p, &iqueue[iqhead * IEV_SZ], ev_len);      p += ev_len;      c -= ev_len;      iqhead = (iqhead + 1) % SEQ_MAX_QUEUE;      iqlen--;    }  RESTORE_INTR (flags);  return count - c;}static voidsequencer_midi_output (int dev){  /*   * Currently NOP   */}voidseq_copy_to_input (unsigned char *event, int len){  unsigned long   flags;  /*     * Verify that the len is valid for the current mode.   */  if (len != 4 && len != 8)    return;  if ((seq_mode == SEQ_1) != (len == 4))    return;  if (iqlen >= (SEQ_MAX_QUEUE - 1))    return;			/* Overflow */  DISABLE_INTR (flags);  memcpy (&iqueue[iqtail * IEV_SZ], event, len);  iqlen++;  iqtail = (iqtail + 1) % SEQ_MAX_QUEUE;  if (SOMEONE_WAITING (midi_sleeper, midi_sleep_flag))    {      WAKE_UP (midi_sleeper, midi_sleep_flag);    }  RESTORE_INTR (flags);#if defined(__FreeBSD__)  if (selinfo[0].si_pid)    selwakeup(&selinfo[0]);#endif}static voidsequencer_midi_input (int dev, unsigned char data){  unsigned int    tstamp;  unsigned char   event[4];  if (data == 0xfe)		/* Ignore active sensing */    return;  tstamp = GET_TIME () - seq_time;  if (tstamp != prev_input_time)    {      tstamp = (tstamp << 8) | SEQ_WAIT;      seq_copy_to_input ((unsigned char *) &tstamp, 4);      prev_input_time = tstamp;    }  event[0] = SEQ_MIDIPUTC;  event[1] = data;  event[2] = dev;  event[3] = 0;  seq_copy_to_input (event, 4);}voidseq_input_event (unsigned char *event, int len){  unsigned long   this_time;  if (seq_mode == SEQ_2)    this_time = tmr->get_time (tmr_no);  else    this_time = GET_TIME () - seq_time;  if (this_time != prev_input_time)    {      unsigned char   tmp_event[8];      tmp_event[0] = EV_TIMING;      tmp_event[1] = TMR_WAIT_ABS;      tmp_event[2] = 0;      tmp_event[3] = 0;      *(unsigned long *) &tmp_event[4] = this_time;      seq_copy_to_input (tmp_event, 8);      prev_input_time = this_time;    }  seq_copy_to_input (event, len);}intsequencer_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count){  unsigned char   event[EV_SZ], ev_code;  int             p = 0, c, ev_size;  int             err;  int             mode = file->mode & O_ACCMODE;  dev = dev >> 4;  DEB (printk ("sequencer_write(dev=%d, count=%d)\n", dev, count));  if (mode == OPEN_READ)    return RET_ERROR (EIO);  if (dev)			/*				 * Patch manager device				 */    return pmgr_write (dev - 1, file, buf, count);  c = count;  while (c >= 4)    {      COPY_FROM_USER (event, buf, p, 4);      ev_code = event[0];      if (ev_code == SEQ_FULLSIZE)	{	  int             err;	  dev = *(unsigned short *) &event[2];	  if (dev < 0 || dev >= max_synthdev)	    return RET_ERROR (ENXIO);	  if (!(synth_open_mask & (1 << dev)))	    return RET_ERROR (ENXIO);	  err = synth_devs[dev]->load_patch (dev, *(short *) &event[0], buf, p + 4, c, 0);	  if (err < 0)	    return err;	  return err;	}      if (ev_code >= 128)	{	  if (seq_mode == SEQ_2 && ev_code == SEQ_EXTENDED)	    {	      printk ("Sequencer: Invalid level 2 event %x\n", ev_code);	      return RET_ERROR (EINVAL);	    }	  ev_size = 8;	  if (c < ev_size)	    {	      if (!seq_playing)		seq_startplay ();	      return count - c;	    }	  COPY_FROM_USER (&event[4], buf, p + 4, 4);	}      else	{	  if (seq_mode == SEQ_2)	    {	      printk ("Sequencer: 4 byte event in level 2 mode\n");	      return RET_ERROR (EINVAL);	    }	  ev_size = 4;	}      if (event[0] == SEQ_MIDIPUTC)	{	  if (!midi_opened[event[2]])	    {	      int             mode;	      int             dev = event[2];	      if (dev >= max_mididev)		{		  printk ("Sequencer Error: Nonexistent MIDI device %d\n", dev);		  return RET_ERROR (ENXIO);		}	      mode = file->mode & O_ACCMODE;	      if ((err = midi_devs[dev]->open (dev, mode,			  sequencer_midi_input, sequencer_midi_output)) < 0)		{		  seq_reset ();		  printk ("Sequencer Error: Unable to open Midi #%d\n", dev);		  return err;		}	      midi_opened[dev] = 1;	    }	}      if (!seq_queue (event, ISSET_FILE_FLAG (file, O_NONBLOCK)))	{	  int             processed = count - c;	  if (!seq_playing)	    seq_startplay ();	  if (!processed && ISSET_FILE_FLAG (file, O_NONBLOCK))	    return RET_ERROR (EAGAIN);	  else	    return processed;	}      p += ev_size;      c -= ev_size;    }  if (!seq_playing)    seq_startplay ();  return count;			/* This will "eat" chunks shorter than 4 bytes (if written				   * alone) Should we really do that ?				 */}static intseq_queue (unsigned char *note, char nonblock){  /*   * Test if there is space in the queue   */  if (qlen >= SEQ_MAX_QUEUE)    if (!seq_playing)      seq_startplay ();		/*				 * Give chance to drain the queue				 */  if (!nonblock && qlen >= SEQ_MAX_QUEUE && !SOMEONE_WAITING (seq_sleeper, seq_sleep_flag))    {      /*       * Sleep until there is enough space on the queue       */      DO_SLEEP (seq_sleeper, seq_sleep_flag, 0);    }  if (qlen >= SEQ_MAX_QUEUE)    {      return 0;			/*				 * To be sure				 */    }  memcpy (&queue[qtail * EV_SZ], note, EV_SZ);  qtail = (qtail + 1) % SEQ_MAX_QUEUE;  qlen++;  return 1;}static intextended_event (unsigned char *q){  int             dev = q[2];  if (dev < 0 || dev >= max_synthdev)    return RET_ERROR (ENXIO);  if (!(synth_open_mask & (1 << dev)))    return RET_ERROR (ENXIO);  switch (q[1])    {    case SEQ_NOTEOFF:      synth_devs[dev]->kill_note (dev, q[3], q[4], q[5]);      break;    case SEQ_NOTEON:      if (q[4] > 127 && q[4] != 255)	return 0;      synth_devs[dev]->start_note (dev, q[3], q[4], q[5]);      break;    case SEQ_PGMCHANGE:      synth_devs[dev]->set_instr (dev, q[3], q[4]);      break;    case SEQ_AFTERTOUCH:      synth_devs[dev]->aftertouch (dev, q[3], q[4]);      break;    case SEQ_BALANCE:      synth_devs[dev]->panning (dev, q[3], (char) q[4]);      break;    case SEQ_CONTROLLER:      synth_devs[dev]->controller (dev, q[3], q[4], *(short *) &q[5]);      break;    case SEQ_VOLMODE:      if (synth_devs[dev]->volume_method != NULL)	synth_devs[dev]->volume_method (dev, q[3]);      break;    default:      return RET_ERROR (EINVAL);    }  return 0;}static intfind_voice (int dev, int chn, int note){  unsigned short  key;  int             i;  key = (chn << 8) | (note + 1);  for (i = 0; i < synth_devs[dev]->alloc.max_voice; i++)    if (synth_devs[dev]->alloc.map[i] == key)      return i;  return -1;}static intalloc_voice (int dev, int chn, int note){  unsigned short  key;  int             voice;  key = (chn << 8) | (note + 1);  voice = synth_devs[dev]->alloc_voice (dev, chn, note,					&synth_devs[dev]->alloc);  synth_devs[dev]->alloc.map[voice] = key;  synth_devs[dev]->alloc.alloc_times[voice] =    synth_devs[dev]->alloc.timestamp++;  return voice;}static voidseq_chn_voice_event (unsigned char *event){  unsigned char   dev = event[1];  unsigned char   cmd = event[2];  unsigned char   chn = event[3];  unsigned char   note = event[4];  unsigned char   parm = event[5];  int             voice = -1;  if ((int) dev > max_synthdev)    return;  if (!(synth_open_mask & (1 << dev)))    return;  if (!synth_devs[dev])    return;  if (seq_mode == SEQ_2)    {      if (synth_devs[dev]->alloc_voice)	voice = find_voice (dev, chn, note);      if (cmd == MIDI_NOTEON && parm == 0)	{	  cmd = MIDI_NOTEOFF;	  parm = 64;	}    }  switch (cmd)    {    case MIDI_NOTEON:      if (note > 127 && note != 255)	/* Not a seq2 feature */	return;      if (voice == -1 && seq_mode == SEQ_2 && synth_devs[dev]->alloc_voice)	{			/* Internal synthesizer (FM, GUS, etc) */	  voice = alloc_voice (dev, chn, note);	}      if (voice == -1)	voice = chn;      if (seq_mode == SEQ_2 && dev < num_synths)	{	  /*	     * The MIDI channel 10 is a percussive channel. Use the note	     * number to select the proper patch (128 to 255) to play.	   */	  if (chn == 9)	    {	      synth_devs[dev]->set_instr (dev, voice, 128 + note);	      note = 60;	/* Middle C */	    }	}      if (seq_mode == SEQ_2)	{	  synth_devs[dev]->setup_voice (dev, voice, chn);	}      synth_devs[dev]->start_note (dev, voice, note, parm);      break;    case MIDI_NOTEOFF:      if (voice == -1)	voice = chn;      synth_devs[dev]->kill_note (dev, voice, note, parm);      break;    case MIDI_KEY_PRESSURE:      if (voice == -1)	voice = chn;      synth_devs[dev]->aftertouch (dev, voice, parm);      break;    default:;    }}static voidseq_chn_common_event (unsigned char *event){  unsigned char   dev = event[1];  unsigned char   cmd = event[2];  unsigned char   chn = event[3];  unsigned char   p1 = event[4];  /* unsigned char   p2 = event[5]; */  unsigned short  w14 = *(short *) &event[6];  if ((int) dev > max_synthdev)    return;  if (!(synth_open_mask & (1 << dev)))    return;  if (!synth_devs[dev])    return;  switch (cmd)    {    case MIDI_PGM_CHANGE:      if (seq_mode == SEQ_2)	{	  synth_devs[dev]->chn_info[chn].pgm_num = p1;	  if (dev >= num_synths)	    synth_devs[dev]->set_instr (dev, chn, p1);	}      else	synth_devs[dev]->set_instr (dev, chn, p1);      break;    case MIDI_CTL_CHANGE:      if (seq_mode == SEQ_2)	{	  if (chn > 15 || p1 > 127)	    break;	  synth_devs[dev]->chn_info[chn].controllers[p1] = w14 & 0x7f;	  if (dev < num_synths)	    {	      int             val = w14 & 0x7f;	      int             i, key;	      if (p1 < 64)	/* Combine MSB and LSB */		{		  val = ((synth_devs[dev]->			  chn_info[chn].controllers[p1 & ~32] & 0x7f) << 7)		    | (synth_devs[dev]->		       chn_info[chn].controllers[p1 | 32] & 0x7f);		  p1 &= ~32;		}	      /* Handle all playing notes on this channel */	      key = (chn << 8);	      for (i = 0; i < synth_devs[dev]->alloc.max_voice; i++)		if ((synth_devs[dev]->alloc.map[i] & 0xff00) == key)		  synth_devs[dev]->controller (dev, i, p1, val);	    }	  else	    synth_devs[dev]->controller (dev, chn, p1, w14);	}      else			/* Mode 1 */	synth_devs[dev]->controller (dev, chn, p1, w14);      break;    case MIDI_PITCH_BEND:      if (seq_mode == SEQ_2)	{	  synth_devs[dev]->chn_info[chn].bender_value = w14;	  if (dev < num_synths)	    {			/* Handle all playing notes on this channel */	      int             i, key;	      key = (chn << 8);	      for (i = 0; i < synth_devs[dev]->alloc.max_voice; i++)		if ((synth_devs[dev]->alloc.map[i] & 0xff00) == key)		  synth_devs[dev]->bender (dev, i, w14);	    }	  else	    synth_devs[dev]->bender (dev, chn, w14);	}      else			/* MODE 1 */	synth_devs[dev]->bender (dev, chn, w14);      break;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -