int SPC_set_state(SPC_Config *cfg) { int i; Settings.APUEnabled = TRUE; Settings.InterpolatedSound = (cfg->is_interpolation) ? TRUE : FALSE; Settings.SoundEnvelopeHeightReading = TRUE; Settings.DisableSoundEcho = (cfg->is_echo) ? FALSE : TRUE; // Settings.EnableExtraNoise = TRUE; Settings.ReverseStereo = 0; Settings.AltSampleDecode = 0; // SPC mixer information //samples_per_mix = cfg->sampling_rate / RATE * cfg->channels; samples_per_mix = cfg->sampling_rate / RATE * cfg->channels; so.playback_rate = cfg->sampling_rate; so.err_rate = (uint32)(SNES_SCANLINE_TIME * 0x10000UL / (1.0 / (double) so.playback_rate)); S9xSetEchoDelay(APU.DSP [APU_EDL] & 0xf); for (i = 0; i < 8; i++) S9xSetSoundFrequency(i, SoundData.channels [i].hertz); so.buffer_size = samples_per_mix; so.stereo = (cfg->channels == 2) ? TRUE : FALSE; if (cfg->resolution == 16){ so.buffer_size *= 2; so.sixteen_bit = TRUE; } else so.sixteen_bit = FALSE; so.encoded = FALSE; so.mute_sound = FALSE; return so.buffer_size; }
static inline void S9xPlaySample(int channel) { Channel *ch = &SoundData.channels[channel]; ch->state = SOUND_SILENT; ch->mode = MODE_NONE; ch->envx = 0; ch->envxx = 0; ch->g_index = 0; ch->gaussian[0] = ch->gaussian[1] = ch->gaussian[2] = ch->gaussian[3] = 0; S9xFixEnvelope(channel, APU.DSP [APU_GAIN + (channel << 4)], APU.DSP [APU_ADSR1 + (channel << 4)], APU.DSP [APU_ADSR2 + (channel << 4)]); ch->sample_number = APU.DSP [APU_SRCN + channel * 0x10]; if (APU.DSP [APU_NON] & (1 << channel)) ch->type = SOUND_NOISE; else ch->type = SOUND_SAMPLE; S9xSetSoundFrequency(channel, ch->hertz); ch->loop = FALSE; ch->needs_decode = TRUE; ch->last_block = FALSE; ch->previous [0] = ch->previous[1] = 0; ch->block_pointer = *S9xGetSampleAddress(ch->sample_number); ch->sample_pointer = 0; ch->env_error = 0; ch->next_sample = 0; ch->interpolate = 0; ch->last_valid_header = 0; switch (ch->mode) { case MODE_ADSR: if (ch->attack_rate == 0) { if (ch->decay_rate == 0 || ch->sustain_level == 8) { ch->state = SOUND_SUSTAIN; ch->envx = (MAX_ENVELOPE_HEIGHT * ch->sustain_level) >> 3; S9xSetEnvRate(ch, ch->sustain_rate, -1, 0, 2 << 28); } else { ch->state = SOUND_DECAY; ch->envx = MAX_ENVELOPE_HEIGHT; S9xSetEnvRate(ch, ch->decay_rate, -1, (MAX_ENVELOPE_HEIGHT * ch->sustain_level) >> 3, 1 << 28); } ch-> left_vol_level = (ch->envx * ch->volume_left) / 128; ch->right_vol_level = (ch->envx * ch->volume_right) / 128; } else {
static inline void S9xSetSoundHertz(int channel, int hertz) { SoundData.channels[channel].hertz = hertz; S9xSetSoundFrequency(channel, hertz); }
/* Restore SPC state ---------------------------------------------------------------- */ static void RestoreSPC() { int i; APURegisters.PC = BackupAPURegisters.PC; APURegisters.YA.B.A = BackupAPURegisters.YA.B.A; APURegisters.X = BackupAPURegisters.X; APURegisters.YA.B.Y = BackupAPURegisters.YA.B.Y; APURegisters.P = BackupAPURegisters.P; APURegisters.S = BackupAPURegisters.S; memcpy (IAPU.RAM, BackupAPURAM, 65536); memcpy (APU.ExtraRAM, BackupAPUExtraRAM, 64); memcpy (APU.DSP, BackupDSPRAM, 128); for (i = 0; i < 4; i ++) { APU.OutPorts[i] = IAPU.RAM[0xf4 + i]; } IAPU.TimerErrorCounter = 0; for (i = 0; i < 3; i ++) { if (IAPU.RAM[0xfa + i] == 0) APU.TimerTarget[i] = 0x100; else APU.TimerTarget[i] = IAPU.RAM[0xfa + i]; } S9xSetAPUControl (IAPU.RAM[0xf1]); /* from snaporig.cpp (ReadOrigSnapshot) */ S9xSetSoundMute (FALSE); IAPU.PC = IAPU.RAM + APURegisters.PC; S9xAPUUnpackStatus (); if (APUCheckDirectPage ()) IAPU.DirectPage = IAPU.RAM + 0x100; else IAPU.DirectPage = IAPU.RAM; Settings.APUEnabled = TRUE; IAPU.APUExecuting = TRUE; S9xFixSoundAfterSnapshotLoad (); S9xSetFrequencyModulationEnable (APU.DSP[APU_PMON]); S9xSetMasterVolume (APU.DSP[APU_MVOL_LEFT], APU.DSP[APU_MVOL_RIGHT]); S9xSetEchoVolume (APU.DSP[APU_EVOL_LEFT], APU.DSP[APU_EVOL_RIGHT]); uint8 mask = 1; int type; for (i = 0; i < 8; i++, mask <<= 1) { // unused // Channel *ch = &SoundData.channels[i]; S9xFixEnvelope (i, APU.DSP[APU_GAIN + (i << 4)], APU.DSP[APU_ADSR1 + (i << 4)], APU.DSP[APU_ADSR2 + (i << 4)]); S9xSetSoundVolume (i, APU.DSP[APU_VOL_LEFT + (i << 4)], APU.DSP[APU_VOL_RIGHT + (i << 4)]); S9xSetSoundFrequency (i, ((APU.DSP[APU_P_LOW + (i << 4)] + (APU.DSP[APU_P_HIGH + (i << 4)] << 8)) & FREQUENCY_MASK) * 8); if (APU.DSP [APU_NON] & mask) type = SOUND_NOISE; else type = SOUND_SAMPLE; S9xSetSoundType (i, type); if ((APU.DSP[APU_KON] & mask) != 0) { APU.KeyedChannels |= mask; S9xPlaySample (i); } } #if 0 unsigned char temp=IAPU.RAM[0xf2]; for(i=0;i<128;i++){ IAPU.RAM[0xf2]=i; S9xSetAPUDSP(APU.DSP[i]); } IAPU.RAM[0xf2]=temp; #endif }