Commit 5916b48f authored by Monty Montgomery's avatar Monty Montgomery

Behavioral change in master panels: Glue the applied

compression/expansion together for all channels.



git-svn-id: https://svn.xiph.org/trunk/postfish@17366 0101bb08-14d6-0310-b084-bc0e0c8e3800
parent 39380cd6
......@@ -37,7 +37,7 @@ OBJ = main.o mainpanel.o multibar.o readout.o input.o output.o clippanel.o \
limit.o limitpanel.o mute.o mixpanel.o mix.o freeverb.o reverbpanel.o \
outpanel.o config.o window.o follower.o linkage.o
GCF = -DETCDIR=\\\"$(ETCDIR)\\\" `pkg-config --cflags gtk+-2.0` -DG_DISABLE_DEPRECATED -DGDK_DISABLE_DEPRECATED -DGTK_DISABLE_DEPRECATED -DGDK_PIXBUF_DISABLE_DEPRECATED
GCF = -DETCDIR=\\\"$(ETCDIR)\\\" `pkg-config --cflags gtk+-2.0`
all:
$(MAKE) target CFLAGS="-O2 -ffast-math -fomit-frame-pointer $(GCF) $(ADD_DEF)"
......@@ -76,7 +76,7 @@ endif
target: $(OBJ) postfish-wisdomrc
./touch-version
$(LD) $(OBJ) $(CFLAGS) -o postfish $(LIBS) `pkg-config --libs gtk+-2.0` -lpthread -lfftw3f -lm #/home/xiphmont/electric-fence-2.1.4/libefence.a
$(LD) $(OBJ) $(CFLAGS) -o postfish $(LIBS) `pkg-config --libs gtk+-2.0` -lpthread -lfftw3f -lm
install: target
$(INSTALL) -d -m 0755 $(BINDIR)
......
......@@ -91,9 +91,9 @@ static void prepare_peak(float *peak, float *x, int n, int ahead,
ps->val=val;
}
static void fill_work(float *A, float *B, float *work,
static void fill_work(float **A, float **B, int ch, float *work,
int ahead, int hold, int mode, peak_state *ps){
int k;
int i,j,k;
if(mode){
/* peak mode */
......@@ -102,36 +102,85 @@ static void fill_work(float *A, float *B, float *work,
if(B){
float bigcache[input_size*2];
memcpy(bigcache,A,sizeof(*work)*input_size);
memcpy(bigcache+input_size,B,sizeof(*work)*input_size);
memcpy(bigcache,A[0],sizeof(*bigcache)*input_size);
memcpy(bigcache+input_size,B[0],sizeof(*bigcache)*input_size);
for(j=1;j<ch;j++){
float *AA = A[j];
float *BB = B[j];
float *bb = bigcache+input_size;
for(i=0;i<input_size;i++)
if(bigcache[i]*bigcache[i]<AA[i]*AA[i])
bigcache[i]=AA[i];
for(i=0;i<input_size;i++)
if(bb[i]*bb[i]<BB[i]*BB[i])
bb[i]=BB[i];
}
prepare_peak(work, bigcache, input_size, ahead, hold, ps);
}else{
prepare_peak(work, A, input_size, ahead, hold, ps);
if(ch>1){
float bigcache[input_size];
memcpy(bigcache,A[0],sizeof(*bigcache)*input_size);
for(j=1;j<ch;j++){
float *AA = A[j];
for(i=0;i<input_size;i++)
if(bigcache[i]*bigcache[i]<AA[i]*AA[i])
bigcache[i]=AA[i];
}
prepare_peak(work, bigcache, input_size, ahead, hold, ps);
}else{
prepare_peak(work, A[0], input_size, ahead, hold, ps);
}
}
}else{
/* rms mode */
float *cachea=A+ahead;
float *cachea=A[0]+ahead;
if(B){
float *cacheb=B[0];
float *worka=work+input_size-ahead;
for(k=0;k<input_size-ahead;k++)
work[k]=cachea[k]*cachea[k];
for(k=0;k<ahead;k++)
worka[k]=B[k]*B[k];
worka[k]=cacheb[k]*cacheb[k];
for(j=1;j<ch;j++){
cachea = A[j]+ahead;
cacheb = B[j];
for(k=0;k<input_size-ahead;k++)
work[k]+=cachea[k]*cachea[k];
for(k=0;k<ahead;k++)
worka[k]+=cacheb[k]*cacheb[k];
}
if(ch>0){
float inv = 1./ch;
for(k=0;k<input_size;k++)
work[k]*=inv;
}
}else{
for(k=0;k<input_size;k++)
work[k]=cachea[k]*cachea[k];
for(j=1;j<ch;j++){
cachea = A[j];
for(k=0;k<input_size;k++)
work[k]+=cachea[k]*cachea[k];
}
if(ch>0){
float inv = 1./ch;
for(k=0;k<input_size;k++)
work[k]*=inv;
}
}
}
}
void bi_compand(float *A,float *B,float *adj,
void bi_compand(float **A,float **B,
int ch,
float *adj,
float corner,
float multiplier,
float currmultiplier,
......@@ -150,7 +199,7 @@ void bi_compand(float *A,float *B,float *adj,
hold=ahead*(1.-lookahead);
ahead*=lookahead;
fill_work(A,B,work,ahead,hold,mode,ps);
fill_work(A,B,ch,work,ahead,hold,mode,ps);
multiplier*=.5;
currmultiplier*=.5;
......@@ -197,7 +246,7 @@ void bi_compand(float *A,float *B,float *adj,
}
void full_compand(float *A,float *B,float *adj,
void full_compand(float **A,float **B,int ch,float *adj,
float multiplier,float currmultiplier,
int mode,
iir_filter *attack, iir_filter *decay,
......@@ -208,7 +257,7 @@ void full_compand(float *A,float *B,float *adj,
float work[input_size];
int ahead=(mode?step_ahead(attack->alpha):impulse_ahead2(attack->alpha));
fill_work(A,B,work,ahead,0,mode,ps);
fill_work(A,B,ch,work,ahead,0,mode,ps);
multiplier*=.5;
currmultiplier*=.5;
......
......@@ -28,7 +28,7 @@ typedef struct {
float val;
} peak_state;
extern void bi_compand(float *A,float *B,float *adj,
extern void bi_compand(float **A,float **B,int ch,float *adj,
float corner,
float multiplier,
float currmultiplier,
......@@ -39,7 +39,7 @@ extern void bi_compand(float *A,float *B,float *adj,
int active,
int over);
extern void full_compand(float *A,float *B,float *adj,
extern void full_compand(float **A,float **B,int ch,float *adj,
float multiplier,float currmultiplier,
int mode,
iir_filter *attack, iir_filter *decay,
......
......@@ -356,7 +356,7 @@ static int multicompand_work_perchannel(multicompand_state *ms,
memset(adj,0,sizeof(*adj)*input_size);
if(u_active)
bi_compand(x,0,(i>=w->freq_bands?0:adj),
bi_compand(&x,0,1,(i>=w->freq_bands?0:adj),
//prevset->static_u[i],
currset->static_u[i],
1.f-1000.f/prevset->under_ratio,
......@@ -373,7 +373,7 @@ static int multicompand_work_perchannel(multicompand_state *ms,
0);
if(o_active)
bi_compand(x,0,(i>=w->freq_bands?0:adj),
bi_compand(&x,0,1,(i>=w->freq_bands?0:adj),
//prevset->static_o[i],
currset->static_o[i],
1.f-1000.f/prevset->over_ratio,
......@@ -417,7 +417,7 @@ static int multicompand_work_perchannel(multicompand_state *ms,
}
if(b_active)
full_compand(x,0,(i>=w->freq_bands?0:adj),
full_compand(&x,0,1,(i>=w->freq_bands?0:adj),
1.f-1000.f/prevset->base_ratio,
1.f-1000.f/currset->base_ratio,
c->base_mode,
......@@ -447,6 +447,199 @@ static int multicompand_work_perchannel(multicompand_state *ms,
return(feedback_p);
}
static int multicompand_work_allchannels(multicompand_state *ms,
float **peakfeed,
float **rmsfeed,
int maxbands,
atten_cache *prevset,
atten_cache *currset,
multicompand_settings *c){
subband_state *ss=&ms->ss;
int active=(ss->effect_active1[0] ||
ss->effect_active0[0] ||
ss->effect_activeC[0]);
int feedback_p=0;
int i,k,ch,bank;
subband_window *w=ss->w1[0];
subband_window *wP=ss->wP[0];
float adj[input_size];
int o_active=0,u_active=0,b_active=0;
if(w==&sw[0]){
bank=0;
}else if(w==&sw[1]){
bank=1;
}else bank=2;
if(active){
for(i=0;i<multicomp_freqs_max;i++){
currset->static_u[i]=c->bc[bank].static_u[i];
currset->static_o[i]=c->bc[bank].static_o[i];
}
currset->under_ratio=c->under_ratio;
currset->over_ratio=c->over_ratio;
currset->base_ratio=c->base_ratio;
/* don't slew from an unknown value */
if(!ss->effect_activeP[0] || !ms->initstate)
memcpy(prevset,currset,sizeof(*currset));
/* don't run filters that will be applied at unity */
if(prevset->under_ratio==1000 && currset->under_ratio==1000){
ms->under_delay[0]=2;
for(i=0;i<multicomp_freqs_max;i++){
memset(&ms->under_peak[i][0],0,sizeof(peak_state));
memset(&ms->under_iir[i][0],0,sizeof(iir_state));
}
}else{
if(ms->under_delay[0]-->0)currset->under_ratio=1000;
if(ms->under_delay[0]<0)ms->under_delay[0]=0;
u_active=1;
}
if(prevset->over_ratio==1000 && currset->over_ratio==1000){
ms->over_delay[0]=2;
for(i=0;i<multicomp_freqs_max;i++){
memset(&ms->over_peak[i][0],0,sizeof(peak_state));
memset(&ms->over_iir[i][0],0,sizeof(iir_state));
}
}else{
if(ms->over_delay[0]-->0)currset->over_ratio=1000;
if(ms->over_delay[0]<0)ms->over_delay[0]=0;
o_active=1;
}
if(prevset->base_ratio==1000 && currset->base_ratio==1000){
ms->base_delay[0]=2;
for(i=0;i<multicomp_freqs_max;i++){
memset(&ms->base_peak[i][0],0,sizeof(peak_state));
memset(&ms->base_iir[i][0],0,sizeof(iir_state));
}
}else{
if(ms->base_delay[0]-->0)currset->base_ratio=1000;
if(ms->base_delay[0]<0)ms->base_delay[0]=0;
b_active=1;
}
} else if (ss->effect_activeP[0]){
/* this lapping channel just became inactive */
reset_filters_onech(ms,0);
}
/* one thing is worth a note here; 'maxbands' can be
'overrange' for the current bank. This is intentional; we
may need to run the additional (allocated and valid)
filters before or after their bands are active. The only
garbage data here is the xxxx_u, xxxx_o and xxxx_b
settings. There are allocated, but unset; if overrange,
they're ignored in the compand worker */
for(i=0;i<maxbands;i++){
float **x=ss->lap[i];
if(u_active || o_active || b_active)
memset(adj,0,sizeof(*adj)*input_size);
if(u_active)
bi_compand(x,0,ms->ch,(i>=w->freq_bands?0:adj),
//prevset->static_u[i],
currset->static_u[i],
1.f-1000.f/prevset->under_ratio,
1.f-1000.f/currset->under_ratio,
c->under_lookahead/1000.f,
c->under_mode,
c->under_softknee,
&ms->under_attack[0],
&ms->under_decay[0],
&ms->under_iir[i][0],
&ms->under_peak[i][0],
ss->effect_active1[0] &&
(i<w->freq_bands),
0);
if(o_active)
bi_compand(x,0,ms->ch,(i>=w->freq_bands?0:adj),
//prevset->static_o[i],
currset->static_o[i],
1.f-1000.f/prevset->over_ratio,
1.f-1000.f/currset->over_ratio,
c->over_lookahead/1000.f,
c->over_mode,
c->over_softknee,
&ms->over_attack[0],
&ms->over_decay[0],
&ms->over_iir[i][0],
&ms->over_peak[i][0],
ss->effect_active1[0] &&
(i<w->freq_bands),
1);
for(ch=0;ch<ms->ch;ch++){
if(ss->visible1[ch]){
feedback_p=1;
if(!mute_channel_muted(ss->mutemask1,ch)){
/* determine rms and peak for feedback */
float max=-1.;
int maxpos=-1;
float rms=0.;
for(k=0;k<input_size;k++){
float val=x[ch][k]*x[ch][k];
if(val>max){
max=val;
maxpos=k;
}
rms+=val;
}
if(u_active || o_active || b_active){
peakfeed[i][ch]=todB(max)*.5+adj[maxpos];
rmsfeed[i][ch]=todB(rms/input_size)*.5+adj[maxpos];
}else{
peakfeed[i][ch]=todB(max)*.5;
rmsfeed[i][ch]=todB(rms/input_size)*.5;
}
}
}
}
if(b_active)
full_compand(x,0,ms->ch,(i>=w->freq_bands?0:adj),
1.f-1000.f/prevset->base_ratio,
1.f-1000.f/currset->base_ratio,
c->base_mode,
&ms->base_attack[0],
&ms->base_decay[0],
&ms->base_iir[i][0],
&ms->base_peak[i][0],
ss->effect_active1[0] &&
i<w->freq_bands);
if(u_active || o_active || b_active){
if(ss->effect_active1[0]){
for(k=0;k<input_size;k++){
float a = fromdB_a(adj[k]);
for(ch=0;ch<ms->ch;ch++)
x[ch][k]*=a;
}
}
}
}
for(;i<wP->freq_bands;i++){
memset(&ms->over_peak[i][0],0,sizeof(peak_state));
memset(&ms->under_peak[i][0],0,sizeof(peak_state));
memset(&ms->base_peak[i][0],0,sizeof(peak_state));
memset(&ms->over_iir[i][0],0,sizeof(iir_state));
memset(&ms->under_iir[i][0],0,sizeof(iir_state));
memset(&ms->base_iir[i][0],0,sizeof(iir_state));
}
return(feedback_p);
}
static void push_feedback(multicompand_state *ms,int bypass,int maxmaxbands){
int i;
......
......@@ -224,19 +224,22 @@ static void work_and_lapping(singlecomp_state *scs,
singlecomp_settings **scset,
time_linkage *in,
time_linkage *out,
int *active){
int i;
int *active,
int link){
int i,j;
int have_feedback=0;
u_int32_t mutemaskC=in->active;
u_int32_t mutemask0=scs->mutemask0;
u_int32_t mutemaskP=scs->mutemaskP;
int iterations = (link?1:scs->ch);
int chper = (link?scs->ch:1);
float peakfeed[scs->ch];
float rmsfeed[scs->ch];
memset(peakfeed,0,sizeof(peakfeed));
memset(rmsfeed,0,sizeof(rmsfeed));
for(i=0;i<scs->ch;i++){
for(i=0;i<iterations;i++){
int o_active=0,u_active=0,b_active=0;
......@@ -267,34 +270,36 @@ static void work_and_lapping(singlecomp_state *scs,
if(activeP) reset_onech_filter(scs,i); /* just became inactive;
reset all filters for
this channel */
/* feedback */
if(scset[i]->panel_visible){
int k;
float rms=0.;
float peak=0.;
float *x=scs->cache[i];
have_feedback=1;
if(!muted0){
for(k=0;k<input_size;k++){
float val=x[k]*x[k];
rms+= val;
if(peak<val)peak=val;
}
}
peakfeed[i]=todB_a(peak)*.5;
rms/=input_size;
rmsfeed[i]=todB_a(rms)*.5;
for(j=i;j<i+chper;j++){
int k;
float rms=0.;
float peak=0.;
float *x=scs->cache[j];
have_feedback=1;
if(!muted0){
for(k=0;k<input_size;k++){
float val=x[k]*x[k];
rms+= val;
if(peak<val)peak=val;
}
}
peakfeed[j]=todB_a(peak)*.5;
rms/=input_size;
rmsfeed[j]=todB_a(rms)*.5;
}
}
/* rotate data vectors */
if(out){
float *temp=out->data[i];
out->data[i]=scs->cache[i];
scs->cache[i]=temp;
}
for(j=i;j<i+chper;j++){
float *temp=out->data[j];
out->data[j]=scs->cache[j];
scs->cache[j]=temp;
}
}
}else if(active0 || activeC){
float adj[input_size]; // under will set it
......@@ -346,7 +351,7 @@ static void work_and_lapping(singlecomp_state *scs,
memset(adj,0,sizeof(*adj)*input_size);
if(u_active)
bi_compand(scs->cache[i],in->data[i],adj,
bi_compand(scs->cache+i,in->data+i,chper,adj,
//scs->prevset[i].u_thresh,
scs->currset[i].u_thresh,
1.f-1000./scs->prevset[i].u_ratio,
......@@ -359,7 +364,7 @@ static void work_and_lapping(singlecomp_state *scs,
active0,0);
if(o_active)
bi_compand(scs->cache[i],in->data[i],adj,
bi_compand(scs->cache+i,in->data+i,chper,adj,
//scs->prevset[i].o_thresh,
scs->currset[i].o_thresh,
1.f-1000.f/scs->prevset[i].o_ratio,
......@@ -374,30 +379,32 @@ static void work_and_lapping(singlecomp_state *scs,
/* feedback before base */
if(scset[i]->panel_visible){
int k;
float rms=0.;
float peak=0.;
float *x=scs->cache[i];
have_feedback=1;
if(!muted0){
for(k=0;k<input_size;k++){
float mul=fromdB_a(adj[k]);
float val=x[k]*mul;
for(j=i;j<i+chper;j++){
int k;
float rms=0.;
float peak=0.;
float *x=scs->cache[j];
have_feedback=1;
if(!muted0){
for(k=0;k<input_size;k++){
float mul=fromdB_a(adj[k]);
float val=x[k]*mul;
val*=val;
rms+= val;
if(peak<val)peak=val;
}
}
peakfeed[i]=todB_a(peak)*.5;
rms/=input_size;
rmsfeed[i]=todB_a(rms)*.5;
val*=val;
rms+= val;
if(peak<val)peak=val;
}
}
peakfeed[j]=todB_a(peak)*.5;
rms/=input_size;
rmsfeed[j]=todB_a(rms)*.5;
}
}
if(b_active)
full_compand(scs->cache[i],in->data[i],adj,
full_compand(scs->cache+i,in->data+i,chper,adj,
1.-1000./scs->prevset[i].b_ratio,
1.-1000./scs->currset[i].b_ratio,
scset[i]->b_mode,
......@@ -406,49 +413,53 @@ static void work_and_lapping(singlecomp_state *scs,
active0);
if(active0 && out){
/* current frame should be manipulated; render into out,
handle transitioning after */
int k;
float *ix=scs->cache[i];
float *ox=out->data[i];
for(k=0;k<input_size;k++)
ox[k]=ix[k]*fromdB_a(adj[k]);
/* is this frame preceeded/followed by an 'inactive' frame?
If so, smooth the transition */
if(!activeP){
if(!mutedP){
for(k=0;k<input_size/2;k++){
float w=window[k];
ox[k]= ox[k]*w + ix[k]*(1.-w);
}
}
}
if(!activeC){
if(!mutedC){
float *cox=ox+input_size/2;
float *cix=ix+input_size/2;
for(k=0;k<input_size/2;k++){
float w=window[k];
cox[k]= cox[k]*(1.-w) + cix[k]*w;
}
}
}
for(j=i;j<i+chper;j++){
/* current frame should be manipulated; render into out,
handle transitioning after */
int k;
float *ix=scs->cache[j];
float *ox=out->data[j];
for(k=0;k<input_size;k++)
ox[k]=ix[k]*fromdB_a(adj[k]);
/* is this frame preceeded/followed by an 'inactive' frame?
If so, smooth the transition */
if(!activeP){
if(!mutedP){
for(k=0;k<input_size/2;k++){
float w=window[k];
ox[k]= ox[k]*w + ix[k]*(1.-w);
}
}
}
if(!activeC){
if(!mutedC){
float *cox=ox+input_size/2;
float *cix=ix+input_size/2;
for(k=0;k<input_size/2;k++){
float w=window[k];
cox[k]= cox[k]*(1.-w) + cix[k]*w;
}
}
}
}
}else if(out){
float *temp=out->data[i];
out->data[i]=scs->cache[i];
scs->cache[i]=temp;
for(j=i;j<i+chper;j++){
float *temp=out->data[j];
out->data[j]=scs->cache[j];
scs->cache[j]=temp;
}
}
}
{
float *temp=scs->cache[i];
scs->cache[i]=in->data[i];
in->data[i]=temp;
}
scs->activeP[i]=active0;
scs->active0[i]=activeC;
for(j=i;j<i+chper;j++){
float *temp=scs->cache[j];
scs->cache[j]=in->data[j];
in->data[j]=temp;
scs->activeP[j]=active0;
scs->active0[j]=activeC;
}
}
if(out){
......@@ -485,7 +496,8 @@ static void work_and_lapping(singlecomp_state *scs,
time_linkage *singlecomp_read_helper(time_linkage *in,
singlecomp_state *scs,
singlecomp_settings **scset,
int *active){
int *active,
int link){
int i;
switch(scs->fillstate){
......@@ -507,7 +519,7 @@ time_linkage *singlecomp_read_helper(time_linkage *in,
}
scs->mutemaskP=scs->mutemask0=in->active;
work_and_lapping(scs,scset,in,0,active);
work_and_lapping(scs,scset,in,0,active,link);
scs->fillstate=1;
scs->out.samples=0;
......@@ -519,7 +531,7 @@ time_linkage *singlecomp_read_helper(time_linkage *in,
/* fall through */
case 1: /* nominal processing */
work_and_lapping(scs,scset,in,&scs->out,active);
work_and_lapping(scs,scset,in,&scs->out,active,link);
if(scs->out.samples<input_size)scs->fillstate=2;
break;
......@@ -545,7 +557,7 @@ time_linkage *singlecomp_read_master(time_linkage *in){
for(i=0;i<master_state.ch;i++)
active[i]=singlecomp_master_set.panel_active;
return singlecomp_read_helper(in, &master_state, master_set_bundle,active);
return singlecomp_read_helper(in, &master_state, master_set_bundle,active,1);
}
time_linkage *singlecomp_read_channel(time_linkage *in){
......@@ -555,5 +567,5 @@ time_linkage *singlecomp_read_channel(time_linkage *in){
for(i=0;i<channel_state.ch;i++)
active[i]=singlecomp_channel_set[i].panel_active;
return singlecomp_read_helper(in, &channel_state, channel_set_bundle,active);
return singlecomp_read_helper(in, &channel_state, channel_set_bundle,active,0);
}
#define VERSION "$Id$ "
/* DO NOT EDIT: Automated versioning hack [Sun Nov 20 21:43:22 EST 2005] */
/* DO NOT EDIT: Automated versioning hack [Sat Aug 21 01:08:29 EDT 2010] */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment