> dispensing with tables and use a special-purpose sin()
> function would probably help a lot as well.
>
In the interests of perpetuating better buzzes for SAOL... :-)
Here's the trick I used for the calculating sin and cos for buzz (not
production code, but the intent is clear):
struct TSinCos {
float m_Sin;
float m_Cos;
};
float gMSBTable[1024]; // 2^10
float gLSBTable[1024]; // 2^10
void InitQuickSinCos() {
for (int i= 0; i < 1024; ++i) {
double phi = i/1024.0*2*PI;
gMSBTable[i].m_Sin = sin(phi);
gMSBTable[i].m_Cos = cos(phi);
}
for (int i= 0; i < 1024; ++i) {
double phi = i/1024.0/1024.0*2*PI;
gLSBTable[i].m_Sin = sin(phi);
gLSBTable[i].m_Cos = cos(phi);
}
}
inline double QuickSinQ20(
int nPhase // fixed point 12.20
)
{
// use sin(u+v) = sin(u)*cos(v)+sin(v)*cos(u)
TSinCos *pU, *pV;
pU = gMSBTable[(nPhase >> 10) & 0x3FF];
pV = gLSBTable[nPhase & 0x3FF];
return pU->m_Sin*pV->m_Cos + pV->m_Sin * pU->m_Cos;
}
inline double QuickSin(double phi) {
// <-- sfx uses a better rounding method here,
// but sfx's buzz uses integer phasors anyway.
return QuickSinQ20((int)(1024*1024*phi)); }
}
Observations
--------------
QuickSinQ20 is accurate to +/- 1^-21. Each table adds 10 bits of precision.
The cost of the table is 32k. The evaluation cost is 2 multiplies, one add,
with most of the lookup being executed in superscalar execution.
QuickSin is accurate to +/- 1^-21*2*PI.
This archive was generated by hypermail 2b29 : Mon Jan 28 2002 - 12:03:56 EST