Что-то типа такого:
#include <fstream.h> //тестовая прога, по-быстрому накиданная из разных кусков для демонстрации
#include <math.h> //caxapa.ru
fstream LogF;
#define SPLINE_LEN 32
signed long Basis[5][SPLINE_LEN];
signed long Coeff[5];
signed long Spline (int X)
{
signed long long V=0,T;
T=Coeff[0];
T*=Basis[0][X];
V+=T;
T=Coeff[1];
T*=Basis[1][X];
V+=T;
T=Coeff[2];
T*=Basis[2][X];
V+=T;
T=Coeff[3];
T*=Basis[3][X];
V+=T;
T=Coeff[4];
T*=Basis[4][X];
V+=T;
return V/16777216;
}
void FitGauss (signed long *Buffer, int Size)
{
double LinearEqA[5][5]={0}, LinearEqC[5]={0}, LinearEqX[5]={0};
int i,j,k,t;
double Tmp;
for (i=0;i<5;i++)
for (j=0;j<Size;j++)
LinearEqC[i]+=(double)(Buffer[j])*(double)(Basis[i][j]);
for (i=0;i<5;i++)
for (j=0;j<5;j++)
for (k=0;k<Size;k++)
LinearEqA[i][j]+=(double)(Basis[i][k])*(double)(Basis[j][k]);
t=5;
for(i=0;i<t-1;i++)
{
k=i;
for(j=i+1;j<t;j++) if(fabs(LinearEqA[j][i])>fabs(LinearEqA[k][i])) k=j;
if(i!=k)
{
for(j=i;j<t;j++) {Tmp=LinearEqA[k][j];LinearEqA[k][j]=LinearEqA[i][j];LinearEqA[i][j]=Tmp;}
Tmp=LinearEqC[k];LinearEqC[k]=LinearEqC[i];LinearEqC[i]=Tmp;
}
Tmp=LinearEqA[i][i];
for(j=i;j<t;j++) LinearEqA[i][j]=LinearEqA[i][j]/Tmp;
LinearEqC[i]=LinearEqC[i]/Tmp;
for(j=i+1;j<t;j++)
{
Tmp=LinearEqA[j][i];LinearEqC[j]-=LinearEqC[i]*Tmp;
for(k=i+1;k<t;k++) LinearEqA[j][k]-=LinearEqA[i][k]*Tmp;
}
}
LinearEqX[t-1]=LinearEqC[t-1]/LinearEqA[t-1][t-1];
for(i=t-2;i>=0;i--)
{
Tmp=0.0;
for(j=i+1;j<t;j++) Tmp+=LinearEqA[i][j]*LinearEqX[j];
LinearEqX[i]=LinearEqC[i]-Tmp;
}
Coeff[0]=LinearEqX[0]*16777216.0;
Coeff[1]=LinearEqX[1]*16777216.0;
Coeff[2]=LinearEqX[2]*16777216.0;
Coeff[3]=LinearEqX[3]*16777216.0;
Coeff[4]=LinearEqX[4]*16777216.0;
// LogF<<LinearEqX[0]<<" "<<Coeff[0]<<" "<<LinearEqX[1]<<" "<<Coeff[1]<<" "<<LinearEqX[2]<<" "<<Coeff[2]<<" "<<LinearEqX[3]<<" "<<Coeff[3]<<" "<<LinearEqX[4]<<" "<<Coeff[4]<<endl;
}
void main (void)
{
int i;
fstream InF, OutF, DiffF, OutDiffF;
signed long Raw[SPLINE_LEN],Diff[SPLINE_LEN];
double Tmp;
LogF.open ("test_log.xls", ios::out|ios::text);
for (i=0; i<SPLINE_LEN; i++)
{
Basis[0][i]=0x00FFFFFF;
Basis[1][i]=cos(i*3.1415926*2.0*1.0 / SPLINE_LEN)*0x00FFFFFF;
Basis[2][i]=cos(i*3.1415926*2.0*2.0 / SPLINE_LEN)*0x00FFFFFF;
Basis[3][i]=cos(i*3.1415926*2.0*4.0 / SPLINE_LEN)*0x00FFFFFF;
Basis[4][i]=cos(i*3.1415926*2.0*8.0 / SPLINE_LEN)*0x00FFFFFF;
/* Tmp=(double)(i) / (double)(SPLINE_LEN);
Basis[1][i]=Tmp * 0x00FFFFFF;
Tmp*=(double)(i) / (double)(SPLINE_LEN);
Basis[2][i]=Tmp * 0x00FFFFFF;
Tmp*=(double)(i) / (double)(SPLINE_LEN);
Basis[3][i]=Tmp * 0x00FFFFFF;
Tmp*=(double)(i) / (double)(SPLINE_LEN);
Basis[4][i]=Tmp * 0x00FFFFFF;*/
// LogF<<Basis[0][i]<<" "<<Basis[1][i]<<" "<<Basis[2][i]<<" "<<Basis[3][i]<<" "<<Basis[4][i]<<endl;
}
InF.open ("test.raw", ios::in|ios::binary);
OutF.open ("test_out.raw", ios::out|ios::binary);
DiffF.open ("test_dif.raw", ios::out|ios::binary);
OutDiffF.open ("test_SnD.raw", ios::out|ios::binary);
for (;;)
{
InF.read ((char*)Raw, SPLINE_LEN*4);
if (InF.fail()) break;
FitGauss (Raw, SPLINE_LEN);
for (i=0; i<SPLINE_LEN; i++) Diff[i]=Raw[i]-Spline(i);
for (i=0; i<SPLINE_LEN; i++)
{
LogF<<Raw[i]<<" "<<Spline(i)<<" "<<Diff[i];
if (i) LogF<<endl;
else LogF<<" "<<Coeff[0]<<" "<<Coeff[1]<<" "<<Coeff[2]<<" "<<Coeff[3]<<" "<<Coeff[4]<<endl;
}
OutF.write ((char*)Coeff,sizeof(Coeff));
OutF.write ((char*)Diff, SPLINE_LEN*4);
for (i=SPLINE_LEN-1; i>0; i--) Diff[i]-=Diff[i-1];
OutDiffF.write ((char*)Coeff,sizeof(Coeff));
OutDiffF.write ((char*)Diff, SPLINE_LEN*4);
for (i=1; i<SPLINE_LEN; i++) Diff[i]=Raw[i]-Raw[i-1];
Diff[0]=Raw[0];
DiffF.write ((char*)Diff, SPLINE_LEN*4);
}
InF.close();
OutF.close();
DiffF.close();
OutDiffF.close();
LogF.close();
}
Разумеется, оно должно хорошо натягиваться на аппроксимирующую кривую. Может, имеет смысл сделать БПФ и записать его выхлоп. Или работать на маленьких интервалах, интерполируя максимум квадратами. В любом случае, суть в том, чтобы провести сжатие с потерями, задав форму части кривой приближённо, и хранить его плюс разницу с реальным, которая уписывается уже в считанные биты и вельми хаффманоугодна.