Page 3 of 3

Re: Gauss Table Creation

Posted: Mon Jun 01, 2020 4:21 pm
by psycopathicteen
Why is it that when I plug the equation into my TI-84 graphing calculator, some of the values differ slightly?

Re: Gauss Table Creation

Posted: Tue Jun 02, 2020 4:47 am
by Jarhmander
Rounding? What the values look like?

Re: Gauss Table Creation

Posted: Wed Jun 03, 2020 5:23 pm
by psycopathicteen
Does anybody have a fourier transform of this? I feel like looking the FFT will explain a lot.

Re: Gauss Table Creation

Posted: Wed Jun 03, 2020 5:33 pm
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.

Re: Gauss Table Creation

Posted: Thu Jun 04, 2020 1:35 pm
by psycopathicteen
We found out it's not an exact Gaussian.

Re: Gauss Table Creation

Posted: Sun Jun 07, 2020 9:28 am
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.

Re: Gauss Table Creation

Posted: Wed Jul 01, 2020 1:27 am
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.