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

📄 sequencer.c

📁 <Linux1.0核心游记>电子书+书后源码+Linux1.0源码
💻 C
📖 第 1 页 / 共 2 页
字号:
voidsequencer_release (int dev, struct fileinfo *file)  {    int             i;    int             mode = file->mode & O_ACCMODE;    dev = dev >> 4;    DEB (printk ("sequencer_release(dev=%d)\n", dev));    if (dev)			/* Patch manager device */      {	dev--;	pmgr_release (dev);	pmgr_present[dev] = 0;	return;      }    /*     * Wait until the queue is empty     */    while (!PROCESS_ABORTING (seq_sleeper, seq_sleep_flag) && qlen)      {	seq_sync ();      }    if (mode != OPEN_READ)      seq_drain_midi_queues ();	/* Ensure the output queues are empty */    seq_reset ();    if (mode != OPEN_READ)      seq_drain_midi_queues ();	/* Flush the all notes off messages */    for (i = 0; i < num_midis; i++)      if (midi_opened[i])	midi_devs[i]->close (i);    if (mode == OPEN_WRITE || mode == OPEN_READWRITE)      for (i = 0; i < num_synths; i++)	if (synth_open_mask & (1 << i))	/* Actually opened */	  if (synth_devs[i])	    synth_devs[i]->close (i);    for (i = 0; i < num_synths; i++)      if (pmgr_present[i])	pmgr_inform (i, PM_E_CLOSED, 0, 0, 0, 0);    sequencer_busy = 0;  }static intseq_sync (void){  if (qlen && !seq_playing && !PROCESS_ABORTING (seq_sleeper, seq_sleep_flag))    seq_startplay ();  if (qlen && !SOMEONE_WAITING (seq_sleeper, seq_sleep_flag))	/* Queue not empty */    {      DO_SLEEP (seq_sleeper, seq_sleep_flag, 0);    }  return qlen;}static voidmidi_outc (int dev, unsigned char data){  /*   * NOTE! Calls sleep(). Don't call this from interrupt.   */  int             n;  /* This routine sends one byte to the Midi channel. */  /* If the output Fifo is full, it waits until there */  /* is space in the queue */  n = 300;			/* Timeout in jiffies */  while (n && !midi_devs[dev]->putc (dev, data))    {      DO_SLEEP (seq_sleeper, seq_sleep_flag, 4);      n--;    }}static voidseq_reset (void){  /*   * NOTE! Calls sleep(). Don't call this from interrupt.   */  int             i, chn;  sound_stop_timer ();  qlen = qhead = qtail = 0;  iqlen = iqhead = iqtail = 0;  for (i = 0; i < num_synths; i++)    if (synth_open_mask & (1 << i))      if (synth_devs[i])	synth_devs[i]->reset (i);  for (i = 0; i < num_midis; i++)    if (midi_written[i])	/* Midi used. Some notes may still be playing */      {	for (chn = 0; chn < 16; chn++)	  {	    midi_outc (i, 		(unsigned char)(0xb0 + (chn & 0xff))); /* Channel msg */	    midi_outc (i, 0x7b);/* All notes off */	    midi_outc (i, 0);	/* Dummy parameter */	  }	midi_devs[i]->close (i);	midi_written[i] = 0;	midi_opened[i] = 0;      }  seq_playing = 0;  if (SOMEONE_WAITING (seq_sleeper, seq_sleep_flag))    printk ("Sequencer Warning: Unexpected sleeping process\n");}intsequencer_ioctl (int dev, struct fileinfo *file,		 unsigned int cmd, unsigned int arg){  int             midi_dev, orig_dev;  int             mode = file->mode & O_ACCMODE;  orig_dev = dev = dev >> 4;  switch (cmd)    {    case SNDCTL_SEQ_SYNC:      if (dev)			/* Patch manager */	return RET_ERROR (EIO);      if (mode == OPEN_READ)	return 0;      while (qlen && !PROCESS_ABORTING (seq_sleeper, seq_sleep_flag))	seq_sync ();      return 0;      break;    case SNDCTL_SEQ_RESET:      if (dev)			/* Patch manager */	return RET_ERROR (EIO);      seq_reset ();      return 0;      break;    case SNDCTL_SEQ_TESTMIDI:      if (dev)			/* Patch manager */	return RET_ERROR (EIO);      midi_dev = IOCTL_IN (arg);      if (midi_dev >= num_midis)	return RET_ERROR (ENXIO);      if (!midi_opened[midi_dev])	{	  int             err, mode;	  mode = file->mode & O_ACCMODE;	  if ((err = midi_devs[midi_dev]->open (midi_dev, mode,						sequencer_midi_input,						sequencer_midi_output)) < 0)	    return err;	}      midi_opened[midi_dev] = 1;      return 0;      break;    case SNDCTL_SEQ_GETINCOUNT:      if (dev)			/* Patch manager */	return RET_ERROR (EIO);      if (mode == OPEN_WRITE)	return 0;      return IOCTL_OUT (arg, iqlen);      break;    case SNDCTL_SEQ_GETOUTCOUNT:      if (mode == OPEN_READ)	return 0;      return IOCTL_OUT (arg, SEQ_MAX_QUEUE - qlen);      break;    case SNDCTL_SEQ_CTRLRATE:      if (dev)			/* Patch manager */	return RET_ERROR (EIO);      /* If *arg == 0, just return the current rate */      return IOCTL_OUT (arg, HZ);      break;    case SNDCTL_SEQ_RESETSAMPLES:      dev = IOCTL_IN (arg);      if (dev < 0 || dev >= num_synths)	return RET_ERROR (ENXIO);      if (!(synth_open_mask & (1 << dev)) && !orig_dev)	return RET_ERROR (EBUSY);      if (!orig_dev && pmgr_present[dev])	pmgr_inform (dev, PM_E_PATCH_RESET, 0, 0, 0, 0);      return synth_devs[dev]->ioctl (dev, cmd, arg);      break;    case SNDCTL_SEQ_NRSYNTHS:      return IOCTL_OUT (arg, num_synths);      break;    case SNDCTL_SEQ_NRMIDIS:      return IOCTL_OUT (arg, num_midis);      break;    case SNDCTL_SYNTH_MEMAVL:      {	int             dev = IOCTL_IN (arg);	if (dev < 0 || dev >= num_synths)	  return RET_ERROR (ENXIO);	if (!(synth_open_mask & (1 << dev)) && !orig_dev)	  return RET_ERROR (EBUSY);	return IOCTL_OUT (arg, synth_devs[dev]->ioctl (dev, cmd, arg));      }      break;    case SNDCTL_FM_4OP_ENABLE:      {	int             dev = IOCTL_IN (arg);	if (dev < 0 || dev >= num_synths)	  return RET_ERROR (ENXIO);	if (!(synth_open_mask & (1 << dev)))	  return RET_ERROR (ENXIO);	synth_devs[dev]->ioctl (dev, cmd, arg);	return 0;      }      break;    case SNDCTL_SYNTH_INFO:      {	struct synth_info inf;	int             dev;	IOCTL_FROM_USER ((char *) &inf, (char *) arg, 0, sizeof (inf));	dev = inf.device;	if (dev < 0 || dev >= num_synths)	  return RET_ERROR (ENXIO);	if (!(synth_open_mask & (1 << dev)) && !orig_dev)	  return RET_ERROR (EBUSY);	return synth_devs[dev]->ioctl (dev, cmd, arg);      }      break;    case SNDCTL_MIDI_INFO:      {	struct midi_info inf;	int             dev;	IOCTL_FROM_USER ((char *) &inf, (char *) arg, 0, sizeof (inf));	dev = inf.device;	if (dev < 0 || dev >= num_midis)	  return RET_ERROR (ENXIO);	IOCTL_TO_USER ((char *) arg, 0, (char *) &(midi_devs[dev]->info), sizeof (inf));	return 0;      }      break;    case SNDCTL_PMGR_IFACE:      {	struct patmgr_info *inf;	int             dev, err;	inf = (struct patmgr_info *) KERNEL_MALLOC (sizeof (*inf));	IOCTL_FROM_USER ((char *) inf, (char *) arg, 0, sizeof (*inf));	dev = inf->device;	if (dev < 0 || dev >= num_synths)	  {	    KERNEL_FREE (inf);	    return RET_ERROR (ENXIO);	  }	if (!synth_devs[dev]->pmgr_interface)	  {	    KERNEL_FREE (inf);	    return RET_ERROR (ENXIO);	  }	if ((err = synth_devs[dev]->pmgr_interface (dev, inf)) == -1)	  {	    KERNEL_FREE (inf);	    return err;	  }	IOCTL_TO_USER ((char *) arg, 0, (char *) inf, sizeof (*inf));	KERNEL_FREE (inf);	return 0;      }      break;    case SNDCTL_PMGR_ACCESS:      {	struct patmgr_info *inf;	int             dev, err;	inf = (struct patmgr_info *) KERNEL_MALLOC (sizeof (*inf));	IOCTL_FROM_USER ((char *) inf, (char *) arg, 0, sizeof (*inf));	dev = inf->device;	if (dev < 0 || dev >= num_synths)	  {	    KERNEL_FREE (inf);	    return RET_ERROR (ENXIO);	  }	if (!pmgr_present[dev])	  {	    KERNEL_FREE (inf);	    return RET_ERROR (ESRCH);	  }	if ((err = pmgr_access (dev, inf)) < 0)	  {	    KERNEL_FREE (inf);	    return err;	  }	IOCTL_TO_USER ((char *) arg, 0, (char *) inf, sizeof (*inf));	KERNEL_FREE (inf);	return 0;      }      break;    case SNDCTL_SEQ_TRESHOLD:      {	int             tmp = IOCTL_IN (arg);	if (dev)		/* Patch manager */	  return RET_ERROR (EIO);	if (tmp < 1)	  tmp = 1;	if (tmp >= SEQ_MAX_QUEUE)	  tmp = SEQ_MAX_QUEUE - 1;	output_treshold = tmp;	return 0;      }      break;    default:      if (dev)			/* Patch manager */	return RET_ERROR (EIO);      if (mode == OPEN_READ)	return RET_ERROR (EIO);      if (!synth_devs[0])	return RET_ERROR (ENXIO);      if (!(synth_open_mask & (1 << 0)))	return RET_ERROR (ENXIO);      return synth_devs[0]->ioctl (0, cmd, arg);      break;    }  return RET_ERROR (EINVAL);}#ifdef ALLOW_SELECTintsequencer_select (int dev, struct fileinfo *file, int sel_type, select_table * wait){  dev = dev >> 4;  switch (sel_type)    {    case SEL_IN:      if (!iqlen)	{	  select_wait (&midi_sleeper, wait);	  return 0;	}      return 1;      break;    case SEL_OUT:      if (qlen >= SEQ_MAX_QUEUE)	{	  select_wait (&seq_sleeper, wait);	  return 0;	}      return 1;      break;    case SEL_EX:      return 0;    }  return 0;}#endifvoidsequencer_timer (void){  seq_startplay ();}intnote_to_freq (int note_num){  /*   * This routine converts a midi note to a frequency (multiplied by 1000)   */  int             note, octave, note_freq;  int             notes[] =  {    261632, 277189, 293671, 311132, 329632, 349232,    369998, 391998, 415306, 440000, 466162, 493880  };				/* Note freq*1000 for octave 5 */#define BASE_OCTAVE	5  octave = note_num / 12;  note = note_num % 12;  note_freq = notes[note];  if (octave < BASE_OCTAVE)    note_freq >>= (BASE_OCTAVE - octave);  else if (octave > BASE_OCTAVE)    note_freq <<= (octave - BASE_OCTAVE);  /* note_freq >>= 1;	 */  return note_freq;}unsigned longcompute_finetune (unsigned long base_freq, int bend, int range){  unsigned long   amount;  int             negative, semitones, cents;  if (!bend)    return base_freq;  if (!range)    return base_freq;  if (!base_freq)    return base_freq;  if (range >= 8192)    range = 8191;  bend = bend * range / 8192;  if (!bend)    return base_freq;  negative = bend < 0 ? 1 : 0;  if (bend < 0)    bend *= -1;  if (bend > range)    bend = range;  if (bend > 2399)    bend = 2399;  semitones = bend / 100;  cents = bend % 100;  amount = semitone_tuning[semitones] * cent_tuning[cents] / 10000;  if (negative)    return (base_freq * 10000) / amount;	/* Bend down */  else    return (base_freq * amount) / 10000;	/* Bend up */}longsequencer_init (long mem_start){  sequencer_ok = 1;  PERMANENT_MALLOC(unsigned char*, queue, SEQ_MAX_QUEUE*EV_SZ, mem_start);  PERMANENT_MALLOC(unsigned char*, iqueue, SEQ_MAX_QUEUE*IEV_SZ, mem_start);  return mem_start;}#else/* Stub version */intsequencer_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count){  return RET_ERROR (EIO);}intsequencer_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count){  return RET_ERROR (EIO);}intsequencer_open (int dev, struct fileinfo *file)  {    return RET_ERROR (ENXIO);  }voidsequencer_release (int dev, struct fileinfo *file)  {  }intsequencer_ioctl (int dev, struct fileinfo *file,		 unsigned int cmd, unsigned int arg){  return RET_ERROR (EIO);}intsequencer_lseek (int dev, struct fileinfo *file, off_t offset, int orig){  return RET_ERROR (EIO);}longsequencer_init (long mem_start){  return mem_start;}intsequencer_select (int dev, struct fileinfo *file, int sel_type, select_table * wait){  return RET_ERROR (EIO);}#endif#endif

⌨️ 快捷键说明

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