forked from Ports/goldeneye-pc-port
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
@@ -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
|
||||
|
||||
Reference in new issue
Block a user