⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fourier_mode_funcs.c

📁 linux下的FFT 频谱分析
💻 C
字号:
#include "fft-spectra.h"#include <math.h>#define SB_TAGS_MARGIN 30               /* Margins for drawing the spectra */#define DELTA_ZOOM 0.1                  /* How much will be scaled the zoom */#define DELTA_MOVE 0.05                 /* How much will we move left or right */#define MAX_ZOOM 5GSList *linetags=NULL;                  /* Display custom vertical lines to see tones of interest. */static float ymax=0;                    /* The largest intensity contribution is needed for intensity_scale_mode. */extern PangoLayout *pango_layout;       /* Pango for rendering text */static GdkGC                            /* Gdk Graphic contexts used for drawing: */    *gc_bg=NULL,                        /* .. background */    *gc_spectra=NULL,                   /* .. the spectra lines */    *gc_sb_bg=NULL,                     /* .. scalebar background */    *gc_sb_fg=NULL,                     /* .. text of pointer in scalebar */    *gc_sb_tags=NULL,                   /* .. scalebar numbers */    *gc_small_tics_lines=NULL,          /* .. grid with smaller intervals */    *gc_large_tics_lines=NULL;          /* .. grid with larger intervals */static GdkPoint *points=NULL;           /* Points for drawing the spectra */static int                              /* Grid of equaly spaced frequency lines is made of two types: */    scalebar_small_dfreq,               /* .. smaller intervals with dashed lines */    scalebar_large_dfreq;               /* .. larger intervals with full lines */static int scalebar_small_tics_start_at_freq=0;     /* Where to start with the frequency lines */int data_display_from=0,                /* Zoom boundaries - range of data points which should be displayed */            data_display_to=0;static int ori_data_display_from,       /* Save the orginal zoom position and restore it on user request */            ori_data_display_to;int intensity_scale_mode=INTENSITY_SCALE_FLEXIBLE;  /* Whether to remember y scale of spectra (intensities) */static int logscale = 0;                /* Scale the intensity logarithmically? */#define DISPLAY_CURVE 0                 /* New name for the same thing: Data interpolation, the default should */#define DISPLAY_VLINES 1                /*  be off, so that single check button may be used also for spectrogram mode. */static int display_type = DISPLAY_VLINES;inline float idata_to_pixel(float idata,float width){    return (idata-data_display_from)*width/(data_display_to-data_display_from+1);}inline float pixel_to_idata(float pixel,float width){    return pixel*(data_display_to-data_display_from+1)/width + data_display_from;}inline float pixel_to_freq(float pixel,float width){    return idata_to_freq(pixel_to_idata(pixel,width));}inline float freq_to_pixel(float freq,float width){    return idata_to_pixel(freq_to_idata(freq),width);}inline float dfreq_to_dpixel(float df,float width){    return freq_to_idata(df)*width/(data_display_to-data_display_from+1);}inline float freq_to_idata(float freq){    return freq/dfreq;}inline float idata_to_freq(float idata){    return idata*dfreq;}linetag_t *get_new_tag(float freq,char *label,char *color){    linetag_t *tag;    MALLOC(tag,linetag_t,1);    tag->freq  = freq;    tag->idata = freq_to_idata(freq);    tag->label = label;    tag->gc    = get_gc(color);    return tag;}/* Read the profile from the config file:    - custom line tags    - window dimensions    - colors    - original display range (but not the current one!)*/void fourier_read_profile(int *width, int *height){    char *color, *note;    GSList *l;    linetag_t *tag;    float freq_from=0, freq_to=0, freq;    /* Remove any existing tags.. */    while (linetags)    {        tag = (linetag_t*)linetags->data;        /* Dont unref GdkGC before an analogue of get_gc() is ready.            g_object_unref(tag->gc);         */        free(tag);        linetags = linetags->next;    }    /* Read the new tags.. */    if ( settings )    {        l = sconf_get_gslist(settings,"linetags");        while (l)        {            note = (char*)l->data;            l = l->next;            color = l ? (char*)l->data : "#ffffff";            l = l->next;            if ( !sconf_get_float("labels",note,&freq) )                sscanf(note,"%f",&freq);            tag = get_new_tag(freq,note,color);            linetags = g_slist_append(linetags,tag);        }    }    /* Read the colors */    gc_bg      = get_gc( sconf_get_string_or_die(settings,"spectra_bg_color") );    gc_spectra = get_gc( sconf_get_string_or_die(settings,"spectra_color") );    gc_sb_bg   = get_gc( sconf_get_string_or_die(settings,"scalebar_bg_color") );    gc_sb_fg   = get_gc( sconf_get_string_or_die(settings,"scalebar_pointer") );    gc_sb_tags = get_gc( sconf_get_string_or_die(settings,"scalebar_numbers") );    gc_large_tics_lines = get_gc( sconf_get_string_or_die(settings,"large_grid_color") );    gc_small_tics_lines = get_gc_new( sconf_get_string_or_die(settings,"small_grid_color") );    gdk_gc_set_line_attributes(gc_small_tics_lines,1,GDK_LINE_ON_OFF_DASH,GDK_CAP_NOT_LAST,GDK_JOIN_MITER);    /* Window dimension */    if ( !sconf_get_int(settings,"spectra_width",width) )        exit_nicely("Could not read config value of \"%s/spectra_width\".\n", settings?settings:"default");    if ( !sconf_get_int(settings,"spectra_height",height) )        exit_nicely("Could not read config value of \"%s/spectra_height\".\n", settings?settings:"default");    /* The original display range*/    if ( !sconf_get_float(settings,"display_from",&freq_from) )        freq_from = 0;    else        freq_from = freq_to_idata(freq_from);    if ( !sconf_get_float(settings,"display_to",&freq_to) )        freq_to = ndata_out-1;    else        freq_to = freq_to_idata(freq_to);    if ( freq_from<0 || freq_from>=ndata_out ) freq_from=0;    if ( freq_to<0 || freq_to>=ndata_out ) freq_to=ndata_out-1;    ori_data_display_from = freq_from;    ori_data_display_to   = freq_to;    if ( data_display_to==data_display_from )        default_zoom_restore();}void fourier_gtk_configure(void){    if (points)        FREE(points);            MALLOC(points,GdkPoint,main_width);}void fourier_main_draw(GdkPixmap *pixmap, int width,int height){    int ipixel,idata_min,idata_max,i,freq_tics;    float max,scale,ymax_tmp=ymax,samples_per_pixel,min;    GSList *l=linetags;    linetag_t *tag;        /* Clean the area */    gdk_draw_rectangle(pixmap,gc_bg, TRUE, 0,0,width,height);    /* Draw vertical tic lines */    if ( view_grid )    {        freq_tics = scalebar_small_tics_start_at_freq;        ipixel = freq_to_pixel(freq_tics,width);        while (ipixel<width)        {            if ( (freq_tics%scalebar_large_dfreq)==0 )                gdk_draw_line(pixmap,gc_large_tics_lines, ipixel,0,ipixel,height);            else                gdk_draw_line(pixmap,gc_small_tics_lines, ipixel,0,ipixel,height);            freq_tics += scalebar_small_dfreq;            ipixel = freq_to_pixel(freq_tics,width);        }    }    /* Draw custom tags */    if ( view_custom_grid )    {        while (l)        {            tag = (linetag_t *) l->data;            if ( tag->idata>data_display_from && tag->idata<data_display_to )            {                ipixel = floor( 0.5+idata_to_pixel(tag->idata,width) );                gdk_draw_line(pixmap,tag->gc, ipixel,0,ipixel,height);                pango_layout_set_text(pango_layout,tag->label,strlen(tag->label));                //pango_layout_get_pixel_size(pango_layout, &tw,&th);                gdk_draw_layout(pixmap, tag->gc, ipixel+5, 5*SB_MARGIN, pango_layout);            }            l = l->next;        }    }    /* Get the sound data, unless reading was stopped by the user. */    if ( !(refresh_status&REFRESH_FFT_STOP) )        get_fft_sample(ndata_in, data, data_display_from,data_display_to,&min,&ymax_tmp,logscale);    if ( intensity_scale_mode==INTENSITY_SCALE_CONSTANT )    {        if ( ymax_tmp>ymax ) ymax=ymax_tmp;    }    else        ymax=ymax_tmp;    scale = ymax ? height/(ymax-min) : 0;       /* Plot results */    samples_per_pixel = 1.0*(data_display_to-data_display_from+1)/width;    if ( samples_per_pixel > 1 )    {        /* More samples than pixels: For each pixel, go through the nearby data            samples and select the one with the largest intensity */        for (ipixel=0; ipixel<width; ipixel++)        {            idata_min = pixel_to_idata(ipixel-0.5,width);            idata_max = pixel_to_idata(ipixel+0.5,width);            max = data[idata_min];            for (i=idata_min+1; i<idata_max; i++)                if ( max<data[i] ) max=data[i];            points[ipixel].x = ipixel;            points[ipixel].y = height-(max-min)*scale;        }    }    else    {        /* More pixels than data samples: For each data sample calculate the            corresponding pixel. */        for (i=data_display_from; i<=data_display_to; i++)        {            ipixel = idata_to_pixel(i,width);            if ( ipixel<0 || ipixel>=width ) exit_nicely("FIXME: ipixel=%d!\n",ipixel);                        points[i-data_display_from].x = ipixel;            points[i-data_display_from].y = height-(data[i]-min)*scale;        }        ipixel = data_display_to-data_display_from+1;    }    if ( display_type==DISPLAY_CURVE )        gdk_draw_lines(pixmap,gc_spectra,points,ipixel);    else    {        /* Display vertical bars.. */        for (i=0; i<ipixel; i++)            gdk_draw_line(pixmap,gc_spectra,points[i].x,points[i].y,points[i].x,height);    }}void fourier_display_type_toggle(void){    if ( display_type == DISPLAY_CURVE )        display_type = DISPLAY_VLINES;    else        display_type = DISPLAY_CURVE;}void fourier_grid_toggle(void){    view_grid = view_grid ? 0 : 1;}void default_zoom_restore(void){    data_display_from = ori_data_display_from;    data_display_to = ori_data_display_to;    if ( mode==MODE_SPECTROGRAM )        spectrogram_clean_screen();}void default_zoom_event(float pressed_x, float released_x){    float from_x,to_x,samples_per_pixel;    if (pressed_x<released_x)    {        from_x = pressed_x;        to_x = released_x;    }    else    {        from_x = released_x;        to_x = pressed_x;    }    samples_per_pixel = 1.0*(data_display_to-data_display_from+1)/main_width;    from_x = samples_per_pixel*from_x + data_display_from;    to_x = samples_per_pixel*to_x + data_display_from;    if ( from_x<0 || from_x>=ndata_out ) from_x = 0;    if ( to_x>=ndata_out || to_x<0 ) to_x = ndata_out-1;        if ( to_x-from_x>MAX_ZOOM )     {        data_display_from = from_x;        data_display_to = to_x;    }    if ( mode==MODE_SPECTROGRAM )        spectrogram_clean_screen();}void default_move_left(void){    float shift;    if ( data_display_from<=0 ) return;    shift = DELTA_MOVE*(data_display_to-data_display_from+1);    if ( shift<1 ) shift=1;    if ( data_display_from<shift )    {        data_display_to -= data_display_from;        data_display_from = 0;    }    else    {        data_display_from -= shift;        data_display_to   -= shift;    }    if ( mode==MODE_SPECTROGRAM )        spectrogram_clean_screen();}void default_move_right(void){    float shift;    if ( data_display_to>=ndata_out ) return;    shift = DELTA_MOVE*(data_display_to-data_display_from+1);    if ( shift<1 ) shift=1;    if ( ndata_out-data_display_to<shift )    {        data_display_from += ndata_out-data_display_to;        data_display_to = ndata_out-1;    }    else    {        data_display_from += shift;        data_display_to   += shift;    }    if ( mode==MODE_SPECTROGRAM )        spectrogram_clean_screen();}void default_zoom_in(void){    float tmp;    tmp = (data_display_to-data_display_from+1)*(DELTA_ZOOM/(1+2*DELTA_ZOOM));    if ( data_display_to-tmp-MAX_ZOOM<data_display_from+tmp ) return;    data_display_from += tmp;    data_display_to   -= tmp;    if ( mode==MODE_SPECTROGRAM )        spectrogram_clean_screen();}void default_zoom_out(void){    float tmp;    tmp = DELTA_ZOOM*(data_display_to-data_display_from);    if ( tmp<1 ) tmp=1;    data_display_from -= tmp;    data_display_to   += tmp;    if ( data_display_from<0 ) data_display_from = 0;    if ( data_display_to>=ndata_out ) data_display_to = ndata_out-1;    if ( mode==MODE_SPECTROGRAM )        spectrogram_clean_screen();}void default_zoom_out_total(void){    data_display_from = 0;    data_display_to = ndata_out-1;    if ( mode==MODE_SPECTROGRAM )        spectrogram_clean_screen();}void default_custom_grid_toggle(void){    view_custom_grid = view_custom_grid ? 0 : 1;}void default_scalebar_draw(GdkPixmap *pixmap, int width,int height){    char buf[10];    float ipixel,freq;    int dw,n,tw,th,i;    n = snprintf(buf,10,"%.0f",idata_to_freq(data_display_to));    pango_layout_set_text(pango_layout,buf,n);    pango_layout_get_pixel_size(pango_layout, &tw,&th);    /* Let's have the numbering spaced 5,10,15etc. */    scalebar_large_dfreq=1;    for (i=0; i<10; i++)    {        dw = dfreq_to_dpixel(scalebar_large_dfreq,width);        if ( dw>SB_TAGS_MARGIN+tw ) break;        if ( i%2 )        {            scalebar_large_dfreq *= 2;            scalebar_small_dfreq = scalebar_large_dfreq/10;        }        else        {            scalebar_small_dfreq = scalebar_large_dfreq;            scalebar_large_dfreq *= 5;        }    }    /* Let the tics and scalebar numbers start on some neat rounded value. */     ipixel = tw/2;    freq   = pixel_to_freq(ipixel,width);    if ( freq!=scalebar_large_dfreq )           freq = (int)freq-((int)freq)%scalebar_large_dfreq + scalebar_large_dfreq;    scalebar_small_tics_start_at_freq = freq;    while (freq_to_pixel(scalebar_small_tics_start_at_freq,width)>0)        scalebar_small_tics_start_at_freq -= scalebar_small_dfreq;    if ( freq_to_pixel(scalebar_small_tics_start_at_freq,width)<0 )        scalebar_small_tics_start_at_freq += scalebar_small_dfreq;    gdk_draw_rectangle(pixmap,gc_sb_bg, TRUE, 0,0,width,height);    do    {        ipixel = freq_to_pixel(freq,width);        n = snprintf(buf,10,"%.0f",freq);        pango_layout_set_text(pango_layout,buf,n);        pango_layout_get_pixel_size(pango_layout, &tw,&th);        gdk_draw_layout(pixmap, gc_sb_tags, ipixel-tw/2, SB_MARGIN, pango_layout);        freq += scalebar_large_dfreq;    }    while ( ipixel+tw+SB_TAGS_MARGIN<width );}void default_scalebar_pointer_draw(GdkPixmap *pixmap, int width,int height,float x){    char buf[10];    float freq;    int n,tw,th;    freq = pixel_to_freq(x,width);    n = snprintf(buf,10,"%.0f", freq);    pango_layout_set_text(pango_layout,buf,n);    pango_layout_get_pixel_size(pango_layout, &tw,&th);    gdk_draw_rectangle(pixmap,gc_sb_bg, TRUE, x-tw/2-SB_MARGIN,0, tw+2*SB_MARGIN,height);    gdk_draw_layout(pixmap, gc_sb_fg, x-tw/2, SB_MARGIN, pango_layout);}void fourier_logarithmic_intensity_toggle(void){    logscale = logscale ? 0 : 1;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -