18 users online:  Alex, Alice3173, Banddy, Blizzard Buffalo, crocodileman94, drollpro, Elie Barnes, fathy2001, GiraffeKiller, Hayashi Neru, Heraga, issun, Lady Rozeldix, Nextalis, Rykon-V73, Samie Zuccati, Soul, WhiteYoshiEgg - Guests: 88 - Bots: 181
Users: 55,592 (2,459 active)
Latest user: giovannemendes

SPC Echo and FIR filter flowchart documentation (Is it correct?)

After studying SNES docs, Anomie's docs, and Higan/Game-Music-Emu source code for days, I wrote up a flowchart for the structure of the SNES echo and FIR filter system. Can anyone verify that it's correct? Especially the FIR filter part?

Note that _echoPointer, echoOffset, echoHistory, and calculateFir are references to Higan source code. EON is a flag (bits), EFB, EDL, and ESA are mono, and MVOL and EVOL are stereo registers.

EDIT: Note that ECEN flag must be enabled in order to write to the echo buffer.

Source material:

Nintendo docs:
Anomie docs:
Higan source:
I reposted this thread in SNESDEV . As far as I can tell, this diagram is correct.

EDIT: Note that ECEN flag must be enabled in order to write to the echo buffer.
Seems correct.

Obviously now with that information you can do other math to specify what kind of echo you can produce with the values. Keep in mind that, at least in N-SPC standards, only echo left/right volume can be smoothly slided, while the others are just constant values. I believe applying periodic functions to the other values can generate interesting results, including the FIR filter.
GitHub - Twitter - YouTube - SnesLab Discord
I'm not working on AMK/NSPC porting (the current workflow is too low-level, "hard-coded", and "messy"). This is more to develop a VST.

So just to make sure, the FIR filter coefficients correspond to the oldest to newest echo history?
since the "default FIR" (in other words no echo output change) is 7F 00 00 00 00 00 00 00, I bet FIR 0 is newest and FIR 7 is oldest.
GitHub - Twitter - YouTube - SnesLab Discord
Higan uses a fixed-size ring buffer, where the elements are read from old to new, then the old is overwritten. People in the Snesdev thread claim that the real SNES uses a shift register.

If this is correct, this introduces an unexpected 7-sample delay in the echo.


EDIT: On the other hand, I finished my own echo implementation, and "without 7-sample delay" sounds better in FF6. Though they're all pretty bad.

I managed to get one perfect run out of my filter, I even recorded it. I've never been able to replicate it again.

(I don't have a real FIR filter, just a 7-sample delay.)


EDIT: I just realized another problem: If the FIR filter adds an extra delay, SNES FIR filter runs at 32000hz and delays for 7/32000th of a second. My JACK server runs at 48000hz and delays for 7/48000th of a second, potentially resulting in an audible difference.

Oh well, time to get out AMK and create some test SPCs...


EDIT: I found the damn bug. My "echo buffer size" slider puts out values with slight floating-point rounding errors, and the int() function rounded "5 blocks" to "4 blocks", destroying the sound.

Also, I can confirm that "default FIR = 7-sample delay" is probably accurate (it sounds closer to the real thing). Although after the struggles I've been through, I'm still doubting everything.