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

📄 gus_wave.c

📁 <Linux1.0核心游记>电子书+书后源码+Linux1.0源码
💻 C
📖 第 1 页 / 共 5 页
字号:
				 */  voices[voice].volume_irq_mode = VMODE_ENVELOPE;  if (((vol - prev_vol) / 64) == 0)	/* 					 * No significant volume change 					 */    {      step_envelope (voice);	/* 				 * Continue with the next phase 				 */      return;    }  if (vol > prev_vol)    {      if (vol >= (4096 - 64))	vol = 4096 - 65;      gus_ramp_range (0, vol);      gus_rampon (0x20);	/* 				 * Increasing, irq 				 */    }  else    {      if (vol <= 64)	vol = 65;      gus_ramp_range (vol, 4030);      gus_rampon (0x60);	/* 				 * Decreasing, irq 				 */    }  voices[voice].current_volume = vol;}static voidinit_envelope (int voice){  voices[voice].env_phase = -1;  voices[voice].current_volume = 64;  step_envelope (voice);}static voidstart_release (int voice){  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 ();  step_envelope (voice);}static voidgus_voice_fade (int voice){  int             instr_no = sample_map[voice], is16bits;  if (instr_no < 0 || instr_no > MAX_SAMPLE)    {      gus_write8 (0x00, 0x03);	/* 				 * Hard stop 				 */      return;    }  is16bits = (samples[instr_no].mode & WAVE_16_BITS) ? 1 : 0;	/* 								 * 8 or 16								 * bit								 * samples 								 */  if (voices[voice].mode & WAVE_ENVELOPES)    {      start_release (voice);      return;    }  /*    * Ramp the volume down but not too quickly.   */  if ((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, irq 				 */  voices[voice].volume_irq_mode = VMODE_HALT;}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, 1, 3, 0, 2, 0, 4, 0, 0, 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 = 0x40;		/* 				 * 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 (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 int#ifdef FUTURE_VERSIONguswave_kill_note (int dev, int voice, int note, int velocity)#elseguswave_kill_note (int dev, int voice, int velocity)#endif{  unsigned long   flags;  DISABLE_INTR (flags);  if (voices[voice].volume_irq_mode == VMODE_START_NOTE)    voices[voice].kill_pending = 1;  else    {      gus_select_voice (voice);      gus_voice_fade (voice);    }  RESTORE_INTR (flags);  return 0;}static voidguswave_aftertouch (int dev, int voice, int pressure){  short           lo_limit, hi_limit;  unsigned long   flags;  return;			/* 				 * Currently disabled 				 */  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, Down, Loop 				 */  RESTORE_INTR (flags);}static voidguswave_panning (int dev, int voice, int value){  if (voice >= 0 || voice < 32)    voices[voice].panning = value;}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;      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;  DISABLE_INTR (flags);/*  * CAUTION! Interrupts disabled. Enable them before returning */  gus_select_voice (voice);  compute_volume (voice, volume);  voices[voice].current_volume = voices[voice].initial_volume;  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)	/* 					 * Too close 					 */    {      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)

⌨️ 快捷键说明

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