Commit 59270848 authored by Monty Montgomery's avatar Monty Montgomery

Must... get... changes... under... source... control...

Subversion is not scary, and there are no monsters under my bed.

Monty



git-svn-id: https://svn.xiph.org/trunk/postfish@6506 0101bb08-14d6-0310-b084-bc0e0c8e3800
parent a6e4c7e4
......@@ -2,7 +2,8 @@
# Fuck the horse it rode in on
# and Fuck its little dog Libtool too
CC=gcc
ADD_DEF= -DUGLY_IEEE754_FLOAT32_HACK=1
CC=gcc
LD=gcc
INSTALL=install
PREFIX=/usr/local
......@@ -10,34 +11,26 @@ BINDIR=$PREFIX/bin
ETCDIR=/etc
MANDIR=$PREFIX/man
# is this a platform that uses IEEE 754/854 32 bit floats? The
# following is good for a speedup on most of these systems, otherwise
# comment it out. Using this define on a system where a 'float' is
# *not* an IEEE 32 bit float will destroy, destroy, destroy the audio.
IEEE=-DNASTY_IEEE_FLOAT32_HACK_IS_FASTER_THAN_LOG=1
SRC = main.c mainpanel.c multibar.c readout.c input.c output.c clippanel.c \
declip.c reconstruct.c multicompand.c windowbutton.c subpanel.c \
feedback.c freq.c eq.c eqpanel.c compandpanel.c subband.c lpc.c \
bessel.c
bessel.c suppresspanel.c suppress.c singlecomp.c singlepanel.c \
limit.c limitpanel.c
OBJ = main.o mainpanel.o multibar.o readout.o input.o output.o clippanel.o \
declip.o reconstruct.o multicompand.o windowbutton.o subpanel.o \
feedback.o freq.o eq.o eqpanel.o compandpanel.o subband.o lpc.o \
bessel.o
bessel.o suppresspanel.o suppress.o singlecomp.o singlepanel.o \
limit.o limitpanel.o
GCF = `pkg-config --cflags gtk+-2.0` -DG_DISABLE_DEPRECATED -DGDK_DISABLE_DEPRECATED -DGTK_DISABLE_DEPRECATED -DGDK_PIXBUF_DISABLE_DEPRECATED
all:
$(MAKE) target CFLAGS="-W -O3 -ffast-math $(GCF) $(IEEE)"
$(MAKE) target CFLAGS="-O3 -ffast-math -fomit-frame-pointer $(GCF) $(ADD_DEF)"
debug:
$(MAKE) target CFLAGS="-g -W -D__NO_MATH_INLINES $(GCF) $(IEEE)"
$(MAKE) target CFLAGS="-g -Wall -W -Wno-unused-parameter -D__NO_MATH_INLINES $(GCF) $(ADD_DEF)"
profile:
$(MAKE) target CFLAGS="-W -pg -g -O3 -ffast-math $(GCF) $(IEEE)" LIBS="-lgprof-helper"
$(MAKE) target CFLAGS="-pg -g -O3 -ffast-math $(GCF) $(ADD_DEF)" LIBS="-lgprof-helper"
clean:
rm -f $(OBJ) *.d gmon.out
......
......@@ -23,20 +23,52 @@
/* code derived directly from mkfilter by the late A.J. Fisher,
University of York <fisher@minster.york.ac.uk> September 1992; this
is only the minimum code needed to build an arbitrary 2nd order
Bessel filter */
is only the minimum code needed to build an arbitrary Bessel filter */
#include "postfish.h"
#define TWOPI (2.0 * M_PIl)
#define EPS 1e-10
#define MAXORDER 2
#define MAXPZ 4
#include "bessel.h"
typedef struct {
double re, im;
} complex;
static complex bessel_poles[] = {
{ -1.00000000000e+00, 0.00000000000e+00},
{ -1.10160133059e+00, 6.36009824757e-01},
{ -1.32267579991e+00, 0.00000000000e+00},
{ -1.04740916101e+00, 9.99264436281e-01},
{ -1.37006783055e+00, 4.10249717494e-01},
{ -9.95208764350e-01, 1.25710573945e+00},
{ -1.50231627145e+00, 0.00000000000e+00},
{ -1.38087732586e+00, 7.17909587627e-01},
{ -9.57676548563e-01, 1.47112432073e+00},
{ -1.57149040362e+00, 3.20896374221e-01},
{ -1.38185809760e+00, 9.71471890712e-01},
{ -9.30656522947e-01, 1.66186326894e+00},
{ -1.68436817927e+00, 0.00000000000e+00},
{ -1.61203876622e+00, 5.89244506931e-01},
{ -1.37890321680e+00, 1.19156677780e+00},
{ -9.09867780623e-01, 1.83645135304e+00},
{ -1.75740840040e+00, 2.72867575103e-01},
{ -1.63693941813e+00, 8.22795625139e-01},
{ -1.37384121764e+00, 1.38835657588e+00},
{ -8.92869718847e-01, 1.99832584364e+00},
{ -1.85660050123e+00, 0.00000000000e+00},
{ -1.80717053496e+00, 5.12383730575e-01},
{ -1.65239648458e+00, 1.03138956698e+00},
{ -1.36758830979e+00, 1.56773371224e+00},
{ -8.78399276161e-01, 2.14980052431e+00},
{ -1.92761969145e+00, 2.41623471082e-01},
{ -1.84219624443e+00, 7.27257597722e-01},
{ -1.66181024140e+00, 1.22110021857e+00},
{ -1.36069227838e+00, 1.73350574267e+00},
{ -8.65756901707e-01, 2.29260483098e+00},
};
#define TWOPI (2.0 * M_PIl)
#define EPS 1e-10
#define MAXPZ 8
typedef struct {
complex poles[MAXPZ], zeros[MAXPZ];
int numpoles, numzeros;
......@@ -66,6 +98,11 @@ static complex csub(complex z1, complex z2){
return z1;
}
static complex cconj(complex z){
z.im = -z.im;
return z;
}
static complex eval(complex coeffs[], int npz, complex z){
complex sum = (complex){0.0,0.0};
int i;
......@@ -105,8 +142,8 @@ static void expand(complex pz[], int npz, complex coeffs[]){
}
}
double mkbessel_2(double raw_alpha,double *ycoeff0,double *ycoeff1){
int i;
double mkbessel(double raw_alpha,int order,double *ycoeff){
int i,p= (order*order)/4;
pzrep splane, zplane;
complex topcoeffs[MAXPZ+1], botcoeffs[MAXPZ+1];
double warped_alpha;
......@@ -115,8 +152,11 @@ double mkbessel_2(double raw_alpha,double *ycoeff0,double *ycoeff1){
memset(&splane,0,sizeof(splane));
memset(&zplane,0,sizeof(zplane));
splane.poles[splane.numpoles++] = (complex){ -1.10160133059e+00, 6.36009824757e-01};
splane.poles[splane.numpoles++] = (complex){ -1.10160133059e+00, -6.36009824757e-01};
if (order & 1) splane.poles[splane.numpoles++] = bessel_poles[p++];
for (i = 0; i < order/2; i++){
splane.poles[splane.numpoles++] = bessel_poles[p];
splane.poles[splane.numpoles++] = cconj(bessel_poles[p++]);
}
warped_alpha = tan(M_PIl * raw_alpha) / M_PIl;
for (i = 0; i < splane.numpoles; i++){
......@@ -137,11 +177,296 @@ double mkbessel_2(double raw_alpha,double *ycoeff0,double *ycoeff1){
expand(zplane.poles, zplane.numpoles, botcoeffs);
dc_gain = evaluate(topcoeffs, zplane.numzeros, botcoeffs, zplane.numpoles, (complex){1.0,0.0});
*ycoeff0 = -(botcoeffs[0].re / botcoeffs[zplane.numpoles].re);
*ycoeff1 = -(botcoeffs[1].re / botcoeffs[zplane.numpoles].re);
for(i=0;i<order;i++)
ycoeff[order-i-1] = -(botcoeffs[i].re / botcoeffs[zplane.numpoles].re);
return hypot(dc_gain.re,dc_gain.im);
}
/* assymetrical attack/decay filter computation */
/* this one is designed for fast attack, slow decay */
void compute_iir_fast_attack2(float *x, int n, iir_state *is,
iir_filter *attack, iir_filter *decay){
double a_c0=attack->c[0],d_c0=decay->c[0];
double a_c1=attack->c[1],d_c1=decay->c[1];
double a_g=attack->g, d_g=decay->g;
double x0=is->x[0],x1=is->x[1];
double y0=is->y[0],y1=is->y[1];
int state=is->state;
int i=0;
if(x[0]>y0)state=0;
while(i<n){
if(state==0){
/* attack case */
while(i<n){
double ya= (x[i]+x0*2.+x1)/a_g + y0*a_c0+y1*a_c1;
if(ya<y0){
state=1;
break;
}
x1=x0;x0=x[i];
y1=y0;x[i]=y0=ya;
i++;
}
}
if(state==1){
/* decay case */
if(y1<y0){
/* decay fixup needed because we're in discontinuous time */
y1=y0;
}
while(1){
double yd = (x[i]+x0*2.+x1)/d_g + y0*d_c0+y1*d_c1;
x1=x0;x0=x[i];
y1=y0;x[i]=y0=yd;
i++;
if(i>=n)break;
if(x[i]>y0){
state=0;
break;
}
}
}
}
is->x[0]=x0;is->x[1]=x1;
is->y[0]=y0;is->y[1]=y1;
is->state=state;
}
/* allow decay to proceed in freefall */
void compute_iir_freefall1(float *x, int n, iir_state *is,
iir_filter *decay){
double d_c0=decay->c[0];
double x0=is->x[0];
double y0=is->y[0];
int i=0;
while(i<n){
double yd;
yd = y0*d_c0;
if(x[i]>yd)yd=x[i];
x0=x[i];
x[i]=y0=yd;
i++;
}
is->x[0]=x0;
is->y[0]=y0;
}
void compute_iir_freefall2(float *x, int n, iir_state *is,
iir_filter *decay){
double d_c0=decay->c[0];
double d_c1=decay->c[1];
double x0=is->x[0];
double x1=is->x[1];
double y0=is->y[0];
double y1=is->y[1];
int i=0;
while(i<n){
double yd;
if(y1<y0)y1=y0; // slope fixup
yd = y0*d_c0+y1*d_c1;
if(x[i]>yd)yd=x[i];
x1=x0;x0=x[i];
y1=y0;x[i]=y0=yd;
i++;
}
is->x[0]=x0;
is->x[1]=x1;
is->y[0]=y0;
is->y[1]=y1;
}
void compute_iir_freefall3(float *x, int n, iir_state *is,
iir_filter *decay){
double d_c0=decay->c[0];
double d_c1=decay->c[1];
double d_c2=decay->c[2];
double x0=is->x[0],y0=is->y[0];
double x1=is->x[1],y1=is->y[1];
double x2=is->x[2],y2=is->y[2];
int i=0;
while(i<n){
double yd;
if(y1<y0)y1=y0; // slope fixup
if(y2<y1)y2=y1; // slope fixup
yd = y0*d_c0+y1*d_c1+y2*d_c2;
if(x[i]>yd)yd=x[i];
x2=x1;x1=x0;x0=x[i];
y2=y1;y1=y0;x[i]=y0=yd;
i++;
}
is->x[0]=x0;is->y[0]=y0;
is->x[1]=x1;is->y[1]=y1;
is->x[2]=x2;is->y[2]=y2;
}
void compute_iir_freefall4(float *x, int n, iir_state *is,
iir_filter *decay){
double d_c0=decay->c[0];
double d_c1=decay->c[1];
double d_c2=decay->c[2];
double d_c3=decay->c[3];
double x0=is->x[0],y0=is->y[0];
double x1=is->x[1],y1=is->y[1];
double x2=is->x[2],y2=is->y[2];
double x3=is->x[3],y3=is->y[3];
int i=0;
while(i<n){
double yd;
if(y1<y0)y1=y0; // slope fixup
if(y2<y1)y2=y1; // slope fixup
if(y3<y2)y3=y2; // slope fixup
yd = y0*d_c0+y1*d_c1+y2*d_c2+y3*d_c3;
if(x[i]>yd)yd=x[i];
x3=x2;x2=x1;x1=x0;x0=x[i];
y3=y2;y2=y1;y1=y0;x[i]=y0=yd;
i++;
}
is->x[0]=x0;is->y[0]=y0;
is->x[1]=x1;is->y[1]=y1;
is->x[2]=x2;is->y[2]=y2;
is->x[3]=x3;is->y[3]=y3;
}
/* symmetric filter computation */
void compute_iir_symmetric2(float *x, int n, iir_state *is,
iir_filter *filter){
double c0=filter->c[0];
double c1=filter->c[1];
double g=filter->g;
double x0=is->x[0];
double x1=is->x[1];
double y0=is->y[0];
double y1=is->y[1];
int i=0;
while(i<n){
double yd= (x[i]+x0*2.+x1)/g + y0*c0+y1*c1;
x1=x0;x0=x[i];
y1=y0;x[i]=y0=yd;
i++;
}
is->x[0]=x0;
is->x[1]=x1;
is->y[0]=y0;
is->y[1]=y1;
}
void compute_iir_symmetric3(float *x, int n, iir_state *is,
iir_filter *filter){
double c0=filter->c[0];
double c1=filter->c[1];
double c2=filter->c[2];
double g=filter->g;
double x0=is->x[0],y0=is->y[0];
double x1=is->x[1],y1=is->y[1];
double x2=is->x[2],y2=is->y[2];
int i=0;
while(i<n){
double yd= (x[i]+(x0+x1)*3.+x2)/g + y0*c0+y1*c1+y2*c2;
x2=x1;x1=x0;x0=x[i];
y2=y1;y1=y0;x[i]=y0=yd;
i++;
}
is->x[0]=x0;is->y[0]=y0;
is->x[1]=x1;is->y[1]=y1;
is->x[2]=x2;is->y[2]=y2;
}
void compute_iir_symmetric4(float *x, int n, iir_state *is,
iir_filter *filter){
double c0=filter->c[0];
double c1=filter->c[1];
double c2=filter->c[2];
double c3=filter->c[3];
double g=filter->g;
double x0=is->x[0],y0=is->y[0];
double x1=is->x[1],y1=is->y[1];
double x2=is->x[2],y2=is->y[2];
double x3=is->x[3],y3=is->y[3];
int i=0;
while(i<n){
double yd= (x[i]+(x0+x2)*4.+x1*6.+x3)/g +
y0*c0+y1*c1+y2*c2+y3*c3;
x3=x2;x2=x1;x1=x0;x0=x[i];
y3=y2;y2=y1;y1=y0;x[i]=y0=yd;
i++;
}
is->x[0]=x0;is->y[0]=y0;
is->x[1]=x1;is->y[1]=y1;
is->x[2]=x2;is->y[2]=y2;
is->x[3]=x3;is->y[3]=y3;
}
/* filter decision wrapper */
void compute_iir2(float *x, int n, iir_state *is,
iir_filter *attack, iir_filter *decay){
if (attack->alpha > decay->alpha){
/* fast attack, slow decay */
compute_iir_fast_attack2(x, n, is, attack, decay);
}else{
compute_iir_symmetric2(x, n, is, attack);
}
}
......@@ -21,4 +21,71 @@
*
*/
extern double mkbessel_2(double raw_alpha,double *ycoeff0,double *ycoeff1);
#include "postfish.h"
extern int input_rate;
#define MAXORDER 4
typedef struct {
double c[MAXORDER];
double g;
int order;
float alpha;
float Hz;
float ms;
} iir_filter;
static inline long impulse_ahead2(float alpha){
return rint(.13f/alpha);
}
static inline long impulse_ahead3(float alpha){
return rint(.22f/alpha);
}
static inline long impulse_ahead4(float alpha){
return rint(.32f/alpha);
}
static inline long step_ahead(float alpha){
return rint(.6f/alpha);
}
static inline float step_freq(long ahead){
return input_rate*.6f/ahead;
}
static inline float impulse_freq2(long ahead){
return input_rate*.13f/ahead;
}
static inline float impulse_freq3(long ahead){
return input_rate*.22f/ahead;
}
static inline float impulse_freq4(long ahead){
return input_rate*.32f/ahead;
}
typedef struct {
double x[MAXORDER];
double y[MAXORDER];
int state;
} iir_state;
extern double mkbessel(double raw_alpha,int order,double *ycoeff);
extern void compute_iir_fast_attack2(float *x, int n, iir_state *is,
iir_filter *attack, iir_filter *decay);
extern void compute_iir_symmetric2(float *x, int n, iir_state *is,
iir_filter *filter);
extern void compute_iir_symmetric3(float *x, int n, iir_state *is,
iir_filter *filter);
extern void compute_iir_symmetric4(float *x, int n, iir_state *is,
iir_filter *filter);
extern void compute_iir2(float *x, int n, iir_state *is,
iir_filter *attack, iir_filter *decay);
extern void compute_iir_freefall1(float *x, int n, iir_state *is,
iir_filter *decay);
extern void compute_iir_freefall2(float *x, int n, iir_state *is,
iir_filter *decay);
extern void compute_iir_freefall3(float *x, int n, iir_state *is,
iir_filter *decay);
extern void compute_iir_freefall4(float *x, int n, iir_state *is,
iir_filter *decay);
This diff is collapsed.
......@@ -21,12 +21,16 @@
*
*/
extern void suppresspanel_create(postfish_mainpanel *mp,
GtkWidget *windowbutton,
GtkWidget *activebutton);
extern void compandpanel_create(postfish_mainpanel *mp,
GtkWidget *windowbutton,
GtkWidget *activebutton);
extern void compandpanel_feedback(int displayit);
extern void compandpanel_reset(void);
extern void compandpanel_set_play(int playp);
......@@ -80,7 +80,7 @@ static feedback_generic *new_declip_feedback(void){
}
static void push_declip_feedback(int *clip,float *peak,int total){
int i,n=input_ch;
int n=input_ch;
declip_feedback *f=(declip_feedback *)
feedback_new(&feedpool,new_declip_feedback);
memcpy(f->clipcount,clip,n*sizeof(*clip));
......@@ -91,7 +91,6 @@ static void push_declip_feedback(int *clip,float *peak,int total){
int pull_declip_feedback(int *clip,float *peak,int *total){
declip_feedback *f=(declip_feedback *)feedback_pull(&feedpool);
int i,j;
if(!f)return 0;
......@@ -147,12 +146,14 @@ int declip_setiterations(float it){
pthread_mutex_lock(&master_mutex);
iterations=it;
pthread_mutex_unlock(&master_mutex);
return 0;
}
int declip_setconvergence(float c){
pthread_mutex_lock(&master_mutex);
convergence=c;
pthread_mutex_unlock(&master_mutex);
return 0;
}
/* called only in playback thread */
......@@ -164,7 +165,7 @@ int declip_reset(void){
}
static void sliding_bark_average(float *f,int n,float width){
int i=0,j;
int i=0;
float acc=0.,del=0.;
float sec[hipad+1];
......@@ -172,7 +173,6 @@ static void sliding_bark_average(float *f,int n,float width){
for(i=0;i<n/2;i++){
float bark=toBark(44100.*i/n);
int hi=widthlookup[i]>>16;
int lo=widthlookup[i]&(0xffff);
float del=hypot(f[(i<<1)+1],f[i<<1])/(lo-hi);
......@@ -317,7 +317,6 @@ time_linkage *declip_read(time_linkage *in){
switch(fillstate){
case 0: /* prime the lapping and cache */
for(i=0;i<input_ch;i++){
int j;
float *temp=in->data[i];
total=0;
memset(work+blocksize/2,0,sizeof(*work)*blocksize/2);
......
......@@ -61,7 +61,7 @@ void eq_set(int freq, float value){
static float *curve_cache=0;
static void workfunc(freq_state *f,float **data,float **peak, float **rms){
int h,i,j,k;
int h,i,j;
float sq_mags[f->qblocksize*2+1];
if(curve_dirty || !curve_cache){
......
......@@ -25,14 +25,14 @@
#define eq_freqs 30
static float eq_freq_list[eq_freqs+1]={
static const float eq_freq_list[eq_freqs+1]={
25,31.5,40,50,63,80,
100,125,160,200,250,315,
400,500,630,800,1000,1250,1600,
2000,2500,3150,4000,5000,6300,
8000,10000,12500,16000,20000,9e10};
static char *eq_freq_labels[eq_freqs]={
static char * const eq_freq_labels[eq_freqs]={
"25","31.5","40","50","63","80",
"100","125","160","200","250","315",
"400","500","630","800","1k","1.2k","1.6k",
......@@ -40,7 +40,6 @@ static char *eq_freq_labels[eq_freqs]={
"8k","10k","12.5k","16k","20k"
};
extern int pull_eq_feedback(float **peak,float **rms);
extern int eq_load(void);
extern int eq_reset();
......
......@@ -41,7 +41,6 @@ typedef struct freq_feedback{
} freq_feedback;
static feedback_generic *new_freq_feedback(void){
int i;
freq_feedback *ret=malloc(sizeof(*ret));
ret->peak=calloc(input_ch,sizeof(*ret->peak));
ret->rms=calloc(input_ch,sizeof(*ret->rms));
......@@ -76,14 +75,13 @@ int pull_freq_feedback(freq_state *ff,float **peak,float **rms){
}
/* called only by initial setup */
int freq_load(freq_state *f,float *frequencies, int bands){
int freq_load(freq_state *f,const float *frequencies, int bands){
int i,j;
int blocksize=input_size*2;
memset(f,0,sizeof(*f));
f->qblocksize=input_size;
f->bands=bands;
f->frequencies=frequencies;
f->fillstate=0;
f->cache_samples=0;
......@@ -332,7 +330,7 @@ time_linkage *freq_read(time_linkage *in, freq_state *f,
void (*func)(freq_state *f,float **data,
float **peak, float **rms),
int bypass){
int i,j,k;
int i;
float feedback_peak[input_ch][f->bands];
float feedback_rms[input_ch][f->bands];
......
......@@ -34,7 +34,6 @@ typedef struct {
int qblocksize;
int bands;
float *frequencies;
float **ho_window;
float *ho_area;
......@@ -51,7 +50,7 @@ typedef struct {
extern void freq_transform_work(float *work,freq_state *f);
extern int pull_freq_feedback(freq_state *ff,float **peak,float **rms);
extern int freq_load(freq_state *f,float *frequencies, int bands);
extern int freq_load(freq_state *f,const float *frequencies, int bands);
extern int freq_reset(freq_state *f);
extern time_linkage *freq_read(time_linkage *in, freq_state *f,
void (*func)(freq_state *f,
......
......@@ -401,7 +401,7 @@ static feedback_generic *new_input_feedback(void){
}
static void push_input_feedback(float *peak,float *rms, off_t cursor){
int i,n=input_ch+2;
int n=input_ch+2;
input_feedback *f=(input_feedback *)
feedback_new(&feedpool,new_input_feedback);
f->cursor=cursor;
......@@ -412,7 +412,7 @@ static void push_input_feedback(float *peak,float *rms, off_t cursor){
int pull_input_feedback(float *peak,float *rms,off_t *cursor){
input_feedback *f=(input_feedback *)feedback_pull(&feedpool);
int i,j,n=input_ch+2;
int n=input_ch+2;
if(!f)return 0;
if(rms)memcpy(rms,f->rms,sizeof(*rms)*n);
if(peak)memcpy(peak,f->peak,sizeof(*peak)*n);
......@@ -496,7 +496,6 @@ time_linkage *input_read(void){
k=0;
for(i=0;i<out.samples;i++){
float mean=0.;
float div=0.;
float divrms=0.;
for(j=0;j<out.channels;j++){
......
/*
*
* postfish
*
* Copyright (C) 2002-2004 Monty and Xiph.Org
*
* Postfish is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* Postfish is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of