Prepend silence to samples
Also switch most of sample loading to struct pointers
This commit is contained in:
parent
a6181cb776
commit
0ef19b45a7
|
@ -3,6 +3,17 @@ character_battle_sprite_stone_palette 0x00F807 N/A N/A Palette16Of555 Also 0x199
|
|||
character_battle_sprite_disabled_palette 0x00F867 /mnu/memsave.bin 0x000034 Palette16Of555
|
||||
locations_bg_palettes 0x03BB00 /nar/ff5_binx.bin 0x03BF80 43 of Palette128Of555
|
||||
font_glyphs_dialogue 0x03E800 256 of SNESTritile length 0x1800
|
||||
sfx_brr_data 0x041E3F Use the below SPC pointers
|
||||
sfx_brr_pointers 0x041F4F 8 of 2 of u16 SPC memory addresses not ROM. Start address followed by loop address.
|
||||
sfx_adsrs 0x041F71 8 of u16
|
||||
sfx_samplerates 0x041F83 8 of u16
|
||||
sfx_data 0x041F95 Contains SPC pointers and tracks
|
||||
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 u16
|
||||
bgm_instrument_indices 0x043DAA 72 of 16 of u16 length 0x900
|
||||
enemy_battle_sprite_palettes 0x0ED000 See enemy_battle_sprite_data for pointers. Some are 8 colours instead of 16.
|
||||
worldmap_blocks 0x0FF0C0 /nar/ff5_binx.bin 0x040300 3 of 4 of 192 of u8 # Top-left corners, top-right corners, bottom-left corners, bottom-right corners
|
||||
worldmap_tiles.bias 0x0FF9C0 /nar/ff5_bin3.bin 0x03FB00 3 of 256 of u8 Add to each pixel of the mode7c tiles
|
||||
|
|
|
|
@ -60,6 +60,9 @@ func load_snes_structs(buffer: StreamPeerBuffer) -> Dictionary:
|
|||
data.job_levels.append(ability_list)
|
||||
return data
|
||||
|
||||
func load_snes_audio_thread(data_and_buffer: Array):
|
||||
SoundLoader.parse_rom(data_and_buffer[0], data_and_buffer[1])
|
||||
|
||||
func load_snes_rom(filename: String):
|
||||
var error := rom_snes.open(filename, File.READ)
|
||||
if error == OK:
|
||||
|
@ -71,11 +74,12 @@ func load_snes_rom(filename: String):
|
|||
var buffer = StreamPeerBuffer.new()
|
||||
buffer.data_array = bytes
|
||||
|
||||
StringLoader.load_snes_rom(buffer, true)
|
||||
# Give this its own buffer, avoid file pointer conflicts
|
||||
var _thread_error = thread.start(SoundLoader, 'parse_rom', buffer.duplicate())
|
||||
self.snes_data = load_snes_structs(buffer)
|
||||
#print(snes_data.job_levels)
|
||||
# Give this its own buffer, avoid file pointer conflicts
|
||||
self.load_snes_audio_thread([self.snes_data, buffer.duplicate()])
|
||||
# var _thread_error = thread.start(self, 'load_snes_audio_thread', [self.snes_data, buffer.duplicate()])
|
||||
StringLoader.load_snes_rom(buffer, true)
|
||||
SpriteLoader.load_from_structs(self.snes_data)
|
||||
SpriteLoader.load_enemy_battle_sprites(self.snes_data, buffer)
|
||||
SpriteLoader.load_battle_bgs(self.snes_data, buffer)
|
||||
|
|
|
@ -17,6 +17,8 @@ const SFX_BRR_SPC_TABLE := 0x041F4F + 2 # (first two bytes are the length of 0x0
|
|||
const SFX_BRR_START := 0x041E3F + 2 # First two bytes are the length of the block, 0x010E = 270 bytes = 16 BRR packets = 480 samples
|
||||
const SFX_ADSR := 0x041F71
|
||||
const SFX_SR := 0x041F83
|
||||
const PREPEND_MS := 50 # Prepend 20ms of silence to each sample for preplay purposes
|
||||
const PLAY_START := PREPEND_MS / 1000.0
|
||||
var bgm_tracks = []
|
||||
var instrument_samples = []
|
||||
var sfx_samples = []
|
||||
|
@ -96,66 +98,59 @@ func make_sample(buffer: StreamPeerBuffer, size: int, sample_rate: int) -> Audio
|
|||
break
|
||||
# Convert int array to byte array
|
||||
var audio_data = PoolByteArray()
|
||||
for j in range(2, samples.size()):
|
||||
var b = samples[j]
|
||||
# Prepend silence, accounting for the two null samples
|
||||
var silent_samples := ((sample_rate * PREPEND_MS) / 1000) - 2
|
||||
audio_data.resize(silent_samples * 2) # 16bit samples in 8bit array
|
||||
audio_data.fill(0)
|
||||
# Pack 16bit samples to 8bit array
|
||||
for b in samples:
|
||||
audio_data.append(b & 0xFF)
|
||||
audio_data.append(b >> 8)
|
||||
audio.data = audio_data
|
||||
return audio
|
||||
|
||||
func get_inst_sample_data(buffer: StreamPeerBuffer, id: int) -> AudioStreamSample:
|
||||
buffer.seek(INST_SR + (id*2))
|
||||
var tuning1 := buffer.get_u8()
|
||||
var tuning2 := buffer.get_u8()
|
||||
var sample_rate := get_reference_pitch_samplerate(tuning1)
|
||||
|
||||
buffer.seek(INST_LOOP + (id*2))
|
||||
var loop_start_packet := buffer.get_u16()/9 # Note that Instrument $1F Steel Guitar has a length of $088B but a loop point of $088D which is 243.22... packets. Luckily it doesn't matter.
|
||||
|
||||
|
||||
var lookup_offset := INST_BRR_LOOKUP + (id*3)
|
||||
buffer.seek(lookup_offset)
|
||||
var brr_offset := read_rom_address(buffer)
|
||||
buffer.seek(brr_offset)
|
||||
func get_inst_sample_data(snes_data: Dictionary, buffer: StreamPeerBuffer, id: int) -> AudioStreamSample:
|
||||
var sample_rate := get_reference_pitch_samplerate(snes_data.bgm_instrument_samplerates[id] & 0xFF)
|
||||
var silent_samples := ((sample_rate * PREPEND_MS) / 1000)
|
||||
var loop_start_packet: int = snes_data.bgm_instrument_loop_starts[id]/9 # Note that Instrument $1F Steel Guitar has a length of $088B but a loop point of $088D which is 243.22... packets. Luckily it doesn't matter.
|
||||
buffer.seek(snes_data.bgm_instrument_brr_pointers[id] & 0x3FFFFF)
|
||||
var size := buffer.get_u16()
|
||||
var num_samples := (size/9)*16
|
||||
var audio := make_sample(buffer, size, sample_rate)
|
||||
audio.loop_mode = AudioStreamSample.LOOP_FORWARD
|
||||
audio.loop_begin = loop_start_packet * 16 # Each 9byte packet is 16 samples
|
||||
audio.loop_end = num_samples-1
|
||||
audio.loop_begin = (loop_start_packet * 16) + silent_samples # Each 9byte packet is 16 samples
|
||||
audio.loop_end = silent_samples + num_samples - 1
|
||||
# print_debug('Loaded instrument #%02X with lookup offset $%06X, BRR data offset $%06X, length $%04X (%f packets, %d samples) and loop point %d samples' % [id, lookup_offset, brr_offset, size, size/9.0, num_samples, audio.loop_begin])
|
||||
return audio
|
||||
|
||||
func load_sfx_samples_data(buffer: StreamPeerBuffer):
|
||||
var sample_rates = []
|
||||
buffer.seek(SFX_SR)
|
||||
for i in SFX_NUM:
|
||||
var tuning1 := buffer.get_u8()
|
||||
var tuning2 := buffer.get_u8()
|
||||
sample_rates.append(get_reference_pitch_samplerate(tuning1))
|
||||
func load_sfx_samples_data(snes_data: Dictionary, buffer: StreamPeerBuffer):
|
||||
var brr_spc_addrs = []
|
||||
var brr_spc_loop_addrs = []
|
||||
buffer.seek(SFX_BRR_SPC_TABLE)
|
||||
for two_of_u16 in snes_data.sfx_brr_pointers:
|
||||
brr_spc_addrs.append(two_of_u16[0])
|
||||
brr_spc_loop_addrs.append(two_of_u16[1])
|
||||
var brr_spc_start = SFX_BRR_START - brr_spc_addrs[0] # Refactor this later to somehow reference sfx_brr_data address from the tsv
|
||||
for i in SFX_NUM:
|
||||
brr_spc_addrs.append(buffer.get_u16())
|
||||
brr_spc_loop_addrs.append(buffer.get_u16())
|
||||
var brr_spc_start = brr_spc_addrs[0]
|
||||
for i in SFX_NUM:
|
||||
brr_spc_addrs[i] += SFX_BRR_START - brr_spc_start
|
||||
for i in SFX_NUM:
|
||||
buffer.seek(brr_spc_addrs[i])
|
||||
buffer.seek(brr_spc_addrs[i] + brr_spc_start)
|
||||
# print('Loading sfx sample #%X with BRR data offset $%06X' % [i, buffer.get_position()])
|
||||
sfx_samples.append(make_sample(buffer, 900, sample_rates[i])) # Use 900 as a limit, it won't be hit, parser stops after End packet anyway
|
||||
var sample_rate := get_reference_pitch_samplerate(snes_data.sfx_samplerates[i] & 0xFF)
|
||||
var silent_samples := ((sample_rate * PREPEND_MS) / 1000)
|
||||
var audio := make_sample(buffer, 900, sample_rate)
|
||||
var loop_start_packet: int = brr_spc_loop_addrs[i] - brr_spc_addrs[i]
|
||||
audio.loop_mode = AudioStreamSample.LOOP_FORWARD
|
||||
audio.loop_begin = (loop_start_packet * 16) + silent_samples # Each 9byte packet is 16 samples
|
||||
audio.loop_end = (len(audio.data)/2) - 1
|
||||
sfx_samples.append(audio) # Use 900 as a limit, it won't be hit, parser stops after End packet anyway
|
||||
emit_signal('audio_sfx_sample_loaded', i)
|
||||
# print('size of %d samples' % sfx_samples[i].data.size())
|
||||
|
||||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func load_samples(buffer: StreamPeerBuffer):
|
||||
load_sfx_samples_data(buffer)
|
||||
func load_samples(snes_data: Dictionary, buffer: StreamPeerBuffer):
|
||||
load_sfx_samples_data(snes_data, buffer)
|
||||
# For some reason, this is a bit slow currently. Might optimize later.
|
||||
for i in INST_NUM:
|
||||
instrument_samples.append(get_inst_sample_data(buffer, i))
|
||||
instrument_samples.append(get_inst_sample_data(snes_data, buffer, i))
|
||||
emit_signal('audio_inst_sample_loaded', i)
|
||||
|
||||
|
||||
|
@ -197,15 +192,15 @@ var player := AudioStreamPlayer.new() # Make one for each channel, later
|
|||
func play_sample(id: int):
|
||||
print('Playing inst sample #%02X' % id)
|
||||
player.stream = instrument_samples[id]
|
||||
player.play()
|
||||
player.play(PLAY_START)
|
||||
|
||||
func play_sfx(id: int):
|
||||
print('Playing sfx sample #%02X' % id)
|
||||
player.stream = sfx_samples[id]
|
||||
player.play()
|
||||
player.play(PLAY_START)
|
||||
|
||||
func parse_rom(buffer: StreamPeerBuffer):
|
||||
load_samples(buffer)
|
||||
func parse_rom(snes_data: Dictionary, buffer: StreamPeerBuffer):
|
||||
load_samples(snes_data, buffer)
|
||||
#load_bgms(buffer)
|
||||
has_loaded_audio_samples = true
|
||||
emit_signal('audio_samples_loaded')
|
||||
|
|
Loading…
Reference in New Issue