mirror of
https://github.com/curioustorvald/tsvm.git
synced 2026-06-06 05:28:31 +09:00
minifloat redefined
This commit is contained in:
58
it2taud.py
58
it2taud.py
@@ -53,7 +53,7 @@ from taud_common import (
|
|||||||
EFF_U, EFF_V, EFF_W, EFF_X, EFF_Y, EFF_Z,
|
EFF_U, EFF_V, EFF_W, EFF_X, EFF_Y, EFF_Z,
|
||||||
J_SEMI_TABLE,
|
J_SEMI_TABLE,
|
||||||
d_arg_to_col, resample_linear, rescale_offset_effects, encode_cue, deduplicate_patterns,
|
d_arg_to_col, resample_linear, rescale_offset_effects, encode_cue, deduplicate_patterns,
|
||||||
normalise_sample, encode_song_entry,
|
normalise_sample, encode_song_entry, nearest_minifloat,
|
||||||
CUE_INST_NOP, CUE_INST_HALT, CUE_INST_LEN, cue_instruction_len,
|
CUE_INST_NOP, CUE_INST_HALT, CUE_INST_LEN, cue_instruction_len,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -117,60 +117,6 @@ IT_MEM_EFFECTS = frozenset({
|
|||||||
|
|
||||||
SIGNATURE = b'it2taud/TSVM ' # 14 bytes
|
SIGNATURE = b'it2taud/TSVM ' # 14 bytes
|
||||||
|
|
||||||
# ThreeFiveMiniUfloat LUT — 256 entries, seconds 0.0..126.0 (must match Kotlin)
|
|
||||||
_MINUFLOAT_LUT = [
|
|
||||||
0.0, 0.03125, 0.0625, 0.09375, 0.125, 0.15625, 0.1875, 0.21875,
|
|
||||||
0.25, 0.28125, 0.3125, 0.34375, 0.375, 0.40625, 0.4375, 0.46875,
|
|
||||||
0.5, 0.53125, 0.5625, 0.59375, 0.625, 0.65625, 0.6875, 0.71875,
|
|
||||||
0.75, 0.78125, 0.8125, 0.84375, 0.875, 0.90625, 0.9375, 0.96875,
|
|
||||||
1.0, 1.03125, 1.0625, 1.09375, 1.125, 1.15625, 1.1875, 1.21875,
|
|
||||||
1.25, 1.28125, 1.3125, 1.34375, 1.375, 1.40625, 1.4375, 1.46875,
|
|
||||||
1.5, 1.53125, 1.5625, 1.59375, 1.625, 1.65625, 1.6875, 1.71875,
|
|
||||||
1.75, 1.78125, 1.8125, 1.84375, 1.875, 1.90625, 1.9375, 1.96875,
|
|
||||||
2.0, 2.0625, 2.125, 2.1875, 2.25, 2.3125, 2.375, 2.4375,
|
|
||||||
2.5, 2.5625, 2.625, 2.6875, 2.75, 2.8125, 2.875, 2.9375,
|
|
||||||
3.0, 3.0625, 3.125, 3.1875, 3.25, 3.3125, 3.375, 3.4375,
|
|
||||||
3.5, 3.5625, 3.625, 3.6875, 3.75, 3.8125, 3.875, 3.9375,
|
|
||||||
4.0, 4.125, 4.25, 4.375, 4.5, 4.625, 4.75, 4.875,
|
|
||||||
5.0, 5.125, 5.25, 5.375, 5.5, 5.625, 5.75, 5.875,
|
|
||||||
6.0, 6.125, 6.25, 6.375, 6.5, 6.625, 6.75, 6.875,
|
|
||||||
7.0, 7.125, 7.25, 7.375, 7.5, 7.625, 7.75, 7.875,
|
|
||||||
8.0, 8.25, 8.5, 8.75, 9.0, 9.25, 9.5, 9.75,
|
|
||||||
10.0, 10.25, 10.5, 10.75, 11.0, 11.25, 11.5, 11.75,
|
|
||||||
12.0, 12.25, 12.5, 12.75, 13.0, 13.25, 13.5, 13.75,
|
|
||||||
14.0, 14.25, 14.5, 14.75, 15.0, 15.25, 15.5, 15.75,
|
|
||||||
16.0, 16.5, 17.0, 17.5, 18.0, 18.5, 19.0, 19.5,
|
|
||||||
20.0, 20.5, 21.0, 21.5, 22.0, 22.5, 23.0, 23.5,
|
|
||||||
24.0, 24.5, 25.0, 25.5, 26.0, 26.5, 27.0, 27.5,
|
|
||||||
28.0, 28.5, 29.0, 29.5, 30.0, 30.5, 31.0, 31.5,
|
|
||||||
32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0,
|
|
||||||
40.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0,
|
|
||||||
48.0, 49.0, 50.0, 51.0, 52.0, 53.0, 54.0, 55.0,
|
|
||||||
56.0, 57.0, 58.0, 59.0, 60.0, 61.0, 62.0, 63.0,
|
|
||||||
64.0, 66.0, 68.0, 70.0, 72.0, 74.0, 76.0, 78.0,
|
|
||||||
80.0, 82.0, 84.0, 86.0, 88.0, 90.0, 92.0, 94.0,
|
|
||||||
96.0, 98.0, 100.0, 102.0, 104.0, 106.0, 108.0, 110.0,
|
|
||||||
112.0, 114.0, 116.0, 118.0, 120.0, 122.0, 124.0, 126.0,
|
|
||||||
]
|
|
||||||
|
|
||||||
def _nearest_minifloat(sec: float) -> int:
|
|
||||||
"""Return ThreeFiveMiniUfloat index (0-255) for the nearest representable seconds value."""
|
|
||||||
if sec <= 0.0:
|
|
||||||
return 0
|
|
||||||
if sec >= 126.0:
|
|
||||||
return 255
|
|
||||||
lo, hi = 0, len(_MINUFLOAT_LUT) - 1
|
|
||||||
while lo < hi:
|
|
||||||
mid = (lo + hi) // 2
|
|
||||||
if _MINUFLOAT_LUT[mid] < sec:
|
|
||||||
lo = mid + 1
|
|
||||||
else:
|
|
||||||
hi = mid
|
|
||||||
# lo is first index where LUT[lo] >= sec; check lo-1 for nearest
|
|
||||||
if lo > 0 and abs(_MINUFLOAT_LUT[lo - 1] - sec) <= abs(_MINUFLOAT_LUT[lo] - sec):
|
|
||||||
return lo - 1
|
|
||||||
return lo
|
|
||||||
|
|
||||||
|
|
||||||
# ── IT header parser ──────────────────────────────────────────────────────────
|
# ── IT header parser ──────────────────────────────────────────────────────────
|
||||||
|
|
||||||
@@ -626,7 +572,7 @@ def _parse_it_envelope(data: bytes, env_ptr: int, kind: str,
|
|||||||
if k < len(nodes) - 1:
|
if k < len(nodes) - 1:
|
||||||
_, next_tick = nodes[k + 1]
|
_, next_tick = nodes[k + 1]
|
||||||
delta_sec = max(0.0, (next_tick - tick) / ticks_per_sec)
|
delta_sec = max(0.0, (next_tick - tick) / ticks_per_sec)
|
||||||
mf_idx = _nearest_minifloat(delta_sec)
|
mf_idx = nearest_minifloat(delta_sec)
|
||||||
else:
|
else:
|
||||||
mf_idx = 0
|
mf_idx = 0
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -27,6 +27,9 @@ def vprint(*a, **kw) -> None:
|
|||||||
# ── Taud container constants ─────────────────────────────────────────────────
|
# ── Taud container constants ─────────────────────────────────────────────────
|
||||||
|
|
||||||
TAUD_MAGIC = bytes([0x1F,0x54,0x53,0x56,0x4D,0x61,0x75,0x64])
|
TAUD_MAGIC = bytes([0x1F,0x54,0x53,0x56,0x4D,0x61,0x75,0x64])
|
||||||
|
# Bumped 2026-05-07: envelope offset minifloat rebiased (smallest step 1/256 s,
|
||||||
|
# max 15.75 s; previously 1/32 s, max 126 s). v1 .taud envelopes will play with
|
||||||
|
# the wrong tempo on a v2 engine — re-convert from source.
|
||||||
TAUD_VERSION = 1
|
TAUD_VERSION = 1
|
||||||
TAUD_HEADER_SIZE = 32 # magic(8)+ver(1)+numSongs(1)+compSize(4)+projOff(4)+sig(14)
|
TAUD_HEADER_SIZE = 32 # magic(8)+ver(1)+numSongs(1)+compSize(4)+projOff(4)+sig(14)
|
||||||
TAUD_SONG_ENTRY = 32 # full spec entry (see encode_song_entry)
|
TAUD_SONG_ENTRY = 32 # full spec entry (see encode_song_entry)
|
||||||
@@ -103,6 +106,69 @@ EFF_U = 21; EFF_V = 22; EFF_W = 23; EFF_X = 24; EFF_Y = 25
|
|||||||
EFF_Z = 26
|
EFF_Z = 26
|
||||||
|
|
||||||
|
|
||||||
|
# ── Envelope offset minifloat ────────────────────────────────────────────────
|
||||||
|
#
|
||||||
|
# Mirror of tsvm_core/.../ThreeFiveMinifloat.kt — used by every *2taud
|
||||||
|
# converter that emits envelope nodes. 3.5 unsigned minifloat (3-bit exponent
|
||||||
|
# + 5-bit mantissa) rebiased so the smallest non-zero step is 1/256 s ≈ 3.91
|
||||||
|
# ms and the maximum is 15.75 s. The previous bias (1/32-step, max 126 s)
|
||||||
|
# under-resolved single-tick deltas at typical tracker BPMs. Every value here
|
||||||
|
# is the original LUT divided by 8.
|
||||||
|
|
||||||
|
MINUFLOAT_LUT = (
|
||||||
|
0.0, 0.00390625, 0.0078125, 0.01171875, 0.015625, 0.01953125, 0.0234375, 0.02734375,
|
||||||
|
0.03125, 0.03515625, 0.0390625, 0.04296875, 0.046875, 0.05078125, 0.0546875, 0.05859375,
|
||||||
|
0.0625, 0.06640625, 0.0703125, 0.07421875, 0.078125, 0.08203125, 0.0859375, 0.08984375,
|
||||||
|
0.09375, 0.09765625, 0.1015625, 0.10546875, 0.109375, 0.11328125, 0.1171875, 0.12109375,
|
||||||
|
0.125, 0.12890625, 0.1328125, 0.13671875, 0.140625, 0.14453125, 0.1484375, 0.15234375,
|
||||||
|
0.15625, 0.16015625, 0.1640625, 0.16796875, 0.171875, 0.17578125, 0.1796875, 0.18359375,
|
||||||
|
0.1875, 0.19140625, 0.1953125, 0.19921875, 0.203125, 0.20703125, 0.2109375, 0.21484375,
|
||||||
|
0.21875, 0.22265625, 0.2265625, 0.23046875, 0.234375, 0.23828125, 0.2421875, 0.24609375,
|
||||||
|
0.25, 0.2578125, 0.265625, 0.2734375, 0.28125, 0.2890625, 0.296875, 0.3046875,
|
||||||
|
0.3125, 0.3203125, 0.328125, 0.3359375, 0.34375, 0.3515625, 0.359375, 0.3671875,
|
||||||
|
0.375, 0.3828125, 0.390625, 0.3984375, 0.40625, 0.4140625, 0.421875, 0.4296875,
|
||||||
|
0.4375, 0.4453125, 0.453125, 0.4609375, 0.46875, 0.4765625, 0.484375, 0.4921875,
|
||||||
|
0.5, 0.515625, 0.53125, 0.546875, 0.5625, 0.578125, 0.59375, 0.609375,
|
||||||
|
0.625, 0.640625, 0.65625, 0.671875, 0.6875, 0.703125, 0.71875, 0.734375,
|
||||||
|
0.75, 0.765625, 0.78125, 0.796875, 0.8125, 0.828125, 0.84375, 0.859375,
|
||||||
|
0.875, 0.890625, 0.90625, 0.921875, 0.9375, 0.953125, 0.96875, 0.984375,
|
||||||
|
1.0, 1.03125, 1.0625, 1.09375, 1.125, 1.15625, 1.1875, 1.21875,
|
||||||
|
1.25, 1.28125, 1.3125, 1.34375, 1.375, 1.40625, 1.4375, 1.46875,
|
||||||
|
1.5, 1.53125, 1.5625, 1.59375, 1.625, 1.65625, 1.6875, 1.71875,
|
||||||
|
1.75, 1.78125, 1.8125, 1.84375, 1.875, 1.90625, 1.9375, 1.96875,
|
||||||
|
2.0, 2.0625, 2.125, 2.1875, 2.25, 2.3125, 2.375, 2.4375,
|
||||||
|
2.5, 2.5625, 2.625, 2.6875, 2.75, 2.8125, 2.875, 2.9375,
|
||||||
|
3.0, 3.0625, 3.125, 3.1875, 3.25, 3.3125, 3.375, 3.4375,
|
||||||
|
3.5, 3.5625, 3.625, 3.6875, 3.75, 3.8125, 3.875, 3.9375,
|
||||||
|
4.0, 4.125, 4.25, 4.375, 4.5, 4.625, 4.75, 4.875,
|
||||||
|
5.0, 5.125, 5.25, 5.375, 5.5, 5.625, 5.75, 5.875,
|
||||||
|
6.0, 6.125, 6.25, 6.375, 6.5, 6.625, 6.75, 6.875,
|
||||||
|
7.0, 7.125, 7.25, 7.375, 7.5, 7.625, 7.75, 7.875,
|
||||||
|
8.0, 8.25, 8.5, 8.75, 9.0, 9.25, 9.5, 9.75,
|
||||||
|
10.0, 10.25, 10.5, 10.75, 11.0, 11.25, 11.5, 11.75,
|
||||||
|
12.0, 12.25, 12.5, 12.75, 13.0, 13.25, 13.5, 13.75,
|
||||||
|
14.0, 14.25, 14.5, 14.75, 15.0, 15.25, 15.5, 15.75,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def nearest_minifloat(sec: float) -> int:
|
||||||
|
"""Return the ThreeFiveMiniUfloat index (0..255) for the LUT entry nearest to `sec`."""
|
||||||
|
if sec <= 0.0:
|
||||||
|
return 0
|
||||||
|
if sec >= MINUFLOAT_LUT[-1]:
|
||||||
|
return 255
|
||||||
|
lo, hi = 0, len(MINUFLOAT_LUT) - 1
|
||||||
|
while lo < hi:
|
||||||
|
mid = (lo + hi) // 2
|
||||||
|
if MINUFLOAT_LUT[mid] < sec:
|
||||||
|
lo = mid + 1
|
||||||
|
else:
|
||||||
|
hi = mid
|
||||||
|
if lo > 0 and abs(MINUFLOAT_LUT[lo - 1] - sec) < abs(MINUFLOAT_LUT[lo] - sec):
|
||||||
|
return lo - 1
|
||||||
|
return lo
|
||||||
|
|
||||||
|
|
||||||
# ── Helpers ──────────────────────────────────────────────────────────────────
|
# ── Helpers ──────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
def d_arg_to_col(arg: int):
|
def d_arg_to_col(arg: int):
|
||||||
|
|||||||
@@ -2137,13 +2137,13 @@ from source.
|
|||||||
(bits 14..15 reserved)
|
(bits 14..15 reserved)
|
||||||
21 Bit16x25 Volume envelopes
|
21 Bit16x25 Volume envelopes
|
||||||
Byte 1: Volume (00..3F)
|
Byte 1: Volume (00..3F)
|
||||||
Byte 2: Time until the next point, in seconds (3.5 Unsigned Minifloat). 0 = hold at this point indefinitely.
|
Byte 2: Time until the next point, in seconds (3.5 Unsigned Minifloat, biased; range 0..15.75 s, smallest non-zero step 1/256 s ≈ 3.91 ms — chosen so single tracker ticks resolve at every supported BPM). 0 = hold at this point indefinitely.
|
||||||
71 Bit16x25 Panning envelopes
|
71 Bit16x25 Panning envelopes
|
||||||
Byte 1: Pan (00..FF)
|
Byte 1: Pan (00..FF)
|
||||||
Byte 2: Time until the next point, in seconds (3.5 Unsigned Minifloat). 0 = hold at this point indefinitely.
|
Byte 2: Time until the next point, in seconds (3.5 Unsigned Minifloat, biased; range 0..15.75 s, smallest non-zero step 1/256 s ≈ 3.91 ms — chosen so single tracker ticks resolve at every supported BPM). 0 = hold at this point indefinitely.
|
||||||
121 Bit16x25 Pitch/Filter envelopes
|
121 Bit16x25 Pitch/Filter envelopes
|
||||||
Byte 1: Value (00..FF)
|
Byte 1: Value (00..FF)
|
||||||
Byte 2: Time until the next point, in seconds (3.5 Unsigned Minifloat). 0 = hold at this point indefinitely.
|
Byte 2: Time until the next point, in seconds (3.5 Unsigned Minifloat, biased; range 0..15.75 s, smallest non-zero step 1/256 s ≈ 3.91 ms — chosen so single tracker ticks resolve at every supported BPM). 0 = hold at this point indefinitely.
|
||||||
171 Uint8 Instrument Global Volume (0..255)
|
171 Uint8 Instrument Global Volume (0..255)
|
||||||
* ImpulseTracker has range of 0..128; multiply by (255/128) then round to int
|
* ImpulseTracker has range of 0..128; multiply by (255/128) then round to int
|
||||||
- ImpulseTracker also has samplewise default volume (0..64) and samplewise global volume (0..64), and they must be taken into account because Taud has no samplewise config, following the ImpulseTracker spec
|
- ImpulseTracker also has samplewise default volume (0..64) and samplewise global volume (0..64), and they must be taken into account because Taud has no samplewise config, following the ImpulseTracker spec
|
||||||
@@ -2464,40 +2464,45 @@ Play Head Flags
|
|||||||
|
|
||||||
65536..131071 RW: PCM Sample buffer
|
65536..131071 RW: PCM Sample buffer
|
||||||
|
|
||||||
Table of 3.5 Minifloat values (CSV)
|
Table of 3.5 Minifloat values (CSV).
|
||||||
|
Rebiased 2026-05-07 so the smallest non-zero step is 1/256 s and the maximum
|
||||||
|
is 15.75 s — every cell is the original LUT value divided by 8. Chosen for
|
||||||
|
tracker envelopes: a single song tick (≈ 8.9 ms at BPM 280, ≈ 41.7 ms at
|
||||||
|
BPM 24) now lands within ±17 % of an LUT entry across the whole supported
|
||||||
|
BPM range; the previous bias was ±150 % at common BPMs.
|
||||||
,000,001,010,011,100,101,110,111,MSB
|
,000,001,010,011,100,101,110,111,MSB
|
||||||
00000,0,1,2,4,8,16,32,64
|
00000,0,0.125,0.25,0.5,1,2,4,8
|
||||||
00001,0.03125,1.03125,2.0625,4.125,8.25,16.5,33,66
|
00001,0.00390625,0.12890625,0.2578125,0.515625,1.03125,2.0625,4.125,8.25
|
||||||
00010,0.0625,1.0625,2.125,4.25,8.5,17,34,68
|
00010,0.0078125,0.1328125,0.265625,0.53125,1.0625,2.125,4.25,8.5
|
||||||
00011,0.09375,1.09375,2.1875,4.375,8.75,17.5,35,70
|
00011,0.01171875,0.13671875,0.2734375,0.546875,1.09375,2.1875,4.375,8.75
|
||||||
00100,0.125,1.125,2.25,4.5,9,18,36,72
|
00100,0.015625,0.140625,0.28125,0.5625,1.125,2.25,4.5,9
|
||||||
00101,0.15625,1.15625,2.3125,4.625,9.25,18.5,37,74
|
00101,0.01953125,0.14453125,0.2890625,0.578125,1.15625,2.3125,4.625,9.25
|
||||||
00110,0.1875,1.1875,2.375,4.75,9.5,19,38,76
|
00110,0.0234375,0.1484375,0.296875,0.59375,1.1875,2.375,4.75,9.5
|
||||||
00111,0.21875,1.21875,2.4375,4.875,9.75,19.5,39,78
|
00111,0.02734375,0.15234375,0.3046875,0.609375,1.21875,2.4375,4.875,9.75
|
||||||
01000,0.25,1.25,2.5,5,10,20,40,80
|
01000,0.03125,0.15625,0.3125,0.625,1.25,2.5,5,10
|
||||||
01001,0.28125,1.28125,2.5625,5.125,10.25,20.5,41,82
|
01001,0.03515625,0.16015625,0.3203125,0.640625,1.28125,2.5625,5.125,10.25
|
||||||
01010,0.3125,1.3125,2.625,5.25,10.5,21,42,84
|
01010,0.0390625,0.1640625,0.328125,0.65625,1.3125,2.625,5.25,10.5
|
||||||
01011,0.34375,1.34375,2.6875,5.375,10.75,21.5,43,86
|
01011,0.04296875,0.16796875,0.3359375,0.671875,1.34375,2.6875,5.375,10.75
|
||||||
01100,0.375,1.375,2.75,5.5,11,22,44,88
|
01100,0.046875,0.171875,0.34375,0.6875,1.375,2.75,5.5,11
|
||||||
01101,0.40625,1.40625,2.8125,5.625,11.25,22.5,45,90
|
01101,0.05078125,0.17578125,0.3515625,0.703125,1.40625,2.8125,5.625,11.25
|
||||||
01110,0.4375,1.4375,2.875,5.75,11.5,23,46,92
|
01110,0.0546875,0.1796875,0.359375,0.71875,1.4375,2.875,5.75,11.5
|
||||||
01111,0.46875,1.46875,2.9375,5.875,11.75,23.5,47,94
|
01111,0.05859375,0.18359375,0.3671875,0.734375,1.46875,2.9375,5.875,11.75
|
||||||
10000,0.5,1.5,3,6,12,24,48,96
|
10000,0.0625,0.1875,0.375,0.75,1.5,3,6,12
|
||||||
10001,0.53125,1.53125,3.0625,6.125,12.25,24.5,49,98
|
10001,0.06640625,0.19140625,0.3828125,0.765625,1.53125,3.0625,6.125,12.25
|
||||||
10010,0.5625,1.5625,3.125,6.25,12.5,25,50,100
|
10010,0.0703125,0.1953125,0.390625,0.78125,1.5625,3.125,6.25,12.5
|
||||||
10011,0.59375,1.59375,3.1875,6.375,12.75,25.5,51,102
|
10011,0.07421875,0.19921875,0.3984375,0.796875,1.59375,3.1875,6.375,12.75
|
||||||
10100,0.625,1.625,3.25,6.5,13,26,52,104
|
10100,0.078125,0.203125,0.40625,0.8125,1.625,3.25,6.5,13
|
||||||
10101,0.65625,1.65625,3.3125,6.625,13.25,26.5,53,106
|
10101,0.08203125,0.20703125,0.4140625,0.828125,1.65625,3.3125,6.625,13.25
|
||||||
10110,0.6875,1.6875,3.375,6.75,13.5,27,54,108
|
10110,0.0859375,0.2109375,0.421875,0.84375,1.6875,3.375,6.75,13.5
|
||||||
10111,0.71875,1.71875,3.4375,6.875,13.75,27.5,55,110
|
10111,0.08984375,0.21484375,0.4296875,0.859375,1.71875,3.4375,6.875,13.75
|
||||||
11000,0.75,1.75,3.5,7,14,28,56,112
|
11000,0.09375,0.21875,0.4375,0.875,1.75,3.5,7,14
|
||||||
11001,0.78125,1.78125,3.5625,7.125,14.25,28.5,57,114
|
11001,0.09765625,0.22265625,0.4453125,0.890625,1.78125,3.5625,7.125,14.25
|
||||||
11010,0.8125,1.8125,3.625,7.25,14.5,29,58,116
|
11010,0.1015625,0.2265625,0.453125,0.90625,1.8125,3.625,7.25,14.5
|
||||||
11011,0.84375,1.84375,3.6875,7.375,14.75,29.5,59,118
|
11011,0.10546875,0.23046875,0.4609375,0.921875,1.84375,3.6875,7.375,14.75
|
||||||
11100,0.875,1.875,3.75,7.5,15,30,60,120
|
11100,0.109375,0.234375,0.46875,0.9375,1.875,3.75,7.5,15
|
||||||
11101,0.90625,1.90625,3.8125,7.625,15.25,30.5,61,122
|
11101,0.11328125,0.23828125,0.4765625,0.953125,1.90625,3.8125,7.625,15.25
|
||||||
11110,0.9375,1.9375,3.875,7.75,15.5,31,62,124
|
11110,0.1171875,0.2421875,0.484375,0.96875,1.9375,3.875,7.75,15.5
|
||||||
11111,0.96875,1.96875,3.9375,7.875,15.75,31.5,63,126
|
11111,0.12109375,0.24609375,0.4921875,0.984375,1.96875,3.9375,7.875,15.75
|
||||||
LSB
|
LSB
|
||||||
|
|
||||||
## Tracker Note Effects
|
## Tracker Note Effects
|
||||||
|
|||||||
@@ -1,7 +1,15 @@
|
|||||||
package net.torvald.tsvm
|
package net.torvald.tsvm
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by minjaesong on 2022-12-30.
|
* 3.5 unsigned minifloat (3-bit exponent + 5-bit mantissa), scaled so the
|
||||||
|
* smallest non-zero step is 1/256 s ≈ 3.91 ms and the maximum representable
|
||||||
|
* value is 15.75 s. Used for Taud envelope point offsets — the resolution at
|
||||||
|
* the low end is fine enough to resolve individual tracker ticks at every
|
||||||
|
* supported BPM (worst case ±17 % at BPM 250+, vs. ±150 % under the original
|
||||||
|
* 1/32-step bias).
|
||||||
|
*
|
||||||
|
* Created by minjaesong on 2022-12-30. Rebiased for tracker tick resolution
|
||||||
|
* on 2026-05-07 (entire LUT divided by 8).
|
||||||
*/
|
*/
|
||||||
@JvmInline
|
@JvmInline
|
||||||
value class ThreeFiveMiniUfloat(val index: Int = 0) {
|
value class ThreeFiveMiniUfloat(val index: Int = 0) {
|
||||||
@@ -11,7 +19,7 @@ value class ThreeFiveMiniUfloat(val index: Int = 0) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val LUT = floatArrayOf(0f,0.03125f,0.0625f,0.09375f,0.125f,0.15625f,0.1875f,0.21875f,0.25f,0.28125f,0.3125f,0.34375f,0.375f,0.40625f,0.4375f,0.46875f,0.5f,0.53125f,0.5625f,0.59375f,0.625f,0.65625f,0.6875f,0.71875f,0.75f,0.78125f,0.8125f,0.84375f,0.875f,0.90625f,0.9375f,0.96875f,1f,1.03125f,1.0625f,1.09375f,1.125f,1.15625f,1.1875f,1.21875f,1.25f,1.28125f,1.3125f,1.34375f,1.375f,1.40625f,1.4375f,1.46875f,1.5f,1.53125f,1.5625f,1.59375f,1.625f,1.65625f,1.6875f,1.71875f,1.75f,1.78125f,1.8125f,1.84375f,1.875f,1.90625f,1.9375f,1.96875f,2f,2.0625f,2.125f,2.1875f,2.25f,2.3125f,2.375f,2.4375f,2.5f,2.5625f,2.625f,2.6875f,2.75f,2.8125f,2.875f,2.9375f,3f,3.0625f,3.125f,3.1875f,3.25f,3.3125f,3.375f,3.4375f,3.5f,3.5625f,3.625f,3.6875f,3.75f,3.8125f,3.875f,3.9375f,4f,4.125f,4.25f,4.375f,4.5f,4.625f,4.75f,4.875f,5f,5.125f,5.25f,5.375f,5.5f,5.625f,5.75f,5.875f,6f,6.125f,6.25f,6.375f,6.5f,6.625f,6.75f,6.875f,7f,7.125f,7.25f,7.375f,7.5f,7.625f,7.75f,7.875f,8f,8.25f,8.5f,8.75f,9f,9.25f,9.5f,9.75f,10f,10.25f,10.5f,10.75f,11f,11.25f,11.5f,11.75f,12f,12.25f,12.5f,12.75f,13f,13.25f,13.5f,13.75f,14f,14.25f,14.5f,14.75f,15f,15.25f,15.5f,15.75f,16f,16.5f,17f,17.5f,18f,18.5f,19f,19.5f,20f,20.5f,21f,21.5f,22f,22.5f,23f,23.5f,24f,24.5f,25f,25.5f,26f,26.5f,27f,27.5f,28f,28.5f,29f,29.5f,30f,30.5f,31f,31.5f,32f,33f,34f,35f,36f,37f,38f,39f,40f,41f,42f,43f,44f,45f,46f,47f,48f,49f,50f,51f,52f,53f,54f,55f,56f,57f,58f,59f,60f,61f,62f,63f,64f,66f,68f,70f,72f,74f,76f,78f,80f,82f,84f,86f,88f,90f,92f,94f,96f,98f,100f,102f,104f,106f,108f,110f,112f,114f,116f,118f,120f,122f,124f,126f)
|
val LUT = floatArrayOf(0f,0.00390625f,0.0078125f,0.01171875f,0.015625f,0.01953125f,0.0234375f,0.02734375f,0.03125f,0.03515625f,0.0390625f,0.04296875f,0.046875f,0.05078125f,0.0546875f,0.05859375f,0.0625f,0.06640625f,0.0703125f,0.07421875f,0.078125f,0.08203125f,0.0859375f,0.08984375f,0.09375f,0.09765625f,0.1015625f,0.10546875f,0.109375f,0.11328125f,0.1171875f,0.12109375f,0.125f,0.12890625f,0.1328125f,0.13671875f,0.140625f,0.14453125f,0.1484375f,0.15234375f,0.15625f,0.16015625f,0.1640625f,0.16796875f,0.171875f,0.17578125f,0.1796875f,0.18359375f,0.1875f,0.19140625f,0.1953125f,0.19921875f,0.203125f,0.20703125f,0.2109375f,0.21484375f,0.21875f,0.22265625f,0.2265625f,0.23046875f,0.234375f,0.23828125f,0.2421875f,0.24609375f,0.25f,0.2578125f,0.265625f,0.2734375f,0.28125f,0.2890625f,0.296875f,0.3046875f,0.3125f,0.3203125f,0.328125f,0.3359375f,0.34375f,0.3515625f,0.359375f,0.3671875f,0.375f,0.3828125f,0.390625f,0.3984375f,0.40625f,0.4140625f,0.421875f,0.4296875f,0.4375f,0.4453125f,0.453125f,0.4609375f,0.46875f,0.4765625f,0.484375f,0.4921875f,0.5f,0.515625f,0.53125f,0.546875f,0.5625f,0.578125f,0.59375f,0.609375f,0.625f,0.640625f,0.65625f,0.671875f,0.6875f,0.703125f,0.71875f,0.734375f,0.75f,0.765625f,0.78125f,0.796875f,0.8125f,0.828125f,0.84375f,0.859375f,0.875f,0.890625f,0.90625f,0.921875f,0.9375f,0.953125f,0.96875f,0.984375f,1f,1.03125f,1.0625f,1.09375f,1.125f,1.15625f,1.1875f,1.21875f,1.25f,1.28125f,1.3125f,1.34375f,1.375f,1.40625f,1.4375f,1.46875f,1.5f,1.53125f,1.5625f,1.59375f,1.625f,1.65625f,1.6875f,1.71875f,1.75f,1.78125f,1.8125f,1.84375f,1.875f,1.90625f,1.9375f,1.96875f,2f,2.0625f,2.125f,2.1875f,2.25f,2.3125f,2.375f,2.4375f,2.5f,2.5625f,2.625f,2.6875f,2.75f,2.8125f,2.875f,2.9375f,3f,3.0625f,3.125f,3.1875f,3.25f,3.3125f,3.375f,3.4375f,3.5f,3.5625f,3.625f,3.6875f,3.75f,3.8125f,3.875f,3.9375f,4f,4.125f,4.25f,4.375f,4.5f,4.625f,4.75f,4.875f,5f,5.125f,5.25f,5.375f,5.5f,5.625f,5.75f,5.875f,6f,6.125f,6.25f,6.375f,6.5f,6.625f,6.75f,6.875f,7f,7.125f,7.25f,7.375f,7.5f,7.625f,7.75f,7.875f,8f,8.25f,8.5f,8.75f,9f,9.25f,9.5f,9.75f,10f,10.25f,10.5f,10.75f,11f,11.25f,11.5f,11.75f,12f,12.25f,12.5f,12.75f,13f,13.25f,13.5f,13.75f,14f,14.25f,14.5f,14.75f,15f,15.25f,15.5f,15.75f)
|
||||||
|
|
||||||
private fun fromFloatToIndex(fval: Float): Int {
|
private fun fromFloatToIndex(fval: Float): Int {
|
||||||
val (llim, hlim) = binarySearchInterval(fval, LUT)
|
val (llim, hlim) = binarySearchInterval(fval, LUT)
|
||||||
|
|||||||
59
xm2taud.py
59
xm2taud.py
@@ -53,7 +53,7 @@ from taud_common import (
|
|||||||
SEL_SET, SEL_UP, SEL_DOWN, SEL_FINE,
|
SEL_SET, SEL_UP, SEL_DOWN, SEL_FINE,
|
||||||
J_SEMI_TABLE,
|
J_SEMI_TABLE,
|
||||||
d_arg_to_col, resample_linear, rescale_offset_effects, encode_cue, deduplicate_patterns,
|
d_arg_to_col, resample_linear, rescale_offset_effects, encode_cue, deduplicate_patterns,
|
||||||
normalise_sample, encode_song_entry,
|
normalise_sample, encode_song_entry, nearest_minifloat,
|
||||||
CUE_INST_NOP, CUE_INST_HALT, CUE_INST_LEN, cue_instruction_len,
|
CUE_INST_NOP, CUE_INST_HALT, CUE_INST_LEN, cue_instruction_len,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -78,61 +78,6 @@ XM_ENV_LOOP = 0x04
|
|||||||
SIGNATURE = b"xm2taud/TSVM " # 14 bytes
|
SIGNATURE = b"xm2taud/TSVM " # 14 bytes
|
||||||
|
|
||||||
|
|
||||||
# ── Minifloat LUT (must match it2taud / engine) ──────────────────────────────
|
|
||||||
|
|
||||||
_MINUFLOAT_LUT = [
|
|
||||||
0.0, 0.03125, 0.0625, 0.09375, 0.125, 0.15625, 0.1875, 0.21875,
|
|
||||||
0.25, 0.28125, 0.3125, 0.34375, 0.375, 0.40625, 0.4375, 0.46875,
|
|
||||||
0.5, 0.53125, 0.5625, 0.59375, 0.625, 0.65625, 0.6875, 0.71875,
|
|
||||||
0.75, 0.78125, 0.8125, 0.84375, 0.875, 0.90625, 0.9375, 0.96875,
|
|
||||||
1.0, 1.03125, 1.0625, 1.09375, 1.125, 1.15625, 1.1875, 1.21875,
|
|
||||||
1.25, 1.28125, 1.3125, 1.34375, 1.375, 1.40625, 1.4375, 1.46875,
|
|
||||||
1.5, 1.53125, 1.5625, 1.59375, 1.625, 1.65625, 1.6875, 1.71875,
|
|
||||||
1.75, 1.78125, 1.8125, 1.84375, 1.875, 1.90625, 1.9375, 1.96875,
|
|
||||||
2.0, 2.0625, 2.125, 2.1875, 2.25, 2.3125, 2.375, 2.4375,
|
|
||||||
2.5, 2.5625, 2.625, 2.6875, 2.75, 2.8125, 2.875, 2.9375,
|
|
||||||
3.0, 3.0625, 3.125, 3.1875, 3.25, 3.3125, 3.375, 3.4375,
|
|
||||||
3.5, 3.5625, 3.625, 3.6875, 3.75, 3.8125, 3.875, 3.9375,
|
|
||||||
4.0, 4.125, 4.25, 4.375, 4.5, 4.625, 4.75, 4.875,
|
|
||||||
5.0, 5.125, 5.25, 5.375, 5.5, 5.625, 5.75, 5.875,
|
|
||||||
6.0, 6.125, 6.25, 6.375, 6.5, 6.625, 6.75, 6.875,
|
|
||||||
7.0, 7.125, 7.25, 7.375, 7.5, 7.625, 7.75, 7.875,
|
|
||||||
8.0, 8.25, 8.5, 8.75, 9.0, 9.25, 9.5, 9.75,
|
|
||||||
10.0, 10.25, 10.5, 10.75, 11.0, 11.25, 11.5, 11.75,
|
|
||||||
12.0, 12.25, 12.5, 12.75, 13.0, 13.25, 13.5, 13.75,
|
|
||||||
14.0, 14.25, 14.5, 14.75, 15.0, 15.25, 15.5, 15.75,
|
|
||||||
16.0, 16.5, 17.0, 17.5, 18.0, 18.5, 19.0, 19.5,
|
|
||||||
20.0, 20.5, 21.0, 21.5, 22.0, 22.5, 23.0, 23.5,
|
|
||||||
24.0, 24.5, 25.0, 25.5, 26.0, 26.5, 27.0, 27.5,
|
|
||||||
28.0, 28.5, 29.0, 29.5, 30.0, 30.5, 31.0, 31.5,
|
|
||||||
32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0,
|
|
||||||
40.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0,
|
|
||||||
48.0, 49.0, 50.0, 51.0, 52.0, 53.0, 54.0, 55.0,
|
|
||||||
56.0, 57.0, 58.0, 59.0, 60.0, 61.0, 62.0, 63.0,
|
|
||||||
64.0, 66.0, 68.0, 70.0, 72.0, 74.0, 76.0, 78.0,
|
|
||||||
80.0, 82.0, 84.0, 86.0, 88.0, 90.0, 92.0, 94.0,
|
|
||||||
96.0, 98.0, 100.0, 102.0, 104.0, 106.0, 108.0, 110.0,
|
|
||||||
112.0, 114.0, 116.0, 118.0, 120.0, 122.0, 124.0, 126.0,
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
def _nearest_minifloat(sec: float) -> int:
|
|
||||||
if sec <= 0.0:
|
|
||||||
return 0
|
|
||||||
if sec >= 126.0:
|
|
||||||
return 255
|
|
||||||
lo, hi = 0, len(_MINUFLOAT_LUT) - 1
|
|
||||||
while lo < hi:
|
|
||||||
mid = (lo + hi) // 2
|
|
||||||
if _MINUFLOAT_LUT[mid] < sec:
|
|
||||||
lo = mid + 1
|
|
||||||
else:
|
|
||||||
hi = mid
|
|
||||||
if lo > 0 and abs(_MINUFLOAT_LUT[lo - 1] - sec) < abs(_MINUFLOAT_LUT[lo] - sec):
|
|
||||||
return lo - 1
|
|
||||||
return lo
|
|
||||||
|
|
||||||
|
|
||||||
# ── Data classes ─────────────────────────────────────────────────────────────
|
# ── Data classes ─────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
class XMHeader:
|
class XMHeader:
|
||||||
@@ -809,7 +754,7 @@ def _xm_envelope_to_taud(env_pts: list, num_pts: int, env_type: int,
|
|||||||
if k < len(nodes) - 1:
|
if k < len(nodes) - 1:
|
||||||
next_frame, _ = nodes[k + 1]
|
next_frame, _ = nodes[k + 1]
|
||||||
delta_sec = max(0.0, (next_frame - frame) / ticks_per_sec)
|
delta_sec = max(0.0, (next_frame - frame) / ticks_per_sec)
|
||||||
mf_idx = _nearest_minifloat(delta_sec)
|
mf_idx = nearest_minifloat(delta_sec)
|
||||||
else:
|
else:
|
||||||
mf_idx = 0
|
mf_idx = 0
|
||||||
else:
|
else:
|
||||||
|
|||||||
Reference in New Issue
Block a user