fix: MP2 not decoding

This commit is contained in:
minjaesong
2026-05-08 00:12:45 +09:00
parent 9017b76f6d
commit 6ce8d2cc1e
5 changed files with 28 additions and 18 deletions

View File

@@ -2340,6 +2340,7 @@ TODO:
linear-freq flag in the song-table flags byte. Spec details in
TAUD_NOTE_EFFECTS.md §1, §E, §F, §G.
[ ] milkytracker-style volume ramping (on sample-end only)
[ ] make Cues tab horizontally scrollable
Play Data: play data are series of tracker-like instructions, visualised as:

View File

@@ -12,6 +12,7 @@ import java.io.OutputStream
import java.nio.charset.Charset
import java.util.*
import java.util.concurrent.atomic.AtomicBoolean
import kotlin.math.absoluteValue
import kotlin.math.ceil
@@ -549,7 +550,7 @@ class VM(
// println("peek $addr -> ${offset}@${memspace?.javaClass?.canonicalName}")
return if (memspace == null)
throw NullPointerException()//null
throw OpenBusException(addr)//null
else if (memspace is UnsafePtr) {
if (addr >= memspace.size)
throw ErrorIllegalAccess(this, addr)
@@ -564,7 +565,7 @@ class VM(
val (memspace, offset) = translateAddr(addr)
return if (memspace == null)
throw NullPointerException()//null
throw OpenBusException(addr)//null
else if (memspace is UnsafePtr) {
if (addr >= memspace.size)
throw ErrorIllegalAccess(this, addr)
@@ -583,7 +584,7 @@ class VM(
val (memspace, offset) = translateAddr(addr)
return if (memspace == null)
throw NullPointerException()//null
throw OpenBusException(addr)//null
else if (memspace is UnsafePtr) {
if (addr >= memspace.size)
throw ErrorIllegalAccess(this, addr)
@@ -608,7 +609,7 @@ class VM(
val (memspace, offset) = translateAddr(addr)
return if (memspace == null)
throw NullPointerException()//null
throw OpenBusException(addr)//null
else if (memspace is UnsafePtr) {
if (addr >= memspace.size)
throw ErrorIllegalAccess(this, addr)
@@ -853,3 +854,10 @@ class PeripheralEntry2(
)
internal fun Int.kB() = this * 1024L
fun Long.memAddrToReadable() = "'${this}' (bank " + this.absoluteValue.minus(if (this < 0) 1 else 0).div(1048576) +
" offset " + this.absoluteValue.minus(if (this < 0) 1 else 0).mod(1048576) + ")"
class OpenBusException(addr: Long) : NullPointerException(
"Address ${addr.memAddrToReadable()} is open bus"
)

View File

@@ -425,7 +425,7 @@ class AudioAdapter(val vm: VM) : PeriBase(VM.PERITYPE_SOUND) {
private var mp2Context = mp2Env.initialise()
private fun decodeMp2() {
val periMmioBase = vm.findPeriSlotNum(this)!! * -786432 - 1L
val periMmioBase = vm.findPeriSlotNum(this)!! * -131072 - 1L
mp2Env.decodeFrameU8(mp2Context, periMmioBase - 2368, true, periMmioBase - 64)
}
@@ -2112,7 +2112,7 @@ class AudioAdapter(val vm: VM) : PeriBase(VM.PERITYPE_SOUND) {
1 -> amigaSlideOnce(voice.noteVal, -mag) // Amiga: subtract from pitch ⇒ adds period
2 -> linearFreqSlideOnce(voice.noteVal, -mag) // Hz/tick: pitch down ⇒ -Hz
else -> voice.noteVal - mag // linear 4096-TET
}.coerceIn(0, 0xFFFE)
}.coerceIn(1, 0xFFFD)
voice.basePitch = voice.noteVal
voice.amigaPeriod = -1.0 // reseed on next per-tick slide
voice.linearFreq = -1.0
@@ -2131,7 +2131,7 @@ class AudioAdapter(val vm: VM) : PeriBase(VM.PERITYPE_SOUND) {
1 -> amigaSlideOnce(voice.noteVal, mag)
2 -> linearFreqSlideOnce(voice.noteVal, mag)
else -> voice.noteVal + mag
}.coerceIn(0, 0xFFFE)
}.coerceIn(1, 0xFFFD)
voice.basePitch = voice.noteVal
voice.amigaPeriod = -1.0
voice.linearFreq = -1.0
@@ -2252,7 +2252,7 @@ class AudioAdapter(val vm: VM) : PeriBase(VM.PERITYPE_SOUND) {
when (sub) {
0x1 -> voice.glissandoOn = (x != 0)
0x2 -> {
voice.noteVal = (voice.noteVal + FINETUNE_OFFSET[x]).coerceIn(0, 0xFFFE)
voice.noteVal = (voice.noteVal + FINETUNE_OFFSET[x]).coerceIn(1, 0xFFFD)
voice.basePitch = voice.noteVal
voice.amigaPeriod = -1.0
voice.linearFreq = -1.0
@@ -2345,7 +2345,7 @@ class AudioAdapter(val vm: VM) : PeriBase(VM.PERITYPE_SOUND) {
1 -> amigaSlideTick(voice, voice.slideArg)
2 -> linearFreqSlideTick(voice, voice.slideArg)
else -> voice.noteVal + voice.slideArg
}.coerceIn(0, 0xFFFE)
}.coerceIn(1, 0xFFFD)
voice.basePitch = voice.noteVal
}
@@ -2367,7 +2367,7 @@ class AudioAdapter(val vm: VM) : PeriBase(VM.PERITYPE_SOUND) {
voice.noteVal = target
voice.tonePortaTarget = -1
} else {
voice.noteVal = freqHzToNoteVal(voice.linearFreq).coerceIn(0, 0xFFFE)
voice.noteVal = freqHzToNoteVal(voice.linearFreq).coerceIn(1, 0xFFFD)
}
voice.basePitch = voice.noteVal
voice.amigaPeriod = -1.0
@@ -2420,14 +2420,14 @@ class AudioAdapter(val vm: VM) : PeriBase(VM.PERITYPE_SOUND) {
if (voice.vibratoActive) {
val sine = lfoSample(voice.vibratoLfoPos, voice.vibratoWave)
val pitchDelta = (sine * voice.mem.huDepth) shr voice.vibratoFineShift
pitchToMixer = (voice.noteVal + pitchDelta).coerceIn(0, 0xFFFE)
pitchToMixer = (voice.noteVal + pitchDelta).coerceIn(1, 0xFFFD)
voice.vibratoLfoPos = (voice.vibratoLfoPos + voice.mem.huSpeed * 4) and 0xFF
}
// Glissando (S$1x) — snap pitchToMixer to nearest semitone but leave noteVal smooth.
if (voice.glissandoOn) {
val semis = ((pitchToMixer * 12 + 2048) / 4096)
pitchToMixer = (semis * 4096 / 12).coerceIn(0, 0xFFFE)
pitchToMixer = (semis * 4096 / 12).coerceIn(1, 0xFFFD)
}
// Tremolo (R) — modulates output volume around base.
@@ -2450,7 +2450,7 @@ class AudioAdapter(val vm: VM) : PeriBase(VM.PERITYPE_SOUND) {
if (voice.arpActive) {
val voiceIdx = ts.tickInRow % 3
val arpDelta = when (voiceIdx) { 1 -> voice.arpOff1 shl 8; 2 -> voice.arpOff2 shl 8; else -> 0 }
pitchToMixer = (voice.basePitch + arpDelta).coerceIn(0, 0xFFFE)
pitchToMixer = (voice.basePitch + arpDelta).coerceIn(1, 0xFFFD)
voice.lastArpVoice = voiceIdx
}
@@ -2487,7 +2487,7 @@ class AudioAdapter(val vm: VM) : PeriBase(VM.PERITYPE_SOUND) {
((voice.envPfValue - 0.5) * 2.0 * 16.0 * 4096.0 / 12.0).toInt()
else 0
val finalPitch = (pitchToMixer + autoVibDelta + pitchEnvDelta).coerceIn(0, 0xFFFE)
val finalPitch = (pitchToMixer + autoVibDelta + pitchEnvDelta).coerceIn(1, 0xFFFD)
voice.playbackRate = computePlaybackRate(inst, finalPitch)
// Filter envelope (filter mode): scale baseCut by envValue (0..1, 0.5 = unity).
@@ -2581,7 +2581,7 @@ class AudioAdapter(val vm: VM) : PeriBase(VM.PERITYPE_SOUND) {
val pitchEnvDelta = if (bg.hasPfEnv && bg.pfEnvOn && !bg.envPfIsFilter)
((bg.envPfValue - 0.5) * 2.0 * 16.0 * 4096.0 / 12.0).toInt()
else 0
val finalPitch = (bg.noteVal + autoVibDelta + pitchEnvDelta).coerceIn(0, 0xFFFE)
val finalPitch = (bg.noteVal + autoVibDelta + pitchEnvDelta).coerceIn(1, 0xFFFD)
bg.playbackRate = computePlaybackRate(inst, finalPitch)
// Filter-mode pf envelope: same scaling rule as foreground.
if (bg.hasPfEnv && bg.pfEnvOn && bg.envPfIsFilter) {

View File

@@ -43,6 +43,7 @@ package net.torvald.tsvm.peripheral
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.toUint
import net.torvald.tsvm.VM
import net.torvald.tsvm.memAddrToReadable
import java.util.*
import kotlin.collections.ArrayList
import kotlin.math.ceil
@@ -398,7 +399,7 @@ class MP2Env(val vm: VM) {
};
// check for valid header: syncword OK, MPEG-Audio Layer 2
if ((syspeek(mp2_frame!!) != 0xFF) || ((syspeek(mp2_frame!! + 1*incr) and 0xFE) != 0xFC)){
throw Error("Invalid MP2 header at $mp2_frame: ${syspeek(mp2_frame!!).toString(16)} ${syspeek(mp2_frame!! + 1*incr).toString(16)}")
throw Error("Invalid MP2 header at ${(mp2_frame as Long).memAddrToReadable()}: ${syspeek(mp2_frame!!).toString(16)} ${syspeek(mp2_frame!! + 1*incr).toString(16)}")
};
// set up the bitstream reader

View File

@@ -54,8 +54,8 @@ public class AppLoader {
ArrayList defaultPeripherals = new ArrayList();
defaultPeripherals.add(new Pair(3, new PeripheralEntry2("net.torvald.tsvm.peripheral.AudioAdapter", vm)));
defaultPeripherals.add(new Pair(4, new PeripheralEntry2("net.torvald.tsvm.peripheral.HostFileHSDPA", vm, "assets/diskMediabin/lnterz_013.mv2", "assets/diskMediabin/ba60d.mov", "", "", 999999999L)));
defaultPeripherals.add(new Pair(2, new PeripheralEntry2("net.torvald.tsvm.peripheral.AudioAdapter", vm)));
defaultPeripherals.add(new Pair(3, new PeripheralEntry2("net.torvald.tsvm.peripheral.HostFileHSDPA", vm, "assets/diskMediabin/lnterz_013.mv2", "assets/diskMediabin/ba60d.mov", "", "", 999999999L)));
EmulInstance reference = new EmulInstance(vm, "net.torvald.tsvm.peripheral.ReferenceGraphicsAdapter", diskPath, 560, 448, defaultPeripherals);