2023-07-25 14:21:10 +09:30
extends Node
2023-07-26 21:52:54 +09:30
signal audio_samples_loaded
2023-07-27 19:53:52 +09:30
signal audio_inst_sample_loaded ( id )
signal audio_sfx_sample_loaded ( id )
2023-07-26 21:52:54 +09:30
var has_loaded_audio_samples : = false
2023-07-25 16:33:45 +09:30
const BGM_NUM : = 70
const INST_NUM : = 35
const SFX_NUM : = 8
2024-07-05 16:01:08 +09:30
const PREPEND_MS : = 20 # Prepend 20ms of silence to each sample for preplay purposes
2023-08-24 14:54:32 +09:30
const PLAY_START : = PREPEND_MS / 1000.0
2024-07-05 16:01:08 +09:30
const BYTES_PER_SAMPLE : = 2 # 16bit samples
2024-07-27 15:53:44 +09:30
const ATTACK_TIME_SMPS : = PoolIntArray ( [ 131072 , 81920 , 49152 , 32768 , 20480 , 12288 , 8192 , 5120 , 3072 , 2048 , 1280 , 768 , 512 , 320 , 192 , 2 ] )
2024-07-26 19:30:38 +09:30
const ATTACK_TIME_SMPS_ENTRIES : = 16
2024-07-27 15:53:44 +09:30
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])
2024-07-26 19:30:38 +09:30
2024-07-05 16:01:08 +09:30
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
# !!! Testing a workaround for a Godot 3.x AudioStreamSample playback: !!!
# !!! Copy the looped samples one or more times to avoid the break in interpolation at buffer end. !!!
# !!! Adding a few ms to the loops removes harshness. !!!
const HACK_EXTEND_LOOP_SAMPLE_EXTRA_MS : = 2 # !!!
func HACK_EXTEND_LOOP_SAMPLE ( audio : AudioStreamSample ) - > AudioStreamSample : # !!!
2024-07-10 22:13:58 +09:30
var output : AudioStreamSample = audio . duplicate ( true ) # !!!
# Prepend silence # !!!
var silent_samples : = ( audio . mix_rate * PREPEND_MS ) / 1000 # !!!
var silence : = PoolByteArray ( ) # !!!
silence . resize ( silent_samples * 2 ) # 16bit samples in 8bit array # !!!
silence . fill ( 0 ) # !!!
output . data = silence + output . data # !!!
output . loop_begin += silent_samples # !!!
output . loop_end += silent_samples # !!!
# Append looped samples # !!!
if output . loop_begin > = output . loop_end : # !!!
return output # !!!
2024-07-05 16:01:08 +09:30
var looped_samples = audio . data . subarray ( audio . loop_begin * BYTES_PER_SAMPLE , - 1 ) # !!!
var loop_len = len ( looped_samples ) # !!!
var target_len = ( audio . mix_rate * HACK_EXTEND_LOOP_SAMPLE_EXTRA_MS / 1000 ) * BYTES_PER_SAMPLE # !!!
2024-07-26 19:30:38 +09:30
while loop_len < target_len : # Keep doubling in length until it's long enough # !!!
2024-07-05 16:01:08 +09:30
looped_samples += looped_samples # !!!
loop_len = len ( looped_samples ) # !!!
2024-07-10 22:13:58 +09:30
output . data += looped_samples # !!!
2024-07-05 16:01:08 +09:30
return output # !!!
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2023-07-25 16:33:45 +09:30
var bgm_tracks = [ ]
var instrument_samples = [ ]
2024-07-05 16:01:08 +09:30
var instrument_samples_HACK_EXTENDED_LOOPS = [ ]
2023-07-25 16:33:45 +09:30
var sfx_samples = [ ]
2024-07-19 23:06:41 +09:30
var audio_renderer_viewport : Viewport
var audio_renderer : Node
2023-08-23 19:58:20 +09:30
func read_rom_address ( buffer : StreamPeerBuffer ) - > int :
2023-07-25 16:33:45 +09:30
# Read a 3-byte little-endian address and wrap the bank to ROM space
2023-08-23 19:58:20 +09:30
return buffer . get_u16 ( ) + ( ( buffer . get_u8 ( ) & 0x3F ) << 16 )
2023-07-25 16:33:45 +09:30
2023-07-25 14:21:10 +09:30
const MAX_15B = 1 << 15
const MAX_16B = 1 << 16
func unsigned16_to_signed ( unsigned ) :
return ( unsigned + MAX_15B ) % MAX_16B - MAX_15B
2023-07-26 14:41:05 +09:30
func get_reference_pitch_samplerate ( tuning1 : int , tuning2 : int = 0 ) - > int :
# This is non-trivial and subject to change
2023-09-23 16:04:51 +09:30
var pitch_scale = tuning1 / 255.0 + tuning2 / 65535.0
2023-07-26 14:41:05 +09:30
if tuning1 < 0x80 :
pitch_scale += 1.0
return int ( pitch_scale * 36000 )
# return (unsigned16_to_signed(pitch) + 0x8000) * 32000/4096
2023-07-25 14:21:10 +09:30
func process_sample ( mantissa : int , exponent : int ) - > int :
# For filter arithmetic the samples need to be in signed form.
# Sign-extend
if mantissa > = 8 :
mantissa |= 0xFFF0
2023-07-25 16:33:45 +09:30
if exponent > 12 :
exponent = 12
2023-07-25 14:21:10 +09:30
var unsigned = ( mantissa << exponent ) & 0xFFFF
return unsigned16_to_signed ( unsigned )
2023-07-26 22:21:25 +09:30
func clamp_short ( i : int ) - > int :
if i < - 0x8000 :
return - 0x8000
if i > 0x7FFF :
return 0x7FFF
return i
2023-07-25 14:21:10 +09:30
2023-08-23 19:58:20 +09:30
func make_sample ( buffer : StreamPeerBuffer , size : int , sample_rate : int ) - > AudioStreamSample :
2023-07-25 14:21:10 +09:30
var audio : = AudioStreamSample . new ( )
audio . mix_rate = sample_rate
audio . stereo = false
audio . set_format ( AudioStreamSample . FORMAT_16_BITS )
if ( size % 9 ) != 0 :
2023-08-23 19:58:20 +09:30
print_debug ( ' Oh no! An instrument sample has an invalid size of %d ! at $ %06X ' % [ size , buffer . get_position ( ) - 2 ] )
2023-07-25 14:21:10 +09:30
return audio
2023-07-26 22:21:25 +09:30
var num_packets : = size / 9
2023-07-25 14:21:10 +09:30
2024-07-10 22:13:58 +09:30
var samples = PoolIntArray ( [ 0 , 0 ] ) # Start with two zero samples for filter purposes, strip them from the actual output later
2023-07-26 22:21:25 +09:30
var i : = 2
for pkt in num_packets :
2023-08-23 19:38:59 +09:30
# Decode a single 9byte BRR packet
2023-08-23 19:58:20 +09:30
var header_byte : = buffer . get_u8 ( )
2023-08-23 19:38:59 +09:30
var exponent : = header_byte >> 4
var filter : = ( header_byte >> 2 ) & 0x03
2024-07-10 22:13:58 +09:30
# var loop := bool(header_byte & 0x02)
2023-08-23 19:38:59 +09:30
var end : = bool ( header_byte & 0x01 )
for sample in 8 :
2023-08-23 19:58:20 +09:30
var b : = buffer . get_u8 ( )
2023-08-23 19:38:59 +09:30
samples . append ( process_sample ( b >> 4 , exponent ) )
samples . append ( process_sample ( b & 0x0F , exponent ) )
# Apply filter
var l : = len ( samples )
2023-07-25 14:21:10 +09:30
match filter :
1 :
2023-08-23 19:38:59 +09:30
for j in range ( l - 16 , l ) :
2023-07-26 22:21:25 +09:30
samples [ j ] = clamp_short ( samples [ j ] + ( samples [ j - 1 ] * 15 ) / 16 )
2023-07-25 14:21:10 +09:30
2 :
2023-08-23 19:38:59 +09:30
for j in range ( l - 16 , l ) :
2023-07-26 22:21:25 +09:30
samples [ j ] = clamp_short ( samples [ j ] + ( samples [ j - 1 ] * 61 ) / 32 - ( samples [ j - 2 ] * 15 ) / 16 )
2023-07-25 14:21:10 +09:30
3 :
2023-08-23 19:38:59 +09:30
for j in range ( l - 16 , l ) :
2023-07-26 22:21:25 +09:30
samples [ j ] = clamp_short ( samples [ j ] + ( samples [ j - 1 ] * 115 ) / 64 - ( samples [ j - 2 ] * 13 ) / 16 )
2023-07-25 14:21:10 +09:30
if end :
2023-07-26 14:41:05 +09:30
# print('End flag on packet')
2023-07-25 14:21:10 +09:30
break
2024-07-10 22:13:58 +09:30
# Remove first two zero samples
samples . remove ( 0 )
samples . remove ( 0 )
2023-08-24 14:54:32 +09:30
# Pack 16bit samples to 8bit array
2024-07-10 22:13:58 +09:30
var out_buff = StreamPeerBuffer . new ( )
for sample in samples :
out_buff . put_16 ( sample )
audio . data = out_buff . data_array
2023-07-25 14:21:10 +09:30
return audio
2023-08-24 14:54:32 +09:30
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 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 )
2023-08-23 19:58:20 +09:30
var size : = buffer . get_u16 ( )
2023-07-26 14:41:05 +09:30
var num_samples : = ( size / 9 ) * 16
2023-08-23 19:58:20 +09:30
var audio : = make_sample ( buffer , size , sample_rate )
2023-07-26 14:41:05 +09:30
audio . loop_mode = AudioStreamSample . LOOP_FORWARD
2024-07-10 22:13:58 +09:30
audio . loop_begin = ( loop_start_packet * 16 ) # Each 9byte packet is 16 samples
audio . loop_end = num_samples
2023-07-26 21:52:54 +09:30
# 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])
2023-07-26 14:41:05 +09:30
return audio
2023-07-25 14:21:10 +09:30
2024-07-05 20:59:54 +09:30
# const SFX_BRR_START := 0x041E3F + 2 # First two bytes are the length of the block, 0x010E = 270 bytes = 16 BRR packets = 480 samples
2023-08-24 14:54:32 +09:30
func load_sfx_samples_data ( snes_data : Dictionary , buffer : StreamPeerBuffer ) :
2023-07-25 18:37:55 +09:30
var brr_spc_addrs = [ ]
var brr_spc_loop_addrs = [ ]
2023-08-24 14:54:32 +09:30
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 ] )
2024-07-17 22:03:27 +09:30
var brr_spc_start = Common . SNES_PSX_addresses . sfx_brr_data . SNES - brr_spc_addrs [ 0 ] # Refactor this later - SFX samples start at $4800 in ARAM, right after the SFX tracks
2023-07-25 18:37:55 +09:30
for i in SFX_NUM :
2023-08-24 14:54:32 +09:30
buffer . seek ( brr_spc_addrs [ i ] + brr_spc_start )
2023-08-23 19:58:20 +09:30
# print('Loading sfx sample #%X with BRR data offset $%06X' % [i, buffer.get_position()])
2023-08-24 14:54:32 +09:30
var sample_rate : = get_reference_pitch_samplerate ( snes_data . sfx_samplerates [ i ] & 0xFF )
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
2024-07-17 22:03:27 +09:30
audio . loop_begin = ( loop_start_packet / 9 ) * 16 # Each 9byte packet is 16 samples
2024-07-05 16:01:08 +09:30
audio . loop_end = ( len ( audio . data ) / 2 )
2023-08-24 14:54:32 +09:30
sfx_samples . append ( audio ) # Use 900 as a limit, it won't be hit, parser stops after End packet anyway
2023-07-27 19:53:52 +09:30
emit_signal ( ' audio_sfx_sample_loaded ' , i )
2023-07-26 14:41:05 +09:30
# print('size of %d samples' % sfx_samples[i].data.size())
2023-07-25 14:21:10 +09:30
# Called when the node enters the scene tree for the first time.
2023-08-24 14:54:32 +09:30
func load_samples ( snes_data : Dictionary , buffer : StreamPeerBuffer ) :
load_sfx_samples_data ( snes_data , buffer )
2024-07-05 16:01:08 +09:30
# For some reason, this is a bit slow currently under certain editor conditions. Might optimize later.
2023-07-25 14:21:10 +09:30
for i in INST_NUM :
2024-07-10 22:13:58 +09:30
var samp : = get_inst_sample_data ( snes_data , buffer , i )
instrument_samples . append ( samp )
2024-07-05 16:01:08 +09:30
# Workaround for Godot 3.x quirk where looping samples are interpolated as if they go to nothing instead of looping
2024-07-10 22:13:58 +09:30
instrument_samples_HACK_EXTENDED_LOOPS . append ( HACK_EXTEND_LOOP_SAMPLE ( samp ) )
# print('Instrument %02X has mix_rate %d Hz and %d samples'%[i, samp.mix_rate, len(samp.data)/2])
2023-07-27 19:53:52 +09:30
emit_signal ( ' audio_inst_sample_loaded ' , i )
2024-07-10 22:13:58 +09:30
# samp.save_to_wav('output/instrument%02d(%dHz)(loop from %d to %d of %d).wav' % [i, samp.mix_rate, samp.loop_begin, samp.loop_end, len(samp.data)/2])
# We start the texture with a bunch of same-size headers
# int32 sample_start // The true start, after the prepended 3 frames of silence
# uint16 sample_length // 3 frames after the true end, because of how we loop
# uint16 sample_loop_begin // 3 frames after the true loop point
# uint16 mixrate
var samples_tex : ImageTexture
const TEX_WIDTH : = 2048
const FILTER_PAD : = 32
func samples_to_texture ( ) :
2024-07-17 22:03:27 +09:30
var num_samples : = SFX_NUM + INST_NUM
2024-07-26 19:30:38 +09:30
var header_length : = ( num_samples * 5 ) + TEX_WIDTH # Use first row for the ADSR tables
2024-07-10 22:13:58 +09:30
# Create header and unwrapped payload separately first
var header_buffer : = StreamPeerBuffer . new ( )
var payload_buffer : = StreamPeerBuffer . new ( )
2024-07-26 19:30:38 +09:30
# Fill first row with ADSR table
2024-07-27 15:53:44 +09:30
for i in ATTACK_TIME_SMPS : # 32 u16 texels
2024-07-26 19:30:38 +09:30
header_buffer . put_u32 ( i )
2024-07-27 15:53:44 +09:30
for i in SPC_PERIOD_TABLE : # 32 u16 texels
header_buffer . put_u16 ( i )
for i in SPC_DECAY_CURVE : # 697 u16 texels
2024-07-26 19:30:38 +09:30
header_buffer . put_u16 ( i )
var remaining_first_row_texels : = TEX_WIDTH - ( header_buffer . get_position ( ) / 2 )
for i in remaining_first_row_texels :
header_buffer . put_u16 ( 0 )
# Do instrument headers and data in parallel
2024-07-17 22:03:27 +09:30
for sample in sfx_samples + instrument_samples :
2024-07-10 22:13:58 +09:30
var sample_data_start : int = header_length + ( payload_buffer . get_position ( ) / 2 ) + FILTER_PAD # After the prepended silence, in texels (2bytes)
var loop_begin : int = sample . loop_begin
var loop_length : int = sample . loop_end - loop_begin
var nonlooping : bool = loop_length < = 0
2024-07-14 23:34:23 +09:30
# print('Processing sample, nonlooping=%s'%nonlooping)
2024-07-10 22:13:58 +09:30
for i in FILTER_PAD : # Prepend frames of silence
payload_buffer . put_16 ( 0 )
payload_buffer . put_data ( sample . data ) # Copy entire S16LE audio data
if nonlooping :
# Append trailing silence for filter safety
for i in FILTER_PAD * 5 :
payload_buffer . put_16 ( 0 )
# Make it loop the trailing silence
loop_begin += FILTER_PAD
loop_length = 1
else :
# Append copies of the loop for filter safety
# var loop_data = sample.data.subarray(sample.loop_begin*2, -1)
# for i in ceil((FILTER_PAD*4)/loop_length):
# payload_buffer.put_data(loop_data)
# Copy frame by frame in case the loop is shorter than padding frames
for i in FILTER_PAD * 4 :
var pos : = payload_buffer . get_position ( )
payload_buffer . seek ( pos - loop_length * 2 )
var frame : = payload_buffer . get_16 ( )
payload_buffer . seek ( pos )
payload_buffer . put_16 ( frame )
header_buffer . put_32 ( sample_data_start )
header_buffer . put_u16 ( loop_begin + FILTER_PAD )
header_buffer . put_u16 ( loop_length )
header_buffer . put_u16 ( sample . mix_rate )
# Combine the unwrapped arrays
var data : = header_buffer . data_array + payload_buffer . data_array
var datasamp : = AudioStreamSample . new ( )
datasamp . data = data
datasamp . mix_rate = 32000
datasamp . format = AudioStreamSample . FORMAT_16_BITS
# datasamp.save_to_wav('output/texture_inst_data.wav')
var needed_rows : = ( len ( data ) / 2 ) / float ( TEX_WIDTH )
var rows : = int ( pow ( 2 , ceil ( log ( needed_rows ) / log ( 2 ) ) ) )
if rows > TEX_WIDTH :
print_debug ( ' Sound Sample Texture rows have exceeded width: %d > %d ' % [ rows , TEX_WIDTH ] )
# Now that the full texture size is known, pad our existing data with zeroes until the end
var final_data_size_bytes = rows * TEX_WIDTH * 2
if final_data_size_bytes > len ( data ) :
var end_padding : = PoolByteArray ( )
end_padding . resize ( final_data_size_bytes - len ( data ) )
end_padding . fill ( 0 )
data = data + end_padding
# data is complete, turn it into an ImageTexture for the shader to use
var samples_img = Image . new ( )
samples_img . create_from_data ( TEX_WIDTH , rows , false , Image . FORMAT_LA8 , data )
self . samples_tex = ImageTexture . new ( )
self . samples_tex . create_from_image ( samples_img , 0 ) #Texture.FLAG_FILTER)
2023-07-25 14:21:10 +09:30
2023-07-25 16:33:45 +09:30
2023-07-25 14:21:10 +09:30
var player : = AudioStreamPlayer . new ( ) # Make one for each channel, later
2024-07-05 20:59:54 +09:30
func play_sample ( id : int , pitch_scale : float = 1.0 ) :
2023-08-23 19:38:59 +09:30
print ( ' Playing inst sample # %02X ' % id )
2024-07-05 20:59:54 +09:30
player . pitch_scale = pitch_scale
2024-07-10 22:13:58 +09:30
player . stream = instrument_samples_HACK_EXTENDED_LOOPS [ id ]
2024-07-05 20:59:54 +09:30
player . play ( PLAY_START / pitch_scale )
2023-07-25 14:21:10 +09:30
func play_sfx ( id : int ) :
2023-08-23 19:38:59 +09:30
print ( ' Playing sfx sample # %02X ' % id )
2024-07-05 20:59:54 +09:30
player . pitch_scale = 1.0
2023-07-25 14:21:10 +09:30
player . stream = sfx_samples [ id ]
2023-08-24 14:54:32 +09:30
player . play ( PLAY_START )
2023-07-25 14:21:10 +09:30
2023-08-24 14:54:32 +09:30
func parse_rom ( snes_data : Dictionary , buffer : StreamPeerBuffer ) :
load_samples ( snes_data , buffer )
2023-08-23 19:58:20 +09:30
#load_bgms(buffer)
2023-07-26 21:52:54 +09:30
has_loaded_audio_samples = true
emit_signal ( ' audio_samples_loaded ' )
2023-07-25 16:33:45 +09:30
2023-07-25 14:21:10 +09:30
func _ready ( ) - > void :
2024-07-19 23:06:41 +09:30
self . player . name = ' player ' # Easier to see in the debugger
add_child ( self . player )
audio_renderer_viewport = Viewport . new ( )
audio_renderer_viewport . name = ' audio_renderer_viewport '
audio_renderer_viewport . size_override_stretch = true
audio_renderer_viewport . transparent_bg = true
audio_renderer_viewport . handle_input_locally = false
audio_renderer_viewport . hdr = false
audio_renderer_viewport . render_target_update_mode = Viewport . UPDATE_ALWAYS
# add_child(self.audio_renderer_viewport)
audio_renderer = preload ( ' res://scripts/audio_renderer.gd ' ) . new ( )
audio_renderer . name = ' audio_renderer '
audio_renderer_viewport . add_child ( audio_renderer )
get_parent ( ) . call_deferred ( ' add_child ' , audio_renderer_viewport )