Commit 52b2fd84 authored by Monty Montgomery's avatar Monty Montgomery

Actually commit some of the compander tinkering.


git-svn-id: https://svn.xiph.org/trunk/postfish@5902 0101bb08-14d6-0310-b084-bc0e0c8e3800
parent 9ee0d754
......@@ -10,6 +10,16 @@ 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
......@@ -19,25 +29,27 @@ OBJ = main.o mainpanel.o multibar.o readout.o input.o output.o clippanel.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)"
$(MAKE) target CFLAGS="-W -O3 -ffast-math $(GCF) $(IEEE)"
debug:
$(MAKE) target CFLAGS="-g -W -D__NO_MATH_INLINES $(GCF)"
$(MAKE) target CFLAGS="-g -W -D__NO_MATH_INLINES $(GCF) $(IEEE)"
profile:
$(MAKE) target CFLAGS="-W -pg -g -O3 $(GCF)"
$(MAKE) target CFLAGS="-W -pg -g -O3 -ffast-math $(GCF) $(IEEE)" LIBS="-lgprof-helper"
clean:
rm -f $(OBJ) *.d
rm -f $(OBJ) *.d gmon.out
%.d: %.c
$(CC) -M $(GCF) $< > $@.$$$$; sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; rm -f $@.$$$$
ifneq ($(MAKECMDGOALS),clean)
include $(SRC:.c=.d)
endif
target: $(OBJ)
target: $(OBJ)
./touch-version
$(LD) $(OBJ) $(CFLAGS) -o postfish `pkg-config --libs gtk+-2.0` -lpthread -lfftw3f -lm
$(LD) $(OBJ) $(CFLAGS) -o postfish $(LIBS) `pkg-config --libs gtk+-2.0` -lpthread -lfftw3f -lm
install:
$(INSTALL) -d -m 0755 $(BINDIR)
......
......@@ -313,7 +313,7 @@ void clippanel_create(postfish_mainpanel *mp,
mainpanel_inbar=mp->inbar;
subpanel_show_all_but_toplevel(panel);
}
void clippanel_feedback(int displayit){
......
This diff is collapsed.
......@@ -27,5 +27,6 @@ extern void compandpanel_create(postfish_mainpanel *mp,
extern void compandpanel_feedback(int displayit);
extern void compandpanel_reset(void);
extern void compandpanel_set_play(int playp);
......@@ -43,7 +43,7 @@ int pull_eq_feedback(float **peak,float **rms){
/* called only by initial setup */
int eq_load(void){
return freq_load(&eq,eq_freq_list,eq_freqs,input_size);
return freq_load(&eq,eq_freq_list,eq_freqs);
}
/* called only in playback thread */
......
......@@ -101,6 +101,7 @@ void eqpanel_create(postfish_mainpanel *mp,
}
gtk_box_pack_start(GTK_BOX(panel->subpanel_box),slidertable,1,1,4);
subpanel_show_all_but_toplevel(panel);
}
......
......@@ -49,55 +49,6 @@ static feedback_generic *new_freq_feedback(void){
return (feedback_generic *)ret;
}
static int seq=0;
static void _analysis(char *base,int i,float *v,int n,int bark,int dB){
int j;
FILE *of;
char buffer[80];
sprintf(buffer,"%s_%d.m",base,i);
of=fopen(buffer,"w");
if(!of)perror("failed to open data dump file");
for(j=0;j<n;j++){
if(bark){
float b=toBark((4000.f*j/n)+.25);
fprintf(of,"%f ",b);
}else
fprintf(of,"%f ",(float)j);
if(dB){
float val=todB(hypot(v[j],v[j+1]));
if(val<-140)val=-140;
fprintf(of,"%f\n",val);
j++;
}else{
fprintf(of,"%f\n",v[j]);
}
}
fclose(of);
}
static void _analysis_append(char *base,int basemod,float *v,int n,int off){
int j;
FILE *of;
char buffer[80];
sprintf(buffer,"%s_%d.m",base,basemod);
of=fopen(buffer,"a");
if(!of)perror("failed to open data dump file");
for(j=0;j<n;j++){
fprintf(of,"%f ",(float)j+off);
fprintf(of,"%f\n",v[j]);
}
fprintf(of,"\n");
fclose(of);
}
/* total, peak, rms are pulled in array[freqs][input_ch] order */
int pull_freq_feedback(freq_state *ff,float **peak,float **rms){
......@@ -125,13 +76,12 @@ 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 blocksize){
int freq_load(freq_state *f,float *frequencies, int bands){
int i,j;
int blocksize=input_size*2;
memset(f,0,sizeof(*f));
f->qblocksize=blocksize/2;
f->qblocksize=input_size;
f->bands=bands;
f->frequencies=frequencies;
......@@ -158,11 +108,6 @@ int freq_load(freq_state *f,float *frequencies, int bands,
for(i=0;i<blocksize;i++)f->window[i]=sin(f->window[i]*M_PIl*.5);
for(i=0;i<blocksize;i++)f->window[i]*=f->window[i];
/* unlike old postfish, we offer all frequencies via smoothly
supersampling the spectrum */
/* I'm too lazy to figure out the integral symbolically, use this
fancy CPU-thing for something */
f->fftwf_buffer = fftwf_malloc(sizeof(*f->fftwf_buffer) * input_ch);
f->fftwf_backward = fftwf_malloc(sizeof(*f->fftwf_backward) * input_ch);
f->fftwf_forward = fftwf_malloc(sizeof(*f->fftwf_forward) * input_ch);
......@@ -286,7 +231,6 @@ void freq_metric_work(float *work,freq_state *f,
for(i=0;i<f->qblocksize*2+1;i++)
sq_mags[i]=(work[i*2]*work[i*2]+work[i*2+1]*work[i*2+1])*64.;
for(i=0;i<f->bands;i++){
float *ho_window=f->ho_window[i];
......@@ -312,36 +256,21 @@ static void feedback_work(freq_state *f,float *peak,float *rms,
}
static void lap_bypass(float *cache,float *in,float *lap,float *out,freq_state *f){
int i;
int i,j;
if(out){
/* we're bypassing, so the input data hasn't spread from the half->block window.
The lap may well be spread though, so we can't cheat and ignore the last third */
for(i=0;i<f->qblocksize;i++)
out[i]=lap[i];
for(;i<f->qblocksize*2;i++)
out[i]=lap[i]+f->window[i-f->qblocksize]*cache[i];
if(f->qblocksize*2<input_size)
for(;i<f->qblocksize*3;i++)
out[i]=lap[i]+cache[i];
if(f->qblocksize*3<input_size)
memcpy(out+f->qblocksize*3,cache+f->qblocksize*3,
sizeof(*out)*(input_size-f->qblocksize*3));
}
/* keep lap up to date; bypassed data has not spread from the half-block padded window */
if(f->qblocksize<input_size/2){
memcpy(lap,in,f->qblocksize*sizeof(*lap));
for(i=f->qblocksize;i<f->qblocksize*2;i++)
lap[i]=in[i]*f->window[i];
}else{
for(i=0;i<f->qblocksize;i++)
lap[i]=lap[i+f->qblocksize*2]+in[i];
for(;i<f->qblocksize*2;i++)
lap[i]=in[i]*f->window[i];
}
for(i=0;i<f->qblocksize;i++)
lap[i]=lap[i+f->qblocksize]+cache[i]*f->window[i];
for(j=0;i<f->qblocksize*2;i++,j++)
lap[i]=lap[i+f->qblocksize]+in[j]*f->window[i];
memset(lap+f->qblocksize*2,0,f->qblocksize*sizeof(*lap));
}
......@@ -361,6 +290,43 @@ static void lap_work(float *work,float *lap,float *out,freq_state *f){
}
static void freq_transwork(freq_state *f,time_linkage *in){
int i,j;
for(i=0;i<input_ch;i++){
/* extrapolation mechanism; avoid harsh transients at edges */
if(f->fillstate==0)
preextrapolate_helper(in->data[i],input_size,
f->cache[i],input_size);
if(in->samples<in->size)
postextrapolate_helper(f->cache[i],input_size,
in->data[i],in->samples,
in->data[i]+in->samples,
in->size-in->samples);
memset(f->fftwf_buffer[i],0,
sizeof(**f->fftwf_buffer)*f->qblocksize);
memcpy(f->fftwf_buffer[i]+f->qblocksize,
f->cache[i],
sizeof(**f->fftwf_buffer)*f->qblocksize);
memcpy(f->fftwf_buffer[i]+f->qblocksize*2,
in->data[i],
sizeof(**f->fftwf_buffer)*f->qblocksize);
memset(f->fftwf_buffer[i]+f->qblocksize*3,0,
sizeof(**f->fftwf_buffer)*f->qblocksize);
for(j=0;j<f->qblocksize*2;j++)
f->fftwf_buffer[i][j+f->qblocksize]*=.25*f->window[j]/f->qblocksize;
/* transform the time data */
fftwf_execute(f->fftwf_forward[i]);
}
}
/* called only by playback thread */
time_linkage *freq_read(time_linkage *in, freq_state *f,
void (*func)(freq_state *f,float **data,
......@@ -414,63 +380,51 @@ time_linkage *freq_read(time_linkage *in, freq_state *f,
}else{
/* extrapolation mechanism; avoid harsh transients at edges */
freq_transwork(f,in);
func(f,f->fftwf_buffer,peakp,rmsp);
blocks++;
for(i=0;i<input_ch;i++){
preextrapolate_helper(in->data[i],input_size,
f->cache[i],input_size);
feedback_work(f,peak[i],rms[i],feedback_peak[i],feedback_rms[i]);
fftwf_execute(f->fftwf_backward[i]);
lap_work(f->fftwf_buffer[i],f->lap[i],0,f);
if(in->samples<in->size)
postextrapolate_helper(f->cache[i],input_size,
in->data[i],in->samples,
in->data[i]+in->samples,
in->size-in->samples);
}
}
/* only need the last two ops to prime the lapping, but they're
the complex ones that span the cache/in gap. We'd need
three, but the passed input window is zero for the first/last
quarter block and the 'cache' is zero (so the middle of the
first window is also zero). */
for(i=0;i<input_ch;i++){
float *temp=in->data[i];
memset(f->cache[i],0,sizeof(**f->cache)*input_size);
in->data[i]=f->cache[i];
f->cache[i]=temp;
}
for(j=0;j<2;j++){
for(i=0;i<input_ch;i++){
switch(j){
case 0:
memcpy(f->fftwf_buffer[i]+f->qblocksize,
f->cache[i]+input_size-f->qblocksize,
sizeof(**f->fftwf_buffer)*f->qblocksize);
memcpy(f->fftwf_buffer[i]+f->qblocksize*2,
in->data[i],
sizeof(**f->fftwf_buffer)*f->qblocksize);
break;
case 1:
memcpy(f->fftwf_buffer[i]+f->qblocksize,
in->data[i],
sizeof(**f->fftwf_buffer)*f->qblocksize*2);
break;
}
memset(f->fftwf_buffer[i],0,
sizeof(**f->fftwf_buffer)*f->qblocksize);
memset(f->fftwf_buffer[i]+f->qblocksize*3,0,
sizeof(**f->fftwf_buffer)*f->qblocksize);
for(k=0;k<f->qblocksize*2;k++)
f->fftwf_buffer[i][k+f->qblocksize]*=.25*f->window[k]/f->qblocksize;
/* transform the time data */
fftwf_execute(f->fftwf_forward[i]);
}
func(f,f->fftwf_buffer,peakp,rmsp);
blocks++;
for(i=0;i<input_ch;i++){
feedback_work(f,peak[i],rms[i],feedback_peak[i],feedback_rms[i]);
fftwf_execute(f->fftwf_backward[i]);
lap_work(f->fftwf_buffer[i],f->lap[i],0,f);
f->cache_samples=in->samples;
f->fillstate=1;
f->out.samples=0;
if(in->samples==in->size)goto tidy_up;
for(i=0;i<input_ch;i++)
memset(in->data[i],0,sizeof(**in->data)*in->size);
in->samples=0;
/* fall through */
case 1: /* finish priming the lapping and cache */
if(bypass){
for(i=0;i<input_ch;i++)
lap_bypass(f->cache[i],in->data[i],f->lap[i],0,f);
}else{
}
freq_transwork(f,in);
func(f,f->fftwf_buffer,peakp,rmsp);
blocks++;
for(i=0;i<input_ch;i++){
feedback_work(f,peak[i],rms[i],feedback_peak[i],feedback_rms[i]);
fftwf_execute(f->fftwf_backward[i]);
lap_work(f->fftwf_buffer[i],f->lap[i],0,f);
}
}
......@@ -482,7 +436,7 @@ time_linkage *freq_read(time_linkage *in, freq_state *f,
}
f->cache_samples=in->samples;
f->fillstate=1;
f->fillstate=2;
f->out.samples=0;
if(in->samples==in->size)goto tidy_up;
......@@ -491,72 +445,23 @@ time_linkage *freq_read(time_linkage *in, freq_state *f,
in->samples=0;
/* fall through */
case 1: /* nominal processing */
case 2: /* nominal processing */
if(bypass){
/* bypass as above but deal with lapping whole block in and out */
for(i=0;i<input_ch;i++)
lap_bypass(f->cache[i],in->data[i],f->lap[i],f->out.data[i],f);
}else{
/* extrapolation mechanism; avoid harsh transients at edges */
freq_transwork(f,in);
func(f,f->fftwf_buffer,peakp,rmsp);
blocks++;
for(i=0;i<input_ch;i++){
if(in->samples<in->size)
postextrapolate_helper(f->cache[i],input_size,
in->data[i],in->samples,
in->data[i]+in->samples,
in->size-in->samples);
}
for(j=input_size/f->qblocksize-1;j>=0;j--){
for(i=0;i<input_ch;i++){
switch(j){
case 0:
/* last block, needed because the half-block wide non-zero
data section of the window will spread out to full window
width when we convolve */
memcpy(f->fftwf_buffer[i]+f->qblocksize,in->data[i],
f->qblocksize*2*sizeof(**f->fftwf_buffer));
break;
case 1:
/* second-to-last block, nonzero section of the input
spans the cache and input blocks */
memcpy(f->fftwf_buffer[i]+f->qblocksize,
f->cache[i]+input_size-f->qblocksize,
sizeof(**f->fftwf_buffer)*f->qblocksize);
memcpy(f->fftwf_buffer[i]+f->qblocksize*2,
in->data[i],
sizeof(**f->fftwf_buffer)*f->qblocksize);
break;
default:
memcpy(f->fftwf_buffer[i]+f->qblocksize,
f->cache[i]+input_size-(f->qblocksize*j),
f->qblocksize*2*sizeof(**f->fftwf_buffer));
break;
}
memset(f->fftwf_buffer[i],0,
sizeof(**f->fftwf_buffer)*f->qblocksize);
memset(f->fftwf_buffer[i]+f->qblocksize*3,0,
sizeof(**f->fftwf_buffer)*f->qblocksize);
for(k=0;k<f->qblocksize*2;k++)
f->fftwf_buffer[i][k+f->qblocksize]*=.25*f->window[k]/f->qblocksize;
/* transform the time data */
fftwf_execute(f->fftwf_forward[i]);
}
feedback_work(f,peak[i],rms[i],feedback_peak[i],feedback_rms[i]);
fftwf_execute(f->fftwf_backward[i]);
lap_work(f->fftwf_buffer[i],f->lap[i],f->out.data[i],f);
func(f,f->fftwf_buffer,peakp,rmsp);
blocks++;
for(i=0;i<input_ch;i++){
feedback_work(f,peak[i],rms[i],feedback_peak[i],feedback_rms[i]);
fftwf_execute(f->fftwf_backward[i]);
lap_work(f->fftwf_buffer[i],f->lap[i],
f->out.data[i]+input_size-f->qblocksize*(j+1),f);
}
}
}
......@@ -567,14 +472,14 @@ time_linkage *freq_read(time_linkage *in, freq_state *f,
}
f->out.samples=f->cache_samples;
f->cache_samples=in->samples;
if(f->out.samples<f->out.size)f->fillstate=2;
if(f->out.samples<f->out.size)f->fillstate=3;
break;
case 2: /* we've pushed out EOF already */
case 3: /* we've pushed out EOF already */
f->out.samples=0;
}
/* finish up the state feedabck */
if(!bypass){
if(!bypass && blocks){
int j;
float scale=1./blocks;
freq_feedback *ff=
......
......@@ -44,14 +44,14 @@ typedef struct {
float **cache;
int cache_samples;
int fillstate; /* 0: uninitialized
1: normal
2: eof processed */
1: half-primed
2: nominal
3: eof processed */
} freq_state;
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,
int blocksize);
extern int freq_load(freq_state *f,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,
......
......@@ -357,7 +357,7 @@ static gboolean mainpanel_keybinding(GtkWidget *widget,
switch(event->keyval){
case GDK_m:
case GDK_t:
/* trigger master dB */
gtk_widget_activate(p->masterdB_a);
break;
......@@ -380,24 +380,21 @@ static gboolean mainpanel_keybinding(GtkWidget *widget,
case GDK_d:
gtk_widget_activate(p->buttonactive[0]);
break;
case GDK_t:
case GDK_c:
gtk_widget_activate(p->buttonactive[1]);
break;
case GDK_n:
case GDK_m:
gtk_widget_activate(p->buttonactive[2]);
break;
case GDK_e:
case GDK_s:
gtk_widget_activate(p->buttonactive[3]);
break;
case GDK_c:
case GDK_e:
gtk_widget_activate(p->buttonactive[4]);
break;
case GDK_l:
gtk_widget_activate(p->buttonactive[5]);
break;
case GDK_o:
gtk_widget_activate(p->buttonactive[6]);
break;
case GDK_a:
gtk_widget_activate(p->cue_set[0]);
break;
......@@ -626,7 +623,7 @@ void mainpanel_create(postfish_mainpanel *panel,char **chlabels){
GtkWidget *box=gtk_hbox_new(0,0);
GtkWidget *masterlabel=gtk_label_new("master:");
panel->masterdB_a=gtk_toggle_button_new_with_label("[m] active");
panel->masterdB_a=gtk_toggle_button_new_with_label("a[t]ten");
panel->masterdB_r=readout_new(" 0.0dB");
panel->masterdB_s=multibar_slider_new(10,sliderlabels,sliderlevels,1);
......@@ -638,9 +635,9 @@ void mainpanel_create(postfish_mainpanel *panel,char **chlabels){
gtk_table_attach(GTK_TABLE(ttable),masterlabel,0,1,3,4,
GTK_FILL,GTK_FILL,0,0);
gtk_box_pack_start(GTK_BOX(box),panel->masterdB_a,0,0,2);
gtk_box_pack_start(GTK_BOX(box),panel->masterdB_s,1,1,0);
gtk_box_pack_start(GTK_BOX(box),panel->masterdB_r,0,0,0);
gtk_box_pack_start(GTK_BOX(box),panel->masterdB_a,0,0,0);
gtk_table_attach_defaults(GTK_TABLE(ttable),box,1,3,3,4);
......@@ -819,12 +816,11 @@ void mainpanel_create(postfish_mainpanel *panel,char **chlabels){
}
mainpanel_panelentry(panel,"_Declip ","[d]",0,clippanel_create);
mainpanel_panelentry(panel,"Cross_Talk ","[t]",1,0);
mainpanel_panelentry(panel,"_Compand/Gate ","[c]",2,compandpanel_create);
mainpanel_panelentry(panel,"_Equalizer ","[e]",3,eqpanel_create);
mainpanel_panelentry(panel,"_Limiter ","[l]",4,0);
mainpanel_panelentry(panel,"_Output Cal. ","[o]",5,0);
mainpanel_panelentry(panel,"_Crosstalk ","[c]",1,0);
mainpanel_panelentry(panel,"_Multicomp ","[m]",2,compandpanel_create);
mainpanel_panelentry(panel,"_Singlecomp ","[s]",3,0);
mainpanel_panelentry(panel,"_Equalizer ","[e]",4,eqpanel_create);
mainpanel_panelentry(panel,"_Limiter ","[l]",5,0);
g_signal_connect (G_OBJECT (panel->toplevel), "delete_event",
G_CALLBACK (shutdown), NULL);
......
......@@ -69,7 +69,7 @@ static void compute(Multibar *m,float *lowvals, float *highvals, int n){
xpad=2;
}else{
if(m->thumbs>1)
xpad=height*3/4+6;
xpad=((height+1)/2)+(height/2-3)*3/2+1;
else
xpad=height/2+1;
}
......@@ -582,7 +582,7 @@ static void draw(GtkWidget *widget,int n){
gdk_draw_line(m->backing,m->boxcolor,x,y+(y1-y)/2,x,0);
if(m->thumbfocus==num){
for(i=0;i<height/2;i++)
for(i=0;i<(height-1)/2;i++)
for(j=0;j<=i*2;j++)
if(!(j&1))
gdk_draw_point(m->backing,black_gc,x-i+j,y+i+2);
......@@ -636,7 +636,7 @@ static void size_request (GtkWidget *widget,GtkRequisition *requisition){
}else{
maxy+=3;
if(m->thumbs>1)
xpad=maxy+(maxy/2-1)/2-1+2;
xpad=((maxy+1)/2)+(maxy/2-3)*3/2+1;
else
xpad=maxy/2+1+2;
}
......
......@@ -21,10 +21,13 @@
*
*/
#include "postfish.h"
#include "feedback.h"
#include "multicompand.h"
#include <fftw3.h>
#include "subband.h"
static int offset=0;
static void _analysis(char *base,int i,float *v,int n,int bark,int dB){
int j;
FILE *of;
......@@ -83,149 +86,595 @@ extern int input_ch;
about a half-order of magnitude less roundoff noise from gain
(compared to other IIR families) */
static float iirg_list[7]={
static float iirg_list[8]={
4.875178475e+06, // 5
1.008216556e+06, // 11
2.524889925e+05, // 22
6.3053949794e+04, // 44
1.5872282930e+04, // 88
4.086422543e+03, // 175
1.049342702e+03 // 350
1.049342702e+03, // 350
2.764099277e+02 // 700
};
static float iirc_list[7][2]={
static float iirc_list[8][2]={
{1.9984308946, -.9984317150}, // 5
{1.9965490514, -.9965530188}, // 11
{1.9931020727, -.9931179150}, // 22