mirror of
https://github.com/curioustorvald/tsvm.git
synced 2026-06-06 13:38:30 +09:00
taud-related changes (docs, converter supports Y eff)
This commit is contained in:
@@ -219,8 +219,8 @@ function captureTrackerDataToFile(outFile) {
|
|||||||
numPats & 0xFF, (numPats >>> 8) & 0xFF, // numPatterns Uint16 LE
|
numPats & 0xFF, (numPats >>> 8) & 0xFF, // numPatterns Uint16 LE
|
||||||
bpmStored, // BPM with −24 bias
|
bpmStored, // BPM with −24 bias
|
||||||
tickRate, // initial tick-rate
|
tickRate, // initial tick-rate
|
||||||
0x00,0x4C, // basenote (0x4C00 -- A3)
|
0x00,0x90, // basenote (0x9000 -- C8)
|
||||||
0x00,0x00,0xDC,0x43, // basefreq (440 Hz)
|
0x00,0xAC,0x02,0x46, // basefreq (8363 Hz)
|
||||||
0, // padding
|
0, // padding
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
18
s3m2taud.py
18
s3m2taud.py
@@ -17,8 +17,9 @@ Effect support:
|
|||||||
table" and "ScreamTracker 3 conversion notes". ST3 shared-memory recalls
|
table" and "ScreamTracker 3 conversion notes". ST3 shared-memory recalls
|
||||||
(D/E/F/I/J/K/L/Q/R/S with $00 arg) are eagerly resolved per channel.
|
(D/E/F/I/J/K/L/Q/R/S with $00 arg) are eagerly resolved per channel.
|
||||||
Cxx is BCD-decoded. K/L are split into H $0000 / G $0000 + volume-column
|
Cxx is BCD-decoded. K/L are split into H $0000 / G $0000 + volume-column
|
||||||
slide. M/N/X/P fold into volume / pan columns. W (global vol slide) and
|
slide. M/N/X/P fold into volume / pan columns. W (global vol slide) is
|
||||||
Y (panbrello) are dropped with a -v warning.
|
dropped with a -v warning. X converts to pan column. Y (panbrello) converts
|
||||||
|
to Taud Y. S5 selects the panbrello LFO waveform.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
@@ -116,6 +117,7 @@ TOP_S = 0x1C # sub-effects
|
|||||||
TOP_T = 0x1D # tempo set/slide
|
TOP_T = 0x1D # tempo set/slide
|
||||||
TOP_U = 0x1E # fine vibrato
|
TOP_U = 0x1E # fine vibrato
|
||||||
TOP_V = 0x1F # global volume
|
TOP_V = 0x1F # global volume
|
||||||
|
TOP_Y = 0x22 # panbrello
|
||||||
|
|
||||||
# Volume / pan column selectors (2-bit field, packed into top of vol/pan byte).
|
# Volume / pan column selectors (2-bit field, packed into top of vol/pan byte).
|
||||||
SEL_SET = 0 # 6-bit value: set vol / pan
|
SEL_SET = 0 # 6-bit value: set vol / pan
|
||||||
@@ -442,10 +444,13 @@ def encode_effect(cmd: int, arg: int, ch: int = 0, row: int = 0) -> tuple:
|
|||||||
val = arg & 0xF
|
val = arg & 0xF
|
||||||
if sub in (0x1, 0x2, 0x3, 0x4, 0xB, 0xC, 0xD, 0xE, 0xF):
|
if sub in (0x1, 0x2, 0x3, 0x4, 0xB, 0xC, 0xD, 0xE, 0xF):
|
||||||
return (TOP_S, (sub << 12) | (val << 8), None, None)
|
return (TOP_S, (sub << 12) | (val << 8), None, None)
|
||||||
|
if sub == 0x5:
|
||||||
|
# Panbrello LFO waveform — maps directly to Taud S$5x00.
|
||||||
|
return (TOP_S, 0x5000 | (val << 8), None, None)
|
||||||
if sub == 0x8:
|
if sub == 0x8:
|
||||||
# Coarse pan: nibble-repeat into Taud's S $80xx full-8-bit pan.
|
# Coarse pan: nibble-repeat into Taud's S $80xx full-8-bit pan.
|
||||||
return (TOP_S, 0x8000 | (val * 0x11), None, None)
|
return (TOP_S, 0x8000 | (val * 0x11), None, None)
|
||||||
# S0/S5/S6/S7/S9/SA: filter, NNA, sound-control, stereo — drop silently.
|
# S0/S6/S7/S9/SA: filter, NNA, sound-control, stereo — drop silently.
|
||||||
return (TOP_NONE, 0, None, None)
|
return (TOP_NONE, 0, None, None)
|
||||||
|
|
||||||
if cmd == EFF_T:
|
if cmd == EFF_T:
|
||||||
@@ -465,8 +470,9 @@ def encode_effect(cmd: int, arg: int, ch: int = 0, row: int = 0) -> tuple:
|
|||||||
return (TOP_NONE, 0, None, (SEL_SET, min(arg >> 2, 0x3F)))
|
return (TOP_NONE, 0, None, (SEL_SET, min(arg >> 2, 0x3F)))
|
||||||
|
|
||||||
if cmd == EFF_Y:
|
if cmd == EFF_Y:
|
||||||
vprint(f" dropped Y{arg:02X} (panbrello) at ch{ch} row{row}")
|
hi = (arg >> 4) & 0xF
|
||||||
return (TOP_NONE, 0, None, None)
|
lo = arg & 0xF
|
||||||
|
return (TOP_Y, ((hi * 0x11) << 8) | (lo * 0x11), None, None)
|
||||||
|
|
||||||
if cmd == EFF_Z:
|
if cmd == EFF_Z:
|
||||||
return (TOP_NONE, 0, None, None)
|
return (TOP_NONE, 0, None, None)
|
||||||
@@ -904,7 +910,7 @@ def assemble_taud(h: S3MHeader, instruments: list, patterns: list) -> bytes:
|
|||||||
num_taud_pats_hi,
|
num_taud_pats_hi,
|
||||||
bpm_stored,
|
bpm_stored,
|
||||||
speed,
|
speed,
|
||||||
) + b'\x00\x4C' + b'\x00\x00\xDC\x43' + b'\x00'
|
) + b'\x00\x90' + b'\x00\xAC\xD02\x46' + b'\x00'
|
||||||
assert len(song_table) == TAUD_SONG_ENTRY
|
assert len(song_table) == TAUD_SONG_ENTRY
|
||||||
|
|
||||||
# Cue sheet (using remapped pattern indices)
|
# Cue sheet (using remapped pattern indices)
|
||||||
|
|||||||
@@ -2211,16 +2211,21 @@ Endianness: Little
|
|||||||
Uint16 Number of patterns (0 is invalid. pattern bin length = numPats * 8 bytes)
|
Uint16 Number of patterns (0 is invalid. pattern bin length = numPats * 8 bytes)
|
||||||
Uint8 Initial BPM (bias of -24. 0x00=24, 0xFF=279)
|
Uint8 Initial BPM (bias of -24. 0x00=24, 0xFF=279)
|
||||||
Uint8 Initial Tickrate (0 is invalid)
|
Uint8 Initial Tickrate (0 is invalid)
|
||||||
Uint16 Current Tuning base note (1..65533). A3 (the default value) is 0x4C00. If zero, assume the default value
|
Uint16 Current Tuning base note (1..65533). A3 (western default) is 0x4C00. C8 (tracker default) is 0x9000. If zero, assume the tracker default value
|
||||||
Float32 Frequency at the base note. Default (A440) is 440.0. If zero, assume the default value
|
Float32 Frequency at the base note. Tracker default is 8363.0. If zero, assume the tracker default
|
||||||
Byte[1] Reserved for future versions
|
Byte[1] Reserved for future versions
|
||||||
|
|
||||||
Taud device can queue up to 2 "playdata" in its buffer, which can be interpreted as a song.
|
Taud device can queue up to 2 "playdata" in its buffer, which can be interpreted as a song.
|
||||||
|
|
||||||
* Known standard tunings
|
* Known standard tunings
|
||||||
A440. ISO standard. Tracker default
|
A440. ISO standard
|
||||||
|
A435. Former French standard (year 1859)
|
||||||
|
A452. Old Philharmonic pitch (19th century Britain)
|
||||||
C256. Power of two
|
C256. Power of two
|
||||||
C311. East Asian tuning (ROK National Gugak Center standard)
|
C262. Modern Chinese a-ak tuning convention
|
||||||
|
C311. Korean hyang-ak tuning standard (ROK National Gugak Center)
|
||||||
|
|
||||||
|
For your reference, tracker default tuning at A3 is 439.526 Hz (8363*2^(3/4) / 32)
|
||||||
|
|
||||||
## Pattern Bin and Cue Sheet
|
## Pattern Bin and Cue Sheet
|
||||||
Raw Pattern Bin/Cue Sheet images
|
Raw Pattern Bin/Cue Sheet images
|
||||||
|
|||||||
Reference in New Issue
Block a user