mirror of
https://github.com/jkdansereau/goldeneye-pc-port.git
synced 2026-10-23 15:52:42 +02:00
port(audio): D202 M-67-M-69 runtime probes — GE_VOICEDUMP, [VOICEMAP], timestamped [WIRE]/[EVT]/[STOP-EVT]
Env-gated diagnostics for the D202 per-voice sample-correctness work (M-67/M-68/M-69), all inert unless the env var is set: - GE_VOICEDUMP (mixer.c aEnvMixerImpl): per-voice resampled mono stream to voicedump.raw, records [stateAddr][nSamples][us][s16 x n]. NB the us stamp is mix time — records render ahead, samples END at the stamp. - [VOICEMAP] (synthesizer.c, under GE_AUDIOTRACE): full PVoice -> decoder/resampler/env-state address map at synth init, tying voicedump slot addresses to WIRE filter addresses. - [WIRE] (load.c) now carries a µs timestamp; sndPlaySfx trace gains t=µs + wavetable pointer. - [EVT]/[STOP-EVT] (snd.c): every ALSndpEvent the player processes, plus the release ramp a STOP/DEACTIVATE computes (deltaUs). - audiodebug.ps1: -VoiceDump switch. With scratchpad/exact_match.py these prove every allocated voice plays the exact ROM sample at the exact ROM pitch (286/320 CC >= 0.85 on the M-69 full-corpus run; remaining failures are dropped allocations + wire attribution, not corruption). Remove once D202 closes.
This commit is contained in:
1 parent
9b31f864d3
commit
4ceb917ad8
5 files changed
+85
-4
No files matched your search
@@ -28,6 +28,7 @@
|
||||
|
||||
#include <PR/abi.h>
|
||||
#include <PR/os.h>
|
||||
#include "system.h"
|
||||
|
||||
/* D202 diag (temporary): per-opcode DMEM address/context trace, gated by
|
||||
* GE_MIXERTRACE=1, to test the M-56 "concurrent voices share/clobber DMEM
|
||||
@@ -407,6 +408,16 @@ void aSetVolumeImpl(u32 flags, u16 v, u16 t, u16 r)
|
||||
}
|
||||
}
|
||||
|
||||
/* D202/M-67 diag (temporary): GE_VOICEDUMP=1 writes each voice's resampled
|
||||
* mono stream (the aEnvMixer input, i.e. post-resample/pre-envelope) to
|
||||
* voicedump.raw as records of [u32 stateAddr][u32 nSamples][u64 us]
|
||||
* [s16 x nSamples], where us is sysGetMicroseconds() at mix time so records
|
||||
* can be correlated with the timestamped [WIRE] (load.c) and [AUDIOTRACE]
|
||||
* (snd.c) lines. Offline, each record is matched against all 261 ROM SFX
|
||||
* decodes (pitch-resampled per keymap) to prove exactly which sample data a
|
||||
* voice played, with no music/reverb masking. Remove once D202 closes. */
|
||||
static FILE *s_voiceDumpFile = NULL;
|
||||
|
||||
void aEnvMixerImpl(u32 flags, u32 stateAddr)
|
||||
{
|
||||
struct {
|
||||
@@ -420,6 +431,19 @@ void aEnvMixerImpl(u32 flags, u32 stateAddr)
|
||||
MTRACE("[ENVMIX] flags=%u state=%p in=%u out=%u dryR=%u wetL=%u wetR=%u count=%u\n",
|
||||
flags, (void *)saved, sCtx.in, sCtx.out, sCtx.dryR, sCtx.wetL, sCtx.wetR, sCtx.count);
|
||||
const s16 *in = DMEM_S16(sCtx.in);
|
||||
|
||||
if (getenv("GE_VOICEDUMP")) {
|
||||
if (!s_voiceDumpFile)
|
||||
s_voiceDumpFile = fopen("voicedump.raw", "wb");
|
||||
if (s_voiceDumpFile) {
|
||||
u32 hdr[2] = { stateAddr, (u32)(sCtx.count >> 1) };
|
||||
u64 us = sysGetMicroseconds();
|
||||
fwrite(hdr, 4, 2, s_voiceDumpFile);
|
||||
fwrite(&us, 8, 1, s_voiceDumpFile);
|
||||
fwrite(in, sizeof(s16), sCtx.count >> 1, s_voiceDumpFile);
|
||||
}
|
||||
}
|
||||
|
||||
s16 *dry[2] = { DMEM_S16(sCtx.out), DMEM_S16(sCtx.dryR) };
|
||||
s16 *wet[2] = { DMEM_S16(sCtx.wetL), DMEM_S16(sCtx.wetR) };
|
||||
u32 nsamples = sCtx.count >> 1;
|
||||
|
||||
@@ -394,8 +394,10 @@ alLoadParam(void *filter, s32 paramID, void *param)
|
||||
#if defined(__x86_64__)
|
||||
if (getenv("GE_AUDIOTRACE")) {
|
||||
static FILE *tf = NULL;
|
||||
extern uint64_t sysGetMicroseconds(void); /* port/src/system.c */
|
||||
if (!tf) { tf = fopen("audiotrace_wire.log", "a"); if (tf) setvbuf(tf, NULL, _IONBF, 0); }
|
||||
if (tf) fprintf(tf, "[WIRE] filter=%p <- table=%p base=%p len=%d book=%p\n",
|
||||
if (tf) fprintf(tf, "[WIRE] t=%llu filter=%p <- table=%p base=%p len=%d book=%p\n",
|
||||
(unsigned long long)sysGetMicroseconds(),
|
||||
(void *)a, (void *)a->table, (void *)a->table->base,
|
||||
a->table->len,
|
||||
(a->table->type == AL_ADPCM_WAVE) ? (void *)a->table->waveInfo.adpcmWave.book : NULL);
|
||||
|
||||
@@ -20,6 +20,10 @@
|
||||
|
||||
#include "synthInternals.h"
|
||||
#include "include/assert.h"
|
||||
#if defined(__x86_64__)
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#ifdef AUD_PROFILE
|
||||
#include <os.h>
|
||||
@@ -117,6 +121,24 @@ void alSynNew(ALSynth *drvr, ALSynConfig *c)
|
||||
alAuxBusParam(drvr->auxBus, AL_FILTER_ADD_SOURCE, &pv->envmixer);
|
||||
|
||||
pv->channelKnob = (ALFilter *)&pv->envmixer;
|
||||
|
||||
#if defined(__x86_64__)
|
||||
/* D202/M-69 diag (temporary): GE_AUDIOTRACE=1 logs the full
|
||||
* PVoice -> decoder/resampler/env-state address map at synth init,
|
||||
* so offline voicedump slot addresses can be tied to WIRE filter
|
||||
* addresses (and hence to wave tables / sound indices). */
|
||||
if (getenv("GE_AUDIOTRACE")) {
|
||||
static FILE *mf = NULL;
|
||||
if (!mf) { mf = fopen("audiotrace_wire.log", "a"); if (mf) setvbuf(mf, NULL, _IONBF, 0); }
|
||||
if (i == 0)
|
||||
fprintf(mf, "[VOICEMAP] sizes pv=%u dec=%u res=%u env=%u\n",
|
||||
(unsigned)sizeof(PVoice), (unsigned)sizeof(ALLoadFilter),
|
||||
(unsigned)sizeof(ALResampler), (unsigned)sizeof(ALEnvMixer));
|
||||
if (mf) fprintf(mf, "[VOICEMAP] i=%d pv=%p dec=%p res=%p envstate=%p\n",
|
||||
i, (void *)pv, (void *)&pv->decoder,
|
||||
(void *)&pv->resampler, (void *)pv->envmixer.state);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
alSaveParam(save, AL_FILTER_SET_SOURCE, drvr->mainBus);
|
||||
|
||||
@@ -292,6 +292,19 @@ void sndHandleEvent(ALSndPlayer *sndp, ALSndpEvent *event) {
|
||||
|
||||
soundState = event->common.state;
|
||||
sound = soundState->sound;
|
||||
#ifdef PORT
|
||||
/* D202/M-67 diag (temporary): log every event the player processes,
|
||||
* so each VOICE- can be attributed to the exact killing event.
|
||||
* Remove once root-caused. */
|
||||
if (getenv("GE_AUDIOTRACE")) {
|
||||
static FILE *fe = NULL;
|
||||
extern uint64_t sysGetMicroseconds(void);
|
||||
if (!fe) { fe = fopen("audiotrace.log", "a"); if (fe) setvbuf(fe, NULL, _IONBF, 0); }
|
||||
if (fe) fprintf(fe, "[EVT] t=%llu type=%d state=%p\n",
|
||||
(unsigned long long)sysGetMicroseconds(),
|
||||
(int)event->common.type, (void *)soundState);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (sound == NULL) {
|
||||
s16 numFree, numAlloc;
|
||||
@@ -486,6 +499,18 @@ void sndHandleEvent(ALSndPlayer *sndp, ALSndpEvent *event) {
|
||||
case SOUND_STATE_PLAYING:
|
||||
sndRemoveEvents(&sndp->evtq, soundState, AL_SNDP_DECAY_EVT);
|
||||
delta = sound->envelope->releaseTime / soundState->pitch_28 / soundState->pitch_2c;
|
||||
#ifdef PORT
|
||||
/* D202/M-67 diag (temporary): log the release ramp a
|
||||
* STOP/DEACTIVATE computes; delta==0 means the voice
|
||||
* is disposed immediately. Remove once root-caused. */
|
||||
if (getenv("GE_AUDIOTRACE")) {
|
||||
static FILE *fs = NULL;
|
||||
if (!fs) { fs = fopen("audiotrace.log", "a"); if (fs) setvbuf(fs, NULL, _IONBF, 0); }
|
||||
if (fs) fprintf(fs, "[STOP-EVT] type=%d state=%p playingState=%d deltaUs=%d\n",
|
||||
(int)event->common.type, (void *)soundState,
|
||||
(int)soundState->playingState, (int)delta);
|
||||
}
|
||||
#endif
|
||||
alSynSetVol(sndp->drvr, &soundState->voice, 0, delta);
|
||||
if (delta != 0) {
|
||||
spAC.common.type = AL_SNDP_END_EVT;
|
||||
@@ -1059,16 +1084,22 @@ ALSoundState *sndPlaySfx(struct ALBankAlt_s *soundBank, s16 soundIndex, ALSoundS
|
||||
(int)sound->envelope->releaseTime,
|
||||
(unsigned)sound->envelope->attackVolume,
|
||||
(unsigned)sound->envelope->decayVolume);
|
||||
if (f2) fprintf(f2, "[AUDIOTRACE] sndPlaySfx: soundIndex=%d -> newState=%p flags=%d "
|
||||
if (f2) {
|
||||
extern uint64_t sysGetMicroseconds(void);
|
||||
fprintf(f2, "[AUDIOTRACE] sndPlaySfx: t=%llu soundIndex=%d -> newState=%p wavetable=%p flags=%d "
|
||||
"keyMap=%p velMin(next)=%d velMax(period)=%d keyMin=0x%02x keyMax=0x%02x "
|
||||
"keyBase=%d detune=%d retrig=%d deltaLoopUs=%d\n",
|
||||
(int)soundIndex, (void *)newState, newState ? (int)newState->unk3e : -1,
|
||||
(unsigned long long)sysGetMicroseconds(),
|
||||
(int)soundIndex, (void *)newState,
|
||||
(void *)(sound ? sound->wavetable : NULL),
|
||||
newState ? (int)newState->unk3e : -1,
|
||||
(void *)kmp,
|
||||
kmp ? (int)kmp->velocityMin : -1, kmp ? (int)kmp->velocityMax : -1,
|
||||
kmp ? (unsigned)kmp->keyMin : 0u, kmp ? (unsigned)kmp->keyMax : 0u,
|
||||
kmp ? (int)kmp->keyBase : -1, kmp ? (int)kmp->detune : -1,
|
||||
(newState && (newState->unk3e & 0x10)) ? 1 : 0,
|
||||
kmp ? (int)(kmp->velocityMax * DELTA_33_MS) : -1);
|
||||
}
|
||||
/* D202/M-65: only 8 voices exist (MUSIC_SFX_SEQ_MAYBE_MAX_SOUNDS).
|
||||
* A SOUND_FLAG_LOOPED voice never self-releases and is skipped by
|
||||
* the preemption scan, so each leaked one permanently costs a
|
||||
|
||||
@@ -45,8 +45,9 @@ param(
|
||||
[int]$FireEvery = 45, # frames between pulses (45 = 0.75 s @60)
|
||||
|
||||
# Probes
|
||||
[switch]$Trace, # GE_AUDIOTRACE=1 -> audiotrace.log
|
||||
[switch]$Trace, # GE_AUDIOTRACE=1 -> audiotrace.log (+ _wire.log)
|
||||
[switch]$Dump, # GE_AUDIODUMP=1 -> audiodump.raw
|
||||
[switch]$VoiceDump, # GE_VOICEDUMP=1 -> voicedump.raw (per-voice, D202/M-67)
|
||||
[switch]$MixerTrace, # GE_MIXERTRACE=1 -- SLOW, see warning below
|
||||
[switch]$Old, # GE_D204_OLD=1: pre-D204 behaviour
|
||||
[switch]$AB, # run twice (old, then new) and compare
|
||||
@@ -132,6 +133,7 @@ function Invoke-AudioRun {
|
||||
if ($OldMode) { $env:GE_D204_OLD = "1" } else { Remove-Item -EA SilentlyContinue Env:\GE_D204_OLD }
|
||||
if ($Trace) { $env:GE_AUDIOTRACE = "1" } else { Remove-Item -EA SilentlyContinue Env:\GE_AUDIOTRACE }
|
||||
if ($Dump) { $env:GE_AUDIODUMP = "1" } else { Remove-Item -EA SilentlyContinue Env:\GE_AUDIODUMP }
|
||||
if ($VoiceDump) { $env:GE_VOICEDUMP = "1" } else { Remove-Item -EA SilentlyContinue Env:\GE_VOICEDUMP }
|
||||
if ($MixerTrace) { $env:GE_MIXERTRACE = "1" } else { Remove-Item -EA SilentlyContinue Env:\GE_MIXERTRACE }
|
||||
if ($inputScript) { $env:GE_INPUTSCRIPT = $inputScript } else { Remove-Item -EA SilentlyContinue Env:\GE_INPUTSCRIPT }
|
||||
|
||||
|
||||
Reference in new issue
Block a user