Instrument sample loop points, correct pitch interpretation
This commit is contained in:
parent
b5800ae0fa
commit
91181e1a78
|
@ -25,6 +25,14 @@ const MAX_16B = 1 << 16
|
||||||
func unsigned16_to_signed(unsigned):
|
func unsigned16_to_signed(unsigned):
|
||||||
return (unsigned + MAX_15B) % MAX_16B - MAX_15B
|
return (unsigned + MAX_15B) % MAX_16B - MAX_15B
|
||||||
|
|
||||||
|
func get_reference_pitch_samplerate(tuning1: int, tuning2: int = 0) -> int:
|
||||||
|
# This is non-trivial and subject to change
|
||||||
|
var pitch_scale = tuning1/256.0 + tuning2/65536.0
|
||||||
|
if tuning1 < 0x80:
|
||||||
|
pitch_scale += 1.0
|
||||||
|
return int(pitch_scale * 36000)
|
||||||
|
# return (unsigned16_to_signed(pitch) + 0x8000) * 32000/4096
|
||||||
|
|
||||||
func process_sample(mantissa: int, exponent: int) -> int:
|
func process_sample(mantissa: int, exponent: int) -> int:
|
||||||
# For filter arithmetic the samples need to be in signed form.
|
# For filter arithmetic the samples need to be in signed form.
|
||||||
# Sign-extend
|
# Sign-extend
|
||||||
|
@ -80,7 +88,7 @@ func make_sample(rom: File, size: int, sample_rate: int) -> AudioStreamSample:
|
||||||
for i in range(samples.size()-8, samples.size()):
|
for i in range(samples.size()-8, samples.size()):
|
||||||
samples[i] = clamp_short(samples[i] + (samples[i-1]*115)/64 - (samples[i-2]*13)/16)
|
samples[i] = clamp_short(samples[i] + (samples[i-1]*115)/64 - (samples[i-2]*13)/16)
|
||||||
if end:
|
if end:
|
||||||
print('End flag on packet')
|
# print('End flag on packet')
|
||||||
break
|
break
|
||||||
var audio_data = PoolByteArray()
|
var audio_data = PoolByteArray()
|
||||||
for i in range(2, samples.size()):
|
for i in range(2, samples.size()):
|
||||||
|
@ -92,22 +100,34 @@ func make_sample(rom: File, size: int, sample_rate: int) -> AudioStreamSample:
|
||||||
|
|
||||||
func get_inst_sample_data(rom: File, id: int) -> AudioStreamSample:
|
func get_inst_sample_data(rom: File, id: int) -> AudioStreamSample:
|
||||||
rom.seek(INST_SR + (id*2))
|
rom.seek(INST_SR + (id*2))
|
||||||
var sample_rate := (rom.get_16() * 32000)/4096
|
var tuning1 := rom.get_8()
|
||||||
|
var tuning2 := rom.get_8()
|
||||||
|
var sample_rate := get_reference_pitch_samplerate(tuning1)
|
||||||
|
|
||||||
|
rom.seek(INST_LOOP + (id*2))
|
||||||
|
var loop_start_packet := rom.get_16()/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)
|
var lookup_offset := INST_BRR_LOOKUP + (id*3)
|
||||||
rom.seek(lookup_offset)
|
rom.seek(lookup_offset)
|
||||||
var brr_offset := read_rom_address(rom)
|
var brr_offset := read_rom_address(rom)
|
||||||
rom.seek(brr_offset)
|
rom.seek(brr_offset)
|
||||||
var size := rom.get_16()
|
var size := rom.get_16()
|
||||||
var sample := make_sample(rom, size, sample_rate)
|
var num_samples := (size/9)*16
|
||||||
#print_debug('Loaded sample instrument #%02X with lookup offset $%06X, BRR data offset $%06X and length $%04X (%f packets)' % [id, lookup_offset, brr_offset, size, size/9.0])
|
var audio := make_sample(rom, size, sample_rate)
|
||||||
return sample
|
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
|
||||||
|
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(rom: File):
|
func load_sfx_samples_data(rom: File):
|
||||||
var sample_rates = []
|
var sample_rates = []
|
||||||
rom.seek(SFX_SR)
|
rom.seek(SFX_SR)
|
||||||
for i in SFX_NUM:
|
for i in SFX_NUM:
|
||||||
sample_rates.append((rom.get_16() * 32000)/4096)
|
var tuning1 := rom.get_8()
|
||||||
|
var tuning2 := rom.get_8()
|
||||||
|
sample_rates.append(get_reference_pitch_samplerate(tuning1))
|
||||||
var brr_spc_addrs = []
|
var brr_spc_addrs = []
|
||||||
var brr_spc_loop_addrs = []
|
var brr_spc_loop_addrs = []
|
||||||
rom.seek(SFX_BRR_SPC_TABLE)
|
rom.seek(SFX_BRR_SPC_TABLE)
|
||||||
|
@ -119,9 +139,9 @@ func load_sfx_samples_data(rom: File):
|
||||||
brr_spc_addrs[i] += SFX_BRR_START - brr_spc_start
|
brr_spc_addrs[i] += SFX_BRR_START - brr_spc_start
|
||||||
for i in SFX_NUM:
|
for i in SFX_NUM:
|
||||||
rom.seek(brr_spc_addrs[i])
|
rom.seek(brr_spc_addrs[i])
|
||||||
print('Loading sfx sample #%X with BRR data offset $%06X' % [i, rom.get_position()])
|
# print('Loading sfx sample #%X with BRR data offset $%06X' % [i, rom.get_position()])
|
||||||
sfx_samples.append(make_sample(rom, 900, sample_rates[i])) # Use 900 as a limit, it won't be hit, parser stops after End packet anyway
|
sfx_samples.append(make_sample(rom, 900, sample_rates[i])) # Use 900 as a limit, it won't be hit, parser stops after End packet anyway
|
||||||
print('size of %d samples' % sfx_samples[i].data.size())
|
# print('size of %d samples' % sfx_samples[i].data.size())
|
||||||
|
|
||||||
|
|
||||||
# Called when the node enters the scene tree for the first time.
|
# Called when the node enters the scene tree for the first time.
|
||||||
|
|
Loading…
Reference in New Issue