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

📄 gus_wave.c

📁 freebsd v4.4内核源码
💻 C
📖 第 1 页 / 共 5 页
字号:
      return;    }  if (vol > prev_vol)    {      if (vol >= (4096 - 64))	vol = 4096 - 65;      gus_ramp_range (0, vol);      gus_rampon (0x20);	/* Increasing volume, with IRQ */    }  else    {      if (vol <= 64)	vol = 65;      gus_ramp_range (vol, 4030);      gus_rampon (0x60);	/* Decreasing volume, with IRQ */    }  voices[voice].current_volume = vol;  RESTORE_INTR (flags);}static voidinit_envelope (int voice){  voices[voice].env_phase = -1;  voices[voice].current_volume = 64;  step_envelope (voice);}static voidstart_release (int voice, long int flags){  if (gus_read8 (0x00) & 0x03)    return;			/* Voice already stopped */  voices[voice].env_phase = 2;	/* Will be incremented by step_envelope */  voices[voice].current_volume =    voices[voice].initial_volume =    gus_read16 (0x09) >> 4;	/* Get current volume */  voices[voice].mode &= ~WAVE_SUSTAIN_ON;  gus_rampoff ();  RESTORE_INTR (flags);  step_envelope (voice);}static voidgus_voice_fade (int voice){  int             instr_no = sample_map[voice], is16bits;  long int        flags;  DISABLE_INTR (flags);  gus_select_voice (voice);  if (instr_no < 0 || instr_no > MAX_SAMPLE)    {      gus_write8 (0x00, 0x03);	/* Hard stop */      voice_alloc->map[voice] = 0;      RESTORE_INTR (flags);      return;    }  is16bits = (samples[instr_no].mode & WAVE_16_BITS) ? 1 : 0;	/* 8 or 16 bits */  if (voices[voice].mode & WAVE_ENVELOPES)    {      start_release (voice, flags);      return;    }  /*   * Ramp the volume down but not too quickly.   */  if ((int) (gus_read16 (0x09) >> 4) < 100)	/* Get current volume */    {      gus_voice_off ();      gus_rampoff ();      gus_voice_init (voice);      return;    }  gus_ramp_range (65, 4030);  gus_ramp_rate (2, 4);  gus_rampon (0x40 | 0x20);	/* Down, once, with IRQ */  voices[voice].volume_irq_mode = VMODE_HALT;  RESTORE_INTR (flags);}static voidgus_reset (void){  int             i;  gus_select_max_voices (24);  volume_base = 3071;  volume_scale = 4;  volume_method = VOL_METHOD_ADAGIO;  for (i = 0; i < 32; i++)    {      gus_voice_init (i);	/* Turn voice off */      gus_voice_init2 (i);    }  INB (u_Status);		/* Touch the status register */  gus_look8 (0x41);		/* Clear any pending DMA IRQs */  gus_look8 (0x49);		/* Clear any pending sample IRQs */  gus_read8 (0x0f);		/* Clear pending IRQs */}static voidgus_initialize (void){  unsigned long   flags;  unsigned char   dma_image, irq_image, tmp;  static unsigned char gus_irq_map[16] =  {0, 0, 0, 3, 0, 2, 0, 4, 0, 1, 0, 5, 6, 0, 0, 7};  static unsigned char gus_dma_map[8] =  {0, 1, 0, 2, 0, 3, 4, 5};  DISABLE_INTR (flags);  gus_write8 (0x4c, 0);		/* Reset GF1 */  gus_delay ();  gus_delay ();  gus_write8 (0x4c, 1);		/* Release Reset */  gus_delay ();  gus_delay ();  /*   * Clear all interrupts   */  gus_write8 (0x41, 0);		/* DMA control */  gus_write8 (0x45, 0);		/* Timer control */  gus_write8 (0x49, 0);		/* Sample control */  gus_select_max_voices (24);  INB (u_Status);		/* Touch the status register */  gus_look8 (0x41);		/* Clear any pending DMA IRQs */  gus_look8 (0x49);		/* Clear any pending sample IRQs */  gus_read8 (0x0f);		/* Clear pending IRQs */  gus_reset ();			/* Resets all voices */  gus_look8 (0x41);		/* Clear any pending DMA IRQs */  gus_look8 (0x49);		/* Clear any pending sample IRQs */  gus_read8 (0x0f);		/* Clear pending IRQs */  gus_write8 (0x4c, 7);		/* Master reset | DAC enable | IRQ enable */  /*   * Set up for Digital ASIC   */  OUTB (0x05, gus_base + 0x0f);  mix_image |= 0x02;		/* Disable line out */  OUTB (mix_image, u_Mixer);  OUTB (0x00, u_IRQDMAControl);  OUTB (0x00, gus_base + 0x0f);  /*   * Now set up the DMA and IRQ interface   *   * The GUS supports two IRQs and two DMAs.   *   * Just one DMA channel is used. This prevents simultaneous ADC and DAC.   * Adding this support requires significant changes to the dmabuf.c, dsp.c   * and audio.c also.   */  irq_image = 0;  tmp = gus_irq_map[gus_irq];  if (!tmp)    printk ("Warning! GUS IRQ not selected\n");  irq_image |= tmp;  irq_image |= 0x40;		/* Combine IRQ1 (GF1) and IRQ2 (Midi) */  dma_image = gus_dma_map[gus_dma_read] << 3;  if(!dma_image)    printk ("Warning!  GUS DMA read channel not selected.\n");  if(gus_dma_read == gus_dma)    {      dma_image = 0x40;		/* dual dma inhibited 				   Combine DMA1 (DRAM) and IRQ2 (ADC) */    }  tmp = gus_dma_map[gus_dma];  if (!tmp)    printk ("Warning! GUS DMA not selected\n");  dma_image |= tmp;  /*   * For some reason the IRQ and DMA addresses must be written twice   */  /*   * Doing it first time   */  OUTB (mix_image, u_Mixer);	/* Select DMA control */  OUTB (dma_image | 0x80, u_IRQDMAControl);	/* Set DMA address */  OUTB (mix_image | 0x40, u_Mixer);	/* Select IRQ control */  OUTB (irq_image, u_IRQDMAControl);	/* Set IRQ address */  /*   * Doing it second time   */  OUTB (mix_image, u_Mixer);	/* Select DMA control */  OUTB (dma_image, u_IRQDMAControl);	/* Set DMA address */  OUTB (mix_image | 0x40, u_Mixer);	/* Select IRQ control */  OUTB (irq_image, u_IRQDMAControl);	/* Set IRQ address */  gus_select_voice (0);		/* This disables writes to IRQ/DMA reg */  mix_image &= ~0x02;		/* Enable line out */  mix_image |= 0x08;		/* Enable IRQ */  OUTB (mix_image, u_Mixer);	/*				 * Turn mixer channels on				 * Note! Mic in is left off.				 */  gus_select_voice (0);		/* This disables writes to IRQ/DMA reg */  gusintr (INT_HANDLER_CALL (0));	/* Serve pending interrupts */  RESTORE_INTR (flags);}intgus_wave_detect (int baseaddr){  unsigned long   i;  unsigned long   loc;  gus_base = baseaddr;  gus_write8 (0x4c, 0);		/* Reset GF1 */  gus_delay ();  gus_delay ();  gus_write8 (0x4c, 1);		/* Release Reset */  gus_delay ();  gus_delay ();  /* See if there is first block there.... */  gus_poke (0L, 0xaa);  if (gus_peek (0L) != 0xaa)    return (0);  /* Now zero it out so that I can check for mirroring .. */  gus_poke (0L, 0x00);  for (i = 1L; i < 1024L; i++)    {      int             n, failed;      /* check for mirroring ... */      if (gus_peek (0L) != 0)	break;      loc = i << 10;      for (n = loc - 1, failed = 0; n <= loc; n++)	{	  gus_poke (loc, 0xaa);	  if (gus_peek (loc) != 0xaa)	    failed = 1;	  gus_poke (loc, 0x55);	  if (gus_peek (loc) != 0x55)	    failed = 1;	}      if (failed)	break;    }  gus_mem_size = i << 10;  return 1;}static intguswave_ioctl (int dev,	       unsigned int cmd, unsigned int arg){  switch (cmd)    {    case SNDCTL_SYNTH_INFO:      gus_info.nr_voices = nr_voices;      IOCTL_TO_USER ((char *) arg, 0, &gus_info, sizeof (gus_info));      return 0;      break;    case SNDCTL_SEQ_RESETSAMPLES:      reset_sample_memory ();      return 0;      break;    case SNDCTL_SEQ_PERCMODE:      return 0;      break;    case SNDCTL_SYNTH_MEMAVL:      return gus_mem_size - free_mem_ptr - 32;    default:      return RET_ERROR (EINVAL);    }}static intguswave_set_instr (int dev, int voice, int instr_no){  int             sample_no;  if (instr_no < 0 || instr_no > MAX_PATCH)    return RET_ERROR (EINVAL);  if (voice < 0 || voice > 31)    return RET_ERROR (EINVAL);  if (voices[voice].volume_irq_mode == VMODE_START_NOTE)    {      voices[voice].sample_pending = instr_no;      return 0;    }  sample_no = patch_table[instr_no];  patch_map[voice] = -1;  if (sample_no < 0)    {      printk ("GUS: Undefined patch %d for voice %d\n", instr_no, voice);      return RET_ERROR (EINVAL);	/* Patch not defined */    }  if (sample_ptrs[sample_no] == -1)	/* Sample not loaded */    {      printk ("GUS: Sample #%d not loaded for patch %d (voice %d)\n",	      sample_no, instr_no, voice);      return RET_ERROR (EINVAL);    }  sample_map[voice] = sample_no;  patch_map[voice] = instr_no;  return 0;}static intguswave_kill_note (int dev, int voice, int note, int velocity){  unsigned long   flags;  DISABLE_INTR (flags);  /* voice_alloc->map[voice] = 0xffff; */  if (voices[voice].volume_irq_mode == VMODE_START_NOTE)    {      voices[voice].kill_pending = 1;      RESTORE_INTR (flags);    }  else    {      RESTORE_INTR (flags);      gus_voice_fade (voice);    }  RESTORE_INTR (flags);  return 0;}static voidguswave_aftertouch (int dev, int voice, int pressure){#if 0  short           lo_limit, hi_limit;  unsigned long   flags;  if (voice < 0 || voice > 31)    return;  if (voices[voice].mode & WAVE_ENVELOPES && voices[voice].env_phase != 2)    return;			/* Don't mix with envelopes */  if (pressure < 32)    {      DISABLE_INTR (flags);      gus_select_voice (voice);      gus_rampoff ();      compute_and_set_volume (voice, 255, 0);	/* Back to original volume */      RESTORE_INTR (flags);      return;    }  hi_limit = voices[voice].current_volume;  lo_limit = hi_limit * 99 / 100;  if (lo_limit < 65)    lo_limit = 65;  DISABLE_INTR (flags);  gus_select_voice (voice);  if (hi_limit > (4095 - 65))    {      hi_limit = 4095 - 65;      gus_voice_volume (hi_limit);    }  gus_ramp_range (lo_limit, hi_limit);  gus_ramp_rate (3, 8);  gus_rampon (0x58);		/* Bidirectional, dow, loop */  RESTORE_INTR (flags);#endif /* 0 */}static voidguswave_panning (int dev, int voice, int value){  if (voice >= 0 || voice < 32)    voices[voice].panning = value;}static voidguswave_volume_method (int dev, int mode){  if (mode == VOL_METHOD_LINEAR || mode == VOL_METHOD_ADAGIO)    volume_method = mode;}static voidcompute_volume (int voice, int volume){  if (volume < 128)    voices[voice].midi_volume = volume;  switch (volume_method)    {    case VOL_METHOD_ADAGIO:      voices[voice].initial_volume =	gus_adagio_vol (voices[voice].midi_volume, voices[voice].main_vol,			voices[voice].expression_vol,			voices[voice].patch_vol);      break;    case VOL_METHOD_LINEAR:	/* Totally ignores patch-volume and expression */      voices[voice].initial_volume =	gus_linear_vol (volume, voices[voice].main_vol);      break;    default:      voices[voice].initial_volume = volume_base +	(voices[voice].midi_volume * volume_scale);    }  if (voices[voice].initial_volume > 4030)    voices[voice].initial_volume = 4030;}static voidcompute_and_set_volume (int voice, int volume, int ramp_time){  int             current, target, rate;  unsigned long   flags;  compute_volume (voice, volume);  voices[voice].current_volume = voices[voice].initial_volume;  DISABLE_INTR (flags);  /*     * CAUTION! Interrupts disabled. Enable them before returning   */  gus_select_voice (voice);  current = gus_read16 (0x09) >> 4;  target = voices[voice].initial_volume;  if (ramp_time == INSTANT_RAMP)    {      gus_rampoff ();      gus_voice_volume (target);      RESTORE_INTR (flags);      return;    }  if (ramp_time == FAST_RAMP)    rate = 63;  else    rate = 16;  gus_ramp_rate (0, rate);  if ((target - current) / 64 == 0)	/* Close enough to target. */    {      gus_rampoff ();      gus_voice_volume (target);      RESTORE_INTR (flags);      return;    }  if (target > current)    {      if (target > (4095 - 65))	target = 4095 - 65;      gus_ramp_range (current, target);      gus_rampon (0x00);	/* Ramp up, once, no IRQ */    }  else    {      if (target < 65)	target = 65;      gus_ramp_range (target, current);      gus_rampon (0x40);	/* Ramp down, once, no irq */    }  RESTORE_INTR (flags);}static voiddynamic_volume_change (int voice){  unsigned char   status;  unsigned long   flags;  DISABLE_INTR (flags);  gus_select_voice (voice);  status = gus_read8 (0x00);	/* Get voice status */  RESTORE_INTR (flags);  if (status & 0x03)    return;			/* Voice was not running */  if (!(voices[voice].mode & WAVE_ENVELOPES))    {      compute_and_set_volume (voice, voices[voice].midi_volume, 1);      return;    }  /*   * Voice is running and has envelopes.   */  DISABLE_INTR (flags);  gus_select_voice (voice);  status = gus_read8 (0x0d);	/* Ramping status */  RESTORE_INTR (flags);  if (status & 0x03)		/* Sustain phase? */    {      compute_and_set_volume (voice, voices[voice].midi_volume, 1);      return;    }  if (voices[voice].env_phase < 0)    return;

⌨️ 快捷键说明

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