mirror of
https://github.com/curioustorvald/tsvm.git
synced 2026-06-06 05:28:31 +09:00
tightening formats
This commit is contained in:
@@ -16,8 +16,8 @@ const NUM_PATTERNS_MAX = 256
|
||||
const NUM_CUES = 1024
|
||||
const CUE_SIZE = 32 // bytes per cue entry (packed 12-bit×20 voices + instruction + pad)
|
||||
|
||||
// Signature written into the file (16 bytes, space-padded)
|
||||
const CAPTURE_SIGNATURE = "LibTaud/TSVM "
|
||||
// Signature written into the file (14 bytes, space-padded)
|
||||
const CAPTURE_SIGNATURE = "LibTaud/TSVM "
|
||||
|
||||
// ── Internal helpers ────────────────────────────────────────────────────────
|
||||
|
||||
@@ -205,8 +205,8 @@ function captureTrackerDataToFile(outFile) {
|
||||
(compressedSize >>> 8) & 0xFF,
|
||||
(compressedSize >>> 16) & 0xFF,
|
||||
(compressedSize >>> 24) & 0xFF,
|
||||
// reserved (2)
|
||||
0x00, 0x00,
|
||||
// reserved (4)
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
].concat(sigBytes) // 8 + 2 + 4 + 2 + 16 = 32 bytes
|
||||
|
||||
// -- 6. Build song-table row (16 bytes) -----------------------------------
|
||||
@@ -219,7 +219,9 @@ function captureTrackerDataToFile(outFile) {
|
||||
numPats & 0xFF, (numPats >>> 8) & 0xFF, // numPatterns Uint16 LE
|
||||
bpmStored, // BPM with −24 bias
|
||||
tickRate, // initial tick-rate
|
||||
0,0,0,0,0,0,0, // 7 bytes padding
|
||||
0x40,0, // basenote
|
||||
0x13,0xd0,0x82,0x43, // basefreq
|
||||
0, // padding
|
||||
]
|
||||
|
||||
// -- 7. Write header (creates / truncates file) ---------------------------
|
||||
|
||||
12
s3m2taud.py
12
s3m2taud.py
@@ -87,7 +87,7 @@ NUM_PATTERNS_MAX = 4095
|
||||
NUM_CUES = 1024
|
||||
CUE_SIZE = 32 # packed 12-bit×20 voices + instruction + pad
|
||||
NUM_VOICES = 20
|
||||
SIGNATURE = b"s3m2taud/TSVM " # 16 bytes
|
||||
SIGNATURE = b"s3m2taud/TSVM " # 14 bytes
|
||||
|
||||
# Taud note constants
|
||||
NOTE_NOP = 0xFFFF
|
||||
@@ -860,13 +860,13 @@ def assemble_taud(h: S3MHeader, instruments: list, patterns: list) -> bytes:
|
||||
song_offset = TAUD_HEADER_SIZE + comp_size + TAUD_SONG_ENTRY
|
||||
num_taud_pats = P * C
|
||||
|
||||
# Header (32 bytes): magic(8)+ver(1)+numSongs(1)+compSize(4)+rsvd(2)+sig(16)
|
||||
sig = (SIGNATURE + b' ' * 16)[:16]
|
||||
# Header (32 bytes): magic(8)+ver(1)+numSongs(1)+compSize(4)+rsvd(4)+sig(14)
|
||||
sig = (SIGNATURE + b' ' * 14)[:14]
|
||||
header = (
|
||||
TAUD_MAGIC +
|
||||
bytes([TAUD_VERSION, 1]) +
|
||||
struct.pack('<I', comp_size) +
|
||||
b'\x00\x00' +
|
||||
b'\x00\x00\x00\x00' +
|
||||
sig
|
||||
)
|
||||
assert len(header) == TAUD_HEADER_SIZE
|
||||
@@ -893,7 +893,7 @@ def assemble_taud(h: S3MHeader, instruments: list, patterns: list) -> bytes:
|
||||
pat_bin, pat_remap, num_taud_pats = deduplicate_patterns(bytes(pat_bin), orig_count)
|
||||
vprint(f" patterns: {orig_count} → {num_taud_pats} unique ({orig_count - num_taud_pats} deduplicated)")
|
||||
|
||||
# Song table row (16 bytes): offset(4)+voices(1)+patsLo(1)+patsHi(1)+bpm(1)+tick(1)+pad(7)
|
||||
# Song table row (16 bytes): offset(4)+voices(1)+patsLo(1)+patsHi(1)+bpm(1)+tick(1)+basenote(2)+basefreq(4)+pad(1)
|
||||
# Built after dedup so num_taud_pats reflects the unique count.
|
||||
num_taud_pats_lo = num_taud_pats & 0xFF
|
||||
num_taud_pats_hi = (num_taud_pats >> 8) & 0xFF
|
||||
@@ -904,7 +904,7 @@ def assemble_taud(h: S3MHeader, instruments: list, patterns: list) -> bytes:
|
||||
num_taud_pats_hi,
|
||||
bpm_stored,
|
||||
speed,
|
||||
) + b'\x00' * 7
|
||||
) + b'\x40\x00' + b'\x13\xd0\x82\x43' + b'\x00'
|
||||
assert len(song_table) == TAUD_SONG_ENTRY
|
||||
|
||||
# Cue sheet (using remapped pattern indices)
|
||||
|
||||
@@ -2200,8 +2200,8 @@ Endianness: Little
|
||||
Uint8 Format version (always 1)
|
||||
Uint8 Number of songs in SONG TABLE
|
||||
Uint32 Compressed size of SAMPLE+INST section (used to calculate offset to SONG TABLE)
|
||||
Uint16 Reserved for future versions
|
||||
Byte[16]Tracker/Converter signature
|
||||
Uint32 Reserved for Taud Project Format. Fill with zero
|
||||
Byte[14]Tracker/Converter signature
|
||||
|
||||
## SONG TABLE
|
||||
Rows of 16 bytes:
|
||||
@@ -2210,7 +2210,7 @@ Rows of 16 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 Tickrate (0 is invalid)
|
||||
Uint16 Current Tuning base note (1-4094), assuming octave 3. C3 (the default value) is 0x4000. If zero, assume the default value
|
||||
Uint16 Current Tuning base note (1..65533), assuming octave 3. C3 (the default value) is 0x4000. If zero, assume the default value
|
||||
Float32 Frequency at the base note. Default (A440) is 261.6255653. If zero, assume the default value
|
||||
Byte[1] Reserved for future versions
|
||||
|
||||
@@ -2239,12 +2239,11 @@ Endianness: Little
|
||||
|
||||
## Header
|
||||
Byte[8] Magic
|
||||
Uint8 Format version (always 129)
|
||||
Uint8 Format version (always 129; high-bit set and number 0x01)
|
||||
Uint8 Number of songs in SONG TABLE
|
||||
Uint32 Compressed size of SAMPLE+INST section (used to calculate offset to SONG TABLE)
|
||||
Uint16 Offset to Project Data (low twobyte)
|
||||
Uint32 Offset to Project Data (low twobyte)
|
||||
Byte[14]Tracker/Converter signature
|
||||
Uint16 Offset to Project Data (high twobyte)
|
||||
|
||||
## Project Data
|
||||
Byte[8] Magic (\x1E T a u d P r J)
|
||||
@@ -2268,11 +2267,11 @@ prefixes:
|
||||
* PCpr. Project copyright string. Encoding: UTF-8
|
||||
* PNam. Project name. Encoding: UTF-8
|
||||
|
||||
* INam. Instrument name table. Strings separated by comma
|
||||
* INam. Instrument name table. Strings separated by 0x1E
|
||||
|
||||
* pNam. Pattern name table. Strings separated by comma
|
||||
* pNam. Pattern name table. Strings separated by 0x1E
|
||||
|
||||
* SNam. Sample name table. Strings separated by comma
|
||||
* SNam. Sample name table. Strings separated by 0x1E
|
||||
|
||||
* sMet. Song metadata table
|
||||
* Repetition of:
|
||||
@@ -2288,15 +2287,15 @@ prefixes:
|
||||
Uint8 Notation index (starting from zero) used by songs
|
||||
Uint32 Size of this notation following this field
|
||||
Uint8 Flags
|
||||
0b nnnn 000t
|
||||
0b 0000 000t
|
||||
t: NOT using interval system (you are responsible for defining every notes expressible)
|
||||
Uint8 Reserved
|
||||
Float32 Interval size (octave system = 2.0f). If Flag 't' is set, this must be NaN. 0f and Infinity are considered illegal
|
||||
Uint16 Notes between interval MINUS ONE (or octave); 12-TET will have value 11. 0 is considered illegal
|
||||
Byte[8] Reserved
|
||||
Byte[*] Name, null terminated. Encoding: UTF-8
|
||||
Byte[*] Notation table. Comma-separated and null-terminated. Encoding: raw bytes
|
||||
Uint16[*] Frequency table. Size of the table is defined by "Notes between interval MINUS ONE". All relative to the base note (Song table will be referred), in 4096-TET note number. Index zero of this table will be 0x0 if you read the spec right
|
||||
Byte[*] Notation table. 0xFF-separated and null-terminated. Encoding: raw bytes
|
||||
Uint16[*] Frequency table. Size of the table is defined by "Notes between interval MINUS ONE". This is a lookup table of relative pitch offsets (against the base tuning note) in 4096-TET space. Index zero of this table will be 0x0 if you read the spec right
|
||||
|
||||
Note: custom notations will use internal index 65535 down to 65520 (index 0 = 65535, index 15 = 65520)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user