mirror of
https://github.com/curioustorvald/tsvm.git
synced 2026-06-06 13:38:30 +09:00
taud: more fixes
This commit is contained in:
@@ -856,8 +856,8 @@ function drawControlHint() {
|
||||
['sep'],
|
||||
['Sp','Edit'],
|
||||
['sep'],
|
||||
['n','Solo'],
|
||||
['m','Mute'],
|
||||
['s','Solo'],
|
||||
['sep'],
|
||||
['Tab','Panel']
|
||||
// ['sep'],
|
||||
@@ -1397,7 +1397,7 @@ function timelineInput(wo, event) {
|
||||
drawVoiceHeaders(); drawSeparators(separatorStyle); drawAlwaysOnElems(); drawVoiceDetail()
|
||||
}
|
||||
else if (keyJustHit && !shiftDown && event.includes(keys.M)) { toggleMute(cursorVox) }
|
||||
else if (keyJustHit && !shiftDown && event.includes(keys.S)) { toggleSolo(cursorVox) }
|
||||
else if (keyJustHit && !shiftDown && event.includes(keys.N)) { toggleSolo(cursorVox) }
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1434,7 +1434,7 @@ function timelineInput(wo, event) {
|
||||
}
|
||||
|
||||
if (keyJustHit && !shiftDown && event.includes(keys.M)) { toggleMute(cursorVox); return }
|
||||
if (keyJustHit && !shiftDown && event.includes(keys.S)) { toggleSolo(cursorVox); return }
|
||||
if (keyJustHit && !shiftDown && event.includes(keys.N)) { toggleSolo(cursorVox); return }
|
||||
|
||||
if (keysym === "<UP>") { cursorRow -= moveDelta; rowMove = true }
|
||||
else if (keysym === "<DOWN>") { cursorRow += moveDelta; rowMove = true }
|
||||
|
||||
@@ -1254,8 +1254,9 @@ def build_sample_inst_bin_it(samples_or_proxy: list,
|
||||
if vol_env:
|
||||
_write_env(inst_bin, base + 21, vol_env)
|
||||
else:
|
||||
# Single-point: hold at sample default volume.
|
||||
inst_bin[base + 21] = min(getattr(s, 'vol', 63), 63)
|
||||
# Single-point envelope held at full-scale; the per-sample level is
|
||||
# carried by IGV (byte 171), so the envelope must be a unit multiplier.
|
||||
inst_bin[base + 21] = 63
|
||||
inst_bin[base + 22] = 0
|
||||
# Force engine to use this single point.
|
||||
struct.pack_into('<H', inst_bin, base + 15, USE_ENV_BIT)
|
||||
|
||||
@@ -506,7 +506,9 @@ def build_sample_inst_bin(samples: list) -> tuple:
|
||||
le = min(s.loop_end, 65535)
|
||||
loop_mode = 1 if (s.flags & 1) else 0
|
||||
flags_byte = loop_mode & 0x3
|
||||
env_vol = min(s.volume, 63)
|
||||
# Envelope first point is full-scale; per-sample level is carried by
|
||||
# IGV (byte 171) so the envelope must contribute a unit multiplier.
|
||||
env_vol = 63
|
||||
vol_env_flags = 0x0020 # use-envelope bit
|
||||
|
||||
base = taud_idx * 192
|
||||
@@ -763,7 +765,7 @@ def assemble_taud(mod: dict) -> bytes:
|
||||
pat_bin_comp_size=len(pat_comp),
|
||||
cue_sheet_comp_size=len(cue_comp),
|
||||
global_vol=0xFF,
|
||||
mixing_vol=0x7F,
|
||||
mixing_vol=180,
|
||||
)
|
||||
assert len(song_table) == TAUD_SONG_ENTRY
|
||||
|
||||
|
||||
@@ -495,8 +495,9 @@ def build_sample_inst_bin(instruments: list) -> tuple:
|
||||
loop_mode = 1 if (inst.flags & 1) else 0
|
||||
flags_byte = loop_mode & 0x3 # 0b 0000 00pp
|
||||
|
||||
# Volume envelope: hold at instrument volume (clamped to 0x3F).
|
||||
env_vol = min(inst.volume, 63)
|
||||
# Volume envelope first point is full-scale; per-sample level is carried
|
||||
# by IGV (byte 171) so the envelope contributes a unit multiplier.
|
||||
env_vol = 63
|
||||
# Vol env-flags: enable use-envelope bit (b=1) so engine reads the single point.
|
||||
vol_env_flags = 0x0020 # b=bit 5
|
||||
|
||||
@@ -820,7 +821,7 @@ def assemble_taud(h: S3MHeader, instruments: list, patterns: list) -> bytes:
|
||||
pat_bin_comp_size=len(pat_comp),
|
||||
cue_sheet_comp_size=len(cue_comp),
|
||||
global_vol=0xFF,
|
||||
mixing_vol=0x7F,
|
||||
mixing_vol=180,
|
||||
)
|
||||
assert len(song_table) == TAUD_SONG_ENTRY
|
||||
|
||||
|
||||
@@ -2111,7 +2111,7 @@ TODO:
|
||||
[x] Fix 4THSYM.it filters
|
||||
[x] 4THSYM.it: pitchbend is wrong, some notes keep playing (loudly!) even if new notes are emitted
|
||||
[x] `*2taud.py`: some notes are emitted with wrong volume-set command. Tested with GSLINGER.mod: on order 0x15 channel 1, mod2taud.py emits volume 8 -- also many of the effects are dropped. Suggested solution: currently all converters write default volume to the voleff when original modules (.mod/.s3m/.it) specify nothing; we should also write nothing and let the engine resolve the value just like other trackers do (also we now have "Instrument Global Volume" on instrument definition unlike the other time). This bug may affecting other formats, not just mod2taud.py, as well
|
||||
[ ] nearly_there_.mod: `C#5 SD300 / ... / C-5 SD200 / A#4 / G#4 (at tickspeed 4)`: every `C-5 SD200` (there are four occurances) gets skipped
|
||||
[x] nearly_there_.mod: `C#5 SD300 / ... / C-5 SD200 / A#4 / G#4 (at tickspeed 4)`: every `C-5 SD200` (there are four occurances) gets skipped
|
||||
[ ] scale Oxxxx when samples get resampled
|
||||
[ ] implement bitcrusher and overdrive (eff sym '8' and '9')
|
||||
|
||||
|
||||
@@ -1469,8 +1469,8 @@ class AudioAdapter(val vm: VM) : PeriBase(VM.PERITYPE_SOUND) {
|
||||
if (i0 in ls until inst.sampleLoopEnd && inst.funkBit(i0 - ls)) b0 = b0 xor 0x80
|
||||
if (i1 in ls until inst.sampleLoopEnd && inst.funkBit(i1 - ls)) b1 = b1 xor 0x80
|
||||
}
|
||||
val s0 = (b0 - 128) / 128.0
|
||||
val s1 = (b1 - 128) / 128.0
|
||||
val s0 = (b0 - 127.5) / 127.5
|
||||
val s1 = (b1 - 127.5) / 127.5
|
||||
val sample = s0 + (s1 - s0) * frac
|
||||
|
||||
if (voice.forward) {
|
||||
@@ -2371,6 +2371,8 @@ class AudioAdapter(val vm: VM) : PeriBase(VM.PERITYPE_SOUND) {
|
||||
}
|
||||
}
|
||||
|
||||
private fun Double.sqrt() = Math.sqrt(this)
|
||||
|
||||
internal fun generateTrackerAudio(playhead: Playhead): ByteArray? {
|
||||
val ts = playhead.trackerState ?: return null
|
||||
|
||||
@@ -2408,7 +2410,7 @@ class AudioAdapter(val vm: VM) : PeriBase(VM.PERITYPE_SOUND) {
|
||||
val swingScale = 1.0 + voice.randomVolBias / 255.0
|
||||
// Volume envelope is bypassed (treated as unity) when S $77 has disabled it.
|
||||
val effEnvVol = if (voice.volEnvOn) voice.envVolume else 1.0
|
||||
val vol = effEnvVol * voice.fadeoutVolume * voice.rowVolume / 63.0 *
|
||||
val vol = effEnvVol.sqrt() * voice.fadeoutVolume * (voice.rowVolume / 63.0).sqrt() *
|
||||
swingScale * gvol * mvol * instGv * playhead.masterVolume / 255.0
|
||||
val pan = if (voice.hasPanEnv && voice.panEnvOn) {
|
||||
val envPanRaw = (voice.envPan * 255.0).roundToInt().coerceIn(0, 255)
|
||||
@@ -2438,7 +2440,7 @@ class AudioAdapter(val vm: VM) : PeriBase(VM.PERITYPE_SOUND) {
|
||||
val instGv = bgInst.instGlobalVolume / 255.0
|
||||
val swingScale = 1.0 + bg.randomVolBias / 255.0
|
||||
val effEnvVol = if (bg.volEnvOn) bg.envVolume else 1.0
|
||||
val vol = effEnvVol * bg.fadeoutVolume * bg.rowVolume / 63.0 *
|
||||
val vol = effEnvVol.sqrt() * bg.fadeoutVolume * (bg.rowVolume / 63.0).sqrt() *
|
||||
swingScale * gvol * mvol * instGv * playhead.masterVolume / 255.0
|
||||
val pan = if (bg.hasPanEnv && bg.panEnvOn) {
|
||||
val envPanRaw = (bg.envPan * 255.0).roundToInt().coerceIn(0, 255)
|
||||
|
||||
Reference in New Issue
Block a user