[BGM] Fix up decay and release handling

This commit is contained in:
Luke Hubmayer-Werner 2024-07-27 15:53:44 +09:30
parent 877f1e491b
commit 0385004534
3 changed files with 143 additions and 98 deletions

View File

@ -1,5 +1,8 @@
#warning-ignore-all:shadowed_variable #warning-ignore-all:shadowed_variable
extends Node 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 music := preload('res://scripts/loaders/snes/music_ff5.gd')
const EventType := music.EventType const EventType := music.EventType
var MUSIC := music.new() var MUSIC := music.new()
@ -10,14 +13,23 @@ class NoteEvent:
var p_note_start: int # For tied notes, this will be earlier than p_event_start and is used for envelope calculations var p_note_start: int # For tied notes, this will be earlier than p_event_start and is used for envelope calculations
var p_end: int var p_end: int
var instrument: int var instrument: int
var pitch: int var pitch: int = 0
var velocity: float var velocity: float = 0.0
var adsr_attack_rate: int var adsr_attack_rate: int
var adsr_decay_rate: int var adsr_decay_rate: int
var adsr_sustain_level: int var adsr_decay_total_periods: int
var adsr_sustain_rate: int 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 class TrackCurve: # built-in Curve class is too restrictive for this
var default: float var default: float
var entries: PoolVector3Array var entries: PoolVector3Array
@ -168,7 +180,7 @@ static func render_channels(tracks: Array, inst_map: Array, _debug_name := 'none
# var current_velocity := 255 # var current_velocity := 255
var current_adsr_attack_rate := 0 var current_adsr_attack_rate := 0
var current_adsr_decay_rate := 0 var current_adsr_decay_rate := 0
var current_adsr_sustain_level := 0 var current_adsr_decay_total_periods := 0
var current_adsr_sustain_rate := 0 var current_adsr_sustain_rate := 0
# First, check if it ends in a GOTO, then store the program counter of the destination # First, check if it ends in a GOTO, then store the program counter of the destination
@ -209,37 +221,27 @@ static func render_channels(tracks: Array, inst_map: Array, _debug_name := 'none
EventType.NOTE: EventType.NOTE:
var note = event[1] var note = event[1]
var duration = event[2] var duration = event[2]
if note >= 0: # Don't shift or play rests
last_note_pretransform_pitch = note # Ties reuse this
last_untied_note_p_start = p
note += (12 * current_octave) + current_transpose
var note_event = NoteEvent.new() var note_event = NoteEvent.new()
note_event.p_event_start = p note_event.p_event_start = p
note_event.p_note_start = p note_event.p_note_start = p
note_event.p_end = p + duration note_event.p_end = p + duration
note_event.instrument = current_instrument note_event.instrument = current_instrument
note_event.pitch = note # pitch_idx #* curve_fine_tuning
note_event.velocity = curve_velocity.get_pulse(p) # current_velocity
note_event.adsr_attack_rate = current_adsr_attack_rate note_event.adsr_attack_rate = current_adsr_attack_rate
note_event.adsr_decay_rate = current_adsr_decay_rate note_event.adsr_decay_rate = current_adsr_decay_rate
note_event.adsr_sustain_level = current_adsr_sustain_level note_event.adsr_decay_total_periods = current_adsr_decay_total_periods
note_event.adsr_sustain_rate = current_adsr_sustain_rate note_event.adsr_sustain_rate = current_adsr_sustain_rate
channel_note_events.append(note_event) if note >= 0: # Don't shift or play rests
# num_notes += 1 last_note_pretransform_pitch = note # Ties reuse this
last_untied_note_p_start = p
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
elif note == music.NOTE_IS_TIE: elif note == music.NOTE_IS_TIE:
if last_note_pretransform_pitch >= 0: if last_note_pretransform_pitch >= 0:
note = last_note_pretransform_pitch + (12 * current_octave) + current_transpose note = last_note_pretransform_pitch + (12 * current_octave) + current_transpose
var note_event = NoteEvent.new()
note_event.p_event_start = p
note_event.p_note_start = last_untied_note_p_start note_event.p_note_start = last_untied_note_p_start
note_event.p_end = p + duration
note_event.instrument = current_instrument
note_event.pitch = note # pitch_idx #* curve_fine_tuning note_event.pitch = note # pitch_idx #* curve_fine_tuning
note_event.velocity = curve_velocity.get_pulse(p) # current_velocity note_event.velocity = curve_velocity.get_pulse(p) # current_velocity
note_event.adsr_attack_rate = current_adsr_attack_rate
note_event.adsr_decay_rate = current_adsr_decay_rate
note_event.adsr_sustain_level = current_adsr_sustain_level
note_event.adsr_sustain_rate = current_adsr_sustain_rate
channel_note_events.append(note_event) channel_note_events.append(note_event)
p += duration p += duration
EventType.VOLUME: EventType.VOLUME:
@ -289,21 +291,21 @@ static func render_channels(tracks: Array, inst_map: Array, _debug_name := 'none
var adsr = sample_default_adsrs[current_instrument] var adsr = sample_default_adsrs[current_instrument]
current_adsr_attack_rate = adsr[0] current_adsr_attack_rate = adsr[0]
current_adsr_decay_rate = adsr[1] current_adsr_decay_rate = adsr[1]
current_adsr_sustain_level = adsr[2] current_adsr_decay_total_periods = get_adsr_decay_total_periods(adsr[2])
current_adsr_sustain_rate = adsr[3] current_adsr_sustain_rate = adsr[3]
EventType.ADSR_DEFAULT: # TODO - Investigate actual scaling and order EventType.ADSR_DEFAULT: # TODO - Investigate actual scaling and order
if current_instrument < len(sample_default_adsrs) and current_instrument > 0: if current_instrument < len(sample_default_adsrs) and current_instrument > 0:
var adsr = sample_default_adsrs[current_instrument] var adsr = sample_default_adsrs[current_instrument]
current_adsr_attack_rate = adsr[0] current_adsr_attack_rate = adsr[0]
current_adsr_decay_rate = adsr[1] current_adsr_decay_rate = adsr[1]
current_adsr_sustain_level = adsr[2] current_adsr_decay_total_periods = get_adsr_decay_total_periods(adsr[2])
current_adsr_sustain_rate = adsr[3] current_adsr_sustain_rate = adsr[3]
EventType.ADSR_ATTACK_RATE: EventType.ADSR_ATTACK_RATE:
current_adsr_attack_rate = event[1] current_adsr_attack_rate = event[1]
EventType.ADSR_DECAY_RATE: EventType.ADSR_DECAY_RATE:
current_adsr_decay_rate = event[1] current_adsr_decay_rate = event[1]
EventType.ADSR_SUSTAIN_LEVEL: EventType.ADSR_SUSTAIN_LEVEL:
current_adsr_sustain_level = event[1] current_adsr_decay_total_periods = get_adsr_decay_total_periods(event[1])
EventType.ADSR_SUSTAIN_RATE: EventType.ADSR_SUSTAIN_RATE:
current_adsr_sustain_rate = event[1] current_adsr_sustain_rate = event[1]
EventType.VIBRATO_ON: EventType.VIBRATO_ON:
@ -419,9 +421,10 @@ static func render_channels(tracks: Array, inst_map: Array, _debug_name := 'none
var midi_events_bytes_t_event_start := StreamPeerBuffer.new() var midi_events_bytes_t_event_start := StreamPeerBuffer.new()
var midi_events_bytes_t_note_start := StreamPeerBuffer.new() var midi_events_bytes_t_note_start := StreamPeerBuffer.new()
var midi_events_bytes_t_end := StreamPeerBuffer.new() # var midi_events_bytes_t_end := StreamPeerBuffer.new()
var midi_events_bytes3 := StreamPeerBuffer.new() var midi_events_bytes2 := StreamPeerBuffer.new()
var midi_events_bytes_adsr := StreamPeerBuffer.new() var midi_events_bytes_adsr := StreamPeerBuffer.new()
var midi_events_bytes_adsr2 := StreamPeerBuffer.new()
var num_notes: int = 0 var num_notes: int = 0
var event_ptr := 0 var event_ptr := 0
@ -439,26 +442,32 @@ static func render_channels(tracks: Array, inst_map: Array, _debug_name := 'none
loop_return_note_event_idx = event_ptr 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_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_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_bytes_t_end.put_32(int(curve_master_tempo.get_integral(event.p_end + loop_p_offset) * 32000)) # t_end
midi_events_bytes3.put_u8(event.instrument) midi_events_bytes2.put_u8(event.instrument)
midi_events_bytes3.put_u8(event.pitch) midi_events_bytes2.put_u8(event.pitch)
midi_events_bytes3.put_u8(int(event.velocity * curve_master_volume.get_pulse(p) * 255.0)) # velocity midi_events_bytes2.put_u8(int(event.velocity * curve_master_volume.get_pulse(p) * 255.0)) # velocity
midi_events_bytes3.put_u8(int((curve_pan.get_pulse(p)+1.0) * 127.5)) # pan midi_events_bytes2.put_u8(int((curve_pan.get_pulse(p)+1.0) * 127.5)) # pan
midi_events_bytes_adsr.put_u8(event.adsr_attack_rate) 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_rate)
midi_events_bytes_adsr.put_u8(event.adsr_sustain_level) midi_events_bytes_adsr.put_u8(event.adsr_decay_total_periods)
midi_events_bytes_adsr.put_u8(event.adsr_sustain_rate) midi_events_bytes_adsr.put_u8(event.adsr_sustain_rate)
midi_events_bytes_adsr2.put_32(0)
event_ptr += 1 event_ptr += 1
num_notes += 1 num_notes += 1
# Fill up end of notes array with dummies # Fill up end of notes array with dummies
var last_note_end: int = 0
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): for i in range(num_notes, MAX_NOTE_EVENTS):
midi_events_bytes_t_event_start.put_32(0x0FFFFFFF) midi_events_bytes_t_event_start.put_32(last_note_end)
midi_events_bytes_t_note_start.put_32(0x0FFFFFFF) midi_events_bytes_t_note_start.put_32(last_note_end)
midi_events_bytes_t_end.put_32(0x0FFFFFFF) # midi_events_bytes_t_end.put_32(0x0FFFFFFF)
midi_events_bytes3.put_32(0) midi_events_bytes2.put_32(0)
midi_events_bytes_adsr.put_32(0) midi_events_bytes_adsr.put_32(0)
data += midi_events_bytes_t_event_start.data_array + midi_events_bytes_t_end.data_array + midi_events_bytes3.data_array + midi_events_bytes_adsr.data_array + midi_events_bytes_t_note_start.data_array midi_events_bytes_adsr2.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_bytes_adsr2.data_array
var t_loop_endpoints := Vector2(-1, -1) var t_loop_endpoints := Vector2(-1, -1)
if highest_channel_p_return >= 0: 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)) t_loop_endpoints = Vector2(curve_master_tempo.get_integral(highest_channel_p_return + 100), curve_master_tempo.get_integral(longest_channel_p_end + 100))

View File

@ -12,14 +12,31 @@ const PREPEND_MS := 20 # Prepend 20ms of silence to each sample for preplay pur
const PLAY_START := PREPEND_MS / 1000.0 const PLAY_START := PREPEND_MS / 1000.0
const BYTES_PER_SAMPLE := 2 # 16bit samples const BYTES_PER_SAMPLE := 2 # 16bit samples
const ATTACK_TIME_SMPS := PoolIntArray([131200, 83200, 48000, 32000, 20480, 12160, 8320, 5120, 3072, 2048, 1280, 768, 512, 320, 192, 0]) const ATTACK_TIME_SMPS := PoolIntArray([131072, 81920, 49152, 32768, 20480, 12288, 8192, 5120, 3072, 2048, 1280, 768, 512, 320, 192, 2])
const ATTACK_TIME_SMPS_ENTRIES := 16 const ATTACK_TIME_SMPS_ENTRIES := 16
const DECAY_TIME_SMPS := PoolIntArray([38400, 23680, 14080, 9280, 5760, 3520, 2368, 1184]) # const DECAY_TIME_SMPS := PoolIntArray([38400, 23680, 14080, 9280, 5760, 3520, 2368, 1184])
const DECAY_TIME_SMPS_ENTRIES := 8 # const DECAY_TIME_SMPS_ENTRIES := 8
const SUSTAIN_DECAY_TIME_SMPS = PoolIntArray([0, 1216000, 896000, 768000, 608000, 448000, 384000, 300800, 227200, 188800, 150400, 112000, 92800, 76800, 57600, 48000, 38400, 28160, 23680, 18880, 14080, 11840, 9280, 7040, 5760, 4800, 3520, 2944, 2368, 1760, 1184, 576]) # const SUSTAIN_DECAY_TIME_SMPS = PoolIntArray([0, 1216000, 896000, 768000, 608000, 448000, 384000, 300800, 227200, 188800, 150400, 112000, 92800, 76800, 57600, 48000, 38400, 28160, 23680, 18880, 14080, 11840, 9280, 7040, 5760, 4800, 3520, 2944, 2368, 1760, 1184, 576])
const SUSTAIN_DECAY_TIME_SMPS_ENTRIES = 32 # const SUSTAIN_DECAY_TIME_SMPS_ENTRIES = 32
const SPC_DECAY_CURVE := PoolIntArray([1024, 1020, 1016, 1012, 1008, 1004, 1000, 996, 992, 988, 984, 980, 976, 972, 968, 964, 960, 956, 952, 948, 944, 940, 936, 932, 928, 924, 920, 916, 912, 908, 904, 900, 896, 892, 888, 884, 880, 876, 872, 868, 864, 860, 856, 852, 848, 844, 840, 836, 832, 828, 824, 820, 816, 812, 808, 804, 800, 796, 792, 788, 784, 780, 776, 772, 768, 765, 762, 759, 756, 753, 750, 747, 744, 741, 738, 735, 732, 729, 726, 723, 720, 717, 714, 711, 708, 705, 702, 699, 696, 693, 690, 687, 684, 681, 678, 675, 672, 669, 666, 663, 660, 657, 654, 651, 648, 645, 642, 639, 636, 633, 630, 627, 624, 621, 618, 615, 612, 609, 606, 603, 600, 597, 594, 591, 588, 585, 582, 579, 576, 573, 570, 567, 564, 561, 558, 555, 552, 549, 546, 543, 540, 537, 534, 531, 528, 525, 522, 519, 516, 513, 510, 508, 506, 504, 502, 500, 498, 496, 494, 492, 490, 488, 486, 484, 482, 480, 478, 476, 474, 472, 470, 468, 466, 464, 462, 460, 458, 456, 454, 452, 450, 448, 446, 444, 442, 440, 438, 436, 434, 432, 430, 428, 426, 424, 422, 420, 418, 416, 414, 412, 410, 408, 406, 404, 402, 400, 398, 396, 394, 392, 390, 388, 386, 384, 382, 380, 378, 376, 374, 372, 370, 368, 366, 364, 362, 360, 358, 356, 354, 352, 350, 348, 346, 344, 342, 340, 338, 336, 334, 332, 330, 328, 326, 324, 322, 320, 318, 316, 314, 312, 310, 308, 306, 304, 302, 300, 298, 296, 294, 292, 290, 288, 286, 284, 282, 280, 278, 276, 274, 272, 270, 268, 266, 264, 262, 260, 258, 256, 255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245, 244, 243, 242, 241, 240, 239, 238, 237, 236, 235, 234, 233, 232, 231, 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, 128, 127, 126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0])
const SPC_DECAY_CURVE_ENTRIES := 535 # len(SPC_DECAY_CURVE) # Includes trailing zero const SPC_DECAY_CURVE := PoolIntArray([2047, 2039, 2031, 2023, 2015, 2007, 1999, 1991, 1983, 1975, 1967, 1959, 1951, 1943, 1935, 1927, 1919, 1911, 1903, 1895, 1887, 1879, 1871, 1863, 1855, 1847, 1839, 1831, 1823, 1815, 1807, 1799, 1791, 1784, 1777, 1770, 1763, 1756, 1749, 1742, 1735, 1728, 1721, 1714, 1707, 1700, 1693, 1686, 1679, 1672, 1665, 1658, 1651, 1644, 1637, 1630, 1623, 1616, 1609, 1602, 1595, 1588, 1581, 1574, 1567, 1560, 1553, 1546, 1539, 1532, 1526, 1520, 1514, 1508, 1502, 1496, 1490, 1484, 1478, 1472, 1466, 1460, 1454, 1448, 1442, 1436, 1430, 1424, 1418, 1412, 1406, 1400, 1394, 1388, 1382, 1376, 1370, 1364, 1358, 1352, 1346, 1340, 1334, 1328, 1322, 1316, 1310, 1304, 1298, 1292, 1286, 1280, 1275, 1270, 1265, 1260, 1255, 1250, 1245, 1240, 1235, 1230, 1225, 1220, 1215, 1210, 1205, 1200, 1195, 1190, 1185, 1180, 1175, 1170, 1165, 1160, 1155, 1150, 1145, 1140, 1135, 1130, 1125, 1120, 1115, 1110, 1105, 1100, 1095, 1090, 1085, 1080, 1075, 1070, 1065, 1060, 1055, 1050, 1045, 1040, 1035, 1030, 1025, 1020, 1016, 1012, 1008, 1004, 1000, 996, 992, 988, 984, 980, 976, 972, 968, 964, 960, 956, 952, 948, 944, 940, 936, 932, 928, 924, 920, 916, 912, 908, 904, 900, 896, 892, 888, 884, 880, 876, 872, 868, 864, 860, 856, 852, 848, 844, 840, 836, 832, 828, 824, 820, 816, 812, 808, 804, 800, 796, 792, 788, 784, 780, 776, 772, 768, 765, 762, 759, 756, 753, 750, 747, 744, 741, 738, 735, 732, 729, 726, 723, 720, 717, 714, 711, 708, 705, 702, 699, 696, 693, 690, 687, 684, 681, 678, 675, 672, 669, 666, 663, 660, 657, 654, 651, 648, 645, 642, 639, 636, 633, 630, 627, 624, 621, 618, 615, 612, 609, 606, 603, 600, 597, 594, 591, 588, 585, 582, 579, 576, 573, 570, 567, 564, 561, 558, 555, 552, 549, 546, 543, 540, 537, 534, 531, 528, 525, 522, 519, 516, 513, 510, 508, 506, 504, 502, 500, 498, 496, 494, 492, 490, 488, 486, 484, 482, 480, 478, 476, 474, 472, 470, 468, 466, 464, 462, 460, 458, 456, 454, 452, 450, 448, 446, 444, 442, 440, 438, 436, 434, 432, 430, 428, 426, 424, 422, 420, 418, 416, 414, 412, 410, 408, 406, 404, 402, 400, 398, 396, 394, 392, 390, 388, 386, 384, 382, 380, 378, 376, 374, 372, 370, 368, 366, 364, 362, 360, 358, 356, 354, 352, 350, 348, 346, 344, 342, 340, 338, 336, 334, 332, 330, 328, 326, 324, 322, 320, 318, 316, 314, 312, 310, 308, 306, 304, 302, 300, 298, 296, 294, 292, 290, 288, 286, 284, 282, 280, 278, 276, 274, 272, 270, 268, 266, 264, 262, 260, 258, 256, 255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245, 244, 243, 242, 241, 240, 239, 238, 237, 236, 235, 234, 233, 232, 231, 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, 128, 127, 126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0])
const SPC_DECAY_CURVE_ENTRIES := len(SPC_DECAY_CURVE) #697
# const SPC_DECAY_CURVE := PoolIntArray([1024, 1020, 1016, 1012, 1008, 1004, 1000, 996, 992, 988, 984, 980, 976, 972, 968, 964, 960, 956, 952, 948, 944, 940, 936, 932, 928, 924, 920, 916, 912, 908, 904, 900, 896, 892, 888, 884, 880, 876, 872, 868, 864, 860, 856, 852, 848, 844, 840, 836, 832, 828, 824, 820, 816, 812, 808, 804, 800, 796, 792, 788, 784, 780, 776, 772, 768, 765, 762, 759, 756, 753, 750, 747, 744, 741, 738, 735, 732, 729, 726, 723, 720, 717, 714, 711, 708, 705, 702, 699, 696, 693, 690, 687, 684, 681, 678, 675, 672, 669, 666, 663, 660, 657, 654, 651, 648, 645, 642, 639, 636, 633, 630, 627, 624, 621, 618, 615, 612, 609, 606, 603, 600, 597, 594, 591, 588, 585, 582, 579, 576, 573, 570, 567, 564, 561, 558, 555, 552, 549, 546, 543, 540, 537, 534, 531, 528, 525, 522, 519, 516, 513, 510, 508, 506, 504, 502, 500, 498, 496, 494, 492, 490, 488, 486, 484, 482, 480, 478, 476, 474, 472, 470, 468, 466, 464, 462, 460, 458, 456, 454, 452, 450, 448, 446, 444, 442, 440, 438, 436, 434, 432, 430, 428, 426, 424, 422, 420, 418, 416, 414, 412, 410, 408, 406, 404, 402, 400, 398, 396, 394, 392, 390, 388, 386, 384, 382, 380, 378, 376, 374, 372, 370, 368, 366, 364, 362, 360, 358, 356, 354, 352, 350, 348, 346, 344, 342, 340, 338, 336, 334, 332, 330, 328, 326, 324, 322, 320, 318, 316, 314, 312, 310, 308, 306, 304, 302, 300, 298, 296, 294, 292, 290, 288, 286, 284, 282, 280, 278, 276, 274, 272, 270, 268, 266, 264, 262, 260, 258, 256, 255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245, 244, 243, 242, 241, 240, 239, 238, 237, 236, 235, 234, 233, 232, 231, 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, 128, 127, 126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0])
# const SPC_DECAY_CURVE_ENTRIES := 535 # len(SPC_DECAY_CURVE) # Includes trailing zero
# Treat 0 as infinite
const SPC_PERIOD_TABLE := PoolIntArray([0, 2048, 1536, 1280, 1024, 768, 640, 512, 384, 320, 256, 192, 160, 128, 96, 80, 64, 48, 40, 32, 24, 20, 16, 12, 10, 8, 6, 5, 4, 3, 2, 1])
const SPC_PERIOD_TABLE_LEN := len(SPC_PERIOD_TABLE) # 32
# This is the number of samples (@32kHz) between each action step for ADSR
# Attack Rate = SPC_PERIOD_TABLE[A*2+1]
# Decay Rate = SPC_PERIOD_TABLE[D*2+16]
# Sustain decay Rate = SPC_PERIOD_TABLE[SR]
#
# Since Attack is linear, we can just calculate the total duration and lerp it.
# Decay and Sustain decay are both exponential and will lookup SPC_DECAY_CURVE.
# 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])
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
# !!! Testing a workaround for a Godot 3.x AudioStreamSample playback: !!! # !!! Testing a workaround for a Godot 3.x AudioStreamSample playback: !!!
@ -207,13 +224,11 @@ func samples_to_texture():
var payload_buffer := StreamPeerBuffer.new() var payload_buffer := StreamPeerBuffer.new()
# Fill first row with ADSR table # Fill first row with ADSR table
for i in ATTACK_TIME_SMPS: for i in ATTACK_TIME_SMPS: # 32 u16 texels
header_buffer.put_u32(i) header_buffer.put_u32(i)
for i in DECAY_TIME_SMPS: for i in SPC_PERIOD_TABLE: # 32 u16 texels
header_buffer.put_u32(i) header_buffer.put_u16(i)
for i in SUSTAIN_DECAY_TIME_SMPS: for i in SPC_DECAY_CURVE: # 697 u16 texels
header_buffer.put_u32(i)
for i in SPC_DECAY_CURVE:
header_buffer.put_u16(i) header_buffer.put_u16(i)
var remaining_first_row_texels := TEX_WIDTH - (header_buffer.get_position()/2) var remaining_first_row_texels := TEX_WIDTH - (header_buffer.get_position()/2)
for i in remaining_first_row_texels: for i in remaining_first_row_texels:

View File

@ -171,28 +171,32 @@ highp float get_instrument_sample(highp float instrument_index, highp float note
// return rescale_int16(get_inst_texel_int16(target_texel)); // return rescale_int16(get_inst_texel_int16(target_texel));
} }
// highp float get_exponential_decay_no_lookup(highp int periods) {
// highp ivec4 low_periods = ivec4(2047, 2015, 1946, 1835) - (periods * ivec4(8, 7, 6, 5));
// highp ivec4 high_periods = ivec4(1672, 1446, 1134, 695) - (periods * ivec4(4, 3, 2, 1));
// highp ivec4 max1 = max(low_periods, high_periods);
// highp ivec2 max2 = max(max1.xy, max1.zw);
// highp int env = max(max(max2.x, max2.y), 0);
// return highp float(env)/2047.0;
// }
const highp int HEADER_START_ATTACK_TIME = 0; const highp int HEADER_START_ATTACK_TIME = 0;
const highp int HEADER_START_DECAY_TIME = HEADER_START_ATTACK_TIME + 2*16; const highp int HEADER_START_PERIOD_TABLE = HEADER_START_ATTACK_TIME + 2*16;
const highp int HEADER_START_SUSTAIN_DECAY_TIME = HEADER_START_DECAY_TIME + 2*8; const highp int HEADER_START_EXPONENTIAL_DECAY_CURVE = HEADER_START_PERIOD_TABLE + 1*32;
const highp int HEADER_START_EXPONENTIAL_DECAY_CURVE = HEADER_START_SUSTAIN_DECAY_TIME + 2*32; const highp float HEADER_LENGTH_EXPONENTIAL_DECAY_CURVE = 697.0;
const highp float HEADER_LENGTH_EXPONENTIAL_DECAY_CURVE = 534.0;
highp int get_attack_time_smps(highp int idx) { highp int get_attack_time_smps(highp int idx) {
highp float idx2 = float(HEADER_START_ATTACK_TIME + (idx*2)); highp float idx2 = float(HEADER_START_ATTACK_TIME + (idx*2));
return unpack_int32(vec4(get_inst_texel(vec2(idx2, 0.0)), get_inst_texel(vec2(idx2 + 1.0, 0.0)))); return unpack_int32(vec4(get_inst_texel(vec2(idx2, 0.0)), get_inst_texel(vec2(idx2 + 1.0, 0.0))));
} }
highp int get_decay_time_smps(highp int idx) { highp int get_rate_period(highp int idx) {
highp float idx2 = float(HEADER_START_DECAY_TIME + (idx*2)); highp float idx2 = float(HEADER_START_PERIOD_TABLE + idx);
return unpack_int32(vec4(get_inst_texel(vec2(idx2, 0.0)), get_inst_texel(vec2(idx2 + 1.0, 0.0)))); return int(unpack_int16(get_inst_texel(vec2(idx2, 0.0))));
} }
highp int get_sustain_decay_time_smps(highp int idx) { highp float get_exponential_decay(highp float periods) { // input in periods, output in [0.0, 1.0]
highp float idx2 = float(HEADER_START_SUSTAIN_DECAY_TIME + (idx*2)); highp float idx = float(HEADER_START_EXPONENTIAL_DECAY_CURVE) + periods;
return unpack_int32(vec4(get_inst_texel(vec2(idx2, 0.0)), get_inst_texel(vec2(idx2 + 1.0, 0.0))));
}
highp float get_exponential_decay(highp float progress) { // input and output [0.0, 1.0]
highp float idx = float(HEADER_START_EXPONENTIAL_DECAY_CURVE) + (progress * HEADER_LENGTH_EXPONENTIAL_DECAY_CURVE);
highp float idx2 = floor(idx); highp float idx2 = floor(idx);
highp float a = unpack_int16(get_inst_texel(vec2(idx2, 0.0))) / 1024.0; highp float a = unpack_int16(get_inst_texel(vec2(idx2, 0.0))) / 2047.0;
highp float b = unpack_int16(get_inst_texel(vec2(idx2 + 1.0, 0.0))) / 1024.0; highp float b = unpack_int16(get_inst_texel(vec2(idx2 + 1.0, 0.0))) / 2047.0;
return mix(a, b, fract(idx)); return mix(a, b, fract(idx));
} }
@ -222,47 +226,64 @@ highp vec4 render_song(highp sampler2D tex, highp int smp) {
for (int channel = 0; channel < NUM_CHANNELS; channel++) { for (int channel = 0; channel < NUM_CHANNELS; channel++) {
highp float row = float(channel * 5); highp float row = float(channel * 5);
highp float event_idx = 0.0; highp float event_idx = 0.0;
highp int smp_start; highp int smp_event_start;
for (int i = 0; i < NUM_CHANNEL_NOTE_PROBES; i++) { for (int i = 0; i < NUM_CHANNEL_NOTE_PROBES; i++) {
highp float step_size = exp2(float(NUM_CHANNEL_NOTE_PROBES - i - 1)); highp float step_size = exp2(float(NUM_CHANNEL_NOTE_PROBES - i - 1));
smp_start = retime_smp(int(unpack_int32(get_midi_texel(tex, event_idx + step_size, row)))); smp_event_start = retime_smp(unpack_int32(get_midi_texel(tex, event_idx + step_size, row)));
event_idx += (smp >= smp_start) ? step_size : 0.0; event_idx += (smp >= smp_event_start) ? step_size : 0.0;
} }
smp_start = retime_smp(int(unpack_int32(get_midi_texel(tex, event_idx, row)))); highp vec4 tex0 = get_midi_texel(tex, event_idx, row);
highp int smp_end = retime_smp(int(unpack_int32(get_midi_texel(tex, event_idx, row+1.0)))); highp vec4 tex1 = get_midi_texel(tex, event_idx, row+1.0);
highp int smp_note_start = retime_smp(int(unpack_int32(get_midi_texel(tex, event_idx, row+4.0)))); 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 note_event_supplement = get_midi_texel(tex, event_idx, row+2.0); // left as [0.0, 1.0] highp vec4 tex4 = get_midi_texel(tex, event_idx, row+4.0);
highp float instrument_idx = trunc(note_event_supplement.x * 255.0); highp vec4 next_tex1 = get_midi_texel(tex, event_idx+1.0, row+1.0);
highp float pitch_idx = note_event_supplement.y * 255.0; smp_event_start = retime_smp(unpack_int32(tex0));
highp float velocity = note_event_supplement.z; // highp int smp_event_end = retime_smp(unpack_int32(tex1));
highp float pan = note_event_supplement.w; highp int smp_note_start = retime_smp(unpack_int32(tex1));
highp ivec4 adsr = ivec4(get_midi_texel(tex, event_idx, row+3.0) * 255.0); highp int next_smp_note_start = retime_smp(unpack_int32(next_tex1));
// ====================At some point I'll look back into packing floats====================
// TBD = note_event_supplement.zw; - tremolo/vibrato/noise/pan_lfo/pitchbend/echo remain
// ====================At some point I'll look back into packing floats====================
highp float sustain_level = float(adsr.z + 1)/8.0;
highp int smp_attack = get_attack_time_smps(adsr.x);
highp int smp_decay = get_decay_time_smps(adsr.y);
highp int smp_sustain_decay = get_sustain_decay_time_smps(adsr.w);
// For now, just branch this // For now, just branch this
if (smp_note_start < smp) { // First sample may not start at zero! if (smp_note_start < smp) { // First sample may not start at zero!
highp int smp_overrun = smp - smp_end; // 256 samples of linear decay to 0 after note_off 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
smp_overrun = (smp_overrun < 0) ? 0 : smp_overrun; if (smp_release_overrun < 256) {
if (smp_overrun < 256) { highp float instrument_idx = trunc(tex2.x * 255.0);
highp float pitch_idx = tex2.y * 255.0;
highp float velocity = tex2.z;
highp float pan = tex2.w;
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
// ====================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);
highp int adsr_decay_total_periods = adsr.z;
highp int adsr_sustain_decay_rate = get_rate_period(adsr.w);
highp int smp_decay_end = smp_attack + (adsr_decay_rate * adsr_decay_total_periods);
highp int smp_progress = smp - smp_note_start; highp int smp_progress = smp - smp_note_start;
highp float t_start = float(smp_note_start)/output_mixrate; highp float t_start = float(smp_note_start)/output_mixrate;
// Branchless attack - just clamp to [0.0, 1.0]
highp float attack_factor = clamp(float(smp_progress)/float(smp_attack), 0.0, 1.0); highp float attack_factor = clamp(float(smp_progress)/float(smp_attack), 0.0, 1.0);
highp float decay_factor = mix(1.0, sustain_level, clamp(float(smp_progress - smp_attack)/float(smp_decay), 0.0, 1.0)); // Two-stage decay - determine if we're in the first or second stage
highp float sustain_decay_factor = 1.0; highp int smp_decay_progress = max(smp_progress - smp_attack, 0);
if (smp_sustain_decay > 0) { highp float decay_periods = 0.0;
// sustain_decay_factor = mix(1.0, 0.0, clamp(float(smp_progress - smp_attack - smp_decay)/float(smp_sustain_decay), 0.0, 1.0)); // For now, just branch it
sustain_decay_factor = get_exponential_decay(clamp(float(smp_progress - smp_attack - smp_decay)/float(smp_sustain_decay), 0.0, 1.0)); if (smp_decay_progress < smp_decay_end) {
decay_periods = float(smp_decay_progress) / float(adsr_decay_rate);
} else {
decay_periods = float(adsr_decay_total_periods);
if (adsr_sustain_decay_rate > 0) {
decay_periods += (float(smp_decay_progress - smp_decay_end) / float(adsr_sustain_decay_rate));
} }
highp float release_factor = float(255-smp_overrun)/255.0; // 256 samples of linear decay to 0 after note_off }
decay_periods = min(decay_periods, HEADER_LENGTH_EXPONENTIAL_DECAY_CURVE); // Don't overshoot!
highp float decay_factor = clamp(get_exponential_decay(decay_periods), 0.0, 1.0);
// 256 samples of linear decay to 0 before next note
highp float release_factor = float(255-smp_release_overrun)/255.0;
highp float samp = get_instrument_sample(instrument_idx, pitch_idx, t-t_start); highp float samp = get_instrument_sample(instrument_idx, pitch_idx, t-t_start);
samp *= velocity * attack_factor * decay_factor * sustain_decay_factor * release_factor; samp *= velocity * attack_factor * decay_factor * release_factor;
// TODO: proper decay and sustain, revisit release // TODO: proper decay and sustain, revisit release
downmixed_stereo += samp * vec2(pan, 1.0-pan) * 0.5; // TODO: double it to maintain the mono level on each channel at center=0.5? downmixed_stereo += samp * vec2(pan, 1.0-pan) * 0.5; // TODO: double it to maintain the mono level on each channel at center=0.5?
} }