Gauss Table Creation

Discussion of hardware and software development for Super NES and Super Famicom. See the SNESdev wiki for more information.

Moderator: Moderators

Forum rules
  • For making cartridges of your Super NES games, see Reproduction.
psycopathicteen
Posts: 3140
Joined: Wed May 19, 2010 6:12 pm

Re: Gauss Table Creation

Post by psycopathicteen »

Why is it that when I plug the equation into my TI-84 graphing calculator, some of the values differ slightly?
User avatar
Jarhmander
Formerly ~J-@D!~
Posts: 569
Joined: Sun Mar 12, 2006 12:36 am
Location: Rive nord de Montréal

Re: Gauss Table Creation

Post by Jarhmander »

Rounding? What the values look like?
((λ (x) (x x)) (λ (x) (x x)))
psycopathicteen
Posts: 3140
Joined: Wed May 19, 2010 6:12 pm

Re: Gauss Table Creation

Post by psycopathicteen »

Does anybody have a fourier transform of this? I feel like looking the FFT will explain a lot.
lidnariq
Posts: 11432
Joined: Sun Apr 13, 2008 11:12 am

Re: Gauss Table Creation

Post by lidnariq »

Fourier transform of a gaussian curve is another gaussian curve.

If you want to plot the transform of the actual contents of the tables, I'd recommend learning Octave or NumPy.
psycopathicteen
Posts: 3140
Joined: Wed May 19, 2010 6:12 pm

Re: Gauss Table Creation

Post by psycopathicteen »

We found out it's not an exact Gaussian.
psycopathicteen
Posts: 3140
Joined: Wed May 19, 2010 6:12 pm

Re: Gauss Table Creation

Post by psycopathicteen »

I figured out why the top of the "Gaussian" table is 1305. I believe the interpolation table was designed to act like linear interpolation + a smoothing filter. If a you have the wave {0, 1, 0, -1, 0, 1, 0} with linear interpolation, it will come out as triangle wave, but the SNES was probably designed to filter this into a sine wave. If you drew a sine wave on top of the triangle wave, with the same slope at the zero points, the sine wave has 2/pi the height of the original wave.
Near
Founder of higan project
Posts: 1553
Joined: Mon Mar 27, 2006 5:23 pm

Re: Gauss Table Creation

Post by Near »

I finally got around to this since I needed the PS1 SPU gaussian table.

I noticed functional code for the PS1 was never posted, so here's my code to generate both tables:

Code: Select all

int16_t gaussianTable[512];

//Sony DSP (SNES)
//can round with + 0.5 as values are always positive
void DSP::gaussianConstructTable() {
  double table[512];
  for(uint n : range(512)) {
    double k = 0.5 + n;
    double s = (sin(M_PI * k * 1.280 / 1024));
    double t = (cos(M_PI * k * 2.000 / 1023) - 1) * 0.50;
    double u = (cos(M_PI * k * 4.000 / 1023) - 1) * 0.08;
    double r = s * (t + u + 1.0) / k;
    table[511 - n] = r;
  }
  for(uint phase : range(128)) {
    double sum = 0.0;
    sum += table[phase +   0];
    sum += table[phase + 256];
    sum += table[511 - phase];
    sum += table[255 - phase];
    double scale = 2048.0 / sum;
    gaussianTable[phase +   0] = int16_t(table[phase +   0] * scale + 0.5);
    gaussianTable[phase + 256] = int16_t(table[phase + 256] * scale + 0.5);
    gaussianTable[511 - phase] = int16_t(table[511 - phase] * scale + 0.5);
    gaussianTable[255 - phase] = int16_t(table[255 - phase] * scale + 0.5);
  }
}

Code: Select all

int16_t gaussianTable[512];

//Sony SPU (PS1)
//using nearbyint(FE_TONEAREST) to round negative values correctly
void SPU::gaussianConstructTable() {
  fesetround(FE_TONEAREST);
  double table[512];
  for(uint n : range(512)) {
    double k = 0.5 + n;
    double s = (sin(M_PI * k * 2.048 / 1024));
    double t = (cos(M_PI * k * 2.000 / 1023) - 1) * 0.50;
    double u = (cos(M_PI * k * 4.000 / 1023) - 1) * 0.08;
    double r = s * (t + u + 1.0) / k;
    table[511 - n] = r;
  }
  double sum = 0.0;
  for(uint n : range(512)) sum += table[n];
  double scale = 0x7f80 * 128 / sum;
  for(uint n : range(512)) table[n] *= scale;
  for(uint phase : range(128)) {
    double sum = 0.0;
    sum += table[phase +   0];
    sum += table[phase + 256];
    sum += table[511 - phase];
    sum += table[255 - phase];
    double diff = (sum - 0x7f80) / 4;
    gaussianTable[phase +   0] = nearbyint(table[phase +   0] - diff);
    gaussianTable[phase + 256] = nearbyint(table[phase + 256] - diff);
    gaussianTable[511 - phase] = nearbyint(table[511 - phase] - diff);
    gaussianTable[255 - phase] = nearbyint(table[255 - phase] - diff);
  }
}
Hopefully it'll help someone. Code is public domain, but be sure to credit Ryphecha and nocash for coming up with this, all I did was implement what they figured out.
psycopathicteen
Posts: 3140
Joined: Wed May 19, 2010 6:12 pm

Re: Gauss Table Creation

Post by psycopathicteen »

Mednafen wrote: Mon Apr 22, 2019 8:09 am Had an idea that fixed it so it generates a 100% match, new version attached.
I think I figured out why when I tried typing this equation in my calculator it didn't work. I didn't notice that besides the math equation for a Sinc*Blackman window, there is code that adjusts the values so that every 256th value adds up to as close to 2048 as possible.
Post Reply