BGM: Add note ties (previously assumed they were also rests)
This commit is contained in:
parent
a50514f7ec
commit
be7874ba27
|
@ -86,7 +86,7 @@ func _init(tracks: Array, instrument_map: Dictionary):
|
|||
|
||||
func play_channel(channel: int, time_offset: float = 0.0) -> int:
|
||||
# Executes the track events until it hits a note/rest, in which case it returns the pulse count to the next action, or the end of the events, in which case it returns -1
|
||||
self.players[channel].stop()
|
||||
# self.players[channel].stop()
|
||||
var track: Array = self.tracks[channel]
|
||||
var l := len(track)
|
||||
var player: AudioStreamPlayer = self.players[channel]
|
||||
|
@ -106,7 +106,10 @@ func play_channel(channel: int, time_offset: float = 0.0) -> int:
|
|||
player.volume_db = linear2db((self.channel_velocity[channel]/255.0) * (self.master_volume/255.0))
|
||||
player.play(max((SoundLoader.PLAY_START - time_offset)/player.pitch_scale, 0))
|
||||
self.channel_current_note[channel] = note
|
||||
elif note == music.NOTE_IS_TIE:
|
||||
pass
|
||||
else:
|
||||
self.players[channel].stop()
|
||||
self.channel_current_note[channel] = -1
|
||||
# TODO: Confirm tempo scaling
|
||||
return duration # Pulses to next instruction
|
||||
|
@ -331,6 +334,7 @@ func render_channels(_t_start: float, _t_end: float, inst_map: Array) -> Array:
|
|||
# the strategy will be to preprocess each channel in a global-state-agnostic way,
|
||||
# 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 instrument_adsrs = RomLoader.snes_data.bgm_instrument_adsrs # TODO: UNHARDCODE THIS
|
||||
var all_note_events = []
|
||||
|
||||
|
@ -412,6 +416,8 @@ func render_channels(_t_start: float, _t_end: float, inst_map: Array) -> Array:
|
|||
note_event.adsr_release = current_adsr_release
|
||||
channel_note_events.append(note_event)
|
||||
# num_notes += 1
|
||||
elif note == music.NOTE_IS_TIE:
|
||||
channel_note_events[-1].p_end += duration
|
||||
p += duration
|
||||
EventType.VOLUME:
|
||||
var new_velocity: float = event[1]/255.0
|
||||
|
@ -612,3 +618,32 @@ func render_channels(_t_start: float, _t_end: float, inst_map: Array) -> Array:
|
|||
smp_loop_start = curve_master_tempo.get_integral(highest_channel_p_return + 100) * 32000
|
||||
smp_loop_end = curve_master_tempo.get_integral(longest_channel_p_end + 100) * 32000
|
||||
return [data, target_time_length, [smp_loop_start, smp_loop_end]]
|
||||
|
||||
func print_channel_events(inst_map: Array) -> void:
|
||||
for channel in self.num_tracks:
|
||||
print('================Channel %d================'%channel)
|
||||
var track: Array = self.tracks[channel]
|
||||
var l := len(track)
|
||||
var p := 0 # current pulse
|
||||
for event in track: #num_notes < MAX_NOTE_EVENTS:
|
||||
var print_str := 'p=%6d : %s '%[p, EventType.keys()[event[0]]]
|
||||
match event[0]:
|
||||
EventType.NOTE:
|
||||
var note = event[1]
|
||||
var duration = event[2]
|
||||
match note:
|
||||
music.NOTE_IS_REST:
|
||||
print('p=%6d : NOTE_REST %d pulses'%[p, duration])
|
||||
music.NOTE_IS_TIE:
|
||||
print('p=%6d : NOTE_TIE %d pulses'%[p, duration])
|
||||
_:
|
||||
print(print_str, event.slice(1, -1))
|
||||
p += duration
|
||||
EventType.PROGCHANGE:
|
||||
var event_idx = event[1]-0x20
|
||||
if event_idx >= 0:
|
||||
print(print_str, ' instrument %02d'%(inst_map[event_idx] - 1))
|
||||
else:
|
||||
print(print_str, event.slice(1, -1))
|
||||
_:
|
||||
print(print_str, event.slice(1, -1))
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
const MAX_TRACKS := 8
|
||||
const MAX_LOOP_DEPTH := 8 # Apparently 4, but eh whatever
|
||||
const NOTE_IS_TIE := -1
|
||||
const NOTE_IS_REST := -2
|
||||
|
||||
enum EventType {
|
||||
ADSR_ATTACK,
|
||||
|
@ -126,6 +128,8 @@ static func get_int_array(size: int) -> PoolIntArray:
|
|||
var EVENT_MAP: Dictionary
|
||||
var NOTE_DURATIONS: PoolByteArray # This might need to be made untyped if a future addition uses PoolIntArray instead
|
||||
var REFERENCE_NOTE: int
|
||||
var NOTE_TIE: int
|
||||
var NOTE_REST: int
|
||||
|
||||
const LOGGING_LEVEL_INFO: bool = false
|
||||
func print_info(s: String) -> void:
|
||||
|
@ -138,8 +142,11 @@ func translate_instruction(buffer: StreamPeer) -> Array:
|
|||
if instruction < 0xD2:
|
||||
var duration = self.NOTE_DURATIONS[instruction % 15]
|
||||
var note = instruction / 15
|
||||
if note >= 12: # 12 and 13 are rests
|
||||
note = -1
|
||||
if note >= 12: # 12 and 13 are rests and ties
|
||||
if note == self.NOTE_REST:
|
||||
note = NOTE_IS_REST
|
||||
else:
|
||||
note = NOTE_IS_TIE
|
||||
return [EventType.NOTE, note, duration]
|
||||
else:
|
||||
# Control codes
|
||||
|
|
|
@ -5,6 +5,8 @@ func _init() -> void:
|
|||
# Durations are in pulses, 48 = 1 quarter note (crotchet)
|
||||
self.NOTE_DURATIONS = PoolByteArray([192, 144, 96, 64, 72, 48, 32, 36, 24, 16, 12, 8, 6, 4, 3]) # See ROM 0x041D7E to 0x041D8C
|
||||
self.REFERENCE_NOTE = 71
|
||||
self.NOTE_TIE = 12
|
||||
self.NOTE_REST = 13
|
||||
|
||||
self.EVENT_MAP = {
|
||||
0xD2: EventType.VOLUME,
|
||||
|
|
Loading…
Reference in New Issue