blargg_err_t SNES_SPC::skip( int count ) { #if SPC_LESS_ACCURATE if ( count > 2 * sample_rate * 2 ) { set_output( 0, 0 ); // Skip a multiple of 4 samples time_t end = count; count = (count & 3) + 1 * sample_rate * 2; end = (end - count) * (clocks_per_sample / 2); m.skipped_kon = 0; m.skipped_koff = 0; // Preserve DSP and timer synchronization // TODO: verify that this really preserves it int old_dsp_time = m.dsp_time + m.spc_time; m.dsp_time = end - m.spc_time + skipping_time; end_frame( end ); m.dsp_time = m.dsp_time - skipping_time + old_dsp_time; dsp.write( SPC_DSP::r_koff, m.skipped_koff & ~m.skipped_kon ); dsp.write( SPC_DSP::r_kon , m.skipped_kon ); clear_echo(); } #endif return play( count, 0 ); }
int SPC_load_spc( THIS, const void* data, long size ) { struct spc_file_t const* spc = (struct spc_file_t const*) data; struct cpu_regs_t regs; if ( size < SPC_FILE_SIZE ) return -1; if ( ci->memcmp( spc->signature, "SNES-SPC700 Sound File Data", 27 ) != 0 ) return -1; regs.pc = spc->pc [1] * 0x100 + spc->pc [0]; regs.a = spc->a; regs.x = spc->x; regs.y = spc->y; regs.status = spc->status; regs.sp = spc->sp; if ( (unsigned long) size >= sizeof *spc ) ci->memcpy( this->boot_rom, spc->ipl_rom, sizeof this->boot_rom ); SPC_load_state( this, ®s, spc->ram, spc->dsp ); clear_echo(this); return 0; }
void Effects_Buffer::clear() { echo_pos = 0; s.low_pass [0] = 0; s.low_pass [1] = 0; mixer.samples_read = 0; for ( int i = bufs_size; --i >= 0; ) bufs [i].clear(); clear_echo(); }
void Effects_Buffer::apply_config() { int i; if ( !bufs_size ) return; s.treble = TO_FIXED( config_.treble ); bool echo_dirty = false; fixed_t old_feedback = s.feedback; s.feedback = TO_FIXED( config_.feedback ); if ( !old_feedback && s.feedback ) echo_dirty = true; // delays for ( i = stereo; --i >= 0; ) { long delay = config_.delay [i] * sample_rate() / 1000 * stereo; delay = max( delay, long (max_read * stereo) ); delay = min( delay, long (echo_size - max_read * stereo) ); if ( s.delay [i] != delay ) { s.delay [i] = delay; echo_dirty = true; } } // side channels for ( i = 2; --i >= 0; ) { chans [i+2].cfg.vol = chans [i].cfg.vol = config_.side_chans [i].vol * 0.5f; chans [i+2].cfg.pan = chans [i].cfg.pan = config_.side_chans [i].pan; } // convert volumes for ( i = chans.size(); --i >= 0; ) { chan_t& ch = chans [i]; ch.vol [0] = TO_FIXED( ch.cfg.vol - ch.cfg.vol * ch.cfg.pan ); ch.vol [1] = TO_FIXED( ch.cfg.vol + ch.cfg.vol * ch.cfg.pan ); if ( ch.cfg.surround ) ch.vol [0] = -ch.vol [0]; } assign_buffers(); // set side channels for ( i = chans.size(); --i >= 0; ) { chan_t& ch = chans [i]; ch.channel.left = chans [ch.cfg.echo*2 ].channel.center; ch.channel.right = chans [ch.cfg.echo*2+1].channel.center; } bool old_echo = !no_echo && !no_effects; // determine whether effects and echo are needed at all no_effects = true; no_echo = true; for ( i = chans.size(); --i >= extra_chans; ) { chan_t& ch = chans [i]; if ( ch.cfg.echo && s.feedback ) no_echo = false; if ( ch.vol [0] != TO_FIXED( 1 ) || ch.vol [1] != TO_FIXED( 1 ) ) no_effects = false; } if ( !no_echo ) no_effects = false; if ( chans [0].vol [0] != TO_FIXED( 1 ) || chans [0].vol [1] != TO_FIXED( 0 ) || chans [1].vol [0] != TO_FIXED( 0 ) || chans [1].vol [1] != TO_FIXED( 1 ) ) no_effects = false; if ( !config_.enabled ) no_effects = true; if ( no_effects ) { for ( i = chans.size(); --i >= 0; ) { chan_t& ch = chans [i]; ch.channel.center = &bufs [2]; ch.channel.left = &bufs [0]; ch.channel.right = &bufs [1]; } } mixer.bufs [0] = &bufs [0]; mixer.bufs [1] = &bufs [1]; mixer.bufs [2] = &bufs [2]; if ( echo_dirty || (!old_echo && (!no_echo && !no_effects)) ) clear_echo(); channels_changed(); }