📄 sound.c
字号:
{
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 + -