[BGM] Fix slide behaviour
Previously it just lerped from the value at the start of the event to the one at the end of the event. This did not account for slides that ended in the middle of the event. Note that slides beginning in the middle of the event are impossible in this sequence format.
This commit is contained in:
parent
f8e3def5d8
commit
8990a6637e
|
@ -12,12 +12,9 @@ class NoteEvent:
|
|||
var p_end: int
|
||||
var instrument: int
|
||||
var pitch: int = 0
|
||||
var pitch_slide: float
|
||||
var pitch_slide_end: float
|
||||
var velocity: float = 0.0
|
||||
var velocity_end: float = 0.0
|
||||
var pan: float
|
||||
var pan_end: float
|
||||
var pitch_slide: Vector3
|
||||
var velocity: Vector3
|
||||
var pan: Vector3
|
||||
var adsr_attack_rate: int
|
||||
var adsr_decay_rate: int
|
||||
var adsr_decay_total_periods: int
|
||||
|
@ -72,6 +69,25 @@ class TrackCurve: # built-in Curve class is too restrictive for this
|
|||
return self.entries[i].y
|
||||
return self.default # Should be unreachable
|
||||
|
||||
func get_pulse_and_slide(pulse: float) -> Vector3: # [value, end_value, p_end_value]
|
||||
var value = self.default
|
||||
var l := len(self.entries)
|
||||
if l == 0 or pulse < self.entries[0].x:
|
||||
return Vector3(value, value, pulse)
|
||||
if pulse >= self.entries[-1].x:
|
||||
value = self.entries[-1].y
|
||||
return Vector3(value, value, pulse)
|
||||
for i in l-1:
|
||||
# Find first entry beyond
|
||||
if pulse < self.entries[i+1].x:
|
||||
if self.entries[i].z > 0: # ramp_to_next
|
||||
value = range_lerp(pulse, self.entries[i].x, self.entries[i+1].x, self.entries[i].y, self.entries[i+1].y)
|
||||
return Vector3(value, self.entries[i+1].y, self.entries[i+1].x)
|
||||
else:
|
||||
value = self.entries[i].y
|
||||
return Vector3(value, value, pulse)
|
||||
return Vector3(value, value, pulse) # Should be unreachable
|
||||
|
||||
func bake_integrals():
|
||||
# Store the starting integrated value (i.e. time for the tempo curve) of each pulse value
|
||||
self.baked_integrals.clear()
|
||||
|
@ -231,8 +247,7 @@ static func render_channels(tracks: Array, inst_map: Array, _debug_name := 'none
|
|||
note_event.p_note_start = p
|
||||
note_event.p_end = p + duration
|
||||
note_event.instrument = current_instrument
|
||||
note_event.pan = curve_pan.get_pulse(p)
|
||||
note_event.pan_end = curve_pan.get_pulse(curve_p_end)
|
||||
note_event.pan = curve_pan.get_pulse_and_slide(p)
|
||||
note_event.adsr_attack_rate = current_adsr_attack_rate
|
||||
note_event.adsr_decay_rate = current_adsr_decay_rate
|
||||
note_event.adsr_decay_total_periods = current_adsr_decay_total_periods
|
||||
|
@ -243,17 +258,14 @@ static func render_channels(tracks: Array, inst_map: Array, _debug_name := 'none
|
|||
curve_pitch_slide.add_point(p, 0) # Reset pitch slide
|
||||
note += (12 * current_octave) + current_transpose
|
||||
note_event.pitch = note # pitch_idx #* curve_fine_tuning
|
||||
note_event.velocity = curve_velocity.get_pulse(p) # current_velocity
|
||||
note_event.velocity_end = curve_velocity.get_pulse(curve_p_end)
|
||||
note_event.velocity = curve_velocity.get_pulse_and_slide(p) # current_velocity
|
||||
elif note == music.NOTE_IS_TIE:
|
||||
if last_note_pretransform_pitch >= 0:
|
||||
note = last_note_pretransform_pitch + (12 * current_octave) + current_transpose
|
||||
note_event.p_note_start = last_untied_note_p_start
|
||||
note_event.pitch = note # pitch_idx #* curve_fine_tuning
|
||||
note_event.pitch_slide = curve_pitch_slide.get_pulse(p)
|
||||
note_event.pitch_slide_end = curve_pitch_slide.get_pulse(curve_p_end)
|
||||
note_event.velocity = curve_velocity.get_pulse(p)
|
||||
note_event.velocity_end = curve_velocity.get_pulse(curve_p_end)
|
||||
note_event.pitch_slide = curve_pitch_slide.get_pulse_and_slide(p)
|
||||
note_event.velocity = curve_velocity.get_pulse_and_slide(p)
|
||||
#else:
|
||||
#curve_pitch_slide.add_point(p, 0) # Reset pitch slide on rest
|
||||
channel_note_events.append(note_event)
|
||||
|
@ -431,11 +443,14 @@ static func render_channels(tracks: Array, inst_map: Array, _debug_name := 'none
|
|||
var loop_return_p = channel_loop_p_returns[channel]
|
||||
var curve_pan: TrackCurve = curve_channel_pans[channel]
|
||||
|
||||
var midi_events_bytes_t_event_start := StreamPeerBuffer.new()
|
||||
var midi_events_bytes_t_note_start := StreamPeerBuffer.new()
|
||||
var midi_events_bytes2 := StreamPeerBuffer.new()
|
||||
var midi_events_bytes_adsr := StreamPeerBuffer.new()
|
||||
var midi_events_bytes4 := StreamPeerBuffer.new()
|
||||
var midi_bytes_t_start_event := StreamPeerBuffer.new()
|
||||
var midi_bytes_t_start_note := StreamPeerBuffer.new()
|
||||
var midi_bytes2 := StreamPeerBuffer.new()
|
||||
var midi_bytes_adsr := StreamPeerBuffer.new()
|
||||
var midi_bytes4 := StreamPeerBuffer.new()
|
||||
var midi_bytes_t_end_volume := StreamPeerBuffer.new()
|
||||
var midi_bytes_t_end_pan := StreamPeerBuffer.new()
|
||||
var midi_bytes_t_end_pitch := StreamPeerBuffer.new()
|
||||
|
||||
var num_notes: int = 0
|
||||
var event_ptr := 0
|
||||
|
@ -451,21 +466,27 @@ static func render_channels(tracks: Array, inst_map: Array, _debug_name := 'none
|
|||
var p = event.p_event_start
|
||||
if loop_return_note_event_idx < 0 and p >= loop_return_p:
|
||||
loop_return_note_event_idx = event_ptr
|
||||
midi_events_bytes_t_event_start.put_32(int(curve_master_tempo.get_integral(p + loop_p_offset) * 32000))
|
||||
midi_events_bytes_t_note_start.put_32(int(curve_master_tempo.get_integral(event.p_note_start + loop_p_offset) * 32000))
|
||||
# midi_events_bytes_t_end.put_32(int(curve_master_tempo.get_integral(event.p_end + loop_p_offset) * 32000)) # t_end
|
||||
midi_events_bytes2.put_u8(event.instrument)
|
||||
midi_events_bytes2.put_u8(event.pitch)
|
||||
midi_events_bytes2.put_u8(int(event.velocity * curve_master_volume.get_pulse(p) * 255.0))
|
||||
midi_events_bytes2.put_u8(int(event.velocity_end * curve_master_volume.get_pulse(p) * 255.0))
|
||||
midi_events_bytes_adsr.put_u8(event.adsr_attack_rate)
|
||||
midi_events_bytes_adsr.put_u8(event.adsr_decay_rate)
|
||||
midi_events_bytes_adsr.put_u8(event.adsr_decay_total_periods)
|
||||
midi_events_bytes_adsr.put_u8(event.adsr_sustain_rate)
|
||||
midi_events_bytes4.put_u8(int((event.pan+1.0) * 127.5))
|
||||
midi_events_bytes4.put_u8(int((event.pan_end+1.0) * 127.5))
|
||||
midi_events_bytes4.put_u8(int((event.pitch_slide*5))+128)
|
||||
midi_events_bytes4.put_u8(int((event.pitch_slide_end*5))+128)
|
||||
midi_bytes_t_start_event.put_32(int(curve_master_tempo.get_integral(p + loop_p_offset) * 32000))
|
||||
midi_bytes_t_start_note.put_32(int(curve_master_tempo.get_integral(event.p_note_start + loop_p_offset) * 32000))
|
||||
midi_bytes_t_end_volume.put_32(int(curve_master_tempo.get_integral(event.velocity.z + loop_p_offset) * 32000))
|
||||
midi_bytes_t_end_pan.put_32(int(curve_master_tempo.get_integral(event.pan.z + loop_p_offset) * 32000))
|
||||
midi_bytes_t_end_pitch.put_32(int(curve_master_tempo.get_integral(event.pitch_slide.z + loop_p_offset) * 32000))
|
||||
# midi_bytes_t_end.put_32(int(curve_master_tempo.get_integral(event.p_end + loop_p_offset) * 32000)) # t_end
|
||||
midi_bytes2.put_u8(event.instrument)
|
||||
midi_bytes2.put_u8(event.pitch)
|
||||
var vel_u8 := event.velocity * curve_master_volume.get_pulse(p) * 255.0
|
||||
midi_bytes2.put_u8(int(vel_u8.x))
|
||||
midi_bytes2.put_u8(int(vel_u8.y))
|
||||
midi_bytes_adsr.put_u8(event.adsr_attack_rate)
|
||||
midi_bytes_adsr.put_u8(event.adsr_decay_rate)
|
||||
midi_bytes_adsr.put_u8(event.adsr_decay_total_periods)
|
||||
midi_bytes_adsr.put_u8(event.adsr_sustain_rate)
|
||||
var pan_u8 := (event.pan+Vector3.ONE) * 127.5
|
||||
midi_bytes4.put_u8(int(pan_u8.x))
|
||||
midi_bytes4.put_u8(int(pan_u8.y))
|
||||
var pitchslide_s8 := event.pitch_slide * 2
|
||||
midi_bytes4.put_u8(int(pitchslide_s8.x) + 128)
|
||||
midi_bytes4.put_u8(int(pitchslide_s8.y) + 128)
|
||||
|
||||
event_ptr += 1
|
||||
num_notes += 1
|
||||
|
@ -474,14 +495,15 @@ static func render_channels(tracks: Array, inst_map: Array, _debug_name := 'none
|
|||
if events:
|
||||
last_note_end = int(curve_master_tempo.get_integral(events[-1].p_end + loop_p_offset) * 32000)
|
||||
for i in range(num_notes, MAX_NOTE_EVENTS):
|
||||
midi_events_bytes_t_event_start.put_32(last_note_end)
|
||||
midi_events_bytes_t_note_start.put_32(last_note_end)
|
||||
# midi_events_bytes_t_end.put_32(0x0FFFFFFF)
|
||||
midi_events_bytes2.put_32(0)
|
||||
midi_events_bytes_adsr.put_32(0)
|
||||
midi_events_bytes4.put_32(0)
|
||||
# data += midi_events_bytes_t_event_start.data_array + midi_events_bytes_t_end.data_array + midi_events_bytes2.data_array + midi_events_bytes_adsr.data_array + midi_events_bytes_t_note_start.data_array
|
||||
data += midi_events_bytes_t_event_start.data_array + midi_events_bytes_t_note_start.data_array + midi_events_bytes2.data_array + midi_events_bytes_adsr.data_array + midi_events_bytes4.data_array
|
||||
midi_bytes_t_start_event.put_32(last_note_end)
|
||||
midi_bytes_t_start_note.put_32(last_note_end)
|
||||
midi_bytes_t_end_volume.put_32(0x0FFFFFFF)
|
||||
midi_bytes_t_end_pan.put_32(0x0FFFFFFF)
|
||||
midi_bytes_t_end_pitch.put_32(0x0FFFFFFF)
|
||||
midi_bytes2.put_32(0)
|
||||
midi_bytes_adsr.put_32(0)
|
||||
midi_bytes4.put_32(0)
|
||||
data += midi_bytes_t_start_event.data_array + midi_bytes_t_start_note.data_array + midi_bytes2.data_array + midi_bytes_adsr.data_array + midi_bytes4.data_array + midi_bytes_t_end_volume.data_array + midi_bytes_t_end_pan.data_array + midi_bytes_t_end_pitch.data_array
|
||||
var t_loop_endpoints := Vector2(-1, -1)
|
||||
if highest_channel_p_return >= 0:
|
||||
t_loop_endpoints = Vector2(curve_master_tempo.get_integral(highest_channel_p_return + 100), curve_master_tempo.get_integral(longest_channel_p_end + 100))
|
||||
|
|
|
@ -224,7 +224,7 @@ highp vec4 render_song(highp sampler2D tex, highp int smp) {
|
|||
|
||||
// Binary search the channels
|
||||
for (int channel = 0; channel < NUM_CHANNELS; channel++) {
|
||||
highp float row = float(channel * 5);
|
||||
highp float row = float(channel * 8);
|
||||
highp float event_idx = 0.0;
|
||||
highp int smp_event_start;
|
||||
for (int i = 0; i < NUM_CHANNEL_NOTE_PROBES; i++) {
|
||||
|
@ -237,27 +237,33 @@ highp vec4 render_song(highp sampler2D tex, highp int smp) {
|
|||
highp vec4 tex2 = get_midi_texel(tex, event_idx, row+2.0);
|
||||
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_tex0 = get_midi_texel(tex, event_idx+1.0, row);
|
||||
highp vec4 tex5 = get_midi_texel(tex, event_idx, row+5.0);
|
||||
highp vec4 tex6 = get_midi_texel(tex, event_idx, row+6.0);
|
||||
highp vec4 tex7 = get_midi_texel(tex, event_idx, row+7.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_note_start = retime_smp(unpack_int32(tex1));
|
||||
highp int next_smp_event_start = retime_smp(unpack_int32(next_tex0));
|
||||
highp int next_smp_note_start = retime_smp(unpack_int32(next_tex1));
|
||||
|
||||
// For now, just branch this
|
||||
if (smp_note_start < smp) { // First sample may not start at zero!
|
||||
highp int smp_release_overrun = (smp_note_start == next_smp_note_start) ? 0 : max(smp - next_smp_note_start + 256, 0); // 256 samples of linear decay to 0 before next non-tie event
|
||||
if (smp_release_overrun < 256) {
|
||||
highp float event_progress = float(smp - smp_event_start)/float(next_smp_event_start - smp_event_start);
|
||||
highp float instrument_idx = trunc(tex2.x * 255.0);
|
||||
highp float pitch_idx = tex2.y * 255.0;
|
||||
highp float velocity = mix(tex2.z, tex2.w, event_progress);
|
||||
highp float pan = mix(tex4.x, tex4.y, event_progress);
|
||||
highp float pitchslide = ((mix(tex4.z, tex4.w, event_progress)*255.0) - 128.0)/5.0;
|
||||
// Calculate slide-based values
|
||||
highp float smp_event_progress = float(smp - smp_event_start);
|
||||
highp ivec3 smp_end_vol_pan_pitch = ivec3(retime_smp(unpack_int32(tex5)), retime_smp(unpack_int32(tex6)), retime_smp(unpack_int32(tex7)));
|
||||
highp vec3 smp_progress_vol_pan_pitch = vec3(smp_end_vol_pan_pitch - smp_event_start);
|
||||
highp vec3 progress_vol_pan_pitch = clamp(smp_event_progress/smp_progress_vol_pan_pitch, 0.0, 1.0);
|
||||
highp float velocity = mix(tex2.z, tex2.w, progress_vol_pan_pitch.x);
|
||||
highp float pan = mix(tex4.x, tex4.y, progress_vol_pan_pitch.y);
|
||||
highp float pitchslide = ((mix(tex4.z, tex4.w, progress_vol_pan_pitch.z)*255.0) - 128.0)/2.0;
|
||||
pitch_idx += pitchslide;
|
||||
|
||||
highp ivec4 adsr = ivec4(tex3 * 255.0);
|
||||
// ====================At some point I'll look back into packing floats====================
|
||||
// TBD = note_event_supplement.zw; - tremolo/vibrato/noise/pan_lfo/pitchbend/echo remain
|
||||
// TBD = note_event_supplement.zw; - tremolo/vibrato/noise/pan_lfo/echo remain
|
||||
// ====================At some point I'll look back into packing floats====================
|
||||
highp int smp_attack = get_attack_time_smps(adsr.x);
|
||||
highp int adsr_decay_rate = get_rate_period(adsr.y*2 + 16);
|
||||
|
|
Loading…
Reference in New Issue