Commit 628a1dcf authored by Monty Montgomery's avatar Monty Montgomery

Rewrite of freq.c/EQ signal path to implement muting, bypassing and smooth

transitions between settings.

Fix mute bug in subband feedback that sent visual feedback up to 0dB on mute 



git-svn-id: https://svn.xiph.org/trunk/postfish@6595 0101bb08-14d6-0310-b084-bc0e0c8e3800
parent 071b759a
......@@ -33,7 +33,7 @@ profile:
$(MAKE) target CFLAGS="-pg -g -O3 -ffast-math $(GCF) $(ADD_DEF)" LIBS="-lgprof-helper"
clean:
rm -f $(OBJ) *.d gmon.out
rm -f $(OBJ) *.d *.d.* gmon.out
%.d: %.c
$(CC) -M $(GCF) $< > $@.$$$$; sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; rm -f $@.$$$$
......
......@@ -29,71 +29,117 @@
extern int input_size;
sig_atomic_t eq_active;
sig_atomic_t eq_visible;
typedef struct{
sig_atomic_t curve_dirty=1;
freq_state eq;
} eq_state;
eq_settings eq_master_set;
eq_settings *eq_channel_set;
static freq_class_setup fc;
static eq_state master_state;
static eq_state channel_state;
freq_state eq;
/* accessed only in playback thread/setup */
int pull_eq_feedback(float **peak,float **rms){
return pull_freq_feedback(&eq,peak,rms);
int pull_eq_feedback_master(float **peak,float **rms){
return pull_freq_feedback(&master_state.eq,peak,rms);
}
int pull_eq_feedback_channel(float **peak,float **rms){
return pull_freq_feedback(&channel_state.eq,peak,rms);
}
/* called only by initial setup */
int eq_load(void){
return freq_load(&eq,eq_freq_list,eq_freqs);
int i;
eq_channel_set=calloc(input_ch,sizeof(*eq_channel_set));
freq_class_load(&fc,eq_freq_list,eq_freqs);
freq_load(&master_state.eq,&fc);
freq_load(&channel_state.eq,&fc);
eq_master_set.curve_dirty=1;
for(i=0;i<input_ch;i++)
eq_channel_set[i].curve_dirty=1;
return 0;
}
/* called only in playback thread */
int eq_reset(){
return freq_reset(&eq);
freq_reset(&master_state.eq);
freq_reset(&channel_state.eq);
return 0;
}
static sig_atomic_t settings[eq_freqs];
void eq_set(int freq, float value){
settings[freq]=rint(value*10.);
curve_dirty=1;
void eq_set(eq_settings *set, int freq, float value){
set->settings[freq]=rint(value*10.);
set->curve_dirty=1;
}
static float *curve_cache=0;
static void workfunc(freq_state *f,float **data,float **peak, float **rms){
int h,i,j;
float sq_mags[f->qblocksize*2+1];
static void workfunc(float *data, eq_settings *set){
int i,j;
if(curve_dirty || !curve_cache){
curve_dirty=0;
if(set->curve_dirty || !set->curve_cache){
set->curve_dirty=0;
if(!curve_cache)curve_cache=malloc((f->qblocksize*2+1)*sizeof(*curve_cache));
memset(curve_cache,0,(f->qblocksize*2+1)*sizeof(*curve_cache));
if(!set->curve_cache)
set->curve_cache=malloc((fc.qblocksize*2+1)*sizeof(*set->curve_cache));
memset(set->curve_cache,0,(fc.qblocksize*2+1)*sizeof(*set->curve_cache));
for(i=0;i<eq_freqs;i++){
float set=fromdB(settings[i]*.1);
for(j=0;j<f->qblocksize*2+1;j++)
curve_cache[j]+=f->ho_window[i][j]*set;
float v=fromdB_a(set->settings[i]*.1);
for(j=0;j<fc.qblocksize*2+1;j++)
set->curve_cache[j]+=fc.ho_window[i][j]*v;
}
}
for(h=0;h<input_ch;h++){
if(eq_active){
for(i=0;i<f->qblocksize*2+1;i++){
data[h][i*2]*=curve_cache[i];
data[h][i*2+1]*=curve_cache[i];
}
}
freq_metric_work(data[h],f,sq_mags,peak[h],rms[h]);
for(i=0;i<fc.qblocksize*2+1;i++){
data[i*2]*=set->curve_cache[i];
data[i*2+1]*=set->curve_cache[i];
}
return;
}
static void workfunc_ch(float *data, int ch){
workfunc(data,eq_channel_set+ch);
}
static void workfunc_m(float *data, int ch){
workfunc(data,&eq_master_set);
}
/* called only by playback thread */
time_linkage *eq_read(time_linkage *in){
return freq_read(in,&eq,workfunc,!(eq_visible||eq_active));
time_linkage *eq_read_master(time_linkage *in){
int active[input_ch];
int visible[input_ch];
int i;
for(i=0;i<input_ch;i++){
active[i]=eq_master_set.panel_active;
visible[i]=eq_master_set.panel_visible;
}
return freq_read(in,&master_state.eq,visible,active,workfunc_m);
}
time_linkage *eq_read_channel(time_linkage *in){
int active[input_ch];
int visible[input_ch];
int i;
for(i=0;i<input_ch;i++){
active[i]=eq_channel_set[i].panel_active;
visible[i]=eq_channel_set[i].panel_visible;
}
return freq_read(in,&master_state.eq,visible,active,workfunc_ch);
}
......@@ -25,6 +25,15 @@
#define eq_freqs 30
typedef struct {
sig_atomic_t settings[eq_freqs];
sig_atomic_t panel_active;
sig_atomic_t panel_visible;
sig_atomic_t curve_dirty;
float *curve_cache;
} eq_settings;
static const float eq_freq_list[eq_freqs+1]={
25,31.5,40,50,63,80,
100,125,160,200,250,315,
......@@ -40,8 +49,10 @@ static char * const eq_freq_labels[eq_freqs]={
"8k","10k","12.5k","16k","20k"
};
extern int pull_eq_feedback(float **peak,float **rms);
extern int pull_eq_feedback_master(float **peak,float **rms);
extern int pull_eq_feedback_ch(float **peak,float **rms);
extern int eq_load(void);
extern int eq_reset();
extern void eq_set(int freq, float value);
extern time_linkage *eq_read(time_linkage *in);
extern void eq_set(eq_settings *eq,int freq, float value);
extern time_linkage *eq_read_master(time_linkage *in);
extern time_linkage *eq_read_channel(time_linkage *in);
......@@ -32,12 +32,13 @@
#include "freq.h"
#include "eq.h"
extern sig_atomic_t eq_active;
extern sig_atomic_t eq_visible;
extern int input_ch;
extern int input_size;
extern int input_rate;
extern eq_settings eq_master_set;
extern eq_settings *eq_channel_set;
typedef struct {
GtkWidget *slider;
GtkWidget *readout;
......@@ -54,7 +55,7 @@ static void slider_change(GtkWidget *w,gpointer in){
sprintf(buffer,"%+3.0fdB",val);
readout_set(READOUT(b->readout),buffer);
eq_set(b->number,val);
eq_set(&eq_master_set,b->number,val);
}
......@@ -69,8 +70,8 @@ void eqpanel_create(postfish_mainpanel *mp,
char *shortcut[]={" e "};
subpanel_generic *panel=subpanel_create(mp,windowbutton,&activebutton,
&eq_active,
&eq_visible,
&eq_master_set.panel_active,
&eq_master_set.panel_visible,
"_Equalization filter",shortcut,
0,1);
......@@ -122,10 +123,10 @@ void eqpanel_feedback(int displayit){
}
}
if(pull_eq_feedback(peakfeed,rmsfeed)==1)
if(pull_eq_feedback_master(peakfeed,rmsfeed)==1)
for(i=0;i<eq_freqs;i++)
multibar_set(MULTIBAR(bars[i].slider),rmsfeed[i],peakfeed[i],
input_ch,(displayit && eq_visible));
input_ch,(displayit && eq_master_set.panel_visible));
}
......
This diff is collapsed.
......@@ -25,12 +25,9 @@
#include <fftw3.h>
typedef struct {
time_linkage out;
feedback_generic_pool feedpool;
float **fftwf_buffer; // need one for each channel
fftwf_plan *fftwf_forward; // need one for each channel
fftwf_plan *fftwf_backward; // need one for each channel
float *fftwf_buffer;
fftwf_plan fftwf_forward;
fftwf_plan fftwf_backward;
int qblocksize;
int bands;
......@@ -39,24 +36,45 @@ typedef struct {
float *ho_area;
float *window;
float **lap;
float **cache;
} freq_class_setup;
typedef struct {
time_linkage out;
feedback_generic_pool feedpool;
freq_class_setup *fc;
int *activeP;
int *active1;
int *active0;
u_int32_t mutemask0;
u_int32_t mutemask1;
u_int32_t mutemaskP;
float **lap1;
float **lap0;
float **lapC;
float **cache1;
float **cache0;
int cache_samples;
int fillstate; /* 0: uninitialized
1: half-primed
2: nominal
3: eof processed */
float **peak;
float **rms;
} 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,const float *frequencies, int bands);
extern int freq_class_load(freq_class_setup *f,const float *frequencies, int bands);
extern int freq_load(freq_state *f,freq_class_setup *fc);
extern int freq_reset(freq_state *f);
extern time_linkage *freq_read(time_linkage *in, freq_state *f,
void (*func)(freq_state *f,
float **data,
float **peak, float **rms),
int bypassp);
extern void freq_metric_work(float *work,freq_state *f,
float *sq_mags,float *peak,float *rms);
extern time_linkage *freq_read(time_linkage *in,
freq_state *f,
int *visible, int *active,
void (*func)(float *,int i));
......@@ -526,12 +526,14 @@ static void push_feedback(multicompand_state *ms,int bypass,int maxmaxbands){
static void multicompand_work_master(void *vs){
multicompand_state *ms=(multicompand_state *)vs;
int i,bypass_visible=1;
int i,j,bypass_visible=1;
int maxmaxbands=0;
for(i=0;i<multicomp_freqs_max;i++){
memset(ms->peak[i],0,input_ch*sizeof(**ms->peak));
memset(ms->rms[i],0,input_ch*sizeof(**ms->rms));
for(j=0;j<input_ch;j++){
ms->peak[i][j]=-150.;
ms->rms[i][j]=-150;
}
}
for(i=0;i<input_ch;i++){
......@@ -546,12 +548,14 @@ static void multicompand_work_master(void *vs){
static void multicompand_work_channel(void *vs){
multicompand_state *ms=(multicompand_state *)vs;
int i,bypass_visible=1;
int i,j,bypass_visible=1;
int maxmaxbands=0;
for(i=0;i<multicomp_freqs_max;i++){
memset(ms->peak[i],0,input_ch*sizeof(**ms->peak));
memset(ms->rms[i],0,input_ch*sizeof(**ms->rms));
for(j=0;j<input_ch;j++){
ms->peak[i][j]=-150.;
ms->rms[i][j]=-150;
}
}
for(i=0;i<input_ch;i++){
......
......@@ -250,11 +250,7 @@ void *playback_thread(void *dummy){
link=singlecomp_read_master(link);
result|=link->samples;
for(i=0;i<input_ch;i++)
if(mute_channel_muted(link->active,i))
memset(link->data[i],0,sizeof(**link->data)*input_size);
link=eq_read(link);
link=eq_read_master(link);
result|=link->samples;
if(!result)break;
......@@ -271,6 +267,10 @@ void *playback_thread(void *dummy){
/* the limiter is single-block zero additional latency */
for(i=0;i<input_ch;i++)
if(mute_channel_muted(link->active,i))
memset(link->data[i],0,sizeof(**link->data)*input_size);
link=limit_read(link);
/************/
......@@ -392,6 +392,7 @@ void *playback_thread(void *dummy){
}
fclose(playback_fd);
}
pipeline_reset();
playback_active=0;
playback_exit=0;
if(audiobuf)free(audiobuf);
......
#define VERSION "$Id$ "
/* DO NOT EDIT: Automated versioning hack [Sat Apr 24 01:12:30 EDT 2004] */
/* DO NOT EDIT: Automated versioning hack [Mon Apr 26 02:02:47 EDT 2004] */
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