blargg_err_t Vgm_Emu::setup_fm() { long ym2612_rate = get_le32( header().ym2612_rate ); long ym2413_rate = get_le32( header().ym2413_rate ); if ( ym2413_rate && get_le32( header().version ) < 0x110 ) update_fm_rates( &ym2413_rate, &ym2612_rate ); uses_fm = false; fm_rate = blip_buf.sample_rate() * oversample_factor; if ( ym2612_rate ) { uses_fm = true; if ( disable_oversampling_ ) fm_rate = ym2612_rate / 144.0; Dual_Resampler::setup( fm_rate / blip_buf.sample_rate(), rolloff, fm_gain * gain() ); RETURN_ERR( ym2612.set_rate( fm_rate, ym2612_rate ) ); ym2612.enable( true ); set_voice_count( 8 ); } if ( !uses_fm && ym2413_rate ) { uses_fm = true; if ( disable_oversampling_ ) fm_rate = ym2413_rate / 72.0; Dual_Resampler::setup( fm_rate / blip_buf.sample_rate(), rolloff, fm_gain * gain() ); int result = ym2413.set_rate( fm_rate, ym2413_rate ); if ( result == 2 ) return "YM2413 FM sound isn't supported"; CHECK_ALLOC( !result ); ym2413.enable( true ); set_voice_count( 8 ); } if ( uses_fm ) { RETURN_ERR( Dual_Resampler::reset( blip_buf.length() * blip_buf.sample_rate() / 1000 ) ); psg.volume( 0.135 * fm_gain * gain() ); } else { ym2612.enable( false ); ym2413.enable( false ); psg.volume( gain() ); } return 0; }
blargg_err_t Sap_Emu::load_mem_( byte const in [], int size ) { file_end = in + size; info_.warning = NULL; info_.type = 'B'; info_.stereo = false; info_.init_addr = -1; info_.play_addr = -1; info_.music_addr = -1; info_.fastplay = 312; RETURN_ERR( parse_info( in, size, &info_ ) ); set_warning( info_.warning ); set_track_count( info_.track_count ); set_voice_count( Sap_Apu::osc_count << info_.stereo ); core.apu_impl().volume( gain() ); static const char* const names [Sap_Apu::osc_count * 2] = { "Wave 1", "Wave 2", "Wave 3", "Wave 4", "Wave 5", "Wave 6", "Wave 7", "Wave 8", }; set_voice_names( names ); static int const types [Sap_Apu::osc_count * 2] = { wave_type+1, wave_type+2, wave_type+3, wave_type+0, wave_type+5, wave_type+6, wave_type+7, wave_type+4, }; set_voice_types( types ); return setup_buffer( 1773447 ); }
blargg_err_t Ay_Emu::load_mem_( byte const in [], int size ) { assert( offsetof (header_t,track_info [2]) == header_t::size ); RETURN_ERR( parse_header( in, size, &file ) ); set_track_count( file.header->max_track + 1 ); if ( file.header->vers > 2 ) set_warning( "Unknown file version" ); int const osc_count = Ay_Apu::osc_count + 1; // +1 for beeper set_voice_count( osc_count ); core.apu().volume( gain() ); static const char* const names [osc_count] = { "Wave 1", "Wave 2", "Wave 3", "Beeper" }; set_voice_names( names ); static int const types [osc_count] = { wave_type+0, wave_type+1, wave_type+2, mixed_type+1 }; set_voice_types( types ); return setup_buffer( spectrum_clock ); }
blargg_err_t Vgm_Emu::load_mem_( byte const data [], int size ) { RETURN_ERR( core.load_mem( data, size ) ); set_voice_count( core.psg[0].osc_count ); double fm_rate = 0.0; if ( !disable_oversampling_ ) fm_rate = sample_rate() * oversample_factor; RETURN_ERR( core.init_chips( &fm_rate ) ); double psg_gain = ( ( core.header().psg_rate[3] & 0xC0 ) == 0x40 ) ? 0.5 : 1.0; if ( core.uses_fm() ) { set_voice_count( 8 ); RETURN_ERR( resampler.setup( fm_rate / sample_rate(), rolloff, gain() ) ); RETURN_ERR( resampler.reset( core.stereo_buf[0].length() * sample_rate() / 1000 ) ); core.psg[0].volume( 0.135 * fm_gain * psg_gain * gain() ); core.psg[1].volume( 0.135 * fm_gain * psg_gain * gain() ); core.ay[0].volume( 0.135 * fm_gain * gain() ); core.ay[1].volume( 0.135 * fm_gain * gain() ); core.huc6280[0].volume( 0.135 * fm_gain * gain() ); core.huc6280[1].volume( 0.135 * fm_gain * gain() ); } else { core.psg[0].volume( psg_gain * gain() ); core.psg[1].volume( psg_gain * gain() ); } static const char* const fm_names [] = { "FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "PCM", "PSG" }; static const char* const psg_names [] = { "Square 1", "Square 2", "Square 3", "Noise" }; set_voice_names( core.uses_fm() ? fm_names : psg_names ); static int const types [8] = { wave_type+1, wave_type+2, wave_type+3, noise_type+1, 0, 0, 0, 0 }; set_voice_types( types ); return Classic_Emu::setup_buffer( core.stereo_buf[0].center()->clock_rate() ); }
bool SamplePlayer::_set(const StringName& p_name, const Variant& p_value) { String name=p_name; if (name=="play/play") { if (library.is_valid()) { String what=p_value; if (what=="") stop_all(); else play(what); played_back=what; } } else if (name=="config/samples") set_sample_library(p_value); else if (name=="config/voices") set_voice_count(p_value); else if (name.begins_with("default/")) { String what=name.right(8); if (what=="volume_db") set_default_volume_db(p_value); else if (what=="pitch_scale") set_default_pitch_scale(p_value); else if (what=="pan") _default.pan=p_value; else if (what=="depth") _default.depth=p_value; else if (what=="height") _default.height=p_value; else if (what=="filter/type") _default.filter_type=FilterType(p_value.operator int()); else if (what=="filter/cutoff") _default.filter_cutoff=p_value; else if (what=="filter/resonance") _default.filter_resonance=p_value; else if (what=="filter/gain") _default.filter_gain=p_value; else if (what=="reverb_room") _default.reverb_room=ReverbRoomType(p_value.operator int()); else if (what=="reverb_send") _default.reverb_send=p_value; else if (what=="chorus_send") _default.chorus_send=p_value; else return false; } else return false; return true; }
blargg_err_t Spc_Emu::load_mem_( byte const* in, long size ) { assert( offsetof (header_t,unused2 [46]) == header_size ); file_data = in; file_size = size; set_voice_count( Snes_Spc::voice_count ); if ( size < Snes_Spc::spc_min_file_size ) return gme_wrong_file_type; return check_spc_header( in ); }
blargg_err_t Sfm_Emu::load_mem_( byte const in [], int size ) { set_voice_count( Spc_Dsp::voice_count ); if ( size < Sfm_Emu::sfm_min_file_size ) return blargg_err_file_type; static const char* const names [Spc_Dsp::voice_count] = { "DSP 1", "DSP 2", "DSP 3", "DSP 4", "DSP 5", "DSP 6", "DSP 7", "DSP 8" }; set_voice_names( names ); return check_sfm_header( in ); }
blargg_err_t Hes_Emu::load_( Data_Reader& in ) { assert( offsetof (header_t,unused [4]) == header_size ); RETURN_ERR( rom.load( in, header_size, &header_, unmapped ) ); RETURN_ERR( check_hes_header( header_.tag ) ); if ( header_.vers != 0 ) set_warning( "Unknown file version" ); if ( memcmp( header_.data_tag, "DATA", 4 ) ) set_warning( "Data header missing" ); if ( memcmp( header_.unused, "\0\0\0\0", 4 ) ) set_warning( "Unknown header data" ); // File spec supports multiple blocks, but I haven't found any, and // many files have bad sizes in the only block, so it's simpler to // just try to load the damn data as best as possible. long addr = get_le32( header_.addr ); long size = get_le32( header_.size ); long const rom_max = 0x100000; if ( addr & ~(rom_max - 1) ) { set_warning( "Invalid address" ); addr &= rom_max - 1; } if ( (unsigned long) (addr + size) > (unsigned long) rom_max ) set_warning( "Invalid size" ); if ( size != rom.file_size() ) { if ( size <= rom.file_size() - 4 && !memcmp( rom.begin() + size, "DATA", 4 ) ) set_warning( "Multiple DATA not supported" ); else if ( size < rom.file_size() ) set_warning( "Extra file data" ); else set_warning( "Missing file data" ); } rom.set_addr( addr ); set_voice_count( apu.osc_count ); apu.volume( gain() ); return setup_buffer( 7159091 ); }
blargg_err_t Ay_Emu::load_mem_( byte const* in, long size ) { assert( offsetof (header_t,track_info [2]) == header_size ); RETURN_ERR( parse_header( in, size, &file ) ); set_track_count( file.header->max_track + 1 ); if ( file.header->vers > 2 ) set_warning( "Unknown file version" ); set_voice_count( osc_count ); apu.volume( gain() ); return setup_buffer( spectrum_clock ); }
blargg_err_t Gbs_Emu::load_( Data_Reader& in ) { RETURN_ERR( core_.load( in ) ); set_warning( core_.warning() ); set_track_count( header().track_count ); set_voice_count( Gb_Apu::osc_count ); core_.apu().volume( gain() ); static const char* const names [Gb_Apu::osc_count] = { "Square 1", "Square 2", "Wave", "Noise" }; set_voice_names( names ); static int const types [Gb_Apu::osc_count] = { wave_type+1, wave_type+2, wave_type+3, mixed_type+1 }; set_voice_types( types ); return setup_buffer( 4194304 ); }
blargg_err_t Sap_Emu::load_mem_( byte const* in, long size ) { file_end = in + size; info.warning = 0; info.type = 'B'; info.stereo = false; info.init_addr = -1; info.play_addr = -1; info.music_addr = -1; info.fastplay = 312; RETURN_ERR( parse_info( in, size, &info ) ); set_warning( info.warning ); set_track_count( info.track_count ); set_voice_count( Sap_Apu::osc_count << info.stereo ); apu_impl.volume( gain() ); return setup_buffer( 1773447 ); }
blargg_err_t Hes_Emu::load_( Data_Reader& in ) { RETURN_ERR( core.load( in ) ); static const char* const names [Hes_Apu::osc_count + Hes_Apu_Adpcm::osc_count] = { "Wave 1", "Wave 2", "Wave 3", "Wave 4", "Multi 1", "Multi 2", "ADPCM" }; set_voice_names( names ); static int const types [Hes_Apu::osc_count + Hes_Apu_Adpcm::osc_count] = { wave_type+0, wave_type+1, wave_type+2, wave_type+3, mixed_type+0, mixed_type+1, mixed_type+2 }; set_voice_types( types ); set_voice_count( core.apu().osc_count + core.adpcm().osc_count ); core.apu().volume( gain() ); core.adpcm().volume( gain() ); return setup_buffer( 7159091 ); }
blargg_err_t Vgm_Emu::load_mem_( byte const* new_data, long new_size ) { assert( offsetof (header_t,unused2 [8]) == header_size ); if ( new_size <= header_size ) return gme_wrong_file_type; header_t const& h = *(header_t const*) new_data; RETURN_ERR( check_vgm_header( h ) ); check( get_le32( h.version ) <= 0x150 ); // psg rate psg_rate = get_le32( h.psg_rate ); if ( !psg_rate ) psg_rate = 3579545; blip_buf.clock_rate( psg_rate ); data = new_data; data_end = new_data + new_size; // get loop loop_begin = data_end; if ( get_le32( h.loop_offset ) ) loop_begin = &data [get_le32( h.loop_offset ) + offsetof (header_t,loop_offset)]; set_voice_count( psg.osc_count ); RETURN_ERR( setup_fm() ); static const char* const fm_names [] = { "FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "PCM", "PSG" }; static const char* const psg_names [] = { "Square 1", "Square 2", "Square 3", "Noise" }; set_voice_names( uses_fm ? fm_names : psg_names ); // do after FM in case output buffer is changed return Classic_Emu::setup_buffer( psg_rate ); }
blargg_err_t Gym_Emu::load_mem_( byte const in [], int size ) { assert( offsetof (header_t,packed [4]) == header_t::size ); log_offset = 0; RETURN_ERR( check_header( in, size, &log_offset ) ); loop_begin = NULL; static const char* const names [] = { "FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "PCM", "PSG" }; set_voice_names( names ); set_voice_count( 8 ); if ( log_offset ) header_ = *(header_t const*) in; else memset( &header_, 0, sizeof header_ ); return blargg_ok; }
blargg_err_t Nsf_Emu::init_sound() { if ( header_.chip_flags & ~(namco_flag | vrc6_flag | fme7_flag) ) set_warning( "Uses unsupported audio expansion hardware" ); { #define APU_NAMES "Square 1", "Square 2", "Triangle", "Noise", "DMC" int const count = Nes_Apu::osc_count; static const char* const apu_names [count] = { APU_NAMES }; set_voice_count( count ); set_voice_names( apu_names ); } static int const types [] = { wave_type | 1, wave_type | 2, wave_type | 0, noise_type | 0, mixed_type | 1, wave_type | 3, wave_type | 4, wave_type | 5, wave_type | 6, wave_type | 7, wave_type | 8, wave_type | 9, wave_type |10, wave_type |11, wave_type |12, wave_type |13 }; set_voice_types( types ); // common to all sound chip configurations double adjusted_gain = gain(); #if NSF_EMU_APU_ONLY { if ( header_.chip_flags ) set_warning( "Uses unsupported audio expansion hardware" ); } #else { if ( header_.chip_flags & (namco_flag | vrc6_flag | fme7_flag) ) set_voice_count( Nes_Apu::osc_count + 3 ); if ( header_.chip_flags & namco_flag ) { namco = BLARGG_NEW Nes_Namco_Apu; CHECK_ALLOC( namco ); adjusted_gain *= 0.75; int const count = Nes_Apu::osc_count + Nes_Namco_Apu::osc_count; static const char* const names [count] = { APU_NAMES, "Wave 1", "Wave 2", "Wave 3", "Wave 4", "Wave 5", "Wave 6", "Wave 7", "Wave 8" }; set_voice_count( count ); set_voice_names( names ); } if ( header_.chip_flags & vrc6_flag ) { vrc6 = BLARGG_NEW Nes_Vrc6_Apu; CHECK_ALLOC( vrc6 ); adjusted_gain *= 0.75; { int const count = Nes_Apu::osc_count + Nes_Vrc6_Apu::osc_count; static const char* const names [count] = { APU_NAMES, "Saw Wave", "Square 3", "Square 4" }; set_voice_count( count ); set_voice_names( names ); } if ( header_.chip_flags & namco_flag ) { int const count = Nes_Apu::osc_count + Nes_Vrc6_Apu::osc_count + Nes_Namco_Apu::osc_count; static const char* const names [count] = { APU_NAMES, "Saw Wave", "Square 3", "Square 4", "Wave 1", "Wave 2", "Wave 3", "Wave 4", "Wave 5", "Wave 6", "Wave 7", "Wave 8" }; set_voice_count( count ); set_voice_names( names ); } } if ( header_.chip_flags & fme7_flag ) { fme7 = BLARGG_NEW Nes_Fme7_Apu; CHECK_ALLOC( fme7 ); adjusted_gain *= 0.75; int const count = Nes_Apu::osc_count + Nes_Fme7_Apu::osc_count; static const char* const names [count] = { APU_NAMES, "Square 3", "Square 4", "Square 5" }; set_voice_count( count ); set_voice_names( names ); } if ( namco ) namco->volume( adjusted_gain ); if ( vrc6 ) vrc6 ->volume( adjusted_gain ); if ( fme7 ) fme7 ->volume( adjusted_gain ); } #endif apu.volume( adjusted_gain ); return 0; }
blargg_err_t Kss_Emu::load_( Data_Reader& in ) { RETURN_ERR( core.load( in ) ); set_warning( core.warning() ); set_track_count( get_le16( header().last_track ) + 1 ); core.scc_enabled = false; if ( header().device_flags & 0x02 ) // Sega Master System { int const osc_count = Sms_Apu::osc_count + Opl_Apu::osc_count; static const char* const names [osc_count] = { "Square 1", "Square 2", "Square 3", "Noise", "FM" }; set_voice_names( names ); static int const types [osc_count] = { wave_type+1, wave_type+3, wave_type+2, mixed_type+1, wave_type+0 }; set_voice_types( types ); // sms.psg set_voice_count( Sms_Apu::osc_count ); check( !core.sms.psg ); CHECK_ALLOC( core.sms.psg = BLARGG_NEW Sms_Apu ); // sms.fm if ( header().device_flags & 0x01 ) { set_voice_count( osc_count ); RETURN_ERR( new_opl_apu( Opl_Apu::type_smsfmunit, &core.sms.fm ) ); } } else // MSX { int const osc_count = Ay_Apu::osc_count + Opl_Apu::osc_count; static const char* const names [osc_count] = { "Square 1", "Square 2", "Square 3", "FM" }; set_voice_names( names ); static int const types [osc_count] = { wave_type+1, wave_type+3, wave_type+2, wave_type+0 }; set_voice_types( types ); // msx.psg set_voice_count( Ay_Apu::osc_count ); check( !core.msx.psg ); CHECK_ALLOC( core.msx.psg = BLARGG_NEW Ay_Apu ); if ( header().device_flags & 0x10 ) set_warning( "MSX stereo not supported" ); // msx.music if ( header().device_flags & 0x01 ) { set_voice_count( osc_count ); RETURN_ERR( new_opl_apu( Opl_Apu::type_msxmusic, &core.msx.music ) ); } // msx.audio if ( header().device_flags & 0x08 ) { set_voice_count( osc_count ); RETURN_ERR( new_opl_apu( Opl_Apu::type_msxaudio, &core.msx.audio ) ); } if ( !(header().device_flags & 0x80) ) { if ( !(header().device_flags & 0x84) ) core.scc_enabled = core.scc_enabled_true; // msx.scc check( !core.msx.scc ); CHECK_ALLOC( core.msx.scc = BLARGG_NEW Scc_Apu ); int const osc_count = Ay_Apu::osc_count + Scc_Apu::osc_count; static const char* const names [osc_count] = { "Square 1", "Square 2", "Square 3", "Wave 1", "Wave 2", "Wave 3", "Wave 4", "Wave 5" }; set_voice_names( names ); static int const types [osc_count] = { wave_type+1, wave_type+3, wave_type+2, wave_type+0, wave_type+4, wave_type+5, wave_type+6, wave_type+7, }; set_voice_types( types ); set_voice_count( osc_count ); } } set_silence_lookahead( 6 ); if ( core.sms.fm || core.msx.music || core.msx.audio ) { if ( !Opl_Apu::supported() ) set_warning( "FM sound not supported" ); else set_silence_lookahead( 3 ); // Opl_Apu is really slow } return setup_buffer( ::clock_rate ); }