Another of those long-due fixes
The sound core is fixed, or mostly.


If you've been playing with melonDS, you may have noticed that effects like surround generally didn't work, and that whenever they worked, they resulted in crappy sound. Resetting or loading different games would also give different results.


So I've been addressing all that junk.


The randomness was easily fixed -- the write position for capture units wasn't being reset properly, so whenever the capture unit was started, it would start writing wherever it was previously left. Not really a good thing.


The rest was trickier though.


The DS sound controller provides 16 channels that can play a few types of audio, and 2 capture units that can capture sound output and write it to memory.

Several games provide different audio modes, typically headphones/stereo/surround. In those games, the audio output isn't directly sent to the speakers, but it is sent to the capture units. The game then alters it as it wishes, and two special channels (1 and 3) are used to send the final output to the speakers.

The mechanism is generally used for the aforementioned audio modes, but some games take it further -- Golden Sun: Dark Dawn goes as far as using it to play its sound effects.

While the mechanism (which we will name "surround setup") may sound simple, getting it to work is actually tricky.


It has been known for a while why it didn't work in melonDS: capture and channel 1/3 playback were done in the wrong order. However, putting them in the right order resulted in distorted, tinny sound. So I just kept it in the wrong order and ignored it.

Until now.

When you start a sound channel on the DS, it doesn't start playing immediately, there is a delay of a few samples. However, capture units start immediately.

The surround setup starts the capture units and their associated output channels at the same time, and gives them the same memory address. The idea is that, since channels are processed before capture units, the output channel reads sound data before the capture unit writes new data, and the distance is the largest possible, as to give the game enough time to apply effects to it.

However, the channel starts with a delay, which means it's lagging behind a little. In the case of melonDS, as the mixer processed 16 samples per run, the output channels would get bits of freshly captured data mixed in with the older data as a result of this. You guess how this goes.

Reducing the number of samples per run to 2 or 1 got rid of the audio distortion, but surround didn't work at all since the channels would only get freshly captured data.

Removing the channel start delay fixed the problem, but obviously it's not proper emulation.


The killer detail is that when the sound controller needs to access memory, it doesn't do so directly, but uses a buffering mechanism (FIFO) for each channel and capture unit. GBAtek mentions their existence, but... that's all.

The FIFOs need to be emulated for surround to work properly.

Which means that I had to do hardware tests to figure out how it works. There are probably still missing details.

Channel FIFOs can hold 8 words (32 bytes) of data. They are filled in chunks of 4 words when needed. An interesting detail is that when starting a channel, two chunks are buffered. Then it seems that a new chunk is buffered every time the FIFO runs less than half full.

Capture unit FIFOs are simple write buffers that hold 4 words. They are flushed to memory either when they're full of when the end of the capture length is reached (regardless of whether the capture loops).


So after implementing the whole FIFO thing, we can finally say that a bunch of sound issues are fixed! Surround works, sound effects in Golden Sun: Dark Dawn work too, some crackling that appeared in Rayman RR2 is gone, etc...
Saizo7 says:
Nov 11th 2017
Keep up the good work, SB! Really looking forward to improving the WiFi stability.
anonymous says:
Nov 13th 2017
Any chance you could upload a Windows build sometime? I've been banging my head against codeblocks and mingw problems for the last two hours.
poudink says:
Nov 13th 2017
There is already a bunch of them. You can download them in the "Downloads" section.
anonymous says:
Nov 14th 2017
Oh thank you, poudink! I'll just go download one of those ancient builds and totally not get any of the benefits of the fixes this post is about. What would I do without you?
AsPika2219 says:
Nov 15th 2017
Good job for fixing the sounds! Waiting for next version! :D
poudink says:
Nov 19th 2017
no need to get angry lol, I didn't know you were asking for this specific build
KostasGangstar says:
Nov 28th 2017
Are we getting a pokewalker addon for this emulator? this thing has no emulator as far as i know it would be a shame for this official hardware to not be emulated like the pocket pikachu consoles 1 & 2 addons in the game boy emulators
Wolfe says:
Nov 29th 2017
@anonymous, I won't upload a .exe because I don't expect people on the internet to trust a random nobody on the internet with a .exe download, but I can write instructions that will hopefully help with compiling from source.

1. Get and install Code::Blocks. I use the version without MinGW pre-included because I set up MinGW separately: http://sourceforge.net/projects/codeblocks/files/Binaries/16.01/Windows/codeblocks-16.01-setup.exe

2. Get MinGW-w64 (https://sourceforge.net/projects/mingw-w64/files/latest/download?source=files). In the installer, I picked Architecture: x86_64. When it asks you which folder to install to, I installed to "C:\MinGW-w64" for simplicity.

3. In Code::Blocks, at the top, go to Settings --> Compiler. In the "Compiler Flags" tab under "Compiler settings", check "Have g++ follow the C++11 ISO C++ language standard." Then go to the "Toolchain executables" tab. If you installed to "C:\MinGW-w64", it should look like this:

- Compiler's installation directory: C:\MinGW-w64\mingw64
- C compiler: x86_64-w64-mingw32-gcc.exe
- C++ compiler: x86_64-w64-mingw32-g++.exe
- Linker for dynamic libs: x86_64-w64-mingw32-g++.exe
- Linker for static libs: x86_64-w64-mingw32-gcc-ar.exe
- Debugger: leave on Default
- Resource compiler: windres.exe
- Make program: mingw32-make.exe

You can click "Auto-detect" once you've done this, to confirm that Code::Blocks recognizes everything properly. It should say "Auto-detected installation path of "GNU GCC Compiler" in "C:\MinGW-w64\mingw64" if you've got everything right.

4. At this point, if you try to compile, you will get "fatal error: SDL2\SDL.h: No such file or directory". melonDS requires SDL2 to compile, so you will want to download that: https://www.libsdl.org/release/SDL2-devel-2.0.7-mingw.tar.gz

To get Code::Blocks to recognize it, I extract the SDL2-2.0.7 folder to "C:\". Go back to Compiler settings, and under the "Search directories" tab, add "C:\SDL2-2.0.7\x86_64-w64-mingw32\include" and "C:\SDL2-2.0.7\x86_64-w64-mingw32\lib". At this point, Code::Blocks should appear to compile, but for me it complained about a "ld.exe cannot find -lSDL2" error. This is probably because MinGW can't find SDL2.dll, as I am only telling it to look at the "include" and "lib" directories, but I'm honestly not sure where to tell Code::Blocks to look at that folder as simply adding it to "Search directories" alongside "include" and "lib" didn't work.

I fix that one by copying the SDL2 files from the SDL2-2.0.7 folder I made earlier to my MinGW-w64 folders as per this process: http://wiki.codeblocks.org/index.php/Using_SDL_with_Code::Blocks#The_Process (ignore the first step, that's just a download to SDL1 and you already have SDL2 downloaded from earlier.) Seems redundant, as I'm already adding the folders to "Search directories", but that's the only way I've been able to get it to work.

5. If you get an error where Code::Blocks complains about strcpy not being declared in this scope (most likely in libui_sdl\DlgInputConfig.cpp), you can add #include <string.h> at the top of the file, with the other includes. This made things work for me, although it appears it may not always be required (or at least, I don't seem to be needing it anymore right now?)

That should hopefully work. Although one thing I'm really confused about is that, last night, Code::Blocks compiled a 721KB exe. Then I tried to compile again, without changing anything, and it wasn't working anymore, so I tweaked my settings and this time it compiled a 741KB exe. After doing this all over from scratch again I am now getting a 735KB exe. I don't know why I've been getting different results every time nor what the difference means, but they all appeared to work just fine regardless so hopefully it's not a problem.

Just keep in mind that Code::Blocks actually runs on unstable arcane magic behind the scenes, so if it's frustrating to work with and things aren't working when it feels like they should, that's probably the problem.
Wolfe says:
Nov 29th 2017
I *knew* I would be making a stupid mistake as I was writing this, and that I'd make myself look like an idiot since I can't go back and edit a comment on here after posting it.

At step 5, the mentioned error is about strncpy, not strcpy, and it comes from libui_sdl\main.cpp, not DlgInputconfig.cpp (I completely got the file wrong and basically I'm an idiot for not checking more thoroughly. I knew something was off, lol.)
If you add #include <string.h> in there it should work. I add it under the #include for <stdio.h>
swagmaster6969696969 says:
Dec 3rd 2017
I hope this emulator is released soon! Good luck! Is this gonna allow hacks to use online conection? Sorry for my bad inglish, Im from Brazil.
hyarsan says:
Dec 3rd 2017
connection* English* I'm*
You are welcome. Anyways, I am hyped!
anonymous says:
Dec 6th 2017
@Wolfe: Thanks, I was finally able to build it.
anonymous says:
Dec 6th 2017
...and I get no audio output on this latest version. :(
swagmaster6969696969 says:
Dec 7th 2017
But that doesn't anser my question!
StapleButter says:
Dec 8th 2017
Online connection is on the TODO list.
Post a comment
Name:
DO NOT FILL