There's something I've never understood about audio interpolation.
https://github.com/snes9xgit/snes9x/blo ... #L429-L512
- Gaussian operates on next 4 incoming samples? Like it knows what the future looks like and is able to pre-act on it?
- And Sinc works on next 8 upcoming inputs?
https://github.com/snes9xgit/snes9x/blo ... #L652-L707
- Assuming the above is true and the brr decoder only works on 4 at a time .. does the filter ever get into a situation where it's working with "stale" data?
https://snes.nesdev.org/wiki/BRR_samples
0 1 2 3 .. 12 13 14 15 - AA BB CC DD EE FF GG HH
When the ptr is at 12-15, are the next AA-DD bytes ready or are they still unknown? Because if Gaussian is at 13 and AA isn't ready, then it's reusing some old value?
And if Sinc uses 8 points, wouldn't that be "crap" data for a few more outputs? I'm just guessing that Gaussian has enough time to do things on-demand and not prepare farther ahead for another 4 bytes, which would appear to affect Sinc ..
Honestly I'm thinking there's some nitty cycle timing that I'm overlooking, because I didn't fully follow the phase timing table.
Thanks anyone!
Snes9x DSP interpolation
Moderator: Moderators
Forum rules
- For making cartridges of your Super NES games, see Reproduction.
- jeffythedragonslayer
- Posts: 344
- Joined: Thu Dec 09, 2021 12:29 pm
Re: Snes9x DSP interpolation
I don't use snes9x that much, but that's quite a few lines of code you've selected after the hyperlink anchors. Can you elaborate on why the code makes you think Gaussian and sinc are looking into the future?
Re: Snes9x DSP interpolation
Code: Select all
int const* in = &v->buf [(v->interp_pos >> 12) + v->buf_pos];
out = filt [0] * in [0];
out += filt [1] * in [1];
..
out += filt [7] * in [7];
out >>= 14;
CLAMP16( out );
return out;
inline VOICE_CLOCK( V4 ) = decode brr
interp_pos >> 12 removes 2048 pitch fractional + buf_pos = current playback sample ?
in[7] = Sinc. buf_pos + 7 = seven bytes after buf_pos sample?
in[3] = Gaussian stops here.
Code: Select all
// Make pointers into gaussian based on fractional position between samples
int offset = v->interp_pos >> 4 & 0xFF;
short const* fwd = gauss + 255 - offset;
short const* rev = gauss + offset; // mirror left half of gaussian
out = (fwd [ 0] * in [0]) >> 11;
out += (fwd [256] * in [1]) >> 11;
out += (rev [256] * in [2]) >> 11;
out = (int16_t) out;
out += (rev [ 0] * in [3]) >> 11;
CLAMP16( out );
out &= ~1;
EDIT:
Didn't know about Mesen2, which is easier to understand
https://github.com/SourMesen/Mesen2/blo ... polation.h
https://github.com/SourMesen/Mesen2/blo ... pVoice.cpp
12-byte circular buffer
_interpolationPos = 0x0000 - 0x7fff
bufferPos = 0 or 4
If _interpolationPos >= 0x4000, decodes next 4 BRR bytes. But if _interpolationPos == 0x3000, then
Code: Select all
cubic:
uint8_t pos = (interpolationPos >> 12) + bufferPos;
float v0 = samples[pos % 12] / 32768.0f;
float v1 = samples[(pos + 1) % 12] / 32768.0f;
float v2 = samples[(pos + 2) % 12] / 32768.0f;
float v3 = samples[(pos + 3) % 12] / 32768.0f;
-
- Posts: 3140
- Joined: Wed May 19, 2010 6:12 pm
Re: Snes9x DSP interpolation
It doesn't actually predict the future, the filtered signal just comes out slightly delayed.