Project

General

Profile

Actions

Emulator Issues #7280

closed

Skies Of Arcadia Legends audio slightly detuned

Added by lunaboy0 about 10 years ago.

Status:
Fixed
Priority:
Normal
Assignee:
-
Category:
DSPHLE
% Done:

0%

Operating system:
N/A
Issue type:
Bug
Milestone:
Regression:
No
Relates to usability:
No
Relates to performance:
No
Easy:
No
Relates to maintainability:
No
Regression start:
Fixed in:

Description

Game Name?
Skies Of Arcadia Legends Pal

Game ID?
GEAP8P

What's the problem? Describe what went wrong in few words.
Music instruments are slightly detuned (can clearly be heard on Horteka island).
Since rev 9b7db5954f1a586373f726dc96ecebfd24b395f2 adpcm sample-loops are rounded to multiples of two samples, causing loop errors.

What did you expect to happen instead?
Dolphin should allow adpcm samples to loop per sample instead of per two samples to avoid detuning when very small sample-loops are used.

What steps will reproduce the problem?

  1. Open dolphin
  2. Set audioplugin to Dsp-HLE
  3. Launch Skies of Arcadia Pal
  4. Go to the island called Horteka (see attached GCI save state)
  5. Listen to the flute playing the melody of the music
  6. When the flute solo begins (music position 2:02 minutes) some notes of the flute instrument are detuned and others are not

Dolphin 3.5 and 3.5-367 are old versions of Dolphin that have known issues and bugs, so don't report issues about them and test the latest Dolphin version first.
Which versions of Dolphin did you test on?
The bug was introduced by rev 9b7db5954f1a586373f726dc96ecebfd24b395f2 (on Master, Mar 28, 2013)
Dolphin-master-3.5-1093-x86 is the first version that gives errors

Does using an older version of Dolphin solve your issue? If yes, which versions of Dolphin used to work?
Yes, revision 53377425d1dfdd3aeabb34b6a7aee833ae1d22af (on Master, the revision before rev 9b7db5954f1a586373f726dc96ecebfd24b395f2)
Dolphin-master-3.5-1091-x86 has correctly tuned instruments (Dolphin-master-3.5-1092-x86 was not available for download)

What are your PC specifications? (including, but not limited to: Operating System, CPU and GPU)
CPU: Intel I7 2600k 3.4 Ghz
GPU: Asus Geforce GTX 570 1280 MB DirectCU-II
RAM: 8 GB
OS: Windows 7 Professional 64 Bit

Are you using the 32 or the 64 bit version of Dolphin?
32-bit (64 bit version has the same errors)

Is there any other relevant information? (e.g. logs, screenshots, configuration files)

A ZIP file with audiologs and GCI savedata can be found here:
http://www7.zippyshare.com/v/94894611/file.html

In revision 9b7db5954f1a586373f726dc96ecebfd24b395f2, the sample-loops have been changed to be multiples of 2.
When Dolphin is decoding 16 bit samples, it uses byte pointers (with half-sample resolution).
For these 16 bit samples, the committed fix is a safety-fix and works correctly.

However, when Dolphin is decoding ADPCM samples, the loop offsets are nibble pointers addressing individual samples:
ADPCM: SampleNr = acc_cur_addr; // Per-sample addressing
PCM: SampleNr = acc_cur_addr / 2; // Per-half-sample addressing

For ADPCM samples each nibble is an unique sample. Forcing bit 0 of the
loop-pointers to zero, forces the loop-offsets to be multiples of 2 samples.
With this algorithm, using uneven loop-positions isn't possible.

Skies Of Arcadia Legends is using low-quality samples with very small sample-loops.
Because of these small loops, one sample more or less in the loop will slightly change the pitch.
The flute instrument in the Horteka song (which plays the main melody) has different samples
mapped to its note-range (for example: C1 - A3 = Sample1, A#3 - F#5 = Sample2, G5 - E7 = Sample3).
Since loops are forced to be multiples of two samples, Sample2 is slightly detuned while Sample3 is not.
This results in detuned notes when the melody passes a sample-boundary in the key-range of the instrument.

The fix: Keep the 'samplepos & ~1' operation for 16-bit samples, but remove it for ADPCM samples.

This bug is also present in the dc-netplay branch (some users need this branch to boot the game).
See issue 6705 - http://code.google.com/p/dolphin-emu/issues/detail?id=6705


Related issues 1 (0 open1 closed)

Has duplicate Emulator - Emulator Issues #6175: Skies of Arcadia Legends: LLE Interpreter Music out of tuneDuplicate

Actions
Actions #1

Updated by JMC4789 about 10 years ago

  • Category set to dsphle

Going to CC delroth on this one.

Actions #2

Updated by skidau about 10 years ago

lunaboy0, thanks for this investigation. Would you please submit a patch to https://github.com/dolphin-emu/dolphin/pulls with the suggested fix? I would guess we add a condition using acc_pb->audio_addr.sample_format to determine whether to compare with or without the ~1.

Actions #3

Updated by delroth about 10 years ago

Suggested fix sounds good to me, the explanation makes a lot of sense.

I think there was another bug open about SoA being out of pitch, can
someone confirm it's related and dedup?

Actions #4

Updated by lunaboy0 about 10 years ago

After taking a closer look at the sampledata reading code, it turns out that the loop pointers are always per-sample based, even for 16 bit samples.
When reading 16 bit samples, the read pointer is multiplied by two, so for 16-bit PCM audio it is guaranteed that ARAM reads are multiples of two bytes.
This means that forcing the lower bit of the loop pointers to zero will always force them to be multiples of two, regardless the sampleformat.

The multiple-of-two-bytes loop pointers commit looks like to be an attempt to fix the 1:32 hours audio-crackling bug (related to issue 6160).
Since this bug was caused by the mixercode and has nothing to do with instrument sampleloops, it looks like this commit didn't fix anything at all.
Revision a1822a3acaf112dd37ed98818acdc0bc5014caba is the real fix of the 1:32 hours audio-crackling bug.

As Delroth said, there is another bugreport (issue 6175) about pitch detuning, but that one is related to DspLLE, while my issue is related to DspHLE.
The pitch detuning of the Horteka instruments is also present in DspLLE.

I've been able to fix the Horteka instruments by replacing the line 'if ((Address & ~1) == (EndAddress & ~1))' with the original 'if (Address >= EndAddress)'.
Replacing this line in AXVoice.h fixes the detuning on DspHLE (this issue)
Replacing this line in DSPAccelerator.cpp fixes the detuning on DspLLE (issue 6175)

Beside Skies of Arcadia, I've also tested several other games (including games that uses PCM16 audio like MarioKart Double Dash and Super Mario Galaxy 2) and I didn't hear any loop errors.

It looks like it is safe to use the original end-of-loop check in both AXVoice.h and DSPAccelerator.cpp and get per-sample looping back.
Do you devs agree with me?

Actions #5

Updated by delroth about 10 years ago

  • Status changed from New to Work started

I agree with this analysis. If skidau thinks it's fine too, please create a pull request on https://github.com/dolphin-emu/dolphin and we'll get that merged.

Thanks!

Actions #6

Updated by delroth about 10 years ago

Issue 6175 has been merged into this issue.

Actions #7

Updated by skidau about 10 years ago

The ~1 is for the capcom music loop bug (Issue 3998). I am quite sure that >= is not correct, but == is. Using == might work now with the audio latency fix in place. i.e.

if (Address == EndAddress)

Issue 3998 is the one that needs to be retested. MKDD and SMG2 do not present the bug described in Issue 3998.

Actions #8

Updated by skidau about 10 years ago

Using "if (Address == EndAddress)", "FAST: Racing League" plays random sounds in the in-game music.

With "if (Address >= EndAddress)", the PN03 in-game music cuts out after playing through once.

Tested on Dolphin 4.0-1546.

Other games that this code affects are:

Resident Evil 3 (cutscenes)
Muramasa: The Demon Blade (high pitched squeal in scene transitions)

Actions #9

Updated by delroth about 10 years ago

Maybe it's time to start doing some proper RE of the accelerator with
hardware testing.

Actions #10

Updated by skidau almost 10 years ago

lunaboy0, would you please check if the Skies of Arcadia music instruments are in tune after applying this patch? The patch applies to Dolphin 4.0-2793. Also, would you please re-upload the gci save file somewhere? The link on zippyshare has expired.

==========================
diff --git a/Source/Core/Core/DSP/DSPAccelerator.cpp b/Source/Core/Core/DSP/DSPAccelerator.cpp
index c330d40..2dd1a2b 100644
--- a/Source/Core/Core/DSP/DSPAccelerator.cpp
+++ b/Source/Core/Core/DSP/DSPAccelerator.cpp
@@ -111,6 +111,7 @@ u16 dsp_read_accelerator()
const u32 EndAddress = (g_dsp.ifx_regs[DSP_ACEAH] << 16) | g_dsp.ifx_regs[DSP_ACEAL];
u32 Address = (g_dsp.ifx_regs[DSP_ACCAH] << 16) | g_dsp.ifx_regs[DSP_ACCAL];
u16 val;

  • u8 audio_size = 0;

    // let's do the "hardware" decode DSP_FORMAT is interesting - the Zelda
    // ucode seems to indicate that the bottom two bits specify the "read size"
    @@ -122,17 +123,20 @@ u16 dsp_read_accelerator()
    {
    case 0x00: // ADPCM audio
    val = ADPCM_Step(Address);

  •   	audio_size = 1;
      	break;
      case 0x0A:  // 16-bit PCM audio
      	val = (DSPHost::ReadHostMemory(Address*2) << 8) | DSPHost::ReadHostMemory(Address*2 + 1);
      	g_dsp.ifx_regs[DSP_YN2] = g_dsp.ifx_regs[DSP_YN1];
      	g_dsp.ifx_regs[DSP_YN1] = val;
    
  •   	audio_size = 1;
      	Address++;
      	break;
      case 0x19:  // 8-bit PCM audio
      	val = DSPHost::ReadHostMemory(Address) << 8;
      	g_dsp.ifx_regs[DSP_YN2] = g_dsp.ifx_regs[DSP_YN1];
      	g_dsp.ifx_regs[DSP_YN1] = val;
    
  •   	audio_size = 0;
      	Address++;
      	break;
      default:
    

@@ -151,7 +155,7 @@ u16 dsp_read_accelerator()
// Somehow, YN1 and YN2 must be initialized with their "loop" values,
// so yeah, it seems likely that we should raise an exception to let
// the DSP program do that, at least if DSP_FORMAT == 0x0A.

  • if ((Address & ~1) == (EndAddress & ~1))
  • if ((Address) == (EndAddress + audio_size))
    {
    // Set address back to start address.
    Address = (g_dsp.ifx_regs[DSP_ACSAH] << 16) | g_dsp.ifx_regs[DSP_ACSAL];
    diff --git a/Source/Core/Core/HW/DSPHLE/UCodes/AXVoice.h b/Source/Core/Core/HW/DSPHLE/UCodes/AXVoice.h
    index 73f20f4..c791f4c 100644
    --- a/Source/Core/Core/HW/DSPHLE/UCodes/AXVoice.h
    +++ b/Source/Core/Core/HW/DSPHLE/UCodes/AXVoice.h
    @@ -149,12 +149,16 @@ void AcceleratorSetup(PB_TYPE* pb, u32* cur_addr)
    u16 AcceleratorGetSample()
    {
    u16 ret;

  • u8 audio_size = 1;

  • if (acc_pb->audio_addr.sample_format == 0x19)

  •   audio_size = 0;
    

    // Have we reached the end address?
    //
    // On real hardware, this would raise an interrupt that is handled by the
    // UCode. We simulate what this interrupt does here.

  • if ((*acc_cur_addr & ~1) == (acc_end_addr & ~1))
  • if ((*acc_cur_addr) == (acc_end_addr + audio_size))
    {
    // loop back to loop_addr.
    *acc_cur_addr = acc_loop_addr;

==========================

Actions #11

Updated by skidau almost 10 years ago

  • Status changed from Work started to Fixed
Actions #13

Updated by lunaboy0 almost 10 years ago

Skidau,

Sorry for the late reaction, but Google was grouping conversation messages to one line in my inbox, causing new messages to slip through unnoticed.
When I read about this fix in the September progress report, I began testing immediately.

I've tested Horteka and several other places in Skies of Arcadia and I didn't hear any audio detuning.
Maybe it's not needed anymore, but here is a re-upload of the GCI save file on Zippyshare:
http://www41.zippyshare.com/v/37002723/file.html

Thank you for fixing this issue. Excellent work!

Actions #14

Updated by skidau almost 10 years ago

lunaboy0, would you please test this version and let me know if the instruments are in tune?

https://dl.dolphin-emu.org/prs/pr-1245-dolphin-latest-x64.7z

Actions

Also available in: Atom PDF