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

📄 gus_wave.c

📁 freebsd v4.4内核源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	    address = address >> 1;	    address &= 0x0001ffffL;	    address |= (hold_address & 0x000c0000L);	  }	gus_write16 (0x42, (address >> 4) & 0xffff);	/* DRAM DMA address */	/*	 * Start the DMA transfer	 */	dma_command = 0x21;	/* IRQ enable, DMA start */	if (patch.mode & WAVE_UNSIGNED)	  dma_command |= 0x80;	/* Invert MSB */	if (patch.mode & WAVE_16_BITS)	  dma_command |= 0x40;	/* 16 bit _DATA_ */	if (audio_devs[gus_devnum]->dmachan > 3)	  dma_command |= 0x04;	/* 16 bit DMA _channel_ */	gus_write8 (0x41, dma_command);		/* Lets bo luteet (=bugs) */	/*	 * Sleep here until the DRAM DMA done interrupt is served	 */	active_device = GUS_DEV_WAVE;	DO_SLEEP (dram_sleeper, dram_sleep_flag, HZ);	if (TIMED_OUT (dram_sleeper, dram_sleep_flag))	  printk ("GUS: DMA Transfer timed out\n");	RESTORE_INTR (flags);      }#endif /* GUS_NO_DMA */      /*       * Now the next part       */      left -= blk_size;      src_offs += blk_size;      target += blk_size;      gus_write8 (0x41, 0);	/* Stop DMA */    }  free_mem_ptr += patch.len;  if (!pmgr_flag)    pmgr_inform (gus_devnum, PM_E_PATCH_LOADED, instr, free_sample, 0, 0);  free_sample++;  return 0;}static voidguswave_hw_control (int dev, unsigned char *event){  int             voice, cmd;  unsigned short  p1, p2;  unsigned long   plong, flags;  cmd = event[2];  voice = event[3];  p1 = *(unsigned short *) &event[4];  p2 = *(unsigned short *) &event[6];  plong = *(unsigned long *) &event[4];  if ((voices[voice].volume_irq_mode == VMODE_START_NOTE) &&      (cmd != _GUS_VOICESAMPLE) && (cmd != _GUS_VOICE_POS))    do_volume_irq (voice);  switch (cmd)    {    case _GUS_NUMVOICES:      DISABLE_INTR (flags);      gus_select_voice (voice);      gus_select_max_voices (p1);      RESTORE_INTR (flags);      break;    case _GUS_VOICESAMPLE:      guswave_set_instr (dev, voice, p1);      break;    case _GUS_VOICEON:      DISABLE_INTR (flags);      gus_select_voice (voice);      p1 &= ~0x20;		/* Don't allow interrupts */      gus_voice_on (p1);      RESTORE_INTR (flags);      break;    case _GUS_VOICEOFF:      DISABLE_INTR (flags);      gus_select_voice (voice);      gus_voice_off ();      RESTORE_INTR (flags);      break;    case _GUS_VOICEFADE:      gus_voice_fade (voice);      break;    case _GUS_VOICEMODE:      DISABLE_INTR (flags);      gus_select_voice (voice);      p1 &= ~0x20;		/* Don't allow interrupts */      gus_voice_mode (p1);      RESTORE_INTR (flags);      break;    case _GUS_VOICEBALA:      DISABLE_INTR (flags);      gus_select_voice (voice);      gus_voice_balance (p1);      RESTORE_INTR (flags);      break;    case _GUS_VOICEFREQ:      DISABLE_INTR (flags);      gus_select_voice (voice);      gus_voice_freq (plong);      RESTORE_INTR (flags);      break;    case _GUS_VOICEVOL:      DISABLE_INTR (flags);      gus_select_voice (voice);      gus_voice_volume (p1);      RESTORE_INTR (flags);      break;    case _GUS_VOICEVOL2:	/* Just update the software voice level */      voices[voice].initial_volume =	voices[voice].current_volume = p1;      break;    case _GUS_RAMPRANGE:      if (voices[voice].mode & WAVE_ENVELOPES)	break;			/* NO-NO */      DISABLE_INTR (flags);      gus_select_voice (voice);      gus_ramp_range (p1, p2);      RESTORE_INTR (flags);      break;    case _GUS_RAMPRATE:      if (voices[voice].mode & WAVE_ENVELOPES)	break;			/* NJET-NJET */      DISABLE_INTR (flags);      gus_select_voice (voice);      gus_ramp_rate (p1, p2);      RESTORE_INTR (flags);      break;    case _GUS_RAMPMODE:      if (voices[voice].mode & WAVE_ENVELOPES)	break;			/* NO-NO */      DISABLE_INTR (flags);      gus_select_voice (voice);      p1 &= ~0x20;		/* Don't allow interrupts */      gus_ramp_mode (p1);      RESTORE_INTR (flags);      break;    case _GUS_RAMPON:      if (voices[voice].mode & WAVE_ENVELOPES)	break;			/* EI-EI */      DISABLE_INTR (flags);      gus_select_voice (voice);      p1 &= ~0x20;		/* Don't allow interrupts */      gus_rampon (p1);      RESTORE_INTR (flags);      break;    case _GUS_RAMPOFF:      if (voices[voice].mode & WAVE_ENVELOPES)	break;			/* NEJ-NEJ */      DISABLE_INTR (flags);      gus_select_voice (voice);      gus_rampoff ();      RESTORE_INTR (flags);      break;    case _GUS_VOLUME_SCALE:      volume_base = p1;      volume_scale = p2;      break;    case _GUS_VOICE_POS:      DISABLE_INTR (flags);      gus_select_voice (voice);      gus_set_voice_pos (voice, plong);      RESTORE_INTR (flags);      break;    default:;    }}static intgus_sampling_set_speed (int speed){  if (speed <= 0)    speed = gus_sampling_speed;  if (speed < 4000)    speed = 4000;  if (speed > 44100)    speed = 44100;  gus_sampling_speed = speed;  if (only_read_access)    {      /* Compute nearest valid recording speed  and return it */      speed = (9878400 / (gus_sampling_speed + 2)) / 16;      speed = (9878400 / (speed * 16)) - 2;    }  return speed;}static intgus_sampling_set_channels (int channels){  if (!channels)    return gus_sampling_channels;  if (channels > 2)    channels = 2;  if (channels < 1)    channels = 1;  gus_sampling_channels = channels;  return channels;}static intgus_sampling_set_bits (int bits){  if (!bits)    return gus_sampling_bits;  if (bits != 8 && bits != 16)    bits = 8;  gus_sampling_bits = bits;  return bits;}static intgus_sampling_ioctl (int dev, unsigned int cmd, unsigned int arg, int local){  switch (cmd)    {    case SOUND_PCM_WRITE_RATE:      if (local)	return gus_sampling_set_speed (arg);      return IOCTL_OUT (arg, gus_sampling_set_speed (IOCTL_IN (arg)));      break;    case SOUND_PCM_READ_RATE:      if (local)	return gus_sampling_speed;      return IOCTL_OUT (arg, gus_sampling_speed);      break;    case SNDCTL_DSP_STEREO:      if (local)	return gus_sampling_set_channels (arg + 1) - 1;      return IOCTL_OUT (arg, gus_sampling_set_channels (IOCTL_IN (arg) + 1) - 1);      break;    case SOUND_PCM_WRITE_CHANNELS:      if (local)	return gus_sampling_set_channels (arg);      return IOCTL_OUT (arg, gus_sampling_set_channels (IOCTL_IN (arg)));      break;    case SOUND_PCM_READ_CHANNELS:      if (local)	return gus_sampling_channels;      return IOCTL_OUT (arg, gus_sampling_channels);      break;    case SNDCTL_DSP_SETFMT:      if (local)	return gus_sampling_set_bits (arg);      return IOCTL_OUT (arg, gus_sampling_set_bits (IOCTL_IN (arg)));      break;    case SOUND_PCM_READ_BITS:      if (local)	return gus_sampling_bits;      return IOCTL_OUT (arg, gus_sampling_bits);    case SOUND_PCM_WRITE_FILTER:	/* NOT POSSIBLE */      return IOCTL_OUT (arg, RET_ERROR (EINVAL));      break;    case SOUND_PCM_READ_FILTER:      return IOCTL_OUT (arg, RET_ERROR (EINVAL));      break;    }  return RET_ERROR (EINVAL);}static voidgus_sampling_reset (int dev){}static intgus_sampling_open (int dev, int mode){  int dev_flag;  int init_flag;#ifdef GUS_NO_DMA  printk ("GUS: DMA mode not enabled. Device not supported\n");  return RET_ERROR (ENXIO);#endif  dev_flag = 0;  init_flag = (gus_busy[gus_devnum] == 0 && gus_busy[gus_dspnum] == 0);  if(mode & OPEN_WRITE)   {     if (gus_busy[gus_devnum])       return RET_ERROR(EBUSY);     if(dev != gus_devnum)       return RET_ERROR(ENXIO);     dev_flag = gus_busy[gus_devnum] = 1;   }  if(mode & OPEN_READ)   {     if(gus_busy[gus_dspnum]) {       if (dev_flag) gus_busy[gus_devnum] = 0;       return RET_ERROR(EBUSY);     }          if(dev != gus_dspnum) {       if (dev_flag) gus_busy[gus_devnum] = 0;       return RET_ERROR(ENXIO);     }   }  if(init_flag)    {      gus_initialize ();      active_device = 0;      gus_reset ();      reset_sample_memory ();      gus_select_max_voices (14);      pcm_active = 0;      dma_active = 0;      pcm_opened = 1;    }  if (mode & OPEN_READ)    {      recording_active = 1;      set_input_volumes ();    }  only_read_access = !(mode & OPEN_WRITE);  return 0;}static voidgus_sampling_close (int dev){  gus_busy[dev] = 0;  if (gus_busy[gus_devnum] == 0 && gus_busy[gus_dspnum] == 0) {    active_device = 0;    gus_reset();    pcm_opened = 0;  }   if (recording_active)    set_input_volumes ();  recording_active = 0;}static voidgus_sampling_update_volume (void){  unsigned long   flags;  int             voice;  if (pcm_active && pcm_opened)    for (voice = 0; voice < gus_sampling_channels; voice++)      {	DISABLE_INTR (flags);	gus_select_voice (voice);	gus_rampoff ();	gus_voice_volume (1530 + (25 * gus_pcm_volume));	gus_ramp_range (65, 1530 + (25 * gus_pcm_volume));	RESTORE_INTR (flags);      }}static voidplay_next_pcm_block (void){  unsigned long   flags;  int             speed = gus_sampling_speed;  int             this_one, is16bits, chn;  unsigned long   dram_loc;  unsigned char   mode[2], ramp_mode[2];  if (!pcm_qlen)    return;  this_one = pcm_head;  for (chn = 0; chn < gus_sampling_channels; chn++)    {      mode[chn] = 0x00;      ramp_mode[chn] = 0x03;	/* Ramping and rollover off */      if (chn == 0)	{	  mode[chn] |= 0x20;	/* Loop IRQ */	  voices[chn].loop_irq_mode = LMODE_PCM;	}      if (gus_sampling_bits != 8)	{	  is16bits = 1;	  mode[chn] |= 0x04;	/* 16 bit data */	}      else	is16bits = 0;      dram_loc = this_one * pcm_bsize;      dram_loc += chn * pcm_banksize;      if (this_one == (pcm_nblk - 1))	/* Last fragment of the DRAM buffer */	{	  mode[chn] |= 0x08;	/* Enable loop */	  ramp_mode[chn] = 0x03;	/* Disable rollover bit */	}      else	{	  if (chn == 0)	    ramp_mode[chn] = 0x04;	/* Enable rollover bit */	}      DISABLE_INTR (flags);      gus_select_voice (chn);      gus_voice_freq (speed);      if (gus_sampling_channels == 1)	gus_voice_balance (7);	/* mono */      else if (chn == 0)	gus_voice_balance (0);	/* left */      else	gus_voice_balance (15);	/* right */      if (!pcm_active)		/* Playback not already active */	{	  /*	   * The playback was not started yet (or there has been a pause).	   * Start the voice (again) and ask for a rollover irq at the end of	   * this_one block. If this_one one is last of the buffers, use just	   * the normal loop with irq.	   */	  gus_voice_off ();	  gus_rampoff ();	  gus_voice_volume (1530 + (25 * gus_pcm_volume));	  gus_ramp_range (65, 1530 + (25 * gus_pcm_volume));	  gus_write_addr (0x0a, dram_loc, is16bits);	/* Starting position */	  gus_write_addr (0x02, chn * pcm_banksize, is16bits);	/* Loop start */	  if (chn != 0)	    gus_write_addr (0x04, pcm_banksize + (pcm_bsize * pcm_nblk) - 1,			    is16bits);	/* Loop end location */	}      if (chn == 0)	gus_write_addr (0x04, dram_loc + pcm_datasize[this_one] - 1,			is16bits);	/* Loop end location */      else	mode[chn] |= 0x08;	/* Enable looping */      if (pcm_datasize[this_one] != pcm_bsize)	{	  /*	   * Incompletely filled block. Possibly the last one.	   */	  if (chn == 0)	    {	      mode[chn] &= ~0x08;	/* Disable looping */	      mode[chn] |= 0x20;	/* Enable IRQ at the end */	      voices[0].loop_irq_mode = LMODE_PCM_STOP;	      ramp_mode[chn] = 0x03;	/* No rollover bit */	    }	  else	    {	      gus_write_addr (0x04, dram_loc + pcm_datasize[this_one],			      is16bits);	/* Loop end location */	      mode[chn] &= ~0x08;	/* Disable looping */	    }	}      RESTORE_INTR (flags);    }  for (chn = 0; chn < gus_sampling_channels; chn++)    {      DISABLE_INTR (flags);      gus_select_voice (chn);      gus_write8 (0x0d, ramp_mode[chn]);      gus_voice_on (mode[chn]);      RESTORE_INTR (flags);    }  pcm_active = 1;}static voidgus_transfer_output_block (int dev, unsigned long buf,			   int total_count, int intrflag, int chn){  /*   * This routine transfers one block of audio data to the DRAM. In mono mode   * it's called just once. When in stereo mode, this_one routine is called   * once for both channels.   *   * The left/mono channel data is transferred to the beginning of dram and the   * right data to the area pointed by gus_page_size.   */  int             this_one, count;  unsigned long   flags;  unsigned char   dma_command;  unsigned long   address, hold_address;  DISABLE_INTR (flags);  count = total_count / gus_sampling_channels;  if (chn == 0)    {      if (pcm_qlen >= pcm_nblk)	printk ("GUS Warning: PCM buffers out of sync\n");      this_one = pcm_current_block = pcm_tail;      pcm_qlen++;      pcm_tail = (pcm_tail + 1) % pcm_nblk;      pcm_datasize[this_one] = count;    }  else    this_one = pcm_current_block;  gus_write8 (0x41, 0);		/* Disable GF1 DMA */  DMAbuf_start_dma (gus_devnum, buf + (chn * count), count, DMA_MODE_WRITE);  address = this_one * pcm_bsize;  address += chn * pcm_banksize;

⌨️ 快捷键说明

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