mirror of
https://github.com/curioustorvald/tsvm.git
synced 2026-06-06 05:28:31 +09:00
song global volume and mixer volume
This commit is contained in:
6
2taud.sh
Executable file
6
2taud.sh
Executable file
@@ -0,0 +1,6 @@
|
||||
#!/usr/bin/env fish
|
||||
|
||||
for f in *.mod; python3 mod2taud.py $f assets/disk0/(basename $f .mod).taud; end
|
||||
for f in *.s3m; python3 s3m2taud.py $f assets/disk0/(basename $f .s3m).taud; end
|
||||
for f in *.it; python3 it2taud.py $f assets/disk0/(basename $f .it).taud; end
|
||||
for f in *.xm; python3 xm2taud.py $f assets/disk0/(basename $f .xm).taud; end
|
||||
@@ -2371,8 +2371,8 @@ taud.uploadTaudFile(fullPathObj.full, 0, PLAYHEAD)
|
||||
audio.setMasterVolume(PLAYHEAD, 255)
|
||||
audio.setMasterPan(PLAYHEAD, 128)
|
||||
const initialTrackerMixerflags = audio.getTrackerMixerFlags(PLAYHEAD)
|
||||
//const initialGlobalVolume =
|
||||
//const initialMixingVolume =
|
||||
const initialGlobalVolume = audio.getSongGlobalVolume(PLAYHEAD)
|
||||
const initialMixingVolume = audio.getSongMixingVolume(PLAYHEAD)
|
||||
|
||||
function isExternalPanel(p) {
|
||||
return p === VIEW_SAMPLES || p === VIEW_INSTRMNT || p === VIEW_FILE
|
||||
|
||||
@@ -109,8 +109,8 @@ function uploadTaudFile(inFile, songIndex, playhead) {
|
||||
let bpmStored = sys.peek(filePtr + entryOff + 7) & 0xFF
|
||||
let tickRate = sys.peek(filePtr + entryOff + 8) & 0xFF
|
||||
let mixerflags = sys.peek(filePtr + entryOff + 15) & 0xFF
|
||||
let songGlobalVolume = sys.peek(filePtr + entryOff + 16) & 0xFF // TODO use it
|
||||
let songMixingVolume = sys.peek(filePtr + entryOff + 17) & 0xFF // TODO use it
|
||||
let songGlobalVolume = sys.peek(filePtr + entryOff + 16) & 0xFF
|
||||
let songMixingVolume = sys.peek(filePtr + entryOff + 17) & 0xFF
|
||||
let patBinCompSize = _peekU32LE(filePtr, entryOff + 18)
|
||||
let cueSheetCompSize = _peekU32LE(filePtr, entryOff + 22)
|
||||
|
||||
@@ -148,6 +148,8 @@ function uploadTaudFile(inFile, songIndex, playhead) {
|
||||
audio.setBPM(playhead, bpm)
|
||||
audio.setTickRate(playhead, tickRate > 0 ? tickRate : 6)
|
||||
audio.setTrackerMixerFlags(playhead, mixerflags)
|
||||
audio.setSongGlobalVolume(playhead, songGlobalVolume)
|
||||
audio.setSongMixingVolume(playhead, songMixingVolume)
|
||||
|
||||
|
||||
fileHandle.close()
|
||||
@@ -196,10 +198,14 @@ function captureTrackerDataToFile(outFile) {
|
||||
let numPats = numPatsActual // Uint16, 1-65535
|
||||
let patsToSave = numPatsActual
|
||||
|
||||
// -- 3. BPM / tick-rate from playhead 0 -----------------------------------
|
||||
// -- 3. BPM / tick-rate / volumes from playhead 0 -------------------------
|
||||
let bpm = audio.getBPM(0) || 125
|
||||
let tickRate = audio.getTickRate(0) || 6
|
||||
let bpmStored = (bpm - 24) & 0xFF
|
||||
let songGlobalVolume = audio.getSongGlobalVolume(0)
|
||||
let songMixingVolume = audio.getSongMixingVolume(0)
|
||||
if (songGlobalVolume === undefined || songGlobalVolume === null) songGlobalVolume = 0x80
|
||||
if (songMixingVolume === undefined || songMixingVolume === null) songMixingVolume = 0x80
|
||||
|
||||
// -- 4. Compress pattern bin ----------------------------------------------
|
||||
let patBinSize = patsToSave * PATTERN_SIZE
|
||||
@@ -262,8 +268,8 @@ function captureTrackerDataToFile(outFile) {
|
||||
0x00,0xA0, // basenote (0xA000 -- C9)
|
||||
0x00,0xAC,0x02,0x46, // basefreq (8363 Hz)
|
||||
sys.peek(baseAddr - 7), // mixer flags
|
||||
0x80, // global volume (default)
|
||||
0x80, // mixing volume (default)
|
||||
songGlobalVolume & 0xFF, // global volume
|
||||
songMixingVolume & 0xFF, // mixing volume
|
||||
// pattern bin compressed size (4)
|
||||
(patCompSize ) & 0xFF,
|
||||
(patCompSize >>> 8) & 0xFF,
|
||||
|
||||
@@ -1742,6 +1742,9 @@ def assemble_taud(h: ITHeader, samples: list, instruments: list,
|
||||
|
||||
# flags byte: bit 1 (f) = Amiga pitch-slide mode (IT linear_slides flag inverted)
|
||||
flags_byte = 0x00 if h.linear_slides else 0x02
|
||||
# IT global/mix volumes are 0..128; rescale to Taud's 0..255 (clamped).
|
||||
global_vol_taud = min(0xFF, round(h.global_vol * 255 / 128))
|
||||
mixing_vol_taud = min(0xFF, round(h.mix_vol * 255 / 128))
|
||||
song_table = encode_song_entry(
|
||||
song_offset=song_offset,
|
||||
num_voices=C,
|
||||
@@ -1753,6 +1756,8 @@ def assemble_taud(h: ITHeader, samples: list, instruments: list,
|
||||
flags_byte=flags_byte,
|
||||
pat_bin_comp_size=len(pat_comp),
|
||||
cue_sheet_comp_size=len(cue_comp),
|
||||
global_vol=global_vol_taud,
|
||||
mixing_vol=mixing_vol_taud,
|
||||
)
|
||||
assert len(song_table) == TAUD_SONG_ENTRY
|
||||
|
||||
|
||||
@@ -770,6 +770,8 @@ def assemble_taud(mod: dict) -> bytes:
|
||||
flags_byte=flags_byte,
|
||||
pat_bin_comp_size=len(pat_comp),
|
||||
cue_sheet_comp_size=len(cue_comp),
|
||||
global_vol=0xFF,
|
||||
mixing_vol=0xFF,
|
||||
)
|
||||
assert len(song_table) == TAUD_SONG_ENTRY
|
||||
|
||||
|
||||
@@ -843,6 +843,8 @@ def assemble_taud(h: S3MHeader, instruments: list, patterns: list) -> bytes:
|
||||
flags_byte=flags_byte,
|
||||
pat_bin_comp_size=len(pat_comp),
|
||||
cue_sheet_comp_size=len(cue_comp),
|
||||
global_vol=0xFF,
|
||||
mixing_vol=0xFF,
|
||||
)
|
||||
assert len(song_table) == TAUD_SONG_ENTRY
|
||||
|
||||
|
||||
@@ -139,6 +139,12 @@ class AudioJSR223Delegate(private val vm: VM) {
|
||||
return getFirstSnd()?.playheads?.get(playhead)?.initialGlobalFlags
|
||||
}
|
||||
|
||||
fun setSongGlobalVolume(playhead: Int, volume: Int) { getPlayhead(playhead)?.globalVolume = volume and 255 }
|
||||
fun getSongGlobalVolume(playhead: Int) = getPlayhead(playhead)?.globalVolume
|
||||
|
||||
fun setSongMixingVolume(playhead: Int, volume: Int) { getPlayhead(playhead)?.mixingVolume = volume and 255 }
|
||||
fun getSongMixingVolume(playhead: Int) = getPlayhead(playhead)?.mixingVolume
|
||||
|
||||
fun putPcmDataByPtr(playhead: Int, ptr: Int, length: Int, destOffset: Int) {
|
||||
getFirstSnd()?.let {
|
||||
val vkMult = if (ptr >= 0) 1 else -1
|
||||
|
||||
@@ -2279,6 +2279,7 @@ class AudioAdapter(val vm: VM) : PeriBase(VM.PERITYPE_SOUND) {
|
||||
var mixL = 0.0
|
||||
var mixR = 0.0
|
||||
val gvol = playhead.globalVolume / 255.0
|
||||
val mvol = playhead.mixingVolume / 255.0
|
||||
for (voice in ts.voices) {
|
||||
if (!voice.active || voice.muted) continue
|
||||
val voiceInst = instruments[voice.instrumentId]
|
||||
@@ -2289,7 +2290,7 @@ class AudioAdapter(val vm: VM) : PeriBase(VM.PERITYPE_SOUND) {
|
||||
// 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 *
|
||||
swingScale * gvol * instGv * playhead.masterVolume / 255.0
|
||||
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)
|
||||
(voice.channelPan + envPanRaw - 128 + voice.randomPanBias).coerceIn(0, 255)
|
||||
@@ -2319,7 +2320,7 @@ class AudioAdapter(val vm: VM) : PeriBase(VM.PERITYPE_SOUND) {
|
||||
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 *
|
||||
swingScale * gvol * instGv * playhead.masterVolume / 255.0
|
||||
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)
|
||||
(bg.channelPan + envPanRaw - 128 + bg.randomPanBias).coerceIn(0, 255)
|
||||
@@ -2703,6 +2704,7 @@ class AudioAdapter(val vm: VM) : PeriBase(VM.PERITYPE_SOUND) {
|
||||
var patBank1: Int = 0,
|
||||
var patBank2: Int = 0,
|
||||
var globalVolume: Int = 0x80, // 8-bit, default $80 (spec §5). Mutated by V $xx00.
|
||||
var mixingVolume: Int = 0x80, // 8-bit, default $80 (spec §5). Final-mix scaler, set once per song.
|
||||
|
||||
var pcmQueue: Queue<ByteArray> = Queue<ByteArray>(),
|
||||
var pcmQueueSizeIndex: Int = 0,
|
||||
@@ -2794,6 +2796,7 @@ class AudioAdapter(val vm: VM) : PeriBase(VM.PERITYPE_SOUND) {
|
||||
bpm = 125
|
||||
tickRate = 6
|
||||
globalVolume = 0x80
|
||||
mixingVolume = 0x80
|
||||
trackerState?.let { ts ->
|
||||
ts.cuePos = 0; ts.rowIndex = 0; ts.tickInRow = 0
|
||||
ts.samplesIntoTick = 0.0; ts.firstRow = true
|
||||
|
||||
Reference in New Issue
Block a user