Цитата
а я вот под камнями заливку землей делаю, как в даташите прописано...
Тут тоже заливка. Главное - обеспечить одинаковый потенциал на земляных выводах. Ну и плюс пути тока.
Пока суть да дело, причесал немного код для большого брата (с точки зрения последующего портирования на DSP) и впилил ревер.
//---------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <winbase.h>
#include <string.h>
#include <math.h>
#pragma hdrstop
//---------------------------------------------------------------------------
typedef struct
{
long Y;
unsigned long TAU;
}HPF;
typedef struct
{
long Y;
unsigned long TAU;
}LPF;
typedef struct
{
unsigned long GAIN;
unsigned long ODDEVEN;
LPF zero;
}SQ_DIST;
typedef struct
{
signed long a0;
signed long a1;
signed long a2;
signed long b1;
signed long b2;
signed long mem0;
signed long mem1;
signed long mem2;
signed long mem3;
}BIQUAD;
typedef struct
{
LPF filter;
LPF filter_low;
int fuse;
}ENV_DETECT;
signed long DebugSample;
static signed long LowPassFilter(signed long s, LPF *f)
{
signed long long acc;
acc=f->Y-s;
acc*=f->TAU;
if (acc>0)
{
acc+=0x8000;
acc>>=16;
}
else
{
acc=-acc;
acc+=0x8000;
acc>>=16;
acc=-acc;
}
acc=f->Y-acc;
if (acc>0x7FFFFFFF) acc=0x7FFFFFFF;
if (acc<-0x7FFFFFFF) acc=-0x7FFFFFFF;
f->Y=acc;
return acc;
}
static unsigned long int_sqrt(unsigned long v)
{
unsigned int mask=0x00008000;
unsigned int result=0;
do
{
result|=mask;
if (result*result>v) result&=~mask;
}
while(mask>>=1);
return result;
}
static signed long HighPassFilter(signed long s, HPF *f)
{
signed long long acc;
acc=f->Y-s;
acc*=f->TAU;
if (acc>0)
{
acc+=0x8000;
acc>>=16;
}
else
{
acc=-acc;
acc+=0x8000;
acc>>=16;
acc=-acc;
}
acc=f->Y-acc;
if (acc>0x7FFFFFFF) acc=0x7FFFFFFF;
if (acc<-0x7FFFFFFF) acc=-0x7FFFFFFF;
f->Y=acc;
return s-f->Y;
}
static signed long SquareDist(signed long s, SQ_DIST *d)
{
signed long long acc;
signed long z;
if (s>d->zero.Y)
{
//Пиковый детектор
z=LowPassFilter(s*3,&d->zero);
}
else
{
z=LowPassFilter(s,&d->zero);
}
//DebugSample=z;
acc=(signed long long)z*d->ODDEVEN;
acc+=1ULL<<15;
acc>>=16;
acc+=s;
if (acc> 0x7FFFFFFF) acc= 0x7FFFFFFF;
if (acc<-0x7FFFFFFF) acc=-0x7FFFFFFF;
acc=acc*d->GAIN;
if (acc> 0x7FFFFFFF) acc= 0x7FFFFFFF;
if (acc<-0x7FFFFFFF) acc=-0x7FFFFFFF;
if (acc>=))
{
acc=0x7FFFFFFFULL-acc;
acc=acc*acc;
acc+=1ULL<<30;
acc>>=31;
/*acc=acc*acc;
acc+=1ULL<<30;
acc>>=31;*/
acc=0x7FFFFFFFULL-acc;
}
else
{
acc=0x7FFFFFFFULL+acc;
acc=acc*acc;
acc+=1ULL<<30;
acc>>=31;
/*acc=acc*acc;
acc+=1ULL<<30;
acc>>=31;*/
acc=acc-0x7FFFFFFFULL;
}
if (acc>0)
{
acc+=1ULL<<8;
acc>>=9;
}
else
{
acc=-acc;
acc+=1ULL<<8;
acc>>=9;
acc=-acc;
}
if (acc>0x7FFFFFFF) acc=0x7FFFFFFF;
if (acc<-0x7FFFFFFF) acc=-0x7FFFFFFF;
return acc;
}
static void SetBiQuad(double Fs, double Fc, double BW, double G, BIQUAD *f)
{
double k,
om,
x;
double fi;
double a0,a1,a2,b1,b2;
k = pow(10, G / 40); /* relative gain */
//BW = BW / (Fc - BW / 2); /* bandwidth in octaves */
printf("biquad: Fc=%g BW=%g\n",Fc,BW);
om = 2 * M_PI * Fc / Fs; /* normalized frequency in radians */
fi = sinh(log(2) / 2 * BW * om / sin(om)) * sin(om); /* stuff */
x = 1 + fi / k; /* b0 */
a0 = (1 + fi * k) / x;
a1 = -2 * cos(om) / x;
a2 = (1 - fi * k) / x;
b1 = -a1;
b2 = -(1 - fi / k) / x;
f->a0=16384.0*a0;
f->a1=16384.0*a1;
f->a2=16384.0*a2;
f->b1=16384.0*b1;
f->b2=16384.0*b2;
printf("biquad: %g %g %g %g %g",a0,a1,a2,b1,b2);
if (
f->a0>0x7FFF || f->a0<-0x8000 ||
f->a1>0x7FFF || f->a1<-0x8000 ||
f->a2>0x7FFF || f->a2<-0x8000 ||
f->b1>0x7FFF || f->b1<-0x8000 ||
f->b2>0x7FFF || f->b2<-0x8000
) printf(" Overload!!!");
printf("\n");
//printf("biquad: %g %g %g %g %g\n",a0,a1,a2,b1,b2);
}
static void SetChebyshev(double Fs, double Fc, double ripple, int lowpass,
BIQUAD *f)
{
double x,
y,
z,
c,
v,
t,
r,
om,
m,
x0,
x1,
x2,
y1p,
y2,
k,
d,
tt,
tt2;
double a0,a1,a2,b1,b2;
// x=-cos(M_PI/4+M_PI/2);
// y=sin(M_PI/4+M_PI/2);
// c=-0.99915455413031497832540334286332;
// v=0.041111761828599317357934264608497;
c = -cos(M_PI / 4);
v = sin(M_PI / 4);
if (ripple > 0) {
t = 100.0 / (100.0 - ripple);
x = sqrt(t * t - 1);
t = 1 / x;
r = t + sqrt(t / x);
y = 0.5 * log(r + 1);
z = 0.5 * log(r - 1);
t = exp(z);
z = (t + 1 / t) / 2;
t = exp(y);
c *= (t - 1 / t) / 2 / z;
v *= (t + 1 / t) / 2 / z;
}
tt = 2 * tan(0.5);
tt2 = tt * tt;
om = 2 * M_PI * Fc / Fs;
m = c * c + v * v;
d = 4 - 4 * c * tt + m * tt2;
x0 = tt2 / d;
x1 = x0 * 2;
x2 = x0;
y1p = (8 - 2 * m * tt2) / d;
y2 = (-4 - 4 * c * tt - m * tt2) / d;
if (lowpass)
k = sin(0.5 - om / 2) / sin(0.5 + om / 2);
else
k = -cos(om / 2 + 0.5) / cos(om / 2 - 0.5);
d = 1 + k * (y1p - y2 * k);
a0 = (x0 - k * (x1 - x2 * k)) / d;
// coeff[1]=(k*(-2*(x0+x2)+x1*k)+x1)/d;
a1 = 2 * a0;
a2 = a0;
// coeff[2]=(k*(x0*k-x1)+x2)/d;
b1 = (k * (2 + y1p * k - 2 * y2) + y1p) / d;
b2 = (-k * (k + y1p) + y2) / d;
if (!lowpass) {
a1 = -a1;
b1 = -b1;
}
f->a0=16384.0*a0;
f->a1=16384.0*a1;
f->a2=16384.0*a2;
f->b1=16384.0*b1;
f->b2=16384.0*b2;
printf("cheb: %g %g %g %g %g",a0,a1,a2,b1,b2);
if (
f->a0>0x7FFF || f->a0<-0x8000 ||
f->a1>0x7FFF || f->a1<-0x8000 ||
f->a2>0x7FFF || f->a2<-0x8000 ||
f->b1>0x7FFF || f->b1<-0x8000 ||
f->b2>0x7FFF || f->b2<-0x8000
) printf(" Overload!!!");
printf("\n");
}
static signed long BiQuad(signed long s, BIQUAD *q)
{
signed long long acc;
acc=(signed long long )s*q->a0;
acc+=(signed long long )q->mem0*q->a1;
acc+=(signed long long )q->mem1*q->a2;
acc+=(signed long long )q->mem2*q->b1;
acc+=(signed long long )q->mem3*q->b2;
q->mem1=q->mem0;
q->mem0=s;
q->mem3=q->mem2;
acc>>=14;
if (acc>0x7FFFFF) acc=0x7FFFFF;
if (acc<-0x7FFFFF) acc=-0x7FFFFF;
return q->mem2=acc;
}
static signed long EnvDetector(signed long s, ENV_DETECT *d)
{
int flag;
signed long z;
signed long z_low;
if (s>d->filter_low.Y)
{
//Пиковый детектор
//z_low=LowPassFilter(s,&d->filter_low);
d->filter_low.Y=s;
z_low=s;
}
else
{
z_low=LowPassFilter(256*3000,&d->filter_low);
}
z=LowPassFilter(z_low,&d->filter);
flag=0;
if (z_low>z)
{
LowPassFilter(z_low*10,&d->filter);
flag=1;
}
if (!d->fuse && flag)
{
d->fuse=5000;
return 256*16384; //Строб
}
if (flag)
{
d->fuse=5000;
}
if (d->fuse) d->fuse--;
return 0;
}
signed long GainStage(signed long s, signed short G)
{
signed long long acc;
acc=(signed long long )s*G;
acc>>=8;
if (acc>0x7FFFFF) acc=0x7FFFFF;
if (acc<-0x7FFFFF) acc=-0x7FFFFF;
return acc;
}
signed long AttStage(signed long s, signed short G)
{
signed long long acc;
acc=(signed long long )s*G;
acc>>=14;
if (acc>0x7FFFFF) acc=0x7FFFFF;
if (acc<-0x7FFFFF) acc=-0x7FFFFF;
return acc;
}
signed short stereo_delay[16384];
#define stereo_delay_length (sizeof(stereo_delay)/sizeof(stereo_delay[0]))
int stereo_delay_p;
typedef struct
{
unsigned short P0;
signed short G0;
unsigned short P1;
signed short G1;
unsigned short P2;
signed short G2;
unsigned short P3;
signed short G3;
unsigned short P4;
signed short G4;
unsigned short P5;
signed short G5;
unsigned short P6;
signed short G6;
unsigned short P7;
signed short G7;
}DELAY_TAPS;
signed short MakeDelay(DELAY_TAPS *d)
{
signed long long acc=0;
signed short p;
unsigned short b=stereo_delay_p;
p=b-d->P0;if (p<0) p+=stereo_delay_length; acc+=(signed long long)stereo_delay[p]*d->G0;
p=b-d->P1;if (p<0) p+=stereo_delay_length; acc+=(signed long long)stereo_delay[p]*d->G1;
p=b-d->P2;if (p<0) p+=stereo_delay_length; acc+=(signed long long)stereo_delay[p]*d->G2;
p=b-d->P3;if (p<0) p+=stereo_delay_length; acc+=(signed long long)stereo_delay[p]*d->G3;
p=b-d->P4;if (p<0) p+=stereo_delay_length; acc+=(signed long long)stereo_delay[p]*d->G4;
p=b-d->P5;if (p<0) p+=stereo_delay_length; acc+=(signed long long)stereo_delay[p]*d->G5;
p=b-d->P6;if (p<0) p+=stereo_delay_length; acc+=(signed long long)stereo_delay[p]*d->G6;
p=b-d->P7;if (p<0) p+=stereo_delay_length; acc+=(signed long long)stereo_delay[p]*d->G7;
acc>>=14;
if (acc>0x7FFF) acc=0x7FFF;
if (acc<-0x7FFF) acc=-0x7FFF;
return acc;
}
DELAY_TAPS Delay_L=
{
0, 16384L*100L/100,
17*44, -16384L*0L/100,
72*44, 16384L*20L/100,
118*44, 16384L*0L/100,
181*44, -16384L*12L/100,
240*44, 16384L*0L/100,
300*44, -16384L*6L/100,
370*44, 16384L*0L/100
};
DELAY_TAPS Delay_R=
{
10*44, 16384L*100L/100,
27*44, -16384L*30L/100,
82*44, 16384L*0L/100,
108*44, 16384L*15L/100,
171*44, -16384L*0L/100,
250*44, 16384L*10L/100,
310*44, -16384L*0L/100,
360*44, 16384L*4L/100
};
DELAY_TAPS Delay_FeedBack=
{
12*44, 16384L*10L/100,
29*44, -16384L*9L/100,
84*44, 16384L*6L/100,
110*44, 16384L*5L/100,
175*44, -16384L*4L/100,
248*44, 16384L*3L/100,
313*44, -16384L*2L/100,
365*44, 16384L*1L/100
};
#pragma argsused
int main(int argc, char* argv[])
{
static const char hdr1[]={
0x52,0x49,0x46,0x46,0x00,0x00,0x00,0x00,0x57,0x41,0x56,0x45,0x66,0x6D,0x74,0x20,
0x10,0x00,0x00,0x00,0x01,0x00,0x02,0x00,0x44,0xAC,0x00,0x00,0x10,0xB1,0x02,0x00,
0x04,0x00,0x10,0x00,0x64,0x61,0x74,0x61,0x00,0x00,0x00,0x00
};
HANDLE fin;
HANDLE fout;
signed short *inbuf;
signed short *outbuf;
unsigned long total_bytes;
unsigned long br;
unsigned long pos=0;
unsigned long rpos=0;
double preeq_G;
signed short ipreeq_G;
HPF dc_offset_remove={0,65536*50/7022};
HPF dc_offset_remove1={0,65535*10/7022};
HPF dc_offset_remove2={0,65535*10/7022};
ENV_DETECT env1={{0,65535*1/7022},{0,65535*1/7022},0};
BIQUAD input_filter={0,0,0,0,0,0,0,0,0};
BIQUAD preeq_b={0,0,0,0,0,0,0,0};
SQ_DIST dist1={256UL*3000,65536*100/100,{0,65535*40/7022}};
SQ_DIST power_amp={256UL*1,65536*30/100,{0,65535*10/7022}};
BIQUAD sand_remove={0,0,0,0,0,0,0,0,0};
BIQUAD sand_remove2={0,0,0,0,0,0,0,0,0};
BIQUAD out_eq[19];
fout = CreateFile("out.wav",GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL, 0);
WriteFile(fout,hdr1,sizeof(hdr1),&br,NULL);
fin = CreateFile("in5.wav",GENERIC_READ,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
SetFilePointer(fin,0x28,NULL,FILE_BEGIN);
ReadFile(fin,&total_bytes,4,&br,NULL);
inbuf=malloc(total_bytes);
outbuf=malloc(total_bytes*2);
ReadFile(fin,inbuf,total_bytes,&br,NULL);
SetChebyshev(44100,5500,1,1,&input_filter);
preeq_G=20;
//SetBiQuad(44100,1600,3.3,preeq_G,&preeq_b);
SetBiQuad(44100,900,4,preeq_G,&preeq_b);
ipreeq_G=(int)(16384.0/pow(10, preeq_G / 20));
SetChebyshev(44100,4500,1,1,&sand_remove);
SetChebyshev(44100,4500,1,1,&sand_remove2);
memset(out_eq,0,sizeof(out_eq));
#define bw_scale (0.5)
/* SetBiQuad(44100,80,bw_scale,7.3,out_eq+0);
SetBiQuad(44100,100,bw_scale,7,out_eq+1);
SetBiQuad(44100,125,bw_scale,6.6,out_eq+2);
SetBiQuad(44100,160,bw_scale,5.9,out_eq+3);
SetBiQuad(44100,200,bw_scale,4.8,out_eq+4);
SetBiQuad(44100,250,bw_scale,3.3,out_eq+5);
SetBiQuad(44100,320,bw_scale,2.1,out_eq+6);
SetBiQuad(44100,400,bw_scale,1.5,out_eq+7);
SetBiQuad(44100,500,bw_scale,0.9,out_eq+8);
SetBiQuad(44100,640,bw_scale,-2.9,out_eq+9);
SetBiQuad(44100,800,bw_scale,-0.9,out_eq+10);
SetBiQuad(44100,1000,bw_scale,0.7,out_eq+11);
SetBiQuad(44100,1280,bw_scale,2,out_eq+12);
SetBiQuad(44100,1600,bw_scale,4.5,out_eq+13);
SetBiQuad(44100,2000,bw_scale,4.4,out_eq+14);
SetBiQuad(44100,2560,bw_scale,5.3,out_eq+15);
SetBiQuad(44100,3200,bw_scale,5.2,out_eq+16);
SetBiQuad(44100,4000,bw_scale,6.2,out_eq+17);
SetBiQuad(44100,5000,bw_scale,5,out_eq+18);*/
SetBiQuad(44100,80,bw_scale,8.3,out_eq+0);
SetBiQuad(44100,100,bw_scale,8,out_eq+1);
SetBiQuad(44100,125,bw_scale,7.6,out_eq+2);
SetBiQuad(44100,160,bw_scale,6.9,out_eq+3);
SetBiQuad(44100,200,bw_scale,6.8,out_eq+4);
SetBiQuad(44100,250,bw_scale,5.3,out_eq+5);
SetBiQuad(44100,320,bw_scale,4.1,out_eq+6);
SetBiQuad(44100,400,bw_scale,3.5,out_eq+7);
SetBiQuad(44100,500,bw_scale,0.9,out_eq+8);
SetBiQuad(44100,640,bw_scale,-1.9,out_eq+9);
SetBiQuad(44100,800,bw_scale,-1.9,out_eq+10);
SetBiQuad(44100,1000,bw_scale,3.7,out_eq+11);
SetBiQuad(44100,1280,bw_scale,2,out_eq+12);
SetBiQuad(44100,1600,bw_scale,5.5,out_eq+13);
SetBiQuad(44100,2000,bw_scale,7.4,out_eq+14);
SetBiQuad(44100,2560,bw_scale,7.3,out_eq+15);
SetBiQuad(44100,3200,bw_scale,7.2,out_eq+16);
SetBiQuad(44100,4000,bw_scale,7.2,out_eq+17);
SetBiQuad(44100,5000,bw_scale,8,out_eq+18);
while(pos<(total_bytes))
{
int i;
int stereo_delay_rp;
signed long L_sample;
signed long R_sample;
signed long sample=256UL*inbuf[rpos++];
sample+=(rand()/(RAND_MAX/256));
//Remove DC
sample=HighPassFilter(sample,&dc_offset_remove);
//Remove High Frequences
sample=BiQuad(sample,&input_filter);
//Detect Attack (for future usage)
if (EnvDetector(sample,&env1))
{
//Trigger
}
//Pre EQ
sample=AttStage(sample,ipreeq_G);
sample=BiQuad(sample,&preeq_b);
//Distortion
sample=SquareDist(sample,&dist1);
sample=HighPassFilter(sample,&dc_offset_remove1);
//Remove sand
sample=BiQuad(sample,&sand_remove);
//EQ
sample=AttStage(sample,16384/8);
for(i=0; i<sizeof(out_eq)/sizeof(BIQUAD); i++)
{
sample=BiQuad(sample,out_eq+i);
}
//Power Amp
sample=SquareDist(sample,&power_amp);
sample=HighPassFilter(sample,&dc_offset_remove2);
//Remove sand
sample=BiQuad(sample,&sand_remove2);
//Generate stereo_delay
if(1)
{
signed long acc=sample/128;
acc+=MakeDelay(&Delay_FeedBack);
if (acc>0x7FFF) acc=0x7FFF;
if (acc<-0x7FFF) acc=-0x7FFF;
stereo_delay[stereo_delay_p]=acc;
L_sample=MakeDelay(&Delay_L);
R_sample=MakeDelay(&Delay_R);
stereo_delay_p++;
if (stereo_delay_p>=stereo_delay_length) stereo_delay_p=0;
}
else
{
L_sample=sample/128;
R_sample=sample/128;
}
//Write out
outbuf[pos++]=L_sample;
outbuf[pos++]=R_sample;
}
total_bytes*=2;
WriteFile(fout,outbuf,total_bytes,&br,NULL);
SetFilePointer(fout,0x28,NULL,FILE_BEGIN);
WriteFile(fout,&total_bytes,4,&br,NULL);
SetFilePointer(fout,0x04,NULL,FILE_BEGIN);
total_bytes+=0x24;
WriteFile(fout,&total_bytes,4,&br,NULL);
CloseHandle(fout);
CloseHandle(fin);
free(inbuf);
free(outbuf);
return 0;
}
//---------------------------------------------------------------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин