[xiph-commits] r18349 - trunk/spectrum
xiphmont at svn.xiph.org
xiphmont at svn.xiph.org
Sat Jun 2 18:22:51 PDT 2012
Author: xiphmont
Date: 2012-06-02 18:22:50 -0700 (Sat, 02 Jun 2012)
New Revision: 18349
Modified:
trunk/spectrum/analyzer.h
trunk/spectrum/io.c
trunk/spectrum/io.h
trunk/spectrum/spec_panel.c
trunk/spectrum/spec_plot.c
trunk/spectrum/spec_plot.h
trunk/spectrum/spec_process.c
trunk/spectrum/version.h
Log:
Modify fish to not spin when input is suspended
runbutton now down at start instaed of waiting for data
Wholesale rework of data/locking flow between io and ui threads; spectrum is now close to being able to reconfig on the fly when a pipe is closed and reopened with a fresh data stream/new header
Modified: trunk/spectrum/analyzer.h
===================================================================
--- trunk/spectrum/analyzer.h 2012-06-02 16:38:29 UTC (rev 18348)
+++ trunk/spectrum/analyzer.h 2012-06-03 01:22:50 UTC (rev 18349)
@@ -1,24 +1,24 @@
/*
*
* gtk2 spectrum analyzer
- *
+ *
* Copyright (C) 2004-2012 Monty
*
* This analyzer 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.
- *
+ *
* The analyzer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with Postfish; see the file COPYING. If not, write to the
* Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
- *
+ *
*/
#ifndef _ANALYZER_H_
@@ -40,6 +40,7 @@
#include <signal.h>
#include <fcntl.h>
#include <fftw3.h>
+#include "spec_plot.h"
/* blocksize for the FFT */
extern int blocksize;
@@ -83,27 +84,16 @@
extern void *process_thread(void *dummy);
extern void process_dump(int mode);
extern void rundata_clear();
-extern void clear_noise_floor();
-extern float **process_fetch(int scale, int mode, int link,
- int *active, int width,
- float *ymax, float *pmax, float *pmin);
+extern fetchdata *process_fetch(int scale, int mode, int link,
+ int *process, int process_n,
+ int height, int width);
-extern pthread_mutex_t feedback_mutex;
-extern int feedback_increment;
-extern float **feedback_acc;
-extern float **feedback_max;
-extern float **feedback_instant;
-extern float **feedback_rp;
-extern sig_atomic_t acc_clear;
extern sig_atomic_t acc_rewind;
extern sig_atomic_t acc_loop;
-
extern sig_atomic_t process_active;
extern sig_atomic_t process_exit;
#define LINKS 5
-static char *link_entries[LINKS]={"independent","sum","subtract ref","subtract from",
- "response/phase"};
#define LINK_INDEPENDENT 0
#define LINK_SUMMED 1
#define LINK_SUB_REF 2
Modified: trunk/spectrum/io.c
===================================================================
--- trunk/spectrum/io.c 2012-06-02 16:38:29 UTC (rev 18348)
+++ trunk/spectrum/io.c 2012-06-03 01:22:50 UTC (rev 18349)
@@ -39,7 +39,6 @@
int rate_force[MAX_FILES] = {0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0};
int signed_force[MAX_FILES] = {0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0};
-extern sig_atomic_t acc_loop;
extern int blocksize;
int blockslice[MAX_FILES]= {-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1};
@@ -425,6 +424,21 @@
return 0;
}
+/* attempts to reopen any inputs that are pipes. Does not check for
+ EOF, ignores non-fifo inputs. Returns nonzero if any pipes
+ reopened. */
+
+int pipe_reload(){
+ int fi;
+ int ret=0;
+ for(fi=0;fi<inputs;fi++)
+ if(!seekable[fi] && isapipe[fi] && !load_one_input(fi)){
+ fprintf(stderr,"reloading....\n");
+ ret=1;
+ }
+ return ret;
+}
+
/* Convert new data from readbuffer into the blockbuffers until the
blockbuffer is full */
static void LBEconvert(int *localslice){
@@ -608,28 +622,21 @@
inputname[fi],strerror(ferror(f[fi])));
}else if (actually_readbytes==0){
/* real, hard EOF/error in a partially filled block */
- /* if this input is a pipe, reload its input state */
- if(!seekable[fi] && isapipe[fi] && !load_one_input(fi)){
- fprintf(stderr,"reloading....\n");
+ if(!partialok){
+ /* partial frame is *not* ok. zero it out. */
+ memset(readbuffer[fi],0,readbuffersize);
+ bytesleft[fi]=0;
+ readbufferfill[fi]=0;
+ readbufferptr[fi]=0;
+ blockbufferfill[fi]=0;
+ }
+ if(loop && seekable[fi] && (!rewound[fi] || (partialok && blockbufferfill[fi]))){
+ /* rewind this file and continue */
+ fseek(f[fi],offset[fi],SEEK_SET);
+ if(length[fi]!=-1)
+ bytesleft[fi]=length[fi]*channels[fi]*((bits[fi]+7)/8);
notdone=1;
- }else{
-
- if(!partialok){
- /* partial frame is *not* ok. zero it out. */
- memset(readbuffer[fi],0,readbuffersize);
- bytesleft[fi]=0;
- readbufferfill[fi]=0;
- readbufferptr[fi]=0;
- blockbufferfill[fi]=0;
- }
- if(loop && (!rewound[fi] || (partialok && blockbufferfill[fi]))){
- /* rewind this file and continue */
- fseek(f[fi],offset[fi],SEEK_SET);
- if(length[fi]!=-1)
- bytesleft[fi]=length[fi]*channels[fi]*((bits[fi]+7)/8);
- notdone=1;
- rewound[fi]=1;
- }
+ rewound[fi]=1;
}
}else{
/* got a read */
Modified: trunk/spectrum/io.h
===================================================================
--- trunk/spectrum/io.h 2012-06-02 16:38:29 UTC (rev 18348)
+++ trunk/spectrum/io.h 2012-06-03 01:22:50 UTC (rev 18349)
@@ -48,6 +48,7 @@
extern pthread_mutex_t ioparam_mutex;
extern int input_load(void);
+extern int pipe_reload(void);
extern int input_read(int loop_p, int partial_p);
extern int rewind_files(void);
Modified: trunk/spectrum/spec_panel.c
===================================================================
--- trunk/spectrum/spec_panel.c 2012-06-02 16:38:29 UTC (rev 18348)
+++ trunk/spectrum/spec_panel.c 2012-06-03 01:22:50 UTC (rev 18349)
@@ -18,7 +18,7 @@
* along with Postfish; see the file COPYING. If not, write to the
* Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
- *
+ *
*/
#include "analyzer.h"
@@ -26,32 +26,29 @@
#include <gdk/gdkkeysyms.h>
#include "fisharray.h"
#include "spec_plot.h"
-#include "io.h"
-sig_atomic_t increment_fish=0;
+GtkWidget *twirlimage;
+GdkPixmap *ff[19];
+GdkBitmap *fb[19];
-static struct panel {
- GtkWidget *twirlimage;
- GdkPixmap *ff[19];
- GdkBitmap *fb[19];
+GtkAccelGroup *group;
+GtkWidget *toplevel;
- GtkAccelGroup *group;
- GtkWidget *toplevel;
+guint fishframe_timer;
+int fishframe_init;
+int fishframe;
+GtkWidget *plot;
+GtkWidget *run;
+GtkWidget **chbuttons;
+GtkWidget *bwtable;
+GtkWidget *bwbutton;
+GtkWidget *bwmodebutton;
+GtkWidget *plot_label_al;
- guint fishframe_timer;
- int fishframe_init;
- int fishframe;
+int plot_ch=0;
+int plot_inputs=0;
- GtkWidget *plot;
- GtkWidget *run;
- GtkWidget **chbuttons;
- GtkWidget *bwtable;
- GtkWidget *bwbutton;
- GtkWidget *bwmodebutton;
- GtkWidget *plot_label_al;
-} p;
-
int plot_scale=0;
int plot_mode=0;
int plot_link=0;
@@ -59,117 +56,304 @@
int plot_lock_y=0;
int plot_depth=90;
int plot_noise=0;
-int plot_last_update=0;
int plot_bw=0;
int plot_bwmode=0;
int plot_bold=0;
int *active;
-static void override_base(GtkWidget *w, int active){
- gtk_widget_modify_base (w, GTK_STATE_NORMAL, &w->style->bg[active?GTK_STATE_ACTIVE:GTK_STATE_NORMAL]);
-}
+/* first up... the Fucking Fish */
+sig_atomic_t increment_fish=0;
-static void replot(struct panel *p){
- int i,lactive[total_ch];
- for(i=0;i<total_ch;i++)
- lactive[i]=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(p->chbuttons[i]));
-
- /* update the spectral display; send new data */
- if(!plot_hold){
- pthread_mutex_lock(&feedback_mutex);
- plot_refresh(PLOT(p->plot),lactive);
- plot_last_update=feedback_increment;
- pthread_mutex_unlock(&feedback_mutex);
- }
-}
-
-static void shutdown(void){
- gtk_main_quit();
-}
-
-/* gotta have the Fucking Fish */
-static int reanimate_fish(struct panel *p){
- if(process_active || (p->fishframe>0 && p->fishframe<12)){
+static int reanimate_fish(void){
+ if(process_active || (fishframe>0 && fishframe<12)){
/* continue spinning */
- if(increment_fish)p->fishframe++;
- if(p->fishframe>=12)p->fishframe=0;
+ if(increment_fish || fishframe>0)fishframe++;
+ if(fishframe==1)increment_fish=0;
+ if(fishframe>=12)fishframe=0;
- gtk_image_set_from_pixmap(GTK_IMAGE(p->twirlimage),
- p->ff[p->fishframe],
- p->fb[p->fishframe]);
+ gtk_image_set_from_pixmap(GTK_IMAGE(twirlimage),
+ ff[fishframe],
+ fb[fishframe]);
- if(p->fishframe==0 && !process_active){
+ if(fishframe==0 && !process_active){
/* reschedule to blink */
- p->fishframe_timer=
- g_timeout_add(rand()%1000*30,(GSourceFunc)reanimate_fish,p);
+ fishframe_timer=
+ g_timeout_add(rand()%1000*30,(GSourceFunc)reanimate_fish,NULL);
return FALSE;
}
}else{
- p->fishframe++;
- if(p->fishframe<=1)p->fishframe=12;
- if(p->fishframe>=19)p->fishframe=0;
+ fishframe++;
+ if(fishframe<=1)fishframe=12;
+ if(fishframe>=19)fishframe=0;
- gtk_image_set_from_pixmap(GTK_IMAGE(p->twirlimage),
- p->ff[p->fishframe],
- p->fb[p->fishframe]);
+ gtk_image_set_from_pixmap(GTK_IMAGE(twirlimage),
+ ff[fishframe],
+ fb[fishframe]);
- if(p->fishframe==12){
+ if(fishframe==12){
/* reschedule to animate */
- p->fishframe_timer=
- g_timeout_add(10,(GSourceFunc)reanimate_fish,p);
+ fishframe_timer=
+ g_timeout_add(10,(GSourceFunc)reanimate_fish,NULL);
return FALSE;
}
- if(p->fishframe==0){
+ if(fishframe==0){
/* reschedule to blink */
- p->fishframe_timer=
- g_timeout_add(rand()%1000*30,(GSourceFunc)reanimate_fish,p);
+ fishframe_timer=
+ g_timeout_add(rand()%1000*30,(GSourceFunc)reanimate_fish,NULL);
return FALSE;
}
}
return TRUE;
}
-static void animate_fish(struct panel *p){
- if(p->fishframe_init){
- g_source_remove(p->fishframe_timer);
- p->fishframe_timer=
- g_timeout_add(70,(GSourceFunc)reanimate_fish,p);
+static void animate_fish(void){
+ if(fishframe_init){
+ g_source_remove(fishframe_timer);
+ fishframe_timer=
+ g_timeout_add(70,(GSourceFunc)reanimate_fish,NULL);
}else{
- p->fishframe_init=1;
- p->fishframe_timer=
- g_timeout_add(rand()%1000*30,(GSourceFunc)reanimate_fish,p);
+ fishframe_init=1;
+ fishframe_timer=
+ g_timeout_add(rand()%1000*30,(GSourceFunc)reanimate_fish,NULL);
}
}
-static void dump(GtkWidget *widget,struct panel *p){
- process_dump(plot_mode);
+/* autoscale movement calculation and damping */
+
+typedef struct {
+ float a;
+ float b1;
+ float b2;
+ float x[2];
+ float y[2];
+} pole2;
+
+static float plot_ymax_target;
+static int plot_ymaxtimer;
+static pole2 plot_ymax_damp;
+static float plot_pmax_target;
+static pole2 plot_pmax_damp;
+static int plot_pmaxtimer;
+static float plot_pmin_target;
+static pole2 plot_pmin_damp;
+static int plot_pmintimer;
+
+static void filter_reset(pole2 *p, float val){
+ p->x[0]=p->x[1]=val;
+ p->y[0]=p->y[1]=val;
}
-#if 0
-static void noise(GtkWidget *widget,struct panel *p){
- if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))){
- if(plot_noise){
- plot_noise=0;
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget),0);
- clear_noise_floor();
- plot_setting(PLOT(p->plot),plot_scale,plot_mode,plot_link,plot_depth,0);
+static void filter_make_critical(float w, pole2 *f){
+ float w0 = tan(M_PI*w*pow(pow(2,.5)-1,-.5));
+ f->a = w0*w0/(1+(2*w0)+w0*w0);
+ f->b1 = 2*f->a*(1/(w0*w0)-1);
+ f->b2 = 1-(4*f->a+f->b1);
+ filter_reset(f,0);
+}
+
+static float filter_filter(float x, pole2 *p){
+ float y =
+ p->a*x + 2*p->a*p->x[0] + p->a*p->x[1] +
+ p->b1*p->y[0] + p->b2*p->y[1];
+ p->y[1] = p->y[0]; p->y[0] = y;
+ p->x[1] = p->x[0]; p->x[0] = x;
+ return y;
+}
+
+#define HYSTERESIS_THRESHOLD .25
+#define HYSTERESIS_TIMERFRAMES 30
+
+static void calculate_autoscale (fetchdata *f,
+ plotparams *pp,
+ int request_reset){
+ int phase = f->phase_active;
+ int height = f->height;
+ int plot_ymax_limit = (plot_depth>140 ? plot_depth : 140);
+ float ymax = f->ymax;
+ float pmax = f->pmax;
+ float pmin = f->pmin;
+
+ /* graph limit updates are conditional depending on mode/link */
+ switch(f->link){
+ case LINK_INDEPENDENT:
+ case LINK_SUMMED:
+ case LINK_PHASE:
+ {
+ float dBpp = plot_depth/height;
+ ymax += dBpp*25;
+ }
+ break;
+ }
+
+ if(ymax<plot_depth - plot_ymax_limit) ymax=plot_depth-plot_ymax_limit;
+ if(ymax>plot_ymax_limit)ymax=plot_ymax_limit;
+
+ pmax+=10;
+ pmin-=10;
+ if(pmax<5)pmax=5;
+ if(pmax>190)pmax=190;
+ if(pmin>-20)pmin=-20;
+ if(pmin<-190)pmin=-190;
+
+ /* phase/response zeros align on phase graphs; verify targets
+ against phase constraints */
+ if(phase){
+ float pzero,mzero = height/plot_depth*ymax;
+
+ /* move mag zero back onscreen if it's off */
+ if(mzero < height*HYSTERESIS_THRESHOLD){
+ ymax = (plot_depth*height*HYSTERESIS_THRESHOLD)/height;
+ }
+ if(mzero > height*(1-HYSTERESIS_THRESHOLD)){
+ ymax = (plot_depth*height*(1-HYSTERESIS_THRESHOLD))/height;
+ }
+
+ mzero = height/plot_depth*ymax;
+ pzero = height/(pmax-pmin)*pmax;
+
+ if(mzero<pzero){
+ /* straightforward; move the dB range down */
+ ymax = pzero*plot_depth/height;
}else{
- plot_noise=1;
- plot_setting(PLOT(p->plot),plot_scale,plot_mode,plot_link,plot_depth,0);
+ /* a little harder as phase has a min and a max.
+ First increase the pmax to match the dB zero. */
+
+ pmax = pmin/(1-height/mzero);
+ pzero = height/(pmax-pmin)*pmax;
+
+ /* That worked, but might have run pmax overrange */
+ if(pmax>190.){
+ /* reconcile by allowing mag to overrange */
+ pmax = 190.;
+ pzero = height/(pmax-pmin)*pmax;
+ ymax = plot_depth*pzero/height;
+ plot_ymaxtimer=0;
+ }
}
+ }
+
+ if(request_reset){
+ pp->ymax=plot_ymax_target=ymax;
+ filter_reset(&plot_ymax_damp,pp->ymax);
+ plot_ymaxtimer=HYSTERESIS_TIMERFRAMES;
+
+ if(phase){
+ pp->pmax=plot_pmax_target=pmax;
+ pp->pmin=plot_pmin_target=pmin;
+ filter_reset(&plot_pmax_damp,pp->pmax);
+ filter_reset(&plot_pmin_damp,pp->pmin);
+ plot_pmaxtimer=HYSTERESIS_TIMERFRAMES;
+ plot_pmintimer=HYSTERESIS_TIMERFRAMES;
+ }
+
}else{
- if(plot_noise){
- gtk_button_set_label(GTK_BUTTON(widget),"clear _noise floor");
- plot_noise=2;
- plot_setting(PLOT(p->plot),plot_scale,plot_mode,plot_link,plot_depth,1);
- }else
- gtk_button_set_label(GTK_BUTTON(widget),"sample _noise floor");
+ /* conditionally set new damped ymax target */
+ if(plot_ymaxtimer>0)
+ plot_ymaxtimer--;
+
+ if(ymax > plot_ymax_target-plot_depth*HYSTERESIS_THRESHOLD)
+ plot_ymaxtimer=HYSTERESIS_TIMERFRAMES;
+
+ if(ymax > plot_ymax_target || plot_ymaxtimer<=0)
+ plot_ymax_target=ymax;
+
+ /* update ymax through scale damping filter */
+ pp->ymax = filter_filter(plot_ymax_target,&plot_ymax_damp);
+
+ /* apply same hyteresis and update to phase */
+ if(phase){
+
+ if(plot_pmaxtimer>0)
+ plot_pmaxtimer--;
+ if(plot_pmintimer>0)
+ plot_pmintimer--;
+
+ if(pmax > plot_pmax_target*(1-HYSTERESIS_THRESHOLD))
+ plot_pmaxtimer=HYSTERESIS_TIMERFRAMES;
+ if(pmax > plot_pmax_target || plot_pmaxtimer<=0)
+ plot_pmax_target=pmax;
+
+ if(pmin < plot_pmin_target*(1-HYSTERESIS_THRESHOLD))
+ plot_pmintimer=HYSTERESIS_TIMERFRAMES;
+ if(pmin < plot_pmin_target || plot_pmintimer<=0)
+ plot_pmin_target=pmin;
+
+ pp->pmax = filter_filter(plot_pmax_target,&plot_pmax_damp);
+ pp->pmin = filter_filter(plot_pmin_target,&plot_pmin_damp);
+
+ }
}
+
+ if(phase){
+ /* when phase is active, the plot_ymax in use is dictated by
+ plot_pmax/plot_pmin, which in turn already took the desired ymax
+ into consideration above */
+ pp->ymax = plot_depth*pp->pmax/(pp->pmax-pp->pmin);
+ }
}
-#endif
-static void depthchange(GtkWidget *widget,struct panel *p){
+/* a gtk2 hack to override checkbox background color */
+static void override_base(GtkWidget *w, int active){
+ gtk_widget_modify_base
+ (w, GTK_STATE_NORMAL,
+ &w->style->bg[active?GTK_STATE_ACTIVE:GTK_STATE_NORMAL]);
+}
+
+/* scale_reset != 0 requests an instant optimal rescale */
+/* inactive_reset performs a reset only if processing is not active */
+/* scale_damp != 0 requests a normal animated rescaling operation.
+ It processing is not active, this is promoted to
+ an instant optimal rescale */
+/* plot_lock_y overrides all scaling requests */
+
+static plotparams pp;
+static int oldphase=0;
+void replot(int scale_reset, int inactive_reset, int scale_damp){
+ int i,process[plot_ch];
+
+ for(i=0;i<plot_ch;i++)
+ process[i]=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(chbuttons[i]));
+
+ /* update the spectral display; send new data */
+ fetchdata *f = process_fetch
+ (plot_scale, plot_mode, plot_link,
+ process, plot_ch, plot_height(PLOT(plot)), plot_width(PLOT(plot)));
+
+ /* the fetched data may indicate the underlying file data has
+ changed... */
+ if(f->reload){
+ /* rebuild the button and file lists */
+
+
+
+ }
+
+
+ if(!plot_lock_y){
+ if(scale_reset ||
+ (f->phase_active != oldphase) ||
+ (!process_active && (inactive_reset || scale_damp)))
+ calculate_autoscale(f,&pp,1);
+ else if(scale_damp)
+ calculate_autoscale(f,&pp,0);
+ }
+ oldphase = f->phase_active;
+
+ pp.depth=plot_depth;
+ pp.bold=plot_bold;
+ plot_draw(PLOT(plot),f,&pp);
+}
+
+static void shutdown(void){
+ gtk_main_quit();
+}
+
+static void dump(GtkWidget *widget,gpointer in){
+ process_dump(plot_mode);
+}
+
+static void depthchange(GtkWidget *widget,gpointer in){
int choice=gtk_combo_box_get_active(GTK_COMBO_BOX(widget));
switch(choice){
case 0: /* 1dB */
@@ -190,11 +374,11 @@
case 5: /*140dB */
plot_depth=140;
break;
- case 6: /*200dB */
- plot_depth=200;
+ case 6: /*190dB */
+ plot_depth=190;
break;
}
- plot_setting(PLOT(p->plot),plot_scale,plot_mode,plot_link,plot_depth,plot_noise);
+ replot(1,1,0);
}
static void set_fg(GtkWidget *c, gpointer in){
@@ -209,152 +393,122 @@
gtk_container_forall (GTK_CONTAINER(c),set_fg,in);
}
-static void set_via_active(struct panel *p, int *active, int *bactive){
- int fi,i;
- int ch=0;
- for(fi=0;fi<inputs;fi++){
- for(i=ch;i<ch+channels[fi];i++)
- gtk_widget_set_sensitive(p->chbuttons[i],1);
- ch+=channels[fi];
- }
- plot_set_active(PLOT(p->plot),active,bactive);
- gtk_alignment_set_padding(GTK_ALIGNMENT(p->plot_label_al),0,0,0,plot_get_right_pad(PLOT(p->plot)));
-}
-
-static void chlabels(GtkWidget *widget,struct panel *p){
+static void chlabels(GtkWidget *widget,gpointer in){
/* scan state, update labels on channel buttons, set sensitivity
based on grouping and mode */
int fi,ch,i;
char buf[80];
- int bactive[total_ch];
- for(i=0;i<total_ch;i++)
- bactive[i]=active[i]=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(p->chbuttons[i]));
-
/* set sensitivity */
switch(plot_link){
case LINK_SUB_REF:
-
- /* first channel in each group insensitive/inactive, used as a reference */
+ /* first channel in each group insensitive/inactive, used as a
+ reference */
ch=0;
- for(fi=0;fi<inputs;fi++){
+ for(fi=0;fi<plot_inputs;fi++){
for(i=ch;i<ch+channels[fi];i++){
if(i==ch){
- gtk_widget_set_sensitive(p->chbuttons[i],0);
- active[i]=0; /* do not frob widget, only plot settings */
+ gtk_widget_set_sensitive(chbuttons[i],0);
}else{
- gtk_widget_set_sensitive(p->chbuttons[i],1);
+ gtk_widget_set_sensitive(chbuttons[i],1);
}
}
ch+=channels[fi];
}
-
- plot_set_active(PLOT(p->plot),active,bactive);
- break;
+ break;
case LINK_SUMMED: /* summing mode */
case LINK_SUB_FROM: /* subtract channels from reference */
+ case LINK_INDEPENDENT: /* normal/independent mode */
+
ch=0;
- for(fi=0;fi<inputs;fi++){
- int any=0;
- for(i=ch;i<ch+channels[fi];i++){
- if(active[i])any=1;
- active[i]=0;
- }
- active[ch]=any;
+ for(fi=0;fi<plot_inputs;fi++){
+ for(i=ch;i<ch+channels[fi];i++)
+ gtk_widget_set_sensitive(chbuttons[i],1);
ch+=channels[fi];
}
-
- set_via_active(p,active,bactive);
break;
- case LINK_INDEPENDENT: /* normal/independent mode */
- set_via_active(p,active,bactive);
- break;
-
case LINK_PHASE: /* response/phase */
ch=0;
- for(fi=0;fi<inputs;fi++){
+ for(fi=0;fi<plot_inputs;fi++){
for(i=ch;i<ch+channels[fi];i++)
if(channels[fi]<2){
- gtk_widget_set_sensitive(p->chbuttons[i],0);
- active[i]=0;
+ gtk_widget_set_sensitive(chbuttons[i],0);
}else{
if(i<ch+2){
- gtk_widget_set_sensitive(p->chbuttons[i],1);
+ gtk_widget_set_sensitive(chbuttons[i],1);
}else{
- gtk_widget_set_sensitive(p->chbuttons[i],0);
- active[i]=0;
+ gtk_widget_set_sensitive(chbuttons[i],0);
}
}
ch+=channels[fi];
}
- plot_set_active(PLOT(p->plot),active,bactive);
- break;
+ break;
}
/* set labels */
switch(plot_link){
case LINK_SUB_REF:
ch=0;
- for(fi=0;fi<inputs;fi++){
+ for(fi=0;fi<plot_inputs;fi++){
for(i=ch;i<ch+channels[fi];i++){
if(i==ch){
- gtk_button_set_label(GTK_BUTTON(p->chbuttons[i]),"reference");
+ gtk_button_set_label(GTK_BUTTON(chbuttons[i]),"reference");
}else{
sprintf(buf,"channel %d", i-ch);
- gtk_button_set_label(GTK_BUTTON(p->chbuttons[i]),buf);
+ gtk_button_set_label(GTK_BUTTON(chbuttons[i]),buf);
}
}
ch+=channels[fi];
}
- break;
+ break;
case LINK_SUB_FROM:
ch=0;
- for(fi=0;fi<inputs;fi++){
+ for(fi=0;fi<plot_inputs;fi++){
for(i=ch;i<ch+channels[fi];i++){
if(i==ch){
- gtk_button_set_label(GTK_BUTTON(p->chbuttons[i]),"output");
+ gtk_button_set_label(GTK_BUTTON(chbuttons[i]),"output");
}else{
sprintf(buf,"channel %d", i-ch);
- gtk_button_set_label(GTK_BUTTON(p->chbuttons[i]),buf);
+ gtk_button_set_label(GTK_BUTTON(chbuttons[i]),buf);
}
}
ch+=channels[fi];
}
- break;
+ break;
case LINK_INDEPENDENT:
case LINK_SUMMED:
ch=0;
- for(fi=0;fi<inputs;fi++){
+ for(fi=0;fi<plot_inputs;fi++){
for(i=ch;i<ch+channels[fi];i++){
sprintf(buf,"channel %d", i-ch);
- gtk_button_set_label(GTK_BUTTON(p->chbuttons[i]),buf);
+ gtk_button_set_label(GTK_BUTTON(chbuttons[i]),buf);
}
ch+=channels[fi];
}
- break;
+ break;
case LINK_PHASE:
ch=0;
- for(fi=0;fi<inputs;fi++){
+ for(fi=0;fi<plot_inputs;fi++){
for(i=ch;i<ch+channels[fi];i++){
if(channels[fi]<2){
- gtk_button_set_label(GTK_BUTTON(p->chbuttons[i]),"unused");
+ gtk_button_set_label(GTK_BUTTON(chbuttons[i]),"unused");
}else if(i==ch){
- gtk_button_set_label(GTK_BUTTON(p->chbuttons[i]),"response");
+ gtk_button_set_label(GTK_BUTTON(chbuttons[i]),"response");
}else if(i==ch+1){
- gtk_button_set_label(GTK_BUTTON(p->chbuttons[i]),"phase");
+ gtk_button_set_label(GTK_BUTTON(chbuttons[i]),"phase");
}else{
- gtk_button_set_label(GTK_BUTTON(p->chbuttons[i]),"unused");
+ gtk_button_set_label(GTK_BUTTON(chbuttons[i]),"unused");
}
}
ch+=channels[fi];
}
- break;
+ break;
}
/* set colors */
@@ -362,11 +516,11 @@
case LINK_SUMMED:
case LINK_SUB_FROM:
ch=0;
- for(fi=0;fi<inputs;fi++){
+ for(fi=0;fi<plot_inputs;fi++){
GdkColor rgb = chcolor(ch);
for(i=ch;i<ch+channels[fi];i++){
- GtkWidget *button=p->chbuttons[i];
+ GtkWidget *button=chbuttons[i];
set_fg(button,&rgb);
}
ch+=channels[fi];
@@ -375,113 +529,104 @@
default:
ch=0;
- for(fi=0;fi<inputs;fi++){
+ for(fi=0;fi<plot_inputs;fi++){
for(i=ch;i<ch+channels[fi];i++){
GdkColor rgb = chcolor(i);
- GtkWidget *button=p->chbuttons[i];
+ GtkWidget *button=chbuttons[i];
set_fg(button,&rgb);
}
ch+=channels[fi];
}
break;
}
- gtk_alignment_set_padding(GTK_ALIGNMENT(p->plot_label_al),0,0,0,plot_get_right_pad(PLOT(p->plot)));
+
+ if(widget)replot(0,1,0);
+ gtk_alignment_set_padding(GTK_ALIGNMENT(plot_label_al),0,0,0,
+ plot_get_right_pad(PLOT(plot)));
}
-static void scalechange(GtkWidget *widget,struct panel *p){
+static void scalechange(GtkWidget *widget,gpointer in){
plot_scale=gtk_combo_box_get_active(GTK_COMBO_BOX(widget));
- plot_setting(PLOT(p->plot),plot_scale,plot_mode,plot_link,plot_depth,plot_noise);
+ replot(0,0,0);
}
-static void modechange(GtkWidget *widget,struct panel *p){
+static void modechange(GtkWidget *widget,gpointer in){
plot_mode=gtk_combo_box_get_active(GTK_COMBO_BOX(widget));
- replot(p);
- plot_setting(PLOT(p->plot),plot_scale,plot_mode,plot_link,plot_depth,plot_noise);
+ replot(0,1,0);
}
-static void linkchange(GtkWidget *widget,struct panel *p){
+static void linkchange(GtkWidget *widget,gpointer in){
plot_link=gtk_combo_box_get_active(GTK_COMBO_BOX(widget));
- replot(p);
- plot_setting(PLOT(p->plot),plot_scale,plot_mode,plot_link,plot_depth,plot_noise);
- chlabels(widget,p);
- gtk_alignment_set_padding(GTK_ALIGNMENT(p->plot_label_al),0,0,0,plot_get_right_pad(PLOT(p->plot)));
+ chlabels(NULL,NULL);
+ gtk_alignment_set_padding(GTK_ALIGNMENT(plot_label_al),
+ 0,0,0,plot_get_right_pad(PLOT(plot)));
+ replot(0,1,0);
}
-static void runchange(GtkWidget *widget,struct panel *p){
+static void runchange(GtkWidget *widget,gpointer in){
if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))){
if(!process_active){
pthread_t thread_id;
process_active=1;
process_exit=0;
- animate_fish(p);
+ animate_fish();
pthread_create(&thread_id,NULL,&process_thread,NULL);
}
}else{
process_exit=1;
- while(process_active)sched_yield();
+ //while(process_active)sched_yield();
}
}
-static void holdchange(GtkWidget *widget,struct panel *p){
+static void holdchange(GtkWidget *widget,gpointer in){
plot_hold=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
override_base(widget,plot_hold);
- replot(p);
- plot_draw(PLOT(p->plot));
+ replot(0,1,0);
}
-static void lockchange(GtkWidget *widget,struct panel *p){
+static void lockchange(GtkWidget *widget,gpointer in){
plot_lock_y=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
override_base(widget,plot_lock_y);
- plot_set_autoscale(PLOT(p->plot),!plot_lock_y);
+ if(!plot_lock_y)replot(0,1,0);
}
-static void boldchange(GtkWidget *widget,struct panel *p){
+static void boldchange(GtkWidget *widget,gpointer in){
plot_bold=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
override_base(widget,plot_bold);
- plot_set_bold(PLOT(p->plot),plot_bold);
+ replot(0,0,0);
}
-static void loopchange(GtkWidget *widget,struct panel *p){
+static void loopchange(GtkWidget *widget,gpointer in){
acc_loop=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
}
-static void clearchange(GtkWidget *widget,struct panel *p){
- acc_clear=1;
- plot_clear(PLOT(p->plot));
- if(!process_active){
- rundata_clear();
- }
+static void clearchange(GtkWidget *widget,gpointer in){
+ rundata_clear();
+ replot(0,0,0);
}
-static void rewindchange(GtkWidget *widget,struct panel *p){
+static void rewindchange(GtkWidget *widget,gpointer in){
acc_rewind=1;
}
-static void bwchange(GtkWidget *widget,struct panel *p){
+static void bwchange(GtkWidget *widget,gpointer in){
plot_bw=gtk_combo_box_get_active(GTK_COMBO_BOX(widget));
if(plot_bw==0){
-
- gtk_widget_set_sensitive(GTK_WIDGET(p->bwmodebutton),0);
- //gtk_widget_hide(p->bwmodebutton);
- //gtk_container_remove(GTK_CONTAINER(p->bwtable),p->bwbutton);
- //gtk_table_attach_defaults(GTK_TABLE(p->bwtable),p->bwbutton,0,2,0,1);
+ gtk_widget_set_sensitive(GTK_WIDGET(bwmodebutton),0);
}else{
-
- gtk_widget_set_sensitive(GTK_WIDGET(p->bwmodebutton),1);
- //gtk_container_remove(GTK_CONTAINER(p->bwtable),p->bwbutton);
- //gtk_table_attach_defaults(GTK_TABLE(p->bwtable),p->bwbutton,0,1,0,1);
- //gtk_widget_show(p->bwmodebutton);
+ gtk_widget_set_sensitive(GTK_WIDGET(bwmodebutton),1);
}
+ replot(0,1,0);
}
-static void bwmodechange(GtkWidget *widget,struct panel *p){
+static void bwmodechange(GtkWidget *widget,gpointer in){
plot_bwmode=gtk_combo_box_get_active(GTK_COMBO_BOX(widget));
+ replot(0,1,0);
}
static gint watch_keyboard(GtkWidget *grab_widget,
GdkEventKey *event,
- gpointer func_data){
- struct panel *p=(struct panel *)func_data;
+ gpointer in){
if(event->type == GDK_KEY_PRESS){
if(event->state == GDK_CONTROL_MASK){
@@ -493,7 +638,7 @@
}
extern char *version;
-void panel_create(struct panel *panel){
+void panel_create(void){
int i;
GdkWindow *root=gdk_get_default_root_window();
@@ -506,16 +651,17 @@
GtkWidget *plot_control_al;
GtkWidget *wbold;
- active = calloc(total_ch,sizeof(*active));
+ active = calloc(plot_ch,sizeof(*active));
- panel->toplevel=gtk_window_new (GTK_WINDOW_TOPLEVEL);
- panel->group = gtk_accel_group_new ();
- gtk_window_add_accel_group (GTK_WINDOW(panel->toplevel), panel->group);
- gtk_window_set_title(GTK_WINDOW(panel->toplevel),(const gchar *)"Spectrum Analyzer");
- gtk_window_set_default_size(GTK_WINDOW(panel->toplevel),1024,400);
- //gtk_widget_set_size_request(GTK_WIDGET(panel->toplevel),1024,400);
- gtk_container_add (GTK_CONTAINER (panel->toplevel), topbox);
- g_signal_connect (G_OBJECT (panel->toplevel), "delete_event",
+ toplevel=gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ group = gtk_accel_group_new ();
+ gtk_window_add_accel_group (GTK_WINDOW(toplevel), group);
+ gtk_window_set_title(GTK_WINDOW(toplevel),
+ (const gchar *)"Spectrum Analyzer");
+ gtk_window_set_default_size(GTK_WINDOW(toplevel),1024,400);
+ //gtk_widget_set_size_request(GTK_WIDGET(toplevel),1024,400);
+ gtk_container_add (GTK_CONTAINER (toplevel), topbox);
+ g_signal_connect (G_OBJECT (toplevel), "delete_event",
G_CALLBACK (shutdown), NULL);
gtk_widget_set_name(topbox,"panel");
@@ -539,20 +685,27 @@
gtk_widget_set_name(lock_range,"top-control");
gtk_widget_set_name(hold_display,"top-control");
gtk_widget_set_name(wbold,"top-control");
- g_signal_connect (G_OBJECT (hold_display), "clicked", G_CALLBACK (holdchange), panel);
- gtk_widget_add_accelerator (hold_display, "activate", panel->group, GDK_h, 0, 0);
- g_signal_connect (G_OBJECT (lock_range), "clicked", G_CALLBACK (lockchange), panel);
- gtk_widget_add_accelerator (lock_range, "activate", panel->group, GDK_y, 0, 0);
- gtk_widget_add_accelerator (lock_range, "activate", panel->group, GDK_Y, 0, 0);
- g_signal_connect (G_OBJECT (wbold), "clicked", G_CALLBACK (boldchange), panel);
- gtk_widget_add_accelerator (wbold, "activate", panel->group, GDK_b, 0, 0);
+ g_signal_connect (G_OBJECT (hold_display), "clicked",
+ G_CALLBACK (holdchange), NULL);
+ gtk_widget_add_accelerator (hold_display, "activate",
+ group, GDK_h, 0, 0);
+ g_signal_connect (G_OBJECT (lock_range), "clicked",
+ G_CALLBACK (lockchange), NULL);
+ gtk_widget_add_accelerator (lock_range, "activate",
+ group, GDK_y, 0, 0);
+ gtk_widget_add_accelerator (lock_range, "activate",
+ group, GDK_Y, 0, 0);
+ g_signal_connect (G_OBJECT (wbold), "clicked",
+ G_CALLBACK (boldchange), NULL);
+ gtk_widget_add_accelerator (wbold, "activate",
+ group, GDK_b, 0, 0);
}
/* plot informational labels */
{
char buf[80];
- GtkWidget *al=panel->plot_label_al=gtk_alignment_new(1,.5,0,0);
+ GtkWidget *al=plot_label_al=gtk_alignment_new(1,.5,0,0);
GtkWidget *box=gtk_hbox_new(0,2);
GtkWidget *text1=gtk_label_new("window:");
GtkWidget *text2=gtk_label_new("sin^4 ");
@@ -577,8 +730,8 @@
}
/* add the spectrum plot box */
- panel->plot=plot_new(blocksize/2+1,inputs,channels,rate);
- gtk_table_attach_defaults (GTK_TABLE (lefttable), panel->plot,0,1,2,3);
+ plot=plot_new();
+ gtk_table_attach_defaults (GTK_TABLE (lefttable), plot,0,1,2,3);
gtk_table_set_row_spacing (GTK_TABLE (lefttable), 2, 4);
gtk_table_set_col_spacing (GTK_TABLE (lefttable), 0, 2);
@@ -607,10 +760,10 @@
w/=19;
for(i=0;i<19;i++){
- panel->ff[i]=gdk_pixmap_new(tp,w,h,-1);
- panel->fb[i]=gdk_pixmap_new(tb,w,h,-1);
- gdk_draw_drawable(panel->ff[i],cgc,tp,i*w,0,0,0,w,h);
- gdk_draw_drawable(panel->fb[i],bgc,tb,i*w,0,0,0,w,h);
+ ff[i]=gdk_pixmap_new(tp,w,h,-1);
+ fb[i]=gdk_pixmap_new(tb,w,h,-1);
+ gdk_draw_drawable(ff[i],cgc,tp,i*w,0,0,0,w,h);
+ gdk_draw_drawable(fb[i],bgc,tb,i*w,0,0,0,w,h);
}
g_object_unref(cgc);
@@ -618,12 +771,12 @@
g_object_unref(tp);
g_object_unref(tb);
- panel->twirlimage=gtk_image_new_from_pixmap(panel->ff[0],panel->fb[0]);
+ twirlimage=gtk_image_new_from_pixmap(ff[0],fb[0]);
gtk_container_set_border_width (GTK_CONTAINER (toptable), 1);
gtk_box_pack_start(GTK_BOX(righttopbox),toptable,0,0,0);
gtk_container_add (GTK_CONTAINER (sepbox), topsep);
- gtk_container_add(GTK_CONTAINER(fishbox),panel->twirlimage);
+ gtk_container_add(GTK_CONTAINER(fishbox),twirlimage);
gtk_table_attach_defaults (GTK_TABLE (toptable), fishbox,0,1,1,2);
gtk_table_attach_defaults (GTK_TABLE (toptable), sepbox,0,1,1,2);
gtk_table_set_row_spacing (GTK_TABLE (toptable), 0, 6);
@@ -638,27 +791,28 @@
char buffer[160];
GtkWidget *label;
- panel->chbuttons = calloc(total_ch,sizeof(*panel->chbuttons));
- for(fi=0;fi<inputs;fi++){
+ chbuttons = calloc(plot_ch,sizeof(*chbuttons));
+ for(fi=0;fi<plot_inputs;fi++){
GtkWidget *al=gtk_alignment_new(0,0,1,0);
GtkWidget *vbox=gtk_vbox_new(0,0);
-
+
char *lastslash = strrchr(inputname[fi],'/');
sprintf(buffer,"%s",(lastslash?lastslash+1:inputname[fi]));
label=gtk_label_new(buffer);
gtk_widget_set_name(label,"readout");
gtk_box_pack_start(GTK_BOX(vbox),label,0,0,0);
-
+
sprintf(buffer,"%dHz %dbit",rate[fi],bits[fi]);
label=gtk_label_new(buffer);
gtk_widget_set_name(label,"readout");
gtk_box_pack_start(GTK_BOX(vbox),label,0,0,0);
for(i=ch;i<ch+channels[fi];i++){
- GtkWidget *button=panel->chbuttons[i]=gtk_toggle_button_new();
+ GtkWidget *button=chbuttons[i]=gtk_toggle_button_new();
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button),1);
- g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (chlabels), panel);
+ g_signal_connect (G_OBJECT (button), "clicked",
+ G_CALLBACK (chlabels), NULL);
gtk_box_pack_start(GTK_BOX(vbox),button,0,0,0);
}
@@ -669,7 +823,7 @@
ch+=channels[fi];
}
- chlabels(NULL,panel);
+ chlabels(NULL,NULL);
}
/* add the action buttons */
@@ -677,9 +831,9 @@
{
/* bandwidth mode */
- GtkWidget *tbox=panel->bwtable=gtk_table_new(2,2,0);
+ GtkWidget *tbox=bwtable=gtk_table_new(2,2,0);
- GtkWidget *menu=panel->bwbutton=gtk_combo_box_new_text();
+ GtkWidget *menu=bwbutton=gtk_combo_box_new_text();
char *entries[]={"native","display"};
//"1Hz","3Hz","10Hz","30Hz","100Hz","300Hz","1kHz",
//"1/24oct","1/12oct","1/6oct","1/3oct"};
@@ -689,15 +843,15 @@
//gtk_combo_box_set_active(GTK_COMBO_BOX(menu),0);
g_signal_connect (G_OBJECT (menu), "changed",
- G_CALLBACK (bwchange), panel);
+ G_CALLBACK (bwchange), NULL);
- GtkWidget *menu2=panel->bwmodebutton=gtk_combo_box_new_text();
+ GtkWidget *menu2=bwmodebutton=gtk_combo_box_new_text();
char *entries2[]={"RBW","VBW"};
for(i=0;i<2;i++)
gtk_combo_box_append_text (GTK_COMBO_BOX (menu2), entries2[i]);
g_signal_connect (G_OBJECT (menu2), "changed",
- G_CALLBACK (bwmodechange), panel);
+ G_CALLBACK (bwmodechange), NULL);
gtk_combo_box_set_active(GTK_COMBO_BOX(menu2),0);
gtk_table_attach_defaults(GTK_TABLE(tbox),menu,0,1,0,1);
@@ -711,18 +865,17 @@
for(i=0;i<3;i++)
gtk_combo_box_append_text (GTK_COMBO_BOX (menu3), entries3[i]);
gtk_combo_box_set_active(GTK_COMBO_BOX(menu3),plot_scale);
- plot_setting(PLOT(panel->plot),plot_scale,plot_mode,plot_link,plot_depth,plot_noise);
g_signal_connect (G_OBJECT (menu3), "changed",
- G_CALLBACK (scalechange), panel);
+ G_CALLBACK (scalechange), NULL);
GtkWidget *menu4=gtk_combo_box_new_text();
- char *entries4[]={"1dB","10dB","20dB","45dB","90dB","140dB","200dB"};
+ char *entries4[]={"1dB","10dB","20dB","45dB","90dB","140dB","190dB"};
for(i=0;i<7;i++)
gtk_combo_box_append_text (GTK_COMBO_BOX (menu4), entries4[i]);
g_signal_connect (G_OBJECT (menu4), "changed",
- G_CALLBACK (depthchange), panel);
+ G_CALLBACK (depthchange), NULL);
gtk_combo_box_set_active(GTK_COMBO_BOX(menu4),4);
gtk_table_attach_defaults(GTK_TABLE(tbox),menu3,0,1,1,2);
@@ -742,19 +895,25 @@
gtk_box_pack_start(GTK_BOX(bbox),menu,0,0,0);
g_signal_connect (G_OBJECT (menu), "changed",
- G_CALLBACK (modechange), panel);
+ G_CALLBACK (modechange), NULL);
}
/* link */
{
GtkWidget *menu=gtk_combo_box_new_text();
+ char *entries[LINKS]={"independent",
+ "sum",
+ "subtract ref",
+ "subtract from",
+ "response/phase"};
+
for(i=0;i<LINKS;i++)
- gtk_combo_box_append_text (GTK_COMBO_BOX (menu), link_entries[i]);
+ gtk_combo_box_append_text (GTK_COMBO_BOX (menu), entries[i]);
gtk_combo_box_set_active(GTK_COMBO_BOX(menu),0);
gtk_box_pack_start(GTK_BOX(bbox),menu,0,0,0);
g_signal_connect (G_OBJECT (menu), "changed",
- G_CALLBACK (linkchange), panel);
+ G_CALLBACK (linkchange), NULL);
}
@@ -766,11 +925,11 @@
/* run/pause */
{
GtkWidget *button=gtk_toggle_button_new_with_mnemonic("_run");
- gtk_widget_add_accelerator (button, "activate", panel->group, GDK_space, 0, 0);
- gtk_widget_add_accelerator (button, "activate", panel->group, GDK_r, 0, 0);
- g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (runchange), panel);
+ gtk_widget_add_accelerator (button, "activate", group, GDK_space, 0, 0);
+ gtk_widget_add_accelerator (button, "activate", group, GDK_r, 0, 0);
+ g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (runchange), NULL);
gtk_box_pack_start(GTK_BOX(bbox),button,0,0,0);
- panel->run=button;
+ run=button;
}
/* loop */
@@ -778,15 +937,15 @@
{
GtkWidget *box=gtk_hbox_new(1,1);
GtkWidget *button=gtk_toggle_button_new_with_mnemonic("_loop");
- gtk_widget_add_accelerator (button, "activate", panel->group, GDK_l, 0, 0);
- g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (loopchange), panel);
+ gtk_widget_add_accelerator (button, "activate", group, GDK_l, 0, 0);
+ g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (loopchange), NULL);
gtk_box_pack_start(GTK_BOX(box),button,1,1,0);
gtk_widget_set_sensitive(button,global_seekable);
button=gtk_button_new_with_mnemonic("re_wind");
- gtk_widget_add_accelerator (button, "activate", panel->group, GDK_w, 0, 0);
- g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (rewindchange), panel);
+ gtk_widget_add_accelerator (button, "activate", group, GDK_w, 0, 0);
+ g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (rewindchange), NULL);
gtk_widget_set_sensitive(button,global_seekable);
gtk_box_pack_start(GTK_BOX(box),button,1,1,0);
@@ -798,14 +957,14 @@
{
GtkWidget *box=gtk_hbox_new(1,1);
GtkWidget *button=gtk_button_new_with_mnemonic("_clear data");
- gtk_widget_add_accelerator (button, "activate", panel->group, GDK_c, 0, 0);
- g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (clearchange), panel);
+ gtk_widget_add_accelerator (button, "activate", group, GDK_c, 0, 0);
+ g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (clearchange), NULL);
gtk_box_pack_start(GTK_BOX(box),button,1,1,0);
button=gtk_button_new_with_mnemonic("_dump data");
- gtk_widget_add_accelerator (button, "activate", panel->group, GDK_d, 0, 0);
- g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (dump), panel);
+ gtk_widget_add_accelerator (button, "activate", group, GDK_d, 0, 0);
+ g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (dump), NULL);
gtk_box_pack_start(GTK_BOX(box),button,1,1,0);
gtk_box_pack_start(GTK_BOX(bbox),box,0,0,0);
@@ -815,28 +974,27 @@
#if 0
{
GtkWidget *button=gtk_toggle_button_new_with_mnemonic("sample _noise floor");
- gtk_widget_add_accelerator (button, "activate", panel->group, GDK_n, 0, 0);
- g_signal_connect (G_OBJECT (button), "toggled", G_CALLBACK (noise), panel);
+ gtk_widget_add_accelerator (button, "activate", group, GDK_n, 0, 0);
+ g_signal_connect (G_OBJECT (button), "toggled", G_CALLBACK (noise), NULL);
gtk_box_pack_start(GTK_BOX(bbox),button,0,0,0);
}
#endif
gtk_box_pack_end(GTK_BOX(rightbox),bbox,0,0,0);
- gtk_widget_show_all(panel->toplevel);
- gtk_combo_box_set_active(GTK_COMBO_BOX(panel->bwbutton),0);
+ gtk_widget_show_all(toplevel);
+ gtk_combo_box_set_active(GTK_COMBO_BOX(bwbutton),0);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(wbold),plot_bold);
- gtk_key_snooper_install(watch_keyboard,panel);
+ gtk_key_snooper_install(watch_keyboard,NULL);
- gtk_alignment_set_padding(GTK_ALIGNMENT(plot_control_al),0,0,plot_get_left_pad(PLOT(panel->plot)),0);
- gtk_alignment_set_padding(GTK_ALIGNMENT(panel->plot_label_al),0,0,0,plot_get_right_pad(PLOT(panel->plot)));
+ gtk_alignment_set_padding(GTK_ALIGNMENT(plot_control_al),0,0,plot_get_left_pad(PLOT(plot)),0);
+ gtk_alignment_set_padding(GTK_ALIGNMENT(plot_label_al),0,0,0,plot_get_right_pad(PLOT(plot)));
}
static gboolean async_event_handle(GIOChannel *channel,
GIOCondition condition,
gpointer data){
- struct panel *panel=data;
char buf[1];
/* read all pending */
@@ -845,24 +1003,20 @@
increment_fish=1;
/* check playback status and update the run button if needed */
- if(process_active && panel->run &&
- !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(panel->run)))
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(panel->run),1);
- if(!process_active && panel->run &&
- gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(panel->run)))
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(panel->run),0);
+ if(process_active && run &&
+ !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(run)))
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(run),1);
+ if(!process_active && run &&
+ gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(run)))
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(run),0);
/* update the spectral display; send new data */
- pthread_mutex_lock(&feedback_mutex);
- if(plot_last_update!=feedback_increment){
- pthread_mutex_unlock(&feedback_mutex);
- replot(panel);
- plot_draw(PLOT(panel->plot));
+ if(!plot_hold)replot(0,0,1);
- while (gtk_events_pending())
- gtk_main_iteration();
- }else
- pthread_mutex_unlock(&feedback_mutex);
+ /* if we're near CPU limit, service the rest of Gtk over next async
+ update request */
+ while (gtk_events_pending())
+ gtk_main_iteration();
return TRUE;
}
@@ -880,7 +1034,6 @@
void panel_go(int argc,char *argv[]){
char *homedir=getenv("HOME");
int found=0;
- memset(&p,0,sizeof(p));
found|=look_for_gtkrc(STR(ETCDIR) "/spectrum-gtkrc");
{
@@ -906,17 +1059,21 @@
found|=look_for_gtkrc("./spectrum-gtkrc");
if(!found){
-
- fprintf(stderr,"Could not find the spectrum-gtkrc configuration file normally\n"
+
+ fprintf(stderr,
+ "Could not find the spectrum-gtkrc configuration file normally\n"
"installed in one of the following places:\n"
"\t./spectrum-gtkrc\n"
"\t$(SPECTRUM_RCDIR)/spectrum-gtkrc\n"
"\t~/.spectrum/spectrum-gtkrc\n\t"
STR(ETCDIR) "/spectrum-gtkrc\n"
- "This configuration file is used to tune the color, font and other detail aspects\n"
- "of the user interface. Although the analyzer will work without it, the UI\n"
- "appearence will likely make the application harder to use due to missing visual\n"
+ "This configuration file is used to tune the color, "
+ "font and other detail aspects\n"
+ "of the user interface. Although the analyzer will "
+ "work without it, the UI\n"
+ "appearence will likely make the application harder to "
+ "use due to missing visual\n"
"cues.\n");
}
@@ -932,32 +1089,28 @@
gtk_rc_add_default_file("spectrum-gtkrc");
gtk_init (&argc, &argv);
- panel_create(&p);
- animate_fish(&p);
+ plot_ch = total_ch; /* true now, won't necessarily be true later */
+ plot_inputs = inputs; /* true now, won't necessarily be true later */
+ filter_make_critical(.04,&plot_ymax_damp);
+ filter_make_critical(.04,&plot_pmax_damp);
+ filter_make_critical(.04,&plot_pmin_damp);
+
+ panel_create();
+ animate_fish();
+
/* set up watching the event pipe */
{
GIOChannel *channel = g_io_channel_unix_new (eventpipe[0]);
- guint id;
-
g_io_channel_set_encoding (channel, NULL, NULL);
g_io_channel_set_buffered (channel, FALSE);
g_io_channel_set_close_on_unref (channel, TRUE);
-
- id = g_io_add_watch (channel, G_IO_IN, async_event_handle, &p);
-
+ g_io_add_watch (channel, G_IO_IN, async_event_handle, NULL);
g_io_channel_unref (channel);
+ }
- }
-
/* we want to be running by default */
- {
- pthread_t thread_id;
- animate_fish(&p);
- process_active=1;
- pthread_create(&thread_id,NULL,&process_thread,NULL);
- }
-
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(run),TRUE);
gtk_main ();
}
Modified: trunk/spectrum/spec_plot.c
===================================================================
--- trunk/spectrum/spec_plot.c 2012-06-02 16:38:29 UTC (rev 18348)
+++ trunk/spectrum/spec_plot.c 2012-06-03 01:22:50 UTC (rev 18349)
@@ -29,9 +29,9 @@
#include "spec_plot.h"
static double log_lfreqs[5]={10.,100.,1000.,10000.,100000};
-static double log_llfreqs[15]={10.,20.,30.,50.,100.,200.,300.,500.,
+static double log_llfreqs[16]={10.,20.,30.,50.,100.,200.,300.,500.,
1000.,2000.,3000.,5000.,10000.,
- 20000.,30000.};
+ 20000.,30000.,50000.};
static double log_tfreqs[37]={5.,6.,7.,8.,9.,20.,30.,40.,50.,60.,70.,80.,90.
,200.,300.,400.,500.,600.,700.,800.,900.,
2000.,3000.,4000.,5000.,6000.,7000.,8000.,9000.,
@@ -45,68 +45,25 @@
static GtkDrawingAreaClass *parent_class = NULL;
-static void compute_imp_scale(GtkWidget *widget){
- Plot *p=PLOT(widget);
- int height=widget->allocation.height-p->pady;
- int i;
- double lfreqs[9]={10000000.,1000000.,100000.,10000.,1000.,100.,10.,1.,.1};
- double tfreqs[64]={9000000.,8000000.,7000000.,6000000.,
- 5000000.,4000000.,3000000.,2000000.,
- 900000.,800000.,700000.,600000.,
- 500000.,400000.,300000.,200000.,
- 90000.,80000.,70000.,60000.,
- 50000.,40000.,30000.,20000.,
- 9000.,8000.,7000.,6000.,
- 5000.,4000.,3000.,2000.,
- 900.,800.,700.,600.,
- 500.,400.,300.,200.,
- 90.,80.,70.,60.,
- 50.,40.,30.,20,
- 9.,8.,7.,6.,
- 5.,4.,3.,2.,
- .9,.8,.7,.6,
- .5,.4,.3,.2};
+static void compute_xgrid(Plot *p, fetchdata *f){
+ if(p->maxrate!=f->maxrate || p->scale!=f->scale || p->width != f->width){
+ GtkWidget *widget=GTK_WIDGET(p);
+ int width = widget->allocation.width-p->padx-(f->phase_active?p->phax:0);
+ int nyq=f->maxrate/2.;
+ int i,j;
- for(i=0;i<9;i++)
- p->ygrid[i]=rint( (log10(p->ymax)-log10(lfreqs[i]))/(log10(p->ymax)-log10(.1)) * (height-1));
- for(i=0;i<64;i++)
- p->ytic[i]=rint( (log10(p->ymax)-log10(tfreqs[i]))/(log10(p->ymax)-log10(.1)) * (height-1));
- p->ygrids=9;
- p->ytics=64;
+ p->xgrids=0;
+ p->xtics=0;
-}
+ /* find the places to plot the x grid lines according to scale */
+ switch(f->scale){
+ case 0: /* log */
-int phase_active_p(Plot *p){
- if(p->link == LINK_PHASE){
- int cho=0;
- int gi;
- for(gi=0;gi<p->groups;gi++)
- if(p->ch[gi]>1 && p->ch_active[cho+1])
- return 1;
- }
- return 0;
-}
-
-static void compute_metadata(GtkWidget *widget){
- Plot *p=PLOT(widget);
- int phase = phase_active_p(p);
- int width = widget->allocation.width-p->padx-(phase?p->phax:0);
- int rate=p->maxrate;
- int nyq=p->maxrate/2.;
- int i;
-
- p->xgrids=0;
- p->xtics=0;
-
- /* find the places to plot the x grid lines according to scale */
- switch(p->scale){
- case 0: /* log */
- {
for(i=0;i<5;i++){
if(log_lfreqs[i]<(nyq-.1))
p->xgrids=i+1;
}
- for(i=0;i<15;i++){
+ for(i=0;i<16;i++){
if(log_llfreqs[i]<(nyq-.1))
p->xlgrids=i+1;
}
@@ -116,18 +73,17 @@
}
for(i=0;i<p->xgrids;i++)
- p->xgrid[i]=rint( (log10(log_lfreqs[i])-log10(5.))/(log10(nyq)-log10(5.)) * (width-1))+p->padx;
+ p->xgrid[i]=rint( (log10(log_lfreqs[i])-log10(5.))/(log10(nyq)-log10(5.)) * (width-1))+p->padx;
for(i=0;i<p->xlgrids;i++)
- p->xlgrid[i]=rint( (log10(log_llfreqs[i])-log10(5.))/(log10(nyq)-log10(5.)) * (width-1))+p->padx;
+ p->xlgrid[i]=rint( (log10(log_llfreqs[i])-log10(5.))/(log10(nyq)-log10(5.)) * (width-1))+p->padx;
for(i=0;i<p->xtics;i++)
- p->xtic[i]=rint( (log10(log_tfreqs[i])-log10(5.))/(log10(nyq)-log10(5.)) * (width-1))+p->padx;
- }
+ p->xtic[i]=rint( (log10(log_tfreqs[i])-log10(5.))/(log10(nyq)-log10(5.)) * (width-1))+p->padx;
- break;
- case 1: /* ISO log */
- {
+ break;
+ case 1: /* ISO log */
+
for(i=0;i<12;i++){
- if(iso_lfreqs[i]<(nyq-.1)){
+ if(iso_lfreqs[i]<(nyq-.1)){
p->xgrids=i+1;
p->xlgrids=i+1;
}
@@ -138,15 +94,30 @@
}
for(i=0;i<p->xgrids;i++)
- p->xgrid[i]=p->xlgrid[i]=rint( (log2(iso_lfreqs[i])-log2(25.))/(log2(nyq)-log2(25.)) * (width-1))+p->padx;
+ p->xgrid[i]=p->xlgrid[i]=rint( (log2(iso_lfreqs[i])-log2(25.))/(log2(nyq)-log2(25.)) * (width-1))+p->padx;
for(i=0;i<p->xtics;i++)
- p->xtic[i]=rint( (log2(iso_tfreqs[i])-log2(25.))/(log2(nyq)-log2(25.)) * (width-1))+p->padx;
- }
+ p->xtic[i]=rint( (log2(iso_tfreqs[i])-log2(25.))/(log2(nyq)-log2(25.)) * (width-1))+p->padx;
- break;
- case 2: /* linear spacing */
- {
- int j;
+ break;
+ case 2: /* linear spacing */
+
+ if(f->maxrate > 100000){
+ p->lin_major = 10000.;
+ p->lin_minor = 2000.;
+ p->lin_mult = 5;
+ p->lin_layout = p->lin_layout_200;
+ }else if(f->maxrate > 50000){
+ p->lin_major = 5000.;
+ p->lin_minor = 1000.;
+ p->lin_mult = 5;
+ p->lin_layout = p->lin_layout_100;
+ }else{
+ p->lin_major=2000.;
+ p->lin_minor=500.;
+ p->lin_mult=4;
+ p->lin_layout = p->lin_layout_50;
+ }
+
for(i=0;;i++){
if(i*p->lin_major >= nyq-.1 || i*p->lin_major>=100000-.1)
break;
@@ -171,8 +142,8 @@
lfreq=j*p->lin_minor;
p->xtic[i]=rint(lfreq/nyq * (width-1))+p->padx;
}
+ break;
}
- break;
}
}
@@ -220,27 +191,27 @@
return rgb;
}
-static void draw(GtkWidget *widget){
+void plot_draw(Plot *p, fetchdata *f, plotparams *pp){
int i;
- Plot *p=PLOT(widget);
+ GtkWidget *widget=GTK_WIDGET(p);
+ GtkWidget *parent=gtk_widget_get_parent(widget);
int height=widget->allocation.height;
int width=widget->allocation.width;
- GtkWidget *parent=gtk_widget_get_parent(widget);
-#if 0
- int impedence = (p->link == LINK_IMPEDENCE_p1 ||
- p->link == LINK_IMPEDENCE_1 ||
- p->link == LINK_IMPEDENCE_10);
-#endif
- int phase = phase_active_p(p);
+
+ if(!GDK_IS_DRAWABLE(p->backing))return;
+ if(!pp)return;
+ if(!f)return;
+
+ int phase = f->phase_active;
int padx = p->padx;
int phax = phase ? p->phax : 0;
int pwidth = width - padx - phax;
+ /* lazy GC init */
if(!p->drawgc){
p->drawgc=gdk_gc_new(p->backing);
gdk_gc_copy(p->drawgc,widget->style->black_gc);
}
-
if(!p->dashes){
p->dashes=gdk_gc_new(p->backing);
gdk_gc_copy(p->dashes, p->drawgc);
@@ -268,10 +239,10 @@
gdk_gc_set_line_attributes(p->phasegc,1,GDK_LINE_SOLID,GDK_CAP_PROJECTING,GDK_JOIN_MITER);
}
+ /* set clip rectangle */
{
const GdkRectangle clip = {p->padx,0,pwidth,height-p->pady};
GdkGCValues values;
- //gdk_gc_get_values(p->drawgc,&values);
values.line_width=1;
gdk_gc_set_values(p->drawgc,&values,GDK_GC_LINE_WIDTH);
gdk_gc_set_clip_rectangle (p->drawgc, &clip);
@@ -289,24 +260,12 @@
gdk_draw_rectangle(p->backing,gc,1,padx,0,pwidth,height-p->pady);
}
- /* draw the noise floor if active */
- #if 0
- if(p->floor){
- GdkColor rgb = {0,0xd000,0xd000,0xd000};
- gdk_gc_set_rgb_fg_color(p->drawgc,&rgb);
+ compute_xgrid(p,f);
+ p->maxrate=f->maxrate;
+ p->scale=f->scale;
+ p->phase_active=f->phase_active;
+ p->width=f->width;
- for(i=0;i<pwidth;i++){
- float val=p->floor[i];
- int y;
-
- /* No noise floor is passed back for display in the modes where it's irrelevant */
- y= rint((height-p->pady-1)/p->depth*(p->ymax-val));
- if(y<height-p->pady)
- gdk_draw_line(p->backing,p->drawgc,padx+i,y,padx+i,height-p->pady-1);
- }
- }
- #endif
-
/* draw the light x grid */
{
int i;
@@ -318,10 +277,11 @@
gdk_gc_set_rgb_fg_color(p->drawgc,&rgb);
for(i=0;i<p->xtics;i++)
- gdk_draw_line(p->backing,p->drawgc,p->xtic[i],0,p->xtic[i],height-p->pady);
+ gdk_draw_line(p->backing,p->drawgc,p->xtic[i],0,
+ p->xtic[i],height-p->pady);
}
- /* draw the x labels */
+ /* draw the x labels */
{
PangoLayout **proper;
switch(p->scale){
@@ -348,46 +308,11 @@
}
/* draw the y grid */
- //if(impedence){ /* impedence mode */
- if(0){
-
- /* light grid */
-
+ {
GdkColor rgb={0,0,0,0};
- rgb.red=0xc000;
- rgb.green=0xff00;
- rgb.blue=0xff00;
- gdk_gc_set_rgb_fg_color(p->drawgc,&rgb);
-
- compute_imp_scale(widget);
-
- for(i=0;i<p->ytics;i++)
- gdk_draw_line(p->backing,p->drawgc,padx,p->ytic[i],pwidth,p->ytic[i]);
-
- /* dark grid */
- rgb.red=0x0000;
- rgb.green=0xc000;
- rgb.blue=0xc000;
-
- gdk_gc_set_rgb_fg_color(p->drawgc,&rgb);
-
- for(i=0;i<p->ygrids;i++){
- int px,py;
- pango_layout_get_pixel_size(p->imp_layout[i],&px,&py);
-
- gdk_draw_layout (p->backing,
- widget->style->black_gc,
- padx-px-2, p->ygrid[i]-py/2,
- p->imp_layout[i]);
-
- gdk_draw_line(p->backing,p->drawgc,padx,p->ygrid[i],pwidth,p->ygrid[i]);
- }
-
- }else{
- GdkColor rgb={0,0,0,0};
float emheight = (height-p->pady)/p->pady;
- float emperdB = emheight/p->depth;
- float pxperdB = (height-p->pady)/p->depth;
+ float emperdB = emheight/pp->depth;
+ float pxperdB = (height-p->pady)/pp->depth;
/* we want no more than <n> major lines per graph */
int maxmajorper = 15;
@@ -411,7 +336,7 @@
/* minimum em seperation? */
if(emperdB>majorsep*majordeltest[i] &&
/* Not over the number of lines limit? */
- p->depth*majordeltest[i]<maxmajorper){
+ pp->depth*majordeltest[i]<maxmajorper){
majordel=majordellist[i];
break;
}
@@ -419,9 +344,11 @@
/* choose appropriate minor and subminor spacing */
int minordellist[]=
- { 10, 25, 50, 100, 250, 500, 1000, 2500, 5000, 10000, 25000, -1, -1};
+ { 10, 25, 50, 100, 250, 500, 1000, 2500, 5000,
+ 10000, 25000, -1, -1};
float minordeltest[]=
- {100, 40, 20, 10, 4, 2, 1, .4, .2, .1, .04, -1, -1};
+ {100, 40, 20, 10, 4, 2, 1, .4, .2,
+ .1, .04, -1, -1};
for(i=0;minordellist[i]>0;i++){
/* minimum px seperation? */
@@ -448,18 +375,18 @@
}
}
- /* Light Y grid */
+ /* draw the light Y grid */
rgb.red=0xc000;
rgb.green=0xff00;
rgb.blue=0xff00;
gdk_gc_set_rgb_fg_color(p->drawgc,&rgb);
gdk_gc_set_rgb_fg_color(p->dashes,&rgb);
- float ymin = (p->ymax - p->depth)*1000;
- int yval = rint((p->ymax*1000/subminordel)+1)*subminordel;
+ float ymin = (pp->ymax - pp->depth)*1000;
+ int yval = rint((pp->ymax*1000/subminordel)+1)*subminordel;
while(1){
- float ydel = (yval - ymin)/(p->depth*1000);
+ float ydel = (yval - ymin)/(pp->depth*1000);
int ymid = rint(height-p->pady-1 - (height-p->pady) * ydel);
if(ymid>=height-p->pady)break;
@@ -475,14 +402,14 @@
yval-=subminordel;
}
- /* Dark Y grid */
+ /* draw the dark Y grid */
rgb.red=0x0000;
rgb.green=0xc000;
rgb.blue=0xc000;
gdk_gc_set_rgb_fg_color(p->drawgc,&rgb);
- ymin = (p->ymax - p->depth)*1000;
- yval = rint((p->ymax*1000/majordel)+1)*majordel;
+ ymin = (pp->ymax - pp->depth)*1000;
+ yval = rint((pp->ymax*1000/majordel)+1)*majordel;
{
int px,py,pxdB,pxN,pxMAX;
@@ -492,25 +419,25 @@
pxMAX+=pxdB;
while(1){
- float ydel = (yval - ymin)/(p->depth*1000);
+ float ydel = (yval - ymin)/(pp->depth*1000);
int ymid = rint(height-p->pady-1 - (height-p->pady) * ydel);
if(ymid>=height-p->pady)break;
if(ymid>=0){
- int do_dB=0;
int label = yval/100+2000;
if(label>=0 && label<=4000 /* in range check */
- && (p->scale<2 || ymid+py/2 < height-p->pady) /* don't collide with DC label */
+ && (p->scale<2 || ymid+py/2 < height-p->pady)
+ /* don't collide with DC label */
){
if(label%10){ /* fractional (decimal) dB */
int sofar=0;
/* -.9dB
- -9.9dB
+ -9.9dB
-99.9
- -999.9 */
+ -999.9 */
if(fabsf(yval*.001)<9.98){
gdk_draw_layout (p->backing,
@@ -565,7 +492,7 @@
}
}
- /* dark x grid */
+ /* draw the dark x grid */
{
int i;
GdkColor rgb={0,0,0,0};
@@ -576,84 +503,74 @@
gdk_gc_set_rgb_fg_color(p->drawgc,&rgb);
for(i=0;i<p->xgrids;i++)
- gdk_draw_line(p->backing,p->drawgc,p->xgrid[i],0,p->xgrid[i],height-p->pady);
+ gdk_draw_line(p->backing,p->drawgc,p->xgrid[i],0,
+ p->xgrid[i],height-p->pady);
}
- gdk_gc_set_line_attributes(p->drawgc,p->bold+1,GDK_LINE_SOLID,GDK_CAP_PROJECTING,
- GDK_JOIN_MITER);
+ gdk_gc_set_line_attributes(p->drawgc,pp->bold+1,GDK_LINE_SOLID,
+ GDK_CAP_PROJECTING, GDK_JOIN_MITER);
/* draw actual data */
- if(p->ydata){
+ if(f->data){
int cho=0;
int gi;
- for(gi=0;gi<p->groups;gi++){
+ for(gi=0;gi<f->groups;gi++){
int ch;
GdkColor rgb;
- for(ch=cho;ch<cho+p->ch[gi];ch++){
- if(p->ch_active[ch]){
+ for(ch=cho;ch<cho+f->channels[gi];ch++){
+ if(f->active[ch]){
- rgb = chcolor(ch);
- gdk_gc_set_rgb_fg_color(p->drawgc,&rgb);
+ rgb = chcolor(ch);
+ gdk_gc_set_rgb_fg_color(p->drawgc,&rgb);
- for(i=0;i<pwidth;i++){
- float valmin=p->ydata[ch][i*2];
- float valmax=p->ydata[ch][i*2+1];
+ for(i=0;i<pwidth;i++){
+ float valmin=f->data[ch][i*2];
+ float valmax=f->data[ch][i*2+1];
float ymin, ymax;
if(!isnan(valmin) && !isnan(valmax)){
- //if(impedence){ /* log scale for impedence */
- if(0){
+ if(phase && ch==cho+1){
- ymin = rint( (log10(p->ymax)-log10(valmin))/
- (log10(p->ymax)-log10(.1)) *
- (height-p->pady-1));
- ymax = rint( (log10(p->ymax)-log10(valmax))/
- (log10(p->ymax)-log10(.1)) *
- (height-p->pady-1));
-
- }else if(phase && ch==cho+1){
-
ymin = rint((height-p->pady-1)/
- (p->pmax-p->pmin)*
- (p->pmax-valmin));
+ (pp->pmax-pp->pmin)*
+ (pp->pmax-valmin));
ymax = rint((height-p->pady-1)/
- (p->pmax-p->pmin)*
- (p->pmax-valmax));
+ (pp->pmax-pp->pmin)*
+ (pp->pmax-valmax));
}else{
- ymin = rint((height-p->pady-1)/p->depth*(p->ymax-valmin));
- ymax = rint((height-p->pady-1)/p->depth*(p->ymax-valmax));
+ ymin = rint((height-p->pady-1)/pp->depth*(pp->ymax-valmin));
+ ymax = rint((height-p->pady-1)/pp->depth*(pp->ymax-valmax));
}
gdk_draw_line(p->backing,p->drawgc,padx+i,ymin,padx+i,ymax);
}
- }
- }
+ }
+ }
}
- cho+=p->ch[gi];
+ cho+=f->channels[gi];
}
}
- /* phase? draw in phase and tics on right axis */
+ /* draw in phase labels and tics on right axis */
+ /* currently messy as hell cut&paste spaghetti, but working */
if(phase){
- float depth = p->pmax-p->pmin;
- int label=ceil(p->pmax/10+18),i;
- float del=(height-p->pady-1)/depth,step;
- float off=p->pmax-ceil(p->pmax*.1)*10;
- step=2;
- if(del>8)step=1;
+ float depth = pp->pmax-pp->pmin;
+ float del=(height-p->pady-1)/depth;
+ float off=pp->pmax-ceil(pp->pmax*.1)*10;
for(i=0;;i++){
int ymid=rint(del * (i*10+off));
- int pv = rint((p->pmax - ymid/(float)(height-p->pady) * (p->pmax - p->pmin))/10);
+ int pv = rint((pp->pmax - ymid/(float)(height-p->pady) *
+ (pp->pmax - pp->pmin))/10);
if(ymid>=height-p->pady)break;
if(ymid>=0 && pv>=-18 && pv<=18 && (pv&1)==0){
- int px,py;
+ int px,py;
pango_layout_get_pixel_size(p->phase_layout[pv+18],&px,&py);
gdk_draw_layout (p->backing,p->phasegc,
width-p->phax+2, ymid-py/2,
@@ -663,78 +580,86 @@
if(del>10){
for(i=0;;i++){
- int ymid=rint(del * (i+off));
- int pv = rint(p->pmax - ymid/(float)(height-p->pady) * (p->pmax - p->pmin));
- if(ymid>=height-p->pady)break;
- if(ymid>=0 && pv>=-180 && pv<=180)
- gdk_draw_line(p->backing,p->phasegc,width-p->phax-(i%5==0?15:10),ymid,width-p->phax-(i%5==0?5:7),ymid);
+ int ymid=rint(del * (i+off));
+ int pv = rint(pp->pmax - ymid/(float)(height-p->pady) *
+ (pp->pmax - pp->pmin));
+ if(ymid>=height-p->pady)break;
+ if(ymid>=0 && pv>=-180 && pv<=180)
+ gdk_draw_line(p->backing,p->phasegc,width-p->phax-(i%5==0?15:10),
+ ymid,width-p->phax-(i%5==0?5:7),ymid);
}
}else if(del>5){
for(i=0;;i++){
- int ymid=rint(del * (i*2+off));
- int pv = rint(p->pmax - ymid/(float)(height-p->pady) * (p->pmax - p->pmin));
- if(ymid>=height-p->pady)break;
- if(ymid>=0 && pv>=-180 && pv<=180)
- gdk_draw_line(p->backing,p->phasegc,width-p->phax-12,ymid,width-p->phax-7,ymid);
+ int ymid=rint(del * (i*2+off));
+ int pv = rint(pp->pmax - ymid/(float)(height-p->pady) *
+ (pp->pmax - pp->pmin));
+ if(ymid>=height-p->pady)break;
+ if(ymid>=0 && pv>=-180 && pv<=180)
+ gdk_draw_line(p->backing,p->phasegc,width-p->phax-12,ymid,
+ width-p->phax-7,ymid);
}
} else if(del>2){
for(i=0;;i++){
- int ymid=rint(del * (i*5+off));
- int pv = rint(p->pmax - ymid/(float)(height-p->pady) * (p->pmax - p->pmin));
- if(ymid>=height-p->pady)break;
- if(ymid>=0 && pv>=-180 && pv<=180)
- gdk_draw_line(p->backing,p->phasegc,width-p->phax-15,ymid,width-p->phax-5,ymid);
+ int ymid=rint(del * (i*5+off));
+ int pv = rint(pp->pmax - ymid/(float)(height-p->pady) *
+ (pp->pmax - pp->pmin));
+ if(ymid>=height-p->pady)break;
+ if(ymid>=0 && pv>=-180 && pv<=180)
+ gdk_draw_line(p->backing,p->phasegc,width-p->phax-15,ymid,
+ width-p->phax-5,ymid);
}
}
if(del>=2){
for(i=0;;i++){
int ymid=rint(del * (i*10+off));
- int pv = rint(p->pmax - ymid/(float)(height-p->pady) * (p->pmax - p->pmin));
+ int pv = rint(pp->pmax - ymid/(float)(height-p->pady) *
+ (pp->pmax - pp->pmin));
if(ymid>=height-p->pady)break;
- if(ymid>=0 && pv>=-180 && pv<=180){
- gdk_draw_line(p->backing,p->phasegc,width-p->phax-5,ymid-1,width-p->phax-1,ymid-1);
- gdk_draw_line(p->backing,p->phasegc,width-p->phax-25,ymid,width-p->phax-1,ymid);
- gdk_draw_line(p->backing,p->phasegc,width-p->phax-5,ymid+1,width-p->phax-1,ymid+1);
+ if(ymid>=0 && pv>=-180 && pv<=180){
+ gdk_draw_line(p->backing,p->phasegc,width-p->phax-5,ymid-1,
+ width-p->phax-1,ymid-1);
+ gdk_draw_line(p->backing,p->phasegc,width-p->phax-25,ymid,
+ width-p->phax-1,ymid);
+ gdk_draw_line(p->backing,p->phasegc,width-p->phax-5,ymid+1,
+ width-p->phax-1,ymid+1);
}
}
}else{
for(i=0;;i++){
- int ymid=rint(del * (i*10+off));
- int pv = rint(p->pmax - ymid/(float)(height-p->pady) * (p->pmax - p->pmin));
- if(ymid>=height-p->pady)break;
- if(ymid>=0 && pv>=-180 && pv<=180)
- gdk_draw_line(p->backing,p->phasegc,width-p->phax-15,ymid,width-p->phax-5,ymid);
+ int ymid=rint(del * (i*10+off));
+ int pv = rint(pp->pmax - ymid/(float)(height-p->pady) *
+ (pp->pmax - pp->pmin));
+ if(ymid>=height-p->pady)break;
+ if(ymid>=0 && pv>=-180 && pv<=180)
+ gdk_draw_line(p->backing,p->phasegc,width-p->phax-15,ymid,
+ width-p->phax-5,ymid);
}
for(i=0;;i++){
int ymid=rint(del * (i*10+off));
- int pv = rint((p->pmax - ymid/(float)(height-p->pady) * (p->pmax - p->pmin))/10);
+ int pv = rint((pp->pmax - ymid/(float)(height-p->pady) *
+ (pp->pmax - pp->pmin))/10);
if(ymid>=height-p->pady)break;
- if(ymid>=0 && pv>=-18 && pv<=18 && (pv&1)==0){
- gdk_draw_line(p->backing,p->phasegc,width-p->phax-5,ymid-1,width-p->phax-1,ymid-1);
- gdk_draw_line(p->backing,p->phasegc,width-p->phax-25,ymid,width-p->phax-1,ymid);
- gdk_draw_line(p->backing,p->phasegc,width-p->phax-5,ymid+1,width-p->phax-1,ymid+1);
+ if(ymid>=0 && pv>=-18 && pv<=18 && (pv&1)==0){
+ gdk_draw_line(p->backing,p->phasegc,width-p->phax-5,ymid-1,
+ width-p->phax-1,ymid-1);
+ gdk_draw_line(p->backing,p->phasegc,width-p->phax-25,ymid,
+ width-p->phax-1,ymid);
+ gdk_draw_line(p->backing,p->phasegc,width-p->phax-5,ymid+1,
+ width-p->phax-1,ymid+1);
}
}
}
}
-}
-static void draw_and_expose(GtkWidget *widget){
- Plot *p=PLOT(widget);
- if(!GDK_IS_DRAWABLE(p->backing))return;
- draw(widget);
- if(!GTK_WIDGET_DRAWABLE(widget))return;
- if(!GDK_IS_DRAWABLE(widget->window))return;
gdk_draw_drawable(widget->window,
- widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
- p->backing,
- 0, 0,
- 0, 0,
- widget->allocation.width,
- widget->allocation.height);
+ widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
+ p->backing,
+ 0, 0,
+ 0, 0,
+ width, height);
}
static gboolean expose( GtkWidget *widget, GdkEventExpose *event ){
@@ -759,15 +684,14 @@
{
int max=0;
int maxy=0;
- for(i=0;p->lin_layout[i];i++){
- if(p->lin_major*i >= p->maxrate/2-.1)break;
- pango_layout_get_pixel_size(p->lin_layout[i],&px,&py);
+ for(i=0;p->lin_layout_50[i];i++){
+ pango_layout_get_pixel_size(p->lin_layout_50[i],&px,&py);
if(px>max)max=px;
if(py>pady)pady=py;
if(py>maxy)maxy=py;
}
- max+=maxy*1.5;
max*=i+1;
+ max+=maxy*1.5;
if(axisx<max)axisx=max;
}
/* find max log layout */
@@ -775,14 +699,13 @@
int max=0;
int maxy=0;
for(i=0;p->log_layout[i];i++){
- if(log_lfreqs[i] >= p->maxrate/2-.1)break;
pango_layout_get_pixel_size(p->log_layout[i],&px,&py);
if(px>max)max=px;
if(py>pady)pady=py;
if(py>maxy)maxy=py;
}
+ max*=(i+1);
max+=maxy*1.5;
- max*=(i+1)*3;
if(axisx<max)axisx=max;
}
/* find max iso layout */
@@ -790,18 +713,16 @@
int max=0;
int maxy=0;
for(i=0;p->iso_layout[i];i++){
- if(iso_lfreqs[i] >= p->maxrate/2-.1)break;
pango_layout_get_pixel_size(p->iso_layout[i],&px,&py);
if(px>max)max=px;
if(py>pady)pady=py;
if(py>maxy)maxy=py;
}
- max+=maxy*1.5;
max*=i+1;
+ max+=maxy*1.5;
if(axisx<max)axisx=max;
}
-
/* find max db layout */
{
int max=0;
@@ -812,20 +733,6 @@
axisy=(max)*8;
if(axisy<max)axisy=max;
}
- /* find max imped layout */
-#if 0
- {
- int max=0;
- for(i=0;p->imp_layout[i];i++){
- pango_layout_get_pixel_size(p->imp_layout[i],&px,&py);
- //if(py>max)max=py;
- if(px>padx)padx=px;
- }
- axisy=(max)*8;
- if(axisy<max)axisy=max;
- }
-#endif
-
/* find max phase layout */
{
int max=0;
@@ -845,173 +752,8 @@
p->phax=phax+2;
}
-
-static void filter_reset(pole2 *p, double val){
- p->x[0]=p->x[1]=val;
- p->y[0]=p->y[1]=val;
-}
-
-static void filter_make_critical(double w, pole2 *f){
- double w0 = tan(M_PI*w*pow(pow(2,.5)-1,-.5));
- f->a = w0*w0/(1+(2*w0)+w0*w0);
- f->b1 = 2*f->a*(1/(w0*w0)-1);
- f->b2 = 1-(4*f->a+f->b1);
- filter_reset(f,0);
-}
-
-static double filter_filter(double x, pole2 *p){
- double y =
- p->a*x + 2*p->a*p->x[0] + p->a*p->x[1] +
- p->b1*p->y[0] + p->b2*p->y[1];
- p->y[1] = p->y[0]; p->y[0] = y;
- p->x[1] = p->x[0]; p->x[0] = x;
- return y;
-}
-
-#define THRESH .25
-#define TIMERFRAMES 20
-
-void plot_rescale (Plot *p, int request_reset){
- float ymax,pmax,pmin;
- int phase = phase_active_p(p);
- int width=GTK_WIDGET(p)->allocation.width-p->padx-(phase ? p->phax : 0);
- int height=GTK_WIDGET(p)->allocation.height-p->pady;
- float **data;
-
- if(!p->configured)return;
-
- data = process_fetch(p->scale, p->mode, p->link,
- p->ch_process,width,&ymax,&pmax,&pmin);
-
- p->ydata=data;
-
- if(!p->autoscale) return;
-
- /* graph limit updates are conditional depending on mode/link */
- switch(p->link){
- case LINK_INDEPENDENT:
- case LINK_SUMMED:
- case LINK_PHASE:
- {
- float dBpp = p->depth/height;
- ymax += dBpp*25;
- }
- break;
- }
-
- if(ymax<p->depth-p->ymax_limit)ymax=p->depth-p->ymax_limit;
- if(ymax>p->ymax_limit)ymax=p->ymax_limit;
-
- pmax+=10;
- pmin-=10;
- if(pmax<5)pmax=5;
- if(pmax>190)pmax=190;
- if(pmin>-20)pmin=-20;
- if(pmin<-190)pmin=-190;
-
- /* phase/response zeros align on phase graphs; verify targets
- against phase constraints */
- if(phase){
- float pzero,mzero = height/p->depth*ymax;
-
- /* move mag zero back onscreen if it's off */
- if(mzero < height*THRESH){
- ymax = (p->depth*height*THRESH)/height;
- }
- if(mzero > height*(1-THRESH)){
- ymax = (p->depth*height*(1-THRESH))/height;
- }
-
- mzero = height/p->depth*ymax;
- pzero = height/(pmax-pmin)*pmax;
-
- if(mzero<pzero){
- /* straightforward; move the dB range down */
- ymax = pzero*p->depth/height;
- }else{
- /* a little harder as phase has a min and a max.
- First increase the pmax to match the dB zero. */
-
- pmax = pmin/(1-height/mzero);
- pzero = height/(pmax-pmin)*pmax;
-
- /* That worked, but might have run p->max overrange */
- if(pmax>190.){
- /* reconcile by allowing mag to overrange */
- pmax = 190.;
- pzero = height/(pmax-pmin)*pmax;
- ymax = p->depth*pzero/height;
- p->ymaxtimer=0;
- }
- }
- }
-
- if(request_reset){
- p->ymax=p->ymax_target=ymax;
- filter_reset(&p->ymax_damp,p->ymax);
- p->ymaxtimer=TIMERFRAMES;
-
- if(phase){
- p->pmax=p->pmax_target=pmax;
- p->pmin=p->pmin_target=pmin;
- filter_reset(&p->pmax_damp,p->pmax);
- filter_reset(&p->pmin_damp,p->pmin);
- p->pmaxtimer=TIMERFRAMES;
- p->pmintimer=TIMERFRAMES;
- }
-
- }else{
- /* conditionally set new damped ymax target */
- if(p->ymaxtimer>0 && ymax < p->ymax*(1-THRESH))
- p->ymaxtimer--;
-
- if(ymax > p->ymax_target){
- p->ymax_target=ymax;
- p->ymaxtimer=TIMERFRAMES;
- }
-
- if(p->ymaxtimer<=0)
- p->ymax_target=ymax;
-
- /* update ymax through scale damping filter */
- p->ymax = filter_filter(p->ymax_target,&p->ymax_damp);
-
- /* apply same hyteresis and update to phase */
- if(phase){
-
- if(p->pmaxtimer>0 && pmax < p->pmax*(1-THRESH))
- p->pmaxtimer--;
- if(pmax > p->pmax_target){
- p->pmax_target=pmax;
- p->pmaxtimer=TIMERFRAMES;
- }
- if(p->pmaxtimer<=0)
- p->pmax_target=pmax;
- p->pmax = filter_filter(p->pmax_target,&p->pmax_damp);
-
- if(p->pmintimer>0 && pmin > p->pmin*(1-THRESH))
- p->pmintimer--;
- if(pmin < p->pmin_target){
- p->pmin_target=pmin;
- p->pmintimer=TIMERFRAMES;
- }
- if(p->pmintimer<=0)
- p->pmin_target=pmin;
- p->pmin = filter_filter(p->pmin_target,&p->pmin_damp);
- }
- }
-
- if(phase){
- /* when phase is active, the p->ymax in use is dictated by
- p->pmax/p->pmin, which in turn already took the desired ymax
- into consideration above */
- p->ymax = p->depth*p->pmax/(p->pmax-p->pmin);
- }
-}
-
static gboolean configure(GtkWidget *widget, GdkEventConfigure *event){
Plot *p=PLOT(widget);
- int rescale = !p->configured;
if (p->backing)
g_object_unref(p->backing);
@@ -1019,20 +761,13 @@
widget->allocation.width,
widget->allocation.height,
-1);
- p->ydata=NULL;
p->configured=1;
-
- compute_metadata(widget);
- plot_rescale(p,rescale);
- draw_and_expose(widget);
-
+ replot(0,0,0);
return TRUE;
}
static void plot_class_init (PlotClass *class){
- int i,w,h;
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
- GdkWindow *root=gdk_get_default_root_window();
parent_class = g_type_class_peek_parent (class);
widget_class->expose_event = expose;
@@ -1041,9 +776,6 @@
}
static void plot_init (Plot *p){
- p->mode=0;
- p->scale=0;
- p->depth=45.;
}
GType plot_get_type (void){
@@ -1062,67 +794,62 @@
0
};
- m_type = g_type_register_static (GTK_TYPE_DRAWING_AREA, "Plot", &m_info, 0);
+ m_type = g_type_register_static (GTK_TYPE_DRAWING_AREA, "Plot",
+ &m_info, 0);
}
return m_type;
}
-GtkWidget* plot_new (int size, int groups, int *channels, int *rate){
+GtkWidget* plot_new (void){
GtkWidget *ret= GTK_WIDGET (g_object_new (plot_get_type (), NULL));
Plot *p=PLOT(ret);
- int g,i;
- int ch=0;
- int maxrate=-1;
- p->groups = groups;
- for(g=0;g<groups;g++){
- ch+=channels[g];
- if(rate[g]>maxrate)maxrate=rate[g];
+ int i;
+
+ /* generate all the text layouts we'll need */
+ /* linear X scale */
+ {
+ char *labels[10]={"DC","10kHz","20kHz","30kHz","40kHz","50kHz","60kHz",
+ "70kHz","80kHz","90kHz"};
+ p->lin_layout_200=calloc(11,sizeof(*p->lin_layout_200));
+ for(i=0;i<10;i++)
+ p->lin_layout_200[i]=gtk_widget_create_pango_layout(ret,labels[i]);
}
+ {
+ char *labels[10]={"DC","5kHz","10kHz","15kHz","20kHz","25kHz","30kHz",
+ "35kHz","40kHz","45kHz"};
+ p->lin_layout_100=calloc(11,sizeof(*p->lin_layout_100));
+ for(i=0;i<10;i++)
+ p->lin_layout_100[i]=gtk_widget_create_pango_layout(ret,labels[i]);
+ }
+ {
+ char *labels[13]={"DC","2kHz","4kHz","6kHz","8kHz","10kHz","12kHz",
+ "14kHz","16kHz","18kHz","20kHz","22kHz","24kHz"};
+ p->lin_layout_50=calloc(14,sizeof(*p->lin_layout_50));
+ for(i=0;i<13;i++)
+ p->lin_layout_50[i]=gtk_widget_create_pango_layout(ret,labels[i]);
+ }
- p->total_ch = ch;
-
- p->ch=channels;
- p->rate=rate;
- p->maxrate=maxrate;
-
- if(maxrate > 100000){
- p->lin_major = 10000.;
- p->lin_minor = 2000.;
- p->lin_mult = 5;
- }else if(maxrate > 50000){
- p->lin_major = 5000.;
- p->lin_minor = 1000.;
- p->lin_mult = 5;
- }else{
- p->lin_major=2000.;
- p->lin_minor=500.;
- p->lin_mult=4;
+ /* log X scale */
+ {
+ char *labels[16]={"10Hz","20","30","50","100Hz",
+ "200","300","500","1kHz",
+ "2k","3k","5k","10kHz",
+ "20k","30k","50k"};
+ p->log_layout=calloc(17,sizeof(*p->log_layout));
+ for(i=0;i<16;i++)
+ p->log_layout[i]=gtk_widget_create_pango_layout(ret,labels[i]);
}
- /* generate all the text layouts we'll need */
- /* linear X scale */
+ /* ISO log X scale */
{
- if(maxrate>100000){
- char *labels[11]={"DC","10kHz","20kHz","30kHz","40kHz","50kHz","60kHz",
- "70kHz","80kHz","90kHz",""};
- p->lin_layout=calloc(12,sizeof(*p->lin_layout));
- for(i=0;i<11;i++)
- p->lin_layout[i]=gtk_widget_create_pango_layout(ret,labels[i]);
- }else if(maxrate > 50000){
- char *labels[11]={"DC","5kHz","10kHz","15kHz","20kHz","25kHz","30kHz",
- "35kHz","40kHz","45kHz",""};
- p->lin_layout=calloc(12,sizeof(*p->lin_layout));
- for(i=0;i<11;i++)
- p->lin_layout[i]=gtk_widget_create_pango_layout(ret,labels[i]);
- }else{
- char *labels[14]={"DC","2kHz","4kHz","6kHz","8kHz","10kHz","12kHz",
- "14kHz","16kHz","18kHz","20kHz","22kHz","24kHz",""};
- p->lin_layout=calloc(15,sizeof(*p->lin_layout));
- for(i=0;i<14;i++)
- p->lin_layout[i]=gtk_widget_create_pango_layout(ret,labels[i]);
- }
+ char *labels[12]={"31Hz","63Hz","125Hz","250Hz","500Hz","1kHz","2kHz",
+ "4kHz","8kHz","16kHz","32kHz","64kHz"};
+ p->iso_layout=calloc(13,sizeof(*p->iso_layout));
+ for(i=0;i<12;i++)
+ p->iso_layout[i]=gtk_widget_create_pango_layout(ret,labels[i]);
}
+
/* phase Y scale */
{
char *labels[37]={"-180\xC2\xB0","-170\xC2\xB0","-160\xC2\xB0",
@@ -1142,32 +869,7 @@
for(i=0;i<37;i++)
p->phase_layout[i]=gtk_widget_create_pango_layout(ret,labels[i]);
}
- /* log X scale */
- {
- char *labels[15]={"10Hz","20","30","50","100Hz",
- "200","300","500","1kHz",
- "2k","3k","5k","10kHz",
- "20k","30k"};
- p->log_layout=calloc(16,sizeof(*p->log_layout));
- for(i=0;i<15;i++)
- p->log_layout[i]=gtk_widget_create_pango_layout(ret,labels[i]);
- }
- /* Impedence Y scale */
- {
- char *labels[9]={"10M\xCE\xA9","1M\xCE\xA9","100k\xCE\xA9","10k\xCE\xA9",
- "1k\xCE\xA9","100\xCE\xA9","10\xCE\xA9","1\xCE\xA9",".1\xCE\xA9"};
- p->imp_layout=calloc(10,sizeof(*p->imp_layout));
- for(i=0;i<9;i++)
- p->imp_layout[i]=gtk_widget_create_pango_layout(ret,labels[i]);
- }
- /* ISO log X scale */
- {
- char *labels[12]={"31Hz","63Hz","125Hz","250Hz","500Hz","1kHz","2kHz",
- "4kHz","8kHz","16kHz","32kHz",""};
- p->iso_layout=calloc(13,sizeof(*p->iso_layout));
- for(i=0;i<12;i++)
- p->iso_layout[i]=gtk_widget_create_pango_layout(ret,labels[i]);
- }
+
/* dB Y scale (integer) */
{
char buf[10];
@@ -1177,6 +879,7 @@
p->db_layout[i+200]=gtk_widget_create_pango_layout(ret,buf);
}
}
+
/* dB Y scale (decimal) */
{
char buf[10];
@@ -1186,119 +889,29 @@
p->db_layout1[i]=gtk_widget_create_pango_layout(ret,buf);
}
}
+
/* dB Y scale (dB) */
p->db_layoutdB=gtk_widget_create_pango_layout(ret,"dB");
+
/* dB Y scale (-) */
p->db_layoutN=gtk_widget_create_pango_layout(ret,"-");
- p->ch_active=calloc(ch,sizeof(*p->ch_active));
- p->ch_process=calloc(ch,sizeof(*p->ch_process));
-
- p->autoscale=1;
-
- filter_make_critical(.04,&p->ymax_damp);
- filter_make_critical(.04,&p->pmax_damp);
- filter_make_critical(.04,&p->pmin_damp);
-
+ p->phase_active=0;
return ret;
}
-void plot_refresh (Plot *p, int *process){
-
- if(!p->configured)return;
-
- if(process)
- memcpy(p->ch_process,process,p->total_ch*sizeof(*process));
-
- plot_rescale(p, 0);
+int plot_get_left_pad (Plot *m){
+ return m->padx;
}
-void plot_clear (Plot *p){
- GtkWidget *widget=GTK_WIDGET(p);
- int phase = phase_active_p(p);
- int width=GTK_WIDGET(p)->allocation.width-p->padx-(phase ? p->phax : 0);
- int i,j;
-
- if(p->ydata)
- for(i=0;i<p->total_ch;i++)
- for(j=0;j<width*2;j++)
- p->ydata[i][j]=-300;
-
- p->ymax_target=p->ymax;
- p->pmax_target=p->pmax;
- p->pmin_target=p->pmin;
- filter_reset(&p->ymax_damp,p->ymax);
- filter_reset(&p->pmax_damp,p->pmax);
- filter_reset(&p->pmin_damp,p->pmin);
-
- draw_and_expose(widget);
+int plot_get_right_pad (Plot *m){
+ return (m->phase_active ? m->phax : 0);
}
-float **plot_get (Plot *p){
- return(p->ydata);
+int plot_width (Plot *m){
+ return GTK_WIDGET(m)->allocation.width;
}
-void plot_setting (Plot *p, int scale, int mode, int link, int depth, int noise){
- GtkWidget *widget=GTK_WIDGET(p);
- int phase = phase_active_p(p);
- int request_scale_reset=0;
-
- p->scale=scale;
- p->noise=noise;
-
- if(p->depth != depth ||
- p->mode != mode ||
- p->link!=link){
- if(depth>140)
- p->ymax_limit=depth;
- else
- p->ymax_limit=140;
- request_scale_reset=1;
- }
-
- compute_metadata(widget);
-
- if(!phase && phase_active_p(p))
- request_scale_reset=1;
-
- p->depth=depth;
- p->mode=mode;
- p->link=link;
-
- plot_rescale(p,request_scale_reset);
- draw_and_expose(widget);
+int plot_height (Plot *m){
+ return GTK_WIDGET(m)->allocation.height;
}
-
-void plot_draw (Plot *p){
- GtkWidget *widget=GTK_WIDGET(p);
- draw_and_expose(widget);
-}
-
-void plot_set_active(Plot *p, int *a, int *b){
- GtkWidget *widget=GTK_WIDGET(p);
- memcpy(p->ch_active,a,p->total_ch*sizeof(*a));
- memcpy(p->ch_process,b,p->total_ch*sizeof(*b));
- plot_rescale(p,1);
- draw_and_expose(widget);
-}
-
-void plot_set_autoscale(Plot *p, int a){
- GtkWidget *widget=GTK_WIDGET(p);
- p->autoscale=a;
- plot_rescale(p,a);
- draw_and_expose(widget);
-}
-
-void plot_set_bold(Plot *p, int b){
- GtkWidget *widget=GTK_WIDGET(p);
- p->bold=b;
- draw_and_expose(widget);
-}
-
-int plot_get_left_pad (Plot *m){
- return m->padx;
-}
-
-int plot_get_right_pad (Plot *m){
- return (phase_active_p(m) ? m->phax : 0);
-}
Modified: trunk/spectrum/spec_plot.h
===================================================================
--- trunk/spectrum/spec_plot.h 2012-06-02 16:38:29 UTC (rev 18348)
+++ trunk/spectrum/spec_plot.h 2012-06-03 01:22:50 UTC (rev 18349)
@@ -1,24 +1,24 @@
/*
*
* gtk2 spectrum analyzer
- *
+ *
* Copyright (C) 2004-2012 Monty
*
* This analyzer 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.
- *
+ *
* The analyzer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with Postfish; see the file COPYING. If not, write to the
* Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
- *
+ *
*/
#ifndef __PLOT_H__
@@ -27,6 +27,7 @@
#include <glib.h>
#include <glib-object.h>
#include <gtk/gtk.h>
+#include "io.h"
G_BEGIN_DECLS
@@ -40,22 +41,48 @@
typedef struct _PlotClass PlotClass;
typedef struct {
- double a;
- double b1;
- double b2;
- double x[2];
- double y[2];
-} pole2;
+ int bits[MAX_FILES];
+ int channels[MAX_FILES];
+ int rate[MAX_FILES];
+ int groups;
+ int total_ch;
+ int maxrate;
+ int reload;
+ int scale;
+ int mode;
+ int link;
+ int phase_active;
+ float **data;
+ float *active;
+ float ymax;
+ float pmax;
+ float pmin;
+ int height;
+ int width;
+ int increment;
+} fetchdata;
+
+typedef struct {
+ float ymax;
+ float pmax;
+ float pmin;
+ float depth;
+ float bold;
+} plotparams;
+
struct _Plot{
- GtkDrawingArea canvas;
+ GtkDrawingArea canvas;
GdkPixmap *backing;
GdkGC *drawgc;
GdkGC *dashes;
GdkGC *graygc;
GdkGC *phasegc;
+ PangoLayout **lin_layout_200;
+ PangoLayout **lin_layout_100;
+ PangoLayout **lin_layout_50;
PangoLayout **lin_layout;
PangoLayout **log_layout;
PangoLayout **iso_layout;
@@ -67,21 +94,11 @@
PangoLayout **phase_layout;
int configured;
- float **ydata;
- float *floor;
-
- int groups;
- int *ch;
- int *ch_active;
- int *ch_process;
int total_ch;
- int datasize;
- int mode;
- int link;
int scale;
- int noise;
- int *rate;
int maxrate;
+ int phase_active;
+ int width;
float lin_major;
float lin_minor;
@@ -99,31 +116,9 @@
int ytic[200];
int ytics;
- float depth;
- float ymax;
- float pmax;
- float pmin;
-
- pole2 ymax_damp;
- pole2 pmax_damp;
- pole2 pmin_damp;
-
- float ymax_target;
- float pmax_target;
- float pmin_target;
- int ymaxtimer;
- int pmaxtimer;
- int pmintimer;
-
- float ymax_limit;
-
float padx;
float phax;
float pady;
-
-
- int bold;
- int autoscale;
};
struct _PlotClass{
@@ -133,21 +128,15 @@
};
GType plot_get_type (void);
-GtkWidget* plot_new (int n, int inputs, int *channels, int *rate);
-void plot_refresh (Plot *m, int *process);
-void plot_setting (Plot *m, int scale, int mode, int link, int depth, int noise);
-void plot_draw (Plot *m);
-void plot_clear (Plot *m);
-int plot_width (Plot *m);
-float** plot_get (Plot *m);
-void plot_set_active (Plot *m, int *, int *);
-void plot_set_autoscale (Plot *m, int);
-void plot_set_bold (Plot *m, int);
-
+GtkWidget* plot_new (void);
+void plot_draw (Plot *m, fetchdata *f, plotparams *pp);
int plot_get_left_pad (Plot *m);
int plot_get_right_pad (Plot *m);
+int plot_height (Plot *m);
+int plot_width (Plot *m);
GdkColor chcolor(int ch);
+extern void replot(int scale_reset, int inactive_reset, int scale_damp);
G_END_DECLS
Modified: trunk/spectrum/spec_process.c
===================================================================
--- trunk/spectrum/spec_process.c 2012-06-02 16:38:29 UTC (rev 18348)
+++ trunk/spectrum/spec_process.c 2012-06-03 01:22:50 UTC (rev 18349)
@@ -1,24 +1,24 @@
/*
*
* gtk2 spectrum analyzer
- *
+ *
* Copyright (C) 2004-2012 Monty
*
* This analyzer 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.
- *
+ *
* The analyzer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with Postfish; see the file COPYING. If not, write to the
* Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
- *
+ *
*/
#include "analyzer.h"
@@ -26,31 +26,30 @@
static float *window=NULL;
static float *freqbuffer=0;
-static fftwf_plan plan;
+static fftwf_plan plan=NULL;
+static int prev_total_ch=-1;
pthread_mutex_t feedback_mutex=PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
int feedback_increment=0;
-float *feedback_count;
-float **plot_data;
-float *process_work;
+float *feedback_count=NULL;
+float *process_work=NULL;
-float **feedback_acc;
-float **feedback_max;
-float **feedback_instant;
+float **feedback_acc=NULL;
+float **feedback_max=NULL;
+float **feedback_instant=NULL;
-float **ph_acc;
-float **ph_max;
-float **ph_instant;
+float **ph_acc=NULL;
+float **ph_max=NULL;
+float **ph_instant=NULL;
-float **xmappingL;
-float **xmappingM;
-float **xmappingH;
+float **xmappingL=NULL;
+float **xmappingM=NULL;
+float **xmappingH=NULL;
int metascale = -1;
int metawidth = -1;
-int metanoise = 0;
+int metareload = 0;
-sig_atomic_t acc_clear=0;
sig_atomic_t acc_rewind=0;
sig_atomic_t acc_loop=0;
@@ -59,10 +58,50 @@
static void init_process(void){
int i;
- if(window==NULL){
+
+ if(!window || prev_total_ch != total_ch){
+
+ if(plan)fftwf_destroy_plan(plan);
+
+ if(feedback_acc){
+ for(i=0;i<prev_total_ch;i++)
+ if(feedback_acc[i])free(feedback_acc[i]);
+ free(feedback_acc);
+ }
+ if(feedback_max){
+ for(i=0;i<prev_total_ch;i++)
+ if(feedback_max[i])free(feedback_max[i]);
+ free(feedback_max);
+ }
+ if(feedback_instant){
+ for(i=0;i<prev_total_ch;i++)
+ if(feedback_instant[i])free(feedback_instant[i]);
+ free(feedback_instant);
+ }
+ if(ph_acc){
+ for(i=0;i<prev_total_ch;i++)
+ if(ph_acc[i])free(ph_acc[i]);
+ free(ph_acc);
+ }
+ if(ph_max){
+ for(i=0;i<prev_total_ch;i++)
+ if(ph_max[i])free(ph_max[i]);
+ free(ph_max);
+ }
+ if(ph_instant){
+ for(i=0;i<prev_total_ch;i++)
+ if(ph_instant[i])free(ph_instant[i]);
+ free(ph_instant);
+ }
+
+ if(process_work)free(process_work);
+ if(feedback_count)free(feedback_count);
+
+ if(freqbuffer)free(freqbuffer);
+ if(window)free(window);
+
process_work=calloc(blocksize+2,sizeof(*process_work));
feedback_count=calloc(total_ch,sizeof(*feedback_count));
- plot_data=calloc(total_ch,sizeof(*plot_data));
feedback_acc=malloc(total_ch*sizeof(*feedback_acc));
feedback_max=malloc(total_ch*sizeof(*feedback_max));
@@ -84,6 +123,8 @@
ph_instant[i]=calloc(blocksize+2,sizeof(**ph_instant));
}
+ prev_total_ch = total_ch;
+
plan=fftwf_plan_dft_r2c_1d(blocksize,freqbuffer,
(fftwf_complex *)freqbuffer,
FFTW_ESTIMATE);
@@ -99,6 +140,7 @@
void rundata_clear(){
int i,j;
+ pthread_mutex_lock(&feedback_mutex);
for(i=0;i<total_ch;i++){
feedback_count[i]=0;
memset(feedback_acc[i],0,(blocksize/2+1)*sizeof(**feedback_acc));
@@ -111,16 +153,12 @@
ph_instant[i][j]=0;
}
}
- acc_clear=0;
+ pthread_mutex_unlock(&feedback_mutex);
}
-extern int plot_noise;
-
/* return 0 on EOF, 1 otherwise */
static int process(){
int fi,i,j,ch;
- int eof_all;
- int noise=plot_noise;
if(acc_rewind)
rewind_files();
@@ -129,25 +167,22 @@
if(input_read(acc_loop,0))
return 0;
- if(acc_clear)
- rundata_clear();
-
/* by channel */
ch=0;
for(fi=0;fi<inputs;fi++){
if(blockbufferfill[fi]){
for(i=ch;i<ch+channels[fi];i++){
-
+
float *data=blockbuffer[i];
/* window the blockbuffer into the FFT buffer */
for(j=0;j<blocksize;j++){
freqbuffer[j]=data[j]*window[j];
}
-
+
/* transform */
fftwf_execute(plan);
-
+
pthread_mutex_lock(&feedback_mutex);
/* perform desired accumulations */
@@ -178,22 +213,22 @@
ph_acc[i][j]+=pR;
ph_acc[i][j+1]+=pI;
-
+
if(feedback_max[i][j>>1]<sqM){
ph_max[i][j]=pR;
ph_max[i][j+1]=pI;
}
}
-
+
feedback_instant[i][j>>1]=sqM;
feedback_acc[i][j>>1]+=sqM;
-
+
if(feedback_max[i][j>>1]<sqM)
feedback_max[i][j>>1]=sqM;
-
+
}
feedback_count[i]++;
-
+
pthread_mutex_unlock(&feedback_mutex);
}
}
@@ -206,8 +241,23 @@
}
void *process_thread(void *dummy){
+ pthread_mutex_lock(&feedback_mutex);
init_process();
- while(!process_exit && process());
+ pthread_mutex_unlock(&feedback_mutex);
+
+ while(1){
+ while(!process_exit && process());
+ pthread_mutex_lock(&feedback_mutex);
+ if(!process_exit && pipe_reload()){
+ /* ah, at least one input was a pipe */
+ init_process();
+ metareload=1;
+ pthread_mutex_unlock(&feedback_mutex);
+ }else{
+ pthread_mutex_unlock(&feedback_mutex);
+ break;
+ }
+ }
process_active=0;
write(eventpipe[1],"",1);
return NULL;
@@ -217,104 +267,156 @@
int fi,i,j,ch;
FILE *out;
- {
- out=fopen("accumulate.m","w");
- ch = 0;
- for(fi=0;fi<inputs;fi++){
- for(i=0;i<blocksize/2+1;i++){
- fprintf(out,"%f ",(double)i*rate[fi]/blocksize);
-
- for(j=ch;j<ch+channels[fi];j++)
- fprintf(out,"%f ",todB(feedback_acc[j][i])*.5);
- fprintf(out,"\n");
- }
+ pthread_mutex_lock(&feedback_mutex);
+
+ out=fopen("accumulate.m","w");
+ ch = 0;
+ for(fi=0;fi<inputs;fi++){
+ for(i=0;i<blocksize/2+1;i++){
+ fprintf(out,"%f ",(double)i*rate[fi]/blocksize);
+
+ for(j=ch;j<ch+channels[fi];j++)
+ fprintf(out,"%f ",todB(feedback_acc[j][i])*.5);
fprintf(out,"\n");
- ch+=channels[fi];
}
- fclose(out);
+ fprintf(out,"\n");
+ ch+=channels[fi];
}
+ fclose(out);
- {
- out=fopen("max.m","w");
- ch = 0;
- for(fi=0;fi<inputs;fi++){
- for(i=0;i<blocksize/2+1;i++){
- fprintf(out,"%f ",(double)i*rate[fi]/blocksize);
-
- for(j=ch;j<ch+channels[fi];j++)
- fprintf(out,"%f ",todB(feedback_max[j][i])*.5);
- fprintf(out,"\n");
- }
+ out=fopen("max.m","w");
+ ch = 0;
+ for(fi=0;fi<inputs;fi++){
+ for(i=0;i<blocksize/2+1;i++){
+ fprintf(out,"%f ",(double)i*rate[fi]/blocksize);
+
+ for(j=ch;j<ch+channels[fi];j++)
+ fprintf(out,"%f ",todB(feedback_max[j][i])*.5);
fprintf(out,"\n");
- ch+=channels[fi];
}
- fclose(out);
+ fprintf(out,"\n");
+ ch+=channels[fi];
}
+ fclose(out);
- {
- out=fopen("instant.m","w");
- ch = 0;
- for(fi=0;fi<inputs;fi++){
- for(i=0;i<blocksize/2+1;i++){
- fprintf(out,"%f ",(double)i*rate[fi]/blocksize);
-
- for(j=ch;j<ch+channels[fi];j++)
- fprintf(out,"%f ",todB(feedback_instant[j][i])*.5);
- fprintf(out,"\n");
- }
+ out=fopen("instant.m","w");
+ ch = 0;
+ for(fi=0;fi<inputs;fi++){
+ for(i=0;i<blocksize/2+1;i++){
+ fprintf(out,"%f ",(double)i*rate[fi]/blocksize);
+
+ for(j=ch;j<ch+channels[fi];j++)
+ fprintf(out,"%f ",todB(feedback_instant[j][i])*.5);
fprintf(out,"\n");
- ch+=channels[fi];
}
- fclose(out);
+ fprintf(out,"\n");
+ ch+=channels[fi];
}
+ fclose(out);
- {
- out=fopen("accphase.m","w");
- ch = 0;
- for(fi=0;fi<inputs;fi++){
+ out=fopen("accphase.m","w");
+ ch = 0;
+ for(fi=0;fi<inputs;fi++){
- /* phase */
- for(i=0;i<blocksize+2;i+=2){
- fprintf(out,"%f ",(double)i*.5*rate[fi]/blocksize);
- fprintf(out,"%f ",atan2(ph_acc[ch+1][i+1],ph_acc[ch+1][i])*57.29);
- fprintf(out,"\n");
- }
+ /* phase */
+ for(i=0;i<blocksize+2;i+=2){
+ fprintf(out,"%f ",(double)i*.5*rate[fi]/blocksize);
+ fprintf(out,"%f ",atan2(ph_acc[ch+1][i+1],ph_acc[ch+1][i])*57.29);
fprintf(out,"\n");
- ch+=channels[fi];
}
- fclose(out);
+ fprintf(out,"\n");
+ ch+=channels[fi];
}
+ fclose(out);
+ pthread_mutex_unlock(&feedback_mutex);
}
/* how many bins to 'trim' off the edge of calculated data when we
know we've hit a boundary of marginal measurement */
#define binspan 5
+static fetchdata fetch_ret;
+
/* the data returned is now 2 vals per bin; a min and a max. The spec
plot merely draws a vertical line between. */
-float **process_fetch(int scale, int mode, int link,
- int *active, int width,
- float *ymax, float *pmax, float *pmin){
+fetchdata *process_fetch(int scale, int mode, int link,
+ int *process_in, int process_n,
+ int height, int width){
int ch,ci,i,j,fi;
float **data;
float **ph;
float *normptr;
float maxrate=-1.;
float nyq;
+ int process[total_ch];
+ pthread_mutex_lock(&feedback_mutex);
init_process();
+ if(total_ch!=fetch_ret.total_ch){
+ if(fetch_ret.data){
+ for(i=0;i<fetch_ret.total_ch;i++)
+ if(fetch_ret.data[i])free(fetch_ret.data[i]);
+ free(fetch_ret.data);
+ fetch_ret.data=NULL;
+ }
+ if(fetch_ret.active){
+ free(fetch_ret.active);
+ fetch_ret.active=NULL;
+ }
+ }
+
+ if(!fetch_ret.data)
+ fetch_ret.data = calloc(total_ch,sizeof(*fetch_ret.data));
+
+ if(!fetch_ret.active)
+ fetch_ret.active = calloc(total_ch,sizeof(*fetch_ret.active));
+
+ fetch_ret.groups=inputs;
+ fetch_ret.scale=scale;
+ fetch_ret.mode=mode;
+ fetch_ret.link=link;
+
+ fetch_ret.height=height;
+ fetch_ret.width=width;
+ fetch_ret.total_ch=total_ch;
+ fetch_ret.increment=feedback_increment;
+ memcpy(fetch_ret.bits,bits,sizeof(fetch_ret.bits));
+ memcpy(fetch_ret.channels,channels,sizeof(fetch_ret.channels));
+ memcpy(fetch_ret.rate,rate,sizeof(fetch_ret.rate));
+
+ /* the passed in process array length doesn't necesarity match the
+ current number of channels */
+ for(i=0;i<process_n && i<total_ch;i++)
+ fetch_ret.active[i] = process[i] = process_in[i];
+ for(;i<total_ch;i++)
+ fetch_ret.active[i] = process[i] = 0;
+
for(fi=0;fi<inputs;fi++)
if(rate[fi]>maxrate)maxrate=rate[fi];
+
nyq=maxrate/2.;
+ fetch_ret.maxrate=maxrate;
+ fetch_ret.reload=metareload;
+ metareload=0;
+ if(link == LINK_PHASE){
+ int cho=0;
+ int gi;
+ fetch_ret.phase_active=0;
+ for(gi=0;gi<inputs;gi++)
+ if(channels[gi]>1 && fetch_ret.active[cho+1]){
+ fetch_ret.phase_active=1;
+ break;
+ }
+ }
+
/* are our scale mappings up to date? */
if(scale != metascale || width != metawidth){
if(!xmappingL) xmappingL = calloc(inputs, sizeof(*xmappingL));
if(!xmappingM) xmappingM = calloc(inputs, sizeof(*xmappingM));
if(!xmappingH) xmappingH = calloc(inputs, sizeof(*xmappingH));
- metanoise=-1;
for(fi=0;fi<inputs;fi++){
@@ -395,10 +497,11 @@
}
for(i=0;i<total_ch;i++)
- if(plot_data[i]){
- plot_data[i] = realloc(plot_data[i],(width+1)*2*sizeof(**plot_data));
+ if(fetch_ret.data[i]){
+ fetch_ret.data[i] = realloc
+ (fetch_ret.data[i],(width+1)*2*sizeof(**fetch_ret.data));
}else{
- plot_data[i] = malloc((width+1)*2*sizeof(**plot_data));
+ fetch_ret.data[i] = malloc((width+1)*2*sizeof(**fetch_ret.data));
}
}
@@ -423,11 +526,11 @@
normptr=feedback_count;
break;
}
-
+
ch=0;
- *ymax = -210.;
- *pmax = -180.;
- *pmin = 180.;
+ fetch_ret.ymax = -210.;
+ fetch_ret.pmax = -180.;
+ fetch_ret.pmin = 180.;
for(fi=0;fi<inputs;fi++){
float *L = xmappingL[fi];
float *M = xmappingM[fi];
@@ -438,8 +541,8 @@
case LINK_INDEPENDENT:
for(ci=0;ci<channels[fi];ci++){
- if(active[ch+ci]){
- float *y = plot_data[ci+ch];
+ if(process[ch+ci]){
+ float *y = fetch_ret.data[ci+ch];
float *m = data[ci+ch];
int prevbin;
float prevy;
@@ -473,7 +576,7 @@
max*=.5;
min*=.5;
- if(max>*ymax)*ymax=max;
+ if(max>fetch_ret.ymax)fetch_ret.ymax=max;
/* link non-overlapping bins into contiguous lines */
if(i>0){
@@ -496,8 +599,20 @@
break;
case LINK_SUMMED:
+
+ /* display first channel, but only if any channels in the group
+ are processed */
{
- float *y = plot_data[ch];
+ int any=0;
+ for(i=ch;i<ch+channels[fi];i++){
+ if(fetch_ret.active[i])any=1;
+ fetch_ret.active[i]=0;
+ }
+ fetch_ret.active[ch]=any;
+ }
+
+ {
+ float *y = fetch_ret.data[ch];
float **m = data+ch;
int prevbin;
float prevy;
@@ -516,7 +631,7 @@
int mid = floor(M[i]);
float del=M[i]-floor(M[i]);
for(ci=0;ci<channels[fi];ci++){
- if(active[ch+ci]){
+ if(process[ch+ci]){
a+=m[ci][mid];
b+=m[ci][mid+1];
}
@@ -527,14 +642,14 @@
}else{
float a=0.;
for(ci=0;ci<channels[fi];ci++){
- if(active[ch+ci]) a+=m[ci][first];
+ if(process[ch+ci]) a+=m[ci][first];
}
firsty=min=max=a;
for(j=first+1;j<last;j++){
a=0.;
for(ci=0;ci<channels[fi];ci++){
- if(active[ch+ci]) a+=m[ci][j];
+ if(process[ch+ci]) a+=m[ci][j];
}
if(a<min)min=a;
if(a>max)max=a;
@@ -549,7 +664,7 @@
min*=.5;
max*=.5;
- if(max>*ymax)*ymax=max;
+ if(max>fetch_ret.ymax)fetch_ret.ymax=max;
/* link non-overlapping bins into contiguous lines */
if(i>0){
@@ -571,96 +686,106 @@
break;
case LINK_SUB_FROM:
- {
- float *y = plot_data[ch];
- if(active[ch]==0){
- for(i=0;i<width*2+2;i++)
- y[i]=-300;
- }else{
- float *y = plot_data[ch];
- float **m = data+ch;
- int prevbin;
- float prevy;
- for(i=0;i<width;i++){
- int first=ceil(L[i]);
- int last=ceil(H[i]);
- float firsty,lasty,min,max;
- /* don't allow roundoff error to skip a bin entirely */
- if(i>0 && prevbin<first)first=prevbin;
- prevbin=last;
+ for(i=ch;i<ch+channels[fi];i++)
+ fetch_ret.active[i]=0;
- if(first==last){
- int mid = floor(M[i]);
- float del=M[i]-floor(M[i]);
- float a=m[0][mid];
- float b=m[0][mid+1];
- for(ci=1;ci<channels[fi];ci++){
- if(active[ch+ci]){
- a-=m[ci][mid];
- b-=m[ci][mid+1];
- }
+ if(process[ch]==0){
+ float *y = fetch_ret.data[ch];
+ for(i=0;i<width*2+2;i++)
+ y[i]=-300;
+ }else{
+ float *y = fetch_ret.data[ch];
+ float **m = data+ch;
+ int prevbin;
+ float prevy;
+
+ fetch_ret.active[ch]=1;
+
+ for(i=0;i<width;i++){
+ int first=ceil(L[i]);
+ int last=ceil(H[i]);
+ float firsty,lasty,min,max;
+
+ /* don't allow roundoff error to skip a bin entirely */
+ if(i>0 && prevbin<first)first=prevbin;
+ prevbin=last;
+
+ if(first==last){
+ int mid = floor(M[i]);
+ float del=M[i]-floor(M[i]);
+ float a=m[0][mid];
+ float b=m[0][mid+1];
+ for(ci=1;ci<channels[fi];ci++){
+ if(process[ch+ci]){
+ a-=m[ci][mid];
+ b-=m[ci][mid+1];
}
- a=todB(a*normalize);
- b=todB(b*normalize);
- firsty=lasty=min=max=(a+(b-a)*del);
- }else{
- float a=m[0][first];
+ }
+ a=todB(a*normalize);
+ b=todB(b*normalize);
+ firsty=lasty=min=max=(a+(b-a)*del);
+ }else{
+ float a=m[0][first];
+ for(ci=1;ci<channels[fi];ci++){
+ if(process[ch+ci]) a-=m[ci][first];
+ }
+ firsty=min=max=a;
+
+ for(j=first+1;j<last;j++){
+ a=m[0][j];
for(ci=1;ci<channels[fi];ci++){
- if(active[ch+ci]) a-=m[ci][first];
+ if(process[ch+ci]) a-=m[ci][j];
}
- firsty=min=max=a;
+ if(a<min)min=a;
+ if(a>max)max=a;
+ }
- for(j=first+1;j<last;j++){
- a=m[0][j];
- for(ci=1;ci<channels[fi];ci++){
- if(active[ch+ci]) a-=m[ci][j];
- }
- if(a<min)min=a;
- if(a>max)max=a;
- }
+ lasty=todB(a*normalize);
+ firsty=todB(firsty*normalize);
+ min=todB(min*normalize);
+ max=todB(max*normalize);
+ }
- lasty=todB(a*normalize);
- firsty=todB(firsty*normalize);
- min=todB(min*normalize);
- max=todB(max*normalize);
- }
+ min*=.5;
+ max*=.5;
- min*=.5;
- max*=.5;
+ if(max>fetch_ret.ymax)fetch_ret.ymax=max;
- if(max>*ymax)*ymax=max;
+ /* link non-overlapping bins into contiguous lines */
+ if(i>0){
+ float midpoint = (prevy+firsty)*.25;
- /* link non-overlapping bins into contiguous lines */
- if(i>0){
- float midpoint = (prevy+firsty)*.25;
+ if(midpoint<min)min=midpoint;
+ if(midpoint>max)max=midpoint;
- if(midpoint<min)min=midpoint;
- if(midpoint>max)max=midpoint;
+ if(midpoint<y[i*2-2])y[i*2-2]=midpoint;
+ if(midpoint>y[i*2-1])y[i*2-1]=midpoint;
+ }
- if(midpoint<y[i*2-2])y[i*2-2]=midpoint;
- if(midpoint>y[i*2-1])y[i*2-1]=midpoint;
- }
+ y[i*2]=min;
+ y[i*2+1]=max;
- y[i*2]=min;
- y[i*2+1]=max;
-
- prevy=lasty;
- }
+ prevy=lasty;
}
}
break;
case LINK_SUB_REF:
+
{
- float *y = plot_data[ch];
+ float *r = data[ch];
+ float *y = fetch_ret.data[ch];
for(i=0;i<width*2+2;i++)
y[i]=-300;
- }
- {
- float *r = data[ch];
+
+ /* first channel in each display group not shown; used as a
+ reference */
+ fetch_ret.active[ch]=0;
+
+ /* process 1->n */
for(ci=1;ci<channels[fi];ci++){
- if(active[ch+ci]){
- float *y = plot_data[ci+ch];
+ if(process[ch+ci]){
+ float *y = fetch_ret.data[ci+ch];
float *m = data[ci+ch];
int prevbin;
float prevy;
@@ -694,7 +819,7 @@
max*=.5;
min*=.5;
- if(max>*ymax)*ymax=max;
+ if(max>fetch_ret.ymax)fetch_ret.ymax=max;
/* link non-overlapping bins into contiguous lines */
if(i>0){
@@ -719,9 +844,12 @@
case LINK_PHASE: /* response/phase */
+ for(i=ch+2;i<ch+channels[fi];i++)
+ fetch_ret.active[i]=0;
+
if(channels[fi]>=2){
- float *om = plot_data[ch];
- float *op = plot_data[ch+1];
+ float *om = fetch_ret.data[ch];
+ float *op = fetch_ret.data[ch+1];
float *r = data[ch];
float *m = data[ch+1];
@@ -734,7 +862,7 @@
/* two vectors only; response and phase */
/* response is a standard minmax vector */
/* phase is averaged to screen resolution */
- if(active[ch] || active[ch+1]){
+ if(process[ch] || process[ch+1]){
int prevbin;
float prevy;
@@ -756,7 +884,7 @@
float b = todB(m[mid+1]/r[mid+1]);
firsty=lasty=min=max=(a+(b-a)*del);
- if(active[ch+1]){
+ if(process[ch+1]){
float aP = (isnan(a) ? NAN : atan2f(p[mid*2+1],p[mid*2]));
float bP = (isnan(b) ? NAN : atan2f(p[mid*2+3],p[mid*2+2]));
P=(aP+(bP-aP)*del)*57.29;
@@ -780,17 +908,17 @@
min=todB(min);
max=todB(max);
- if(active[ch+1])
+ if(process[ch+1])
P = atan2f(I,R)*57.29;
}
max*=.5;
min*=.5;
- if(max>*ymax)*ymax=max;
- if(P>*pmax)*pmax = P;
- if(P<*pmin)*pmin = P;
+ if(max>fetch_ret.ymax)fetch_ret.ymax=max;
+ if(P>fetch_ret.pmax)fetch_ret.pmax = P;
+ if(P<fetch_ret.pmin)fetch_ret.pmin = P;
- if(active[ch+1] && min>-70){
+ if(process[ch+1] && min>-70){
float midpoint = (prevP+P)*.5;
op[i*2]=P;
op[i*2+1]=P;
@@ -830,7 +958,7 @@
}
ch+=channels[fi];
}
-
- return plot_data;
+
+ pthread_mutex_unlock(&feedback_mutex);
+ return &fetch_ret;
}
-
Modified: trunk/spectrum/version.h
===================================================================
--- trunk/spectrum/version.h 2012-06-02 16:38:29 UTC (rev 18348)
+++ trunk/spectrum/version.h 2012-06-03 01:22:50 UTC (rev 18349)
@@ -1,2 +1,2 @@
#define VERSION "$Id$ "
-/* DO NOT EDIT: Automated versioning hack [Thu May 31 20:32:33 EDT 2012] */
+/* DO NOT EDIT: Automated versioning hack [Sat Jun 2 21:20:35 EDT 2012] */
More information about the commits
mailing list