diff --git a/data/5/addresses_SNES_PSX.tsv b/data/5/addresses_SNES_PSX.tsv index 734e65d..1691e16 100644 --- a/data/5/addresses_SNES_PSX.tsv +++ b/data/5/addresses_SNES_PSX.tsv @@ -15,7 +15,7 @@ sfx_brr_data 0x041E41 270 of u8 Use the below SPC pointers bytelength_sfx_brr_pointers 0x041F4F u16 Used by the memcpy routine that copies the below data to the SPC (0x0020 = 32 bytes) sfx_brr_pointers 0x041F51 8 of 2 of u16 SPC memory addresses not ROM. Start address followed by loop address. bytelength_sfx_adsrs 0x041F71 u16 0x0010 = 16 bytes -sfx_adsrs 0x041F73 8 of 4 of u4 +sfx_adsrs 0x041F73 8 of ADSR bytelength_sfx_samplerates 0x041F83 u16 0x0010 = 16 bytes sfx_samplerates 0x041F85 8 of u16 bytelength_sfx_data 0x041F95 u16 0x1C00 = 7168 bytes @@ -25,7 +25,7 @@ bgm_song_pointers 0x043B97 72 of u24 bgm_instrument_brr_pointers 0x043C6F 35 of u24 bgm_instrument_loop_starts 0x043CD8 35 of u16 bgm_instrument_samplerates 0x043D1E 35 of u16 -bgm_instrument_adsrs 0x043D64 35 of 4 of u4 +bgm_instrument_adsrs 0x043D64 35 of ADSR bgm_instrument_indices 0x043DAA 72 of 16 of u16 length 0x900 worldmap_compressed_tilesets 0x070000 tilesets 0 up to 0x434 diff --git a/data/structs_SNES_stubs.tsv b/data/structs_SNES_stubs.tsv index e26faa1..96132c8 100644 --- a/data/structs_SNES_stubs.tsv +++ b/data/structs_SNES_stubs.tsv @@ -24,3 +24,10 @@ u5 r5 u5 g5 u5 b5 u1 0 + +struct ADSR +u4 attack_rate +u3 decay_rate +u1 enabled +u5 sustain_rate +u3 sustain_level diff --git a/scripts/MusicRenderer.gd b/scripts/MusicRenderer.gd index 93e25b0..650ca93 100644 --- a/scripts/MusicRenderer.gd +++ b/scripts/MusicRenderer.gd @@ -1,8 +1,5 @@ #warning-ignore-all:shadowed_variable extends Node -const SOUND_LOADER := preload('res://scripts/loaders/SoundLoader.gd') -const SPC_DECAY_CURVE := SOUND_LOADER.SPC_DECAY_CURVE -const SPC_DECAY_CURVE_ENTRIES := SOUND_LOADER.SPC_DECAY_CURVE_ENTRIES const music := preload('res://scripts/loaders/snes/music_ff5.gd') const EventType := music.EventType var MUSIC := music.new() @@ -21,15 +18,6 @@ class NoteEvent: var adsr_sustain_rate: int -static func get_adsr_decay_total_periods(adsr_sustain_level: int) -> int: - # Set decay_total_periods based on sustain_level - var target_env = adsr_sustain_level << 8 # SL is 3bit, and is compared to top 3 bits of 11bit envelope to determine when decay ends - for i in SPC_DECAY_CURVE_ENTRIES: - if SPC_DECAY_CURVE[i] <= target_env: - return i - return SPC_DECAY_CURVE_ENTRIES - - class TrackCurve: # built-in Curve class is too restrictive for this var default: float var entries: PoolVector3Array @@ -133,6 +121,7 @@ static func render_channels(tracks: Array, inst_map: Array, _debug_name := 'none # then once all the global tracks are known, as well as the longest unlooped length, # do a second pass to generate the final events # self.print_channel_events(inst_map) + var all_adsr_decay_total_periods: PoolIntArray = SoundLoader.all_adsr_decay_total_periods var sample_default_adsrs = RomLoader.snes_data.sfx_adsrs + RomLoader.snes_data.bgm_instrument_adsrs # TODO: UNHARDCODE THIS var all_note_events = [] @@ -289,23 +278,23 @@ static func render_channels(tracks: Array, inst_map: Array, _debug_name := 'none current_instrument = inst_map[current_instrument-0x20] - 1 + SoundLoader.SFX_NUM if current_instrument < len(sample_default_adsrs) and current_instrument > 0: var adsr = sample_default_adsrs[current_instrument] - current_adsr_attack_rate = adsr[0] - current_adsr_decay_rate = adsr[1] - current_adsr_decay_total_periods = get_adsr_decay_total_periods(adsr[2]) - current_adsr_sustain_rate = adsr[3] + current_adsr_attack_rate = adsr.attack_rate + current_adsr_decay_rate = adsr.decay_rate + current_adsr_sustain_rate = adsr.sustain_rate + current_adsr_decay_total_periods = all_adsr_decay_total_periods[adsr.sustain_level] EventType.ADSR_DEFAULT: # TODO - Investigate actual scaling and order if current_instrument < len(sample_default_adsrs) and current_instrument > 0: var adsr = sample_default_adsrs[current_instrument] - current_adsr_attack_rate = adsr[0] - current_adsr_decay_rate = adsr[1] - current_adsr_decay_total_periods = get_adsr_decay_total_periods(adsr[2]) - current_adsr_sustain_rate = adsr[3] + current_adsr_attack_rate = adsr.attack_rate + current_adsr_decay_rate = adsr.decay_rate + current_adsr_sustain_rate = adsr.sustain_rate + current_adsr_decay_total_periods = all_adsr_decay_total_periods[adsr.sustain_level] EventType.ADSR_ATTACK_RATE: current_adsr_attack_rate = event[1] EventType.ADSR_DECAY_RATE: current_adsr_decay_rate = event[1] EventType.ADSR_SUSTAIN_LEVEL: - current_adsr_decay_total_periods = get_adsr_decay_total_periods(event[1]) + current_adsr_decay_total_periods = all_adsr_decay_total_periods[event[1]] EventType.ADSR_SUSTAIN_RATE: current_adsr_sustain_rate = event[1] EventType.VIBRATO_ON: diff --git a/scripts/loaders/SoundLoader.gd b/scripts/loaders/SoundLoader.gd index 24e4fc5..d683299 100644 --- a/scripts/loaders/SoundLoader.gd +++ b/scripts/loaders/SoundLoader.gd @@ -33,6 +33,19 @@ const SPC_PERIOD_TABLE_LEN := len(SPC_PERIOD_TABLE) # 32 # Attack increases by 0x20==32 per period, or 0x400==1024 at the highest value of 15, and the Attack phase ends when envelope > 0x7FF==2047 # const ATTACK_PERIODS := PoolIntArray([64*2048, 64*1280, 64*768, 64*512, 64*320, 64*192, 64*128, 64*80, 64*48, 64*32, 64*20, 64*12, 64*8, 64*5, 64*3, 2*1]) # const DECAY_PERIODS := PoolIntArray([64, 40, 24, 16, 10, 6, 4, 2]) +static func get_adsr_decay_total_periods(adsr_sustain_level: int) -> int: + # Set decay_total_periods based on sustain_level + var target_env = adsr_sustain_level << 8 # SL is 3bit, and is compared to top 3 bits of 11bit envelope to determine when decay ends + for i in SPC_DECAY_CURVE_ENTRIES: + if SPC_DECAY_CURVE[i] <= target_env: + return i + return SPC_DECAY_CURVE_ENTRIES +static func generate_all_adsr_decay_total_periods() -> PoolIntArray: + var output = PoolIntArray() + for i in 8: + output.append(get_adsr_decay_total_periods(i)) + return output +onready var all_adsr_decay_total_periods := generate_all_adsr_decay_total_periods() # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! # !!! Testing a workaround for a Godot 3.x AudioStreamSample playback: !!! diff --git a/shaders/audio_renderer.gdshader b/shaders/audio_renderer.gdshader index 7ddfb65..62e87f8 100644 --- a/shaders/audio_renderer.gdshader +++ b/shaders/audio_renderer.gdshader @@ -238,9 +238,8 @@ highp vec4 render_song(highp sampler2D tex, highp int smp) { highp vec4 tex3 = get_midi_texel(tex, event_idx, row+3.0); highp vec4 tex4 = get_midi_texel(tex, event_idx, row+4.0); highp vec4 next_tex1 = get_midi_texel(tex, event_idx+1.0, row+1.0); - smp_event_start = retime_smp(unpack_int32(tex0)); - // highp int smp_event_end = retime_smp(unpack_int32(tex1)); - highp int smp_note_start = retime_smp(unpack_int32(tex1)); + smp_event_start = retime_smp(unpack_int32(tex0)); + highp int smp_note_start = retime_smp(unpack_int32(tex1)); highp int next_smp_note_start = retime_smp(unpack_int32(next_tex1)); // For now, just branch this