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

📄 sound.c

📁 NES game Emulator in Linux.c and asm codes.
💻 C
📖 第 1 页 / 共 4 页
字号:
    {
     pvs->env_state = pvs->adsr_state = SUSTAIN;
     pvs->env_update_count = pvs->sr;
    }
    continue;

   case SUSTAIN:
    envx -= (((int) envx - 1) >> 8) + 1;    //mult by 1-1/256
    continue;

   case RELEASE:
   //says add 1/256??  That won't release, must be subtract.
   //But how often?  Oh well, who cares, I'll just
   //pick a number. :)
    envx -= (ENVX_MAX_BASE >> 8);   //sub 1/256th
    if ((envx == 0) || (envx > ENVX_MAX))
    {
     pvs->envx = envx;
     SPC_VoiceOff(voice, "release");
     break;
    }
    continue;

   case INCREASE:
    envx += (ENVX_MAX_BASE >> 6);   //add 1/64th
    if (envx >= ENVX_MAX)
    {
     pvs->env_sample_latch = pvs->voice_sample_latch;
     envx = ENVX_MAX;
     break;
    }
    continue;

   case DECREASE:
    envx -= (ENVX_MAX_BASE >> 6);   //sub 1/64th
    if (envx == 0 || envx > ENVX_MAX)    //underflow
    {
     pvs->env_sample_latch = pvs->voice_sample_latch;
     envx = 0;
     break;
    }
    continue;

   case EXP:
    envx -= (((int) envx - 1) >> 8) + 1;    //mult by 1-1/256

    if (envx == 0 || envx > ENVX_MAX)   //underflow
    {
     pvs->env_sample_latch = pvs->voice_sample_latch;
     envx = 0;
     break;
    }
    continue;

   case BENT:
    if (envx < (ENVX_MAX_BASE / 4 * 3))
     envx += ENVX_MAX_BASE / 64;    //add 1/64th
    else
     envx += ENVX_MAX_BASE / 256;   //add 1/256th
    if (envx >= ENVX_MAX)
    {
     pvs->env_sample_latch = pvs->voice_sample_latch;
     envx = ENVX_MAX;
     break;
    }
    continue;

   //case VOICE_OFF:
   //case DIRECT:
   //break;
   }
  }
  break;
 }

 SPC_DSP[(voice << 4) + DSP_VOICE_ENVX] = envx >> ENVX_DOWNSHIFT_BITS;
 pvs->envx = envx;

 return envx;
}

INLINE static void SPC_KeyOn(int voices)
{
 int voice, cursamp, adsr1, adsr2, gain;
 unsigned short *samp_dir = (unsigned short *)
  &SPCRAM[(int) SPC_DSP[DSP_DIR] << 8];

 if (voices)
 {
  /* Ignore voices forcibly disabled */
  voices &= SPC_MASK;

  /* Clear key-on bits when acknowledged */
  SPC_DSP[DSP_KON] = voices & SPC_DSP[DSP_KOF];

  /* Don't acknowledge key-on when key-off is set */
  voices &= ~SPC_DSP[DSP_KOF];

  /* 8-sample delay before key on */
  keying_on |= voices;

  for (voice = 0; voice < 8; voice++)
  {
   if (!(voices & (1 << voice))) continue;

   SNDvoices[voice].key_wait = 8;
  }
 }

 if (!keying_on) return;

 for (voice = 0; voice < 8; voice++)
 {
  struct voice_state *pvs;

  if (!(keying_on & (1 << voice))) continue;

  pvs = &SNDvoices[voice];

  if (pvs->key_wait--) continue;

  keying_on &= ~(1 << voice);

  /* Clear sample-end-block-decoded flag for voices being keyed on */
  SPC_DSP[DSP_ENDX] &= ~(1 << voice);

  cursamp = SPC_DSP[(voice << 4) + DSP_VOICE_SRCN];
  pvs->brrptr = pvs->sample_start_address = samp_dir[cursamp * 2];
  pvs->pitch_counter = 0x1000*3;
  pvs->bufptr = -1;
  pvs->brr_samples_left = 0;
  pvs->brr_header = 0;
  pvs->voice_sample_latch = pvs->env_sample_latch =
   sound_sample_latch;

  pvs->env_counter = apu_counter_reset_value;

  pvs->lvol = (signed char) SPC_DSP[(voice << 4) + DSP_VOICE_LVOL];
  pvs->rvol = (signed char) SPC_DSP[(voice << 4) + DSP_VOICE_RVOL];

  pvs->adsr_state = ATTACK;

  adsr1 = SPC_DSP[(voice << 4) + DSP_VOICE_ADSR1];
  if (adsr1 & 0x80)
  {
   //ADSR mode
   adsr2 = SPC_DSP[(voice << 4) + DSP_VOICE_ADSR2];

#ifndef ZERO_ENVX_ON_KEY_ON
   // Don't set envelope to zero if sound was playing
   if (!(SNDkeys & (1 << voice)))
#endif
   {
    SPC_DSP[(voice << 4) + DSP_VOICE_ENVX] = 0;
    pvs->envx = 0;
    SPC_DSP[(voice << 4) + DSP_VOICE_OUTX] = 0;
    pvs->outx = 0;
   }

   pvs->env_state = pvs->adsr_state;
   pvs->env_update_count = pvs->ar;
  }
  else
  {
   //GAIN mode
   gain = SPC_DSP[(voice << 4) + DSP_VOICE_GAIN];
   pvs->env_update_count = pvs->gain_update_count;
   if (gain & 0x80)
   {
#ifndef ZERO_ENVX_ON_KEY_ON
    // Don't set envelope to zero if sound was playing
    if (!(SNDkeys & (1 << voice)))
#endif
    {
     SPC_DSP[(voice << 4) + DSP_VOICE_ENVX] = 0;
     pvs->envx = 0;
     SPC_DSP[(voice << 4) + DSP_VOICE_OUTX] = 0;
     pvs->outx = 0;
    }

    pvs->env_state = gain >> 5;

   }
   else
   {
    SPC_DSP[(voice << 4) + DSP_VOICE_ENVX] = (gain & 0x7F);
    pvs->envx = (gain & 0x7F) << ENVX_DOWNSHIFT_BITS;
    pvs->env_state = DIRECT;
   }
  }

  SNDkeys |= (1 << voice);
 }
}

INLINE static void SPC_KeyOff(int voices)
{
 int voice;

 SPC_DSP[DSP_KOF] = voices;

 voices &= SNDkeys;

 for (voice = 0; voice < 8; voice++)
 {
  if (voices & (1 << voice))
  {
   SNDvoices[voice].env_state = RELEASE;
   SNDvoices[voice].env_update_count = apu_counter_reset_value;
  }
 }
}

static int sound_enable_mode = 0;

static int last_position;

void Reset_Sound_DSP()
{
 int i, samples;

 samples = 2 * SOUND_FREQ / SOUND_LAG;

 if (sound_enable_mode == 2) samples <<= 1;

 memset(SPC_DSP, 0, 256);
 SPC_DSP[DSP_FLG] = DSP_FLG_NECEN | DSP_FLG_MUTE;

 main_lvol = main_rvol = echo_lvol = echo_rvol = 0;
 echo_base = echo_delay = echo_address = echo_feedback = 0;

 SPC_MASK = 0xFF;
 SNDkeys = 0;
 sound_output_position = 0;
 block_written = TRUE;
#ifdef DUMP_SOUND
 block_dumped = TRUE;
#endif

 noise_vol = 0;
 noise_update_count = counter_update_table[0];
 noise_countdown = apu_counter_reset_value;

 sound_sample_latch = 0;

 for (i = 0; i < 8; i++)
 {
  FIR_coeff[i] = 0;
  SNDvoices[i].last2 = SNDvoices[i].last1 = 0;
  SNDvoices[i].envx = 0;
  SNDvoices[i].outx = 0;
  SNDvoices[i].env_state = VOICE_OFF;
  SNDvoices[i].voice_sample_latch = SNDvoices[i].env_sample_latch =
   sound_sample_latch;
  SNDvoices[i].ar = attack_time(0);
  SNDvoices[i].dr = decay_time(0);
  SNDvoices[i].sr = exp_time(0);
  SNDvoices[i].sl = ENVX_MAX_BASE / 8;
  SNDvoices[i].lvol = 0;
  SNDvoices[i].rvol = 0;
  SNDvoices[i].gain_update_count = 0;
 }

 if (!sound_enable_mode) return;

 last_position = 0;

 if (sound_bits == 8)
 {
  for (i = 0; i < samples; i++)
  {
   ((output_sample_8 *) sound_buffer_preload)[i] = OUTPUT_ZERO_BASE_8;
  }
 }
 else
 {
  for (i = 0; i < samples; i++)
  {
   ((output_sample_16 *) sound_buffer_preload)[i] = OUTPUT_ZERO_BASE_16;
  }
 }

}

void Remove_Sound()
{
 if (noise_buffer)
 {
  free(noise_buffer);
  noise_buffer = 0;
 }
 if (outx_buffer)
 {
  free(outx_buffer);
  outx_buffer = 0;
 }
 if (mix_buffer)
 {
  free(mix_buffer);
  mix_buffer = 0;
 }
 if (sound_buffer_preload)
 {
  free(sound_buffer_preload);
  sound_buffer_preload = 0;
 }
 if (stream_buffer)
 {
  stop_audio_stream(stream_buffer);
  stream_buffer = 0;
 }

 remove_sound();
 sound_enabled = sound_enable_mode = 0;
}

int Install_Sound(int stereo)
{
 int samples;
 if (sound_enable_mode) Remove_Sound();
 srand(0);

 set_volume_per_voice(0);
 if (install_sound(DIGI_AUTODETECT, MIDI_NONE, NULL))
 {
  return sound_enabled = sound_enable_mode = 0;
 }

 if (digi_driver->id == DIGI_NONE)
 {
  Remove_Sound();
  return sound_enabled = sound_enable_mode = 0;
 }

 samples = 2 * SOUND_FREQ / SOUND_LAG;

 if (sound_bits == 8)
 {
  stream_buffer = play_audio_stream(samples / 2, 8,
   stereo ? TRUE : FALSE, SOUND_FREQ, 255, 128);
  sound_buffer_preload =
   malloc(sizeof(output_sample_8[(stereo ? 2 : 1) * samples]));
 }
 else
 {
  stream_buffer = play_audio_stream(samples / 2, 16,
   stereo ? TRUE : FALSE, SOUND_FREQ, 255, 128);
  sound_buffer_preload =
   malloc(sizeof(output_sample_16[(stereo ? 2 : 1) * samples]));
 }

 noise_buffer = (output_sample_16 *)
  malloc(sizeof(output_sample_16 [samples]));

 outx_buffer = (char *) malloc(sizeof(char [samples]));

 mix_buffer = (int *) malloc(sizeof(int [(stereo ? 2 : 1) * samples]));

 if (!stream_buffer || !sound_buffer_preload || !noise_buffer || !outx_buffer
  || !mix_buffer)
 {
  Remove_Sound();
  return sound_enabled = sound_enable_mode = 0;
 }

 set_volume(255, -1);
 sound_enabled = sound_enable_mode = stereo + 1;

 return sound_enabled;

}

void update_sound_block(void)
{
 int samples;
 int data_block;
 void *sound_buffer;

#ifdef DUMP_SOUND
 static FILE *snd_dump = NULL;
#endif

 if (!sound_enabled) return;

 if (block_written && SPC_ENABLED) return;

#ifdef DUMP_SOUND
 if (!block_dumped)
 {
  block_dumped = TRUE;
  if (!snd_dump)
  {
   snd_dump = fopen("snd.dmp", "ab");
  }

  samples = SOUND_FREQ / SOUND_LAG;

  /* Write from block not being written to */
  data_block = sound_output_position >= samples ? 0 : samples;

  if (sound_enable_mode == 2)
  {
   data_block <<= 1;
   samples <<= 1;
  }

  if (sound_bits == 8)
  {
   if (snd_dump && SPC_ENABLED)
   {
    fwrite(((output_sample_8 *) sound_buffer_preload) + data_block, 1,
     sizeof(output_sample_8[samples]), snd_dump);
   }
  }
  else
  {
   if (snd_dump && SPC_ENABLED)
   {
    fwrite(((output_sample_16 *) sound_buffer_preload) + data_block, 1,
     sizeof(output_sample_16[samples]), snd_dump);
   }
  }
 }
#endif

 sound_buffer = get_audio_stream_buffer(stream_buffer);
 if (!sound_buffer) return;

 block_written = TRUE;
 samples = SOUND_FREQ / SOUND_LAG;

 /* Write from block not being written to */
 data_block = sound_output_position >= samples ? 0 : samples;

 if (sound_enable_mode == 2)
 {
  data_block <<= 1;
  samples <<= 1;
 }

 if (sound_bits == 8)
 {
  if (SPC_ENABLED)
  {
   memcpy(sound_buffer,
    ((output_sample_8 *) sound_buffer_preload) + data_block,
    sizeof(output_sample_8[samples]));
  }
  else
  {
   memset(sound_buffer, 0, sizeof(output_sample_8[samples]));
  }
 }
 else
 {
  if (SPC_ENABLED)
  {
   memcpy(sound_buffer,
    ((output_sample_16 *) sound_buffer_preload) + data_block,
    sizeof(output_sample_16[samples]));
  }
  else
  {
   memset(sound_buffer, 0, sizeof(output_sample_16[samples]));
  }
 }

 free_audio_stream_buffer(stream_buffer);
}

unsigned samples_output = 0;

INLINE static int get_brr_blocks(int voice, struct voice_state *pvs)
{
 if (pvs->pitch_counter >= 0)
 {
  return get_brr_block(voice, pvs);
 }
 return 0;

⌨️ 快捷键说明

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