Emulator Issues #3573
closedAudioDMA plays old samples/more samples than supposed to
0%
Description
Some games with AX ucode use multiple audio DMA fragments for their ringbuffer, updating g_audioDMA.SourceAddress in the audio DMA interrupt handler. The DMA of a fragment happens while the data is filled into the given fragment.
There are two things that can go wrong here:
- The guest CPU gets too far behind audio DMA, so audio DMA reads old samples from the last run through the ringbuffer. This happens regularly with Metroid Prime at the title screen/main menu.
- The guest CPU is too slow to set SourceAddress in time. This happens with interpreter and Metroid Prime at the title screen/main menu. This results in about half of the last fragment already been DMAed before SourceAddress is set(and the transfer restarted).
Metroid Prime is not using the DSP at the title screen, but decodes/streams audio using guest CPU.
Other games affected by this are Sonic Unleashed, New Super Mario Bros, but only when using DSPLLE, which does not bypass the CPU like DSPHLE.
A workaround is to read the whole audio DMA fragment in one go at the end of the DMA transfer.
Defering scheduling of the audio DMA to when the guest CPU sets g_AudioDMA.Enable does not help.
Updated by mylek4 about 14 years ago
I've seen something similar happen with LLE in some games which introduces noise. It seems like sound gets pushed out to the backend while its buffer is still getting written to. I think I came up with something similar to the workaround you described:
void UpdateAudioDMA()
{
if (g_audioDMA.BlocksLeft)
{
g_audioDMA.ReadAddress += 32;
g_audioDMA.BlocksLeft--;
if (g_audioDMA.BlocksLeft == 0)
{
dsp_plugin->DSP_SendAIBuffer(g_audioDMA.SourceAddress, 8*g_audioDMA.AudioDMAControl.NumBlocks); // <------
Pushing the sound out all at once before generating the interrupt seems to fix it at the expense of delaying things ~96 samples. I can't say with certainty this doesn't have any negative side effects but I haven't seen any problems with it.
Updated by pierre about 14 years ago
- Status changed from New to Fixed
Fixed in r6582.
Unknown if that is how the hardware works, or if this just papers over a timing problem in core.