Sony's soundchips (as used in SNES and PSX) are using a "gauss_table" with 512 entries for pitch interpolations:
PSX: http://nocash.emubase.de/psx-spx.htm#spuadpcmpitch
SNES: http://nocash.emubase.de/fullsnes.htm#s ... spbrrpitch
Above docs are containing the table contents as extracted from real hardware.
So far, the table contents are known, and everything is fine. But, just for curiosity: How did Sony create those tables?
The guy who did originally dump one of that tables (and who branded the name "gauss" table) did later admit that he doesn't have a clue if the table/interpolation has any relation to Gauss at all. Anyway, the table content does seem to resemble to something that is called "gaussian normal distribution" - so after all, the name "gauss_table" seems to be correct.
Here's a formula that does - more or less - reproduce the contents for table[0..511]:
table[i] = (e^(-((siz-i)^2)/curv)) * (volume) - offset
e = Euler's Number (2.718281828...)
siz = index of last table entry (511) (or maybe 512 in case the table excludes the highest point)
offset = some small offset, needed to get table[0]=0 for SNES, and table[0]=-1 for PSX
volume = volume factor (should be equal to "table[siz]+offset")
curv = some constant that somehow affects the shape of the curve
The "volume" should be kinda obvious since
table[siz]=(e^(0/curv) * (volume) - offset
If siz should be 512 rather than 511, then (for obtaining the "volume" value) one must guess the value for table[512], the value should be same or maybe one bigger than table[511].
The "offset" value is needed to get table[0]=0 for SNES, and table[0]=-1 for PSX. Without subtracting that offset, table[0] would be some positive value (the formula won't reach zero until somewhere at table[-infinite]).
with some experimentation, I ended up with these offset values
offset=circa 10 for SNES
offset=circa 50 for PSX
that assuming that offset is constant for all table entries. I might be also variable, something like "offset=(512-i)/10" instead of "offset=50" or whatever. But anyways, the offset is needed only for fine-tuning.
And "curv" can be calculated as:
curv = -(siz-i)^2 / log.e((table[i]+offset)/volume)
aka
curv = -(siz-i)^2 / ln((table[i]+offset)/volume)
aka, when picking i=256 for example,
curv = -(siz-256)^2 / ln((table[256]+offset)/volume)
and then I got this curv values from above formula:
curv=circa 53240 for SNES
curv=circa 42484 for PSX
So, with above stuff, three table entries are used as reference points:
table[siz]=highest point, used to calculate "volume"
table[256]=some random point, used to calculate "curv"
table[0]=lowest point, used to compute "offset" (done by experimentation, not really calculated)
and with the computed volume, curv, offset values, it should be theoretically possible to calculate all other table entries.
Unfortunately, the results are still far away from perfection. Maybe I got something wrong, or maybe Sony used some rounded value like e=2.7 rather than e=2.718281828... or the overall formula isn't correct at all.
Any ideas?
PS. credits to Felix Laepple for pointing me on the basic formula.
PSX: http://nocash.emubase.de/psx-spx.htm#spuadpcmpitch
SNES: http://nocash.emubase.de/fullsnes.htm#s ... spbrrpitch
Above docs are containing the table contents as extracted from real hardware.
So far, the table contents are known, and everything is fine. But, just for curiosity: How did Sony create those tables?
The guy who did originally dump one of that tables (and who branded the name "gauss" table) did later admit that he doesn't have a clue if the table/interpolation has any relation to Gauss at all. Anyway, the table content does seem to resemble to something that is called "gaussian normal distribution" - so after all, the name "gauss_table" seems to be correct.
Here's a formula that does - more or less - reproduce the contents for table[0..511]:
table[i] = (e^(-((siz-i)^2)/curv)) * (volume) - offset
e = Euler's Number (2.718281828...)
siz = index of last table entry (511) (or maybe 512 in case the table excludes the highest point)
offset = some small offset, needed to get table[0]=0 for SNES, and table[0]=-1 for PSX
volume = volume factor (should be equal to "table[siz]+offset")
curv = some constant that somehow affects the shape of the curve
The "volume" should be kinda obvious since
table[siz]=(e^(0/curv) * (volume) - offset
If siz should be 512 rather than 511, then (for obtaining the "volume" value) one must guess the value for table[512], the value should be same or maybe one bigger than table[511].
The "offset" value is needed to get table[0]=0 for SNES, and table[0]=-1 for PSX. Without subtracting that offset, table[0] would be some positive value (the formula won't reach zero until somewhere at table[-infinite]).
with some experimentation, I ended up with these offset values
offset=circa 10 for SNES
offset=circa 50 for PSX
that assuming that offset is constant for all table entries. I might be also variable, something like "offset=(512-i)/10" instead of "offset=50" or whatever. But anyways, the offset is needed only for fine-tuning.
And "curv" can be calculated as:
curv = -(siz-i)^2 / log.e((table[i]+offset)/volume)
aka
curv = -(siz-i)^2 / ln((table[i]+offset)/volume)
aka, when picking i=256 for example,
curv = -(siz-256)^2 / ln((table[256]+offset)/volume)
and then I got this curv values from above formula:
curv=circa 53240 for SNES
curv=circa 42484 for PSX
So, with above stuff, three table entries are used as reference points:
table[siz]=highest point, used to calculate "volume"
table[256]=some random point, used to calculate "curv"
table[0]=lowest point, used to compute "offset" (done by experimentation, not really calculated)
and with the computed volume, curv, offset values, it should be theoretically possible to calculate all other table entries.
Unfortunately, the results are still far away from perfection. Maybe I got something wrong, or maybe Sony used some rounded value like e=2.7 rather than e=2.718281828... or the overall formula isn't correct at all.
Any ideas?
PS. credits to Felix Laepple for pointing me on the basic formula.