gtkanal.c

Go to the documentation of this file.
00001 /*
00002  *      GTK plotting routines source file
00003  *
00004  *      Copyright (c) 1999 Mark Taylor
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2 of the License, or (at your option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Library General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the
00018  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00019  * Boston, MA 02111-1307, USA.
00020  */
00021 
00022 /* $Id: gtkanal.c,v 1.41 2007/07/24 17:46:09 bouvigne Exp $ */
00023 
00024 #ifdef HAVE_CONFIG_H
00025 # include <config.h>
00026 #endif
00027 
00028 #include <gtk/gtk.h>
00029 
00030 #include "main.h"
00031 #include "lame.h"
00032 #include "machine.h"
00033 #include "encoder.h"
00034 #include "lame-analysis.h"
00035 #include "get_audio.h"
00036 #include "gtkanal.h"
00037 #include "gpkplotting.h"
00038 #include "lame_global_flags.h"
00039 
00040 /* this file should be removed. The few data items accessed in 'gfc'
00041    should be made accessable by writing a lame_set_variable() function */
00042 #include "util.h"
00043 
00044 #include "console.h"
00045 
00046 
00047 #ifdef _WIN32
00048 #  include <windows.h>
00049 #  define msleep(t) Sleep(t)
00050 #else
00051 #  include <unistd.h>
00052 #  define msleep(t) usleep((t) * 1000)
00053 #endif
00054 
00055 
00056 
00057 
00059 #define STR(x)   #x
00060 
00061 #define XSTR(x)  STR(x)
00062 
00063 #define MP3X_MAJOR_VERSION      0 /* Major version number */
00064 #define MP3X_MINOR_VERSION     82 /* Minor version number */
00065 #define MP3X_ALPHA_VERSION      0 /* Set number if this is an alpha version, otherwise zero */
00066 #define MP3X_BETA_VERSION       0 /* Set number if this is a beta version, otherwise zero */
00067 
00068 
00069 plotting_data *pinfo;
00070 plotting_data *pplot;
00071 plotting_data Pinfo[NUMPINFO];
00072 
00073 
00074 /* global variables for the state of the system */
00075 static gint idle_keepgoing;  /* processing of frames is ON */
00076 static gint idle_count_max;  /* number of frames to process before plotting */
00077 static gint idle_count;      /* pause & plot when idle_count=idel_count_max */
00078 static gint idle_end = 0;    /* process all frames, stop at last frame  */
00079 static gint idle_back = 0;   /* set when we are displaying the old data */
00080 static int mp3done = 0;      /* last frame has been read */
00081 static GtkWidget *frameprogress; /* progress bar */
00082 static GtkWidget *framecounter; /* progress counter */
00083 
00084 static int subblock_draw[3] = { 1, 1, 1 };
00085 
00086 /* main window */
00087 GtkWidget *window;
00088 /* Backing pixmap for drawing areas */
00089 GtkWidget *pcmbox;           /* PCM data plotted here */
00090 GtkWidget *winbox;           /* mpg123 synthesis data plotted here */
00091 GtkWidget *enerbox[2];       /* spectrum, gr=0,1 plotted here */
00092 GtkWidget *mdctbox[2];       /* mdct coefficients gr=0,1 plotted here */
00093 GtkWidget *sfbbox[2];        /* scalefactors gr=0,1 plotted here */
00094 GtkWidget *headerbox;        /* mpg123 header info shown here */
00095 
00096 
00097 struct gtkinfostruct {
00098     int     filetype;        /* input file type 0=WAV, 1=MP3 */
00099     int     msflag;          /* toggle between L&R vs M&S PCM data display */
00100     int     chflag;          /* toggle between L & R channels */
00101     int     kbflag;          /* toggle between wave # and barks */
00102     int     flag123;         /* show mpg123 frame info, OR ISO encoder frame info */
00103     double  avebits;         /* running average bits per frame */
00104     int     approxbits;      /* (approx) bits per frame */
00105     int     maxbits;         /* max bits per frame used so far */
00106     int     totemph;         /* total of frames with de-emphasis */
00107     int     totms;           /* total frames with ms_stereo */
00108     int     totis;           /* total frames with i_stereo */
00109     int     totshort;        /* total granules with short blocks */
00110     int     totmix;          /* total granules with mixed blocks */
00111     int     totpreflag;      /* total granules with preflag */
00112     int     pupdate;         /* plot while processing, or only when needed */
00113     int     sfblines;        /* plot scalefactor bands in MDCT plot */
00114     int     difference;      /* plot original - decoded instead of orig vs. decoded */
00115     int     totalframes;
00116 } gtkinfo;
00117 
00118 
00119 static lame_global_flags *gfp;
00120 lame_internal_flags *gfc;
00121 
00122 /**********************************************************************
00123  * read one frame and encode it
00124  **********************************************************************/
00125 int
00126 gtkmakeframe(void)
00127 {
00128     int     iread = 0;
00129     static int init = 0;
00130     static int mpglag;
00131     static short int Buffer[2][1152];
00132     short int mpg123pcm[2][1152];
00133     int     ch, j;
00134     int     mp3count = 0;
00135     int     mp3out = 0;
00136     int     channels_out;
00137     char    mp3buffer[LAME_MAXMP3BUFFER];
00138     extern plotting_data *mpg123_pinfo;
00139     static int frameNum = 0;
00140     int     framesize = lame_get_framesize(gfp);
00141 
00142     channels_out = (lame_get_mode(gfp) == MONO) ? 1 : 2;
00143 
00144     pinfo->frameNum = frameNum;
00145     pinfo->sampfreq = lame_get_out_samplerate(gfp);
00146     pinfo->framesize = framesize;
00147     pinfo->stereo = channels_out;
00148 
00149     /* If the analsys code is enabled, lame will writes data into gfc->pinfo,
00150      * and mpg123 will write data into mpg123_pinfo.  Set these so
00151      * the libraries put this data in the right place: */
00152     gfc->pinfo = pinfo;
00153     mpg123_pinfo = pinfo;
00154 
00155     if (is_mpeg_file_format(input_format)) {
00156         iread = get_audio16(gfp, Buffer);
00157 
00158 
00159         /* add a delay of framesize-DECDELAY, which will make the total delay
00160          * exactly one frame, so we can sync MP3 output with WAV input */
00161         for (ch = 0; ch < channels_out; ch++) {
00162             for (j = 0; j < framesize - DECDELAY; j++)
00163                 pinfo->pcmdata2[ch][j] = pinfo->pcmdata2[ch][j + framesize];
00164             for (j = 0; j < framesize; j++) /*rescale from int to short int */
00165                 pinfo->pcmdata2[ch][j + framesize - DECDELAY] = Buffer[ch][j];
00166         }
00167 
00168         pinfo->frameNum123 = frameNum - 1;
00169         ++frameNum;
00170 
00171     }
00172     else {
00173 
00174         /* feed data to encoder until encoder produces some output */
00175         while (lame_get_frameNum(gfp) == pinfo->frameNum) {
00176 
00177             if (!init) {
00178                 init = 1;
00179                 mpglag = 1;
00180                 lame_decode_init();
00181             }
00182 
00183             iread = get_audio16(gfp, Buffer);
00184             if (iread > framesize) {
00185                 /* NOTE: frame analyzer requires that we encode one frame
00186                  * for each pass through this loop.  If lame_encode_buffer()
00187                  * is feed data too quickly, it will sometimes encode multiple frames
00188                  * breaking this loop.
00189                  */
00190                 error_printf("Warning: get_audio is returning too much data.\n");
00191             }
00192             if (iread <= 0)
00193                 break;  /* eof */
00194 
00195             mp3count = lame_encode_buffer(gfp, Buffer[0], Buffer[1], iread,
00196                                           mp3buffer, (int) sizeof(mp3buffer));
00197 
00198             assert(!(mp3count > 0 && lame_get_frameNum(gfp) == pinfo->frameNum));
00199             /* not possible to produce mp3 data without encoding at least
00200              * one frame of data which would increment frameNum */
00201         }
00202         frameNum = lame_get_frameNum(gfp); /* use the internal MP3 frame counter */
00203 
00204 
00205         /* decode one frame of output */
00206         mp3out = lame_decode1(mp3buffer, mp3count, mpg123pcm[0], mpg123pcm[1]); /* re-synthesis to pcm */
00207         /* mp3out = 0:  need more data to decode */
00208         /* mp3out = -1:  error.  Lets assume 0 pcm output */
00209         /* mp3out = number of samples output */
00210         if (mp3out > 0)
00211             assert(mp3out == pinfo->framesize);
00212         if (mp3out != 0) {
00213             /* decoded output is for frame pinfo->frameNum123
00214              * add a delay of framesize-DECDELAY, which will make the total delay
00215              * exactly one frame */
00216             pinfo->frameNum123 = pinfo->frameNum - mpglag;
00217             for (ch = 0; ch < pinfo->stereo; ch++) {
00218                 for (j = 0; j < pinfo->framesize - DECDELAY; j++)
00219                     pinfo->pcmdata2[ch][j] = pinfo->pcmdata2[ch][j + pinfo->framesize];
00220                 for (j = 0; j < pinfo->framesize; j++) {
00221                     pinfo->pcmdata2[ch][j + pinfo->framesize - DECDELAY] =
00222                         (mp3out == -1) ? 0 : mpg123pcm[ch][j];
00223                 }
00224             }
00225         }
00226         else {
00227             if (mpglag == MAXMPGLAG) {
00228                 error_printf("READ_AHEAD set too low - not enough frame buffering.\n"
00229                              "MP3x display of input and output PCM data out of sync.\n");
00230                 error_flush();
00231             }
00232             else
00233                 mpglag++;
00234             pinfo->frameNum123 = -1; /* no frame output */
00235         }
00236     }
00237     return iread;
00238 }
00239 
00240 
00241 void
00242 plot_frame(void)
00243 {
00244     int     i, j, n, ch, gr;
00245     gdouble *xcord, *ycord;
00246     gdouble xmx, xmn, ymx, ymn;
00247     double *data, *data2, *data3;
00248     char    title2[80];
00249     char    label[80], label2[80];
00250     char   *title;
00251     plotting_data *pplot1;
00252     plotting_data *pplot2 = NULL;
00253 
00254     double  en, samp;
00255     int     sampindex, version = 0;
00256     int     barthick;
00257     static int firstcall = 1;
00258     static GdkColor *barcolor, *color, *grcolor[2];
00259     static GdkColor yellow, gray, cyan, magenta, orange, pink, red, green, blue, black, oncolor,
00260         offcolor;
00261     int     blocktype[2][2];
00262     int     headbits;
00263     int     mode_gr = 2;
00264 
00265     /* find the frame where mpg123 produced output coming from input frame
00266      * pinfo.  i.e.:   out_frame + out_frame_lag = input_frame  */
00267     for (i = 1; i <= MAXMPGLAG; i++) {
00268         if ((pplot - i)->frameNum123 == pplot->frameNum) {
00269             pplot2 = pplot - i;
00270             break;
00271         }
00272     }
00273     if (i > MAXMPGLAG) {
00274         error_printf("input/output pcm syncing problem.  should not happen!\n");
00275         pplot2 = pplot - 1;
00276     }
00277 
00278 
00279     /* however, the PCM data is delayed by 528 samples in the encoder filterbanks.
00280      * We added another 1152-528 delay to this so the PCM data is *exactly* one
00281      * frame behind the header & MDCT information */
00282     pplot1 = pplot2 + 1; /* back one frame for header info, MDCT */
00283 
00284     /* allocate these GC's only once */
00285     if (firstcall) {
00286         firstcall = 0;
00287         /*    grcolor[0] = &magenta; */
00288         grcolor[0] = &blue;
00289         grcolor[1] = &green;
00290         barcolor = &gray;
00291 
00292         setcolor(headerbox, &oncolor, 255, 0, 0);
00293         setcolor(headerbox, &offcolor, 175, 175, 175);
00294         setcolor(pcmbox, &red, 255, 0, 0);
00295         setcolor(pcmbox, &pink, 255, 0, 255);
00296         setcolor(pcmbox, &magenta, 255, 0, 100);
00297         setcolor(pcmbox, &orange, 255, 127, 0);
00298         setcolor(pcmbox, &cyan, 0, 255, 255);
00299         setcolor(pcmbox, &green, 0, 255, 0);
00300         setcolor(pcmbox, &blue, 0, 0, 255);
00301         setcolor(pcmbox, &black, 0, 0, 0);
00302         setcolor(pcmbox, &gray, 100, 100, 100);
00303         setcolor(pcmbox, &yellow, 255, 255, 0);
00304 
00305     }
00306 
00307   /*******************************************************************
00308    * frame header info
00309    *******************************************************************/
00310     if (pplot1->sampfreq)
00311         samp = pplot1->sampfreq;
00312     else
00313         samp = 1;
00314     sampindex = SmpFrqIndex((long) samp, &version);
00315 
00316     ch = gtkinfo.chflag;
00317 
00318     headbits = 32 + ((pplot1->stereo == 2) ? 256 : 136);
00319     gtkinfo.approxbits = (pplot1->bitrate * 1000 * 1152.0 / samp) - headbits;
00320     sprintf(title2, "%3.1fkHz %ikbs ", samp / 1000, pplot1->bitrate);
00321     gtk_text_freeze(GTK_TEXT(headerbox));
00322     gtk_text_backward_delete(GTK_TEXT(headerbox), gtk_text_get_length(GTK_TEXT(headerbox)));
00323     gtk_text_set_point(GTK_TEXT(headerbox), 0);
00324     gtk_text_insert(GTK_TEXT(headerbox), NULL, &oncolor, NULL, title2, -1);
00325     title = " mono ";
00326     if (2 == pplot1->stereo)
00327         title = pplot1->js ? " js " : " s ";
00328     gtk_text_insert(GTK_TEXT(headerbox), NULL, &oncolor, NULL, title, -1);
00329     color = pplot1->ms_stereo ? &oncolor : &offcolor;
00330     gtk_text_insert(GTK_TEXT(headerbox), NULL, color, NULL, "ms ", -1);
00331     color = pplot1->i_stereo ? &oncolor : &offcolor;
00332     gtk_text_insert(GTK_TEXT(headerbox), NULL, color, NULL, "is ", -1);
00333 
00334     color = pplot1->crc ? &oncolor : &offcolor;
00335     gtk_text_insert(GTK_TEXT(headerbox), NULL, color, NULL, "crc ", -1);
00336     color = pplot1->padding ? &oncolor : &offcolor;
00337     gtk_text_insert(GTK_TEXT(headerbox), NULL, color, NULL, "pad ", -1);
00338 
00339     color = pplot1->emph ? &oncolor : &offcolor;
00340     gtk_text_insert(GTK_TEXT(headerbox), NULL, color, NULL, "em ", -1);
00341 
00342     sprintf(title2, "bv=%i,%i ", pplot1->big_values[0][ch], pplot1->big_values[1][ch]);
00343     gtk_text_insert(GTK_TEXT(headerbox), NULL, &black, NULL, title2, -1);
00344 
00345     color = pplot1->scfsi[ch] ? &oncolor : &offcolor;
00346     sprintf(title2, "scfsi=%i            ", pplot1->scfsi[ch]);
00347     gtk_text_insert(GTK_TEXT(headerbox), NULL, color, NULL, title2, -1);
00348     if (gtkinfo.filetype)
00349         sprintf(title2, " mdb=%i %i/NA", pplot1->maindata, pplot1->totbits);
00350     else
00351         sprintf(title2, " mdb=%i   %i/%i",
00352                 pplot1->maindata, pplot1->totbits, pplot1->totbits + pplot->resvsize);
00353     gtk_text_insert(GTK_TEXT(headerbox), NULL, &oncolor, NULL, title2, -1);
00354     gtk_text_thaw(GTK_TEXT(headerbox));
00355 
00356 
00357 
00358   /*******************************************************************
00359    * block type
00360    *******************************************************************/
00361     for (gr = 0; gr < mode_gr; gr++)
00362         if (gtkinfo.flag123)
00363             blocktype[gr][ch] = pplot1->mpg123blocktype[gr][ch];
00364         else
00365             blocktype[gr][ch] = pplot->blocktype[gr][ch];
00366 
00367 
00368   /*******************************************************************
00369    * draw the PCM data *
00370    *******************************************************************/
00371     n = 1600;           /* PCM frame + FFT window:   224 + 1152 + 224  */
00372     xcord = g_malloc(n * sizeof(gdouble));
00373     ycord = g_malloc(n * sizeof(gdouble));
00374 
00375 
00376     if (gtkinfo.msflag)
00377         title = ch ? "Side Channel" : "Mid Channel";
00378     else
00379         title = ch ? "Right Channel" : "Left Channel";
00380 
00381     sprintf(title2, "%s  mask_ratio=%3.2f  %3.2f  ener_ratio=%3.2f  %3.2f",
00382             title,
00383             pplot->ms_ratio[0], pplot->ms_ratio[1],
00384             pplot->ms_ener_ratio[0], pplot->ms_ener_ratio[1]);
00385 
00386 
00387     ymn = -32767;
00388     ymx = 32767;
00389     xmn = 0;
00390     xmx = 1600 - 1;
00391 
00392     /*  0  ... 224      draw in black, connecting to 224 pixel
00393      * 1375 .. 1599     draw in black  connecting to 1375 pixel
00394      * 224 ... 1375     MP3 frame.  draw in blue
00395      */
00396 
00397     /* draw the title */
00398     gpk_graph_draw(pcmbox, 0, xcord, ycord, xmn, ymn, xmx, ymx, 1, title2, &black);
00399 
00400 
00401     /* draw some hash marks dividing the frames */
00402     ycord[0] = ymx * .8;
00403     ycord[1] = ymn * .8;
00404     for (gr = 0; gr <= 2; gr++) {
00405         xcord[0] = 223.5 + gr * 576;
00406         xcord[1] = 223.5 + gr * 576;
00407         gpk_rectangle_draw(pcmbox, xcord, ycord, xmn, ymn, xmx, ymx, &yellow);
00408     }
00409     for (gr = 0; gr < mode_gr; gr++) {
00410         if (blocktype[gr][ch] == 2)
00411             for (i = 1; i <= 2; i++) {
00412                 xcord[0] = 223.5 + gr * 576 + i * 192;
00413                 xcord[1] = 223.5 + gr * 576 + i * 192;
00414                 gpk_rectangle_draw(pcmbox, xcord, ycord, xmn, ymn, xmx, ymx, &yellow);
00415             }
00416     }
00417     /* bars representing FFT windows */
00418     xcord[0] = 0;
00419     ycord[0] = ymn + 3000;
00420     xcord[1] = 1024 - 1;
00421     ycord[1] = ymn + 1000;
00422     gpk_rectangle_draw(pcmbox, xcord, ycord, xmn, ymn, xmx, ymx, grcolor[0]);
00423     xcord[0] = 576;
00424     ycord[0] = ymn + 2000;
00425     xcord[1] = 576 + 1024 - 1;
00426     ycord[1] = ymn;
00427     gpk_rectangle_draw(pcmbox, xcord, ycord, xmn, ymn, xmx, ymx, grcolor[1]);
00428 
00429 
00430     /* plot PCM data */
00431     for (i = 0; i < n; i++) {
00432         xcord[i] = i;
00433         if (gtkinfo.msflag)
00434             ycord[i] = ch ? .5 * (pplot->pcmdata[0][i] - pplot->pcmdata[1][i]) :
00435                 .5 * (pplot->pcmdata[0][i] + pplot->pcmdata[1][i]);
00436         else
00437             ycord[i] = pplot->pcmdata[ch][i];
00438     }
00439 
00440     /* skip plot if we are doing an mp3 file */
00441     if (!gtkinfo.filetype) {
00442         gpk_graph_draw(pcmbox, n, xcord, ycord, xmn, ymn, xmx, ymx, 0, title2, &black);
00443     }
00444 
00445 
00446   /*******************************************************************/
00447     /* draw the PCM re-synthesis data */
00448   /*******************************************************************/
00449     n = 1152;
00450     /*
00451        sprintf(title2,"Re-synthesis  mask_ratio=%3.2f  %3.2f  ener_ratio=%3.2f  %3.2f",
00452        pplot->ms_ratio[0],pplot->ms_ratio[1],
00453        pplot->ms_ener_ratio[0],pplot->ms_ener_ratio[1]);
00454      */
00455     title = "Re-synthesis";
00456     if (gtkinfo.difference)
00457         title = "Re-synthesis difference (amplified 20db)";
00458 
00459 
00460     ymn = -32767;
00461     ymx = 32767;
00462     xmn = 0;
00463     xmx = 1600 - 1;
00464     gpk_graph_draw(winbox, 0, xcord, ycord, xmn, ymn, xmx, ymx, 1, title, &black);
00465     /* draw some hash marks dividing the frames */
00466     ycord[0] = ymx * .8;
00467     ycord[1] = ymn * .8;
00468     for (gr = 0; gr <= 2; gr++) {
00469         xcord[0] = 223.5 + gr * 576;
00470         xcord[1] = 223.5 + gr * 576;
00471         gpk_rectangle_draw(winbox, xcord, ycord, xmn, ymn, xmx, ymx, &yellow);
00472     }
00473     for (gr = 0; gr < 2; gr++) {
00474         if (blocktype[gr][ch] == 2)
00475             for (i = 1; i <= 2; i++) {
00476                 xcord[0] = 223.5 + gr * 576 + i * 192;
00477                 xcord[1] = 223.5 + gr * 576 + i * 192;
00478                 gpk_rectangle_draw(winbox, xcord, ycord, xmn, ymn, xmx, ymx, &yellow);
00479             }
00480     }
00481 
00482     /* this piece of PCM data from previous frame */
00483     n = 224;
00484     for (j = 1152 - n, i = 0; i < n; i++, j++) {
00485         xcord[i] = i;
00486         if (gtkinfo.msflag)
00487             ycord[i] = ch ? .5 * (pplot1->pcmdata2[0][j] -
00488                                   pplot1->pcmdata2[1][j]) :
00489                 .5 * (pplot1->pcmdata2[0][j] + pplot1->pcmdata2[1][j]);
00490         else
00491             ycord[i] = pplot1->pcmdata2[ch][j];
00492     }
00493 
00494     /* this piece of PCM data from current frame */
00495     n = 1152;
00496     for (i = 0; i < n; i++) {
00497         xcord[i + 224] = i + 224;
00498         if (gtkinfo.msflag)
00499             ycord[i + 224] = ch ? .5 * (pplot2->pcmdata2[0][i] - pplot2->pcmdata2[1][i]) :
00500                 .5 * (pplot2->pcmdata2[0][i] + pplot2->pcmdata2[1][i]);
00501         else
00502             ycord[i + 224] = pplot2->pcmdata2[ch][i];
00503     }
00504 
00505     n = 1152 + 224;
00506     if (gtkinfo.difference) {
00507         for (i = 0; i < n; i++) {
00508             if (gtkinfo.msflag)
00509                 ycord[i] -= ch ? .5 * (pplot->pcmdata[0][i] - pplot->pcmdata[1][i]) :
00510                     .5 * (pplot->pcmdata[0][i] + pplot->pcmdata[1][i]);
00511             else
00512                 ycord[i] -= pplot->pcmdata[ch][i];
00513         }
00514         ycord[i] *= 100;
00515     }
00516 
00517 
00518     gpk_graph_draw(winbox, n, xcord, ycord, xmn, ymn, xmx, ymx, 0, title, &black);
00519 
00520 
00521 
00522 
00523 
00524   /*******************************************************************/
00525     /* draw the MDCT energy spectrum */
00526   /*******************************************************************/
00527     for (gr = 0; gr < mode_gr; gr++) {
00528         int     bits, bits2;
00529         char   *blockname = "";
00530         switch (blocktype[gr][ch]) {
00531         case 0:
00532             blockname = "normal";
00533             break;
00534         case 1:
00535             blockname = "start";
00536             break;
00537         case 2:
00538             blockname = "short";
00539             break;
00540         case 3:
00541             blockname = "end";
00542             break;
00543         }
00544         strcpy(label, blockname);
00545         if (pplot1->mixed[gr][ch])
00546             strcat(label, "(mixed)");
00547 
00548 
00549 
00550 
00551         n = 576;
00552         if (gtkinfo.flag123) {
00553             data = pplot1->mpg123xr[gr][0];
00554             data2 = pplot1->mpg123xr[gr][1];
00555         }
00556         else {
00557             data = pplot->xr[gr][0];
00558             data2 = pplot->xr[gr][1];
00559         }
00560 
00561 
00562         xmn = 0;
00563         xmx = n - 1;
00564         ymn = 0;
00565         ymx = 11;
00566 
00567         /* draw title, erase old plot */
00568         if (gtkinfo.flag123) {
00569             bits = pplot1->mainbits[gr][ch];
00570             bits2 = pplot1->sfbits[gr][ch];
00571         }
00572         else {
00573             bits = pplot->LAMEmainbits[gr][ch];
00574             bits2 = pplot->LAMEsfbits[gr][ch];
00575         }
00576         sprintf(title2, "MDCT%1i(%s) bits=%i/%i ", gr, label, bits, bits2);
00577         gpk_bargraph_draw(mdctbox[gr], 0, xcord, ycord, xmn, ymn, xmx, ymx, 1, title2, 0, barcolor);
00578 
00579         /* draw some hash marks showing scalefactor bands */
00580         if (gtkinfo.sfblines) {
00581             int     fac, nsfb, *scalefac;
00582             if (blocktype[gr][ch] == SHORT_TYPE) {
00583                 nsfb = SBMAX_s;
00584                 i = nsfb - 7;
00585                 fac = 3;
00586                 scalefac = gfc->scalefac_band.s;
00587             }
00588             else {
00589                 nsfb = SBMAX_l;
00590                 i = nsfb - 10;
00591                 fac = 1;
00592                 scalefac = gfc->scalefac_band.l;
00593             }
00594             for (; i < nsfb; i++) {
00595                 ycord[0] = .8 * ymx;
00596                 ycord[1] = ymn;
00597                 xcord[0] = fac * scalefac[i];
00598                 xcord[1] = xcord[0];
00599                 gpk_rectangle_draw(mdctbox[gr], xcord, ycord, xmn, ymn, xmx, ymx, &yellow);
00600             }
00601         }
00602 
00603 
00604 
00605         ymn = 9e20;
00606         ymx = -9e20;
00607         for (i = 0; i < n; i++) {
00608             double  coeff;
00609             xcord[i] = i;
00610             if (gtkinfo.msflag) {
00611                 coeff = ch ? .5 * (data[i] - data2[i]) : .5 * (data[i] + data2[i]);
00612             }
00613             else {
00614                 coeff = ch ? data2[i] : data[i];
00615             }
00616             if (blocktype[gr][ch] == SHORT_TYPE && !subblock_draw[i % 3])
00617                 coeff = 0;
00618             ycord[i] = coeff * coeff * 1e10;
00619             ycord[i] = log10(MAX(ycord[i], (double) 1));
00620 
00621 #if 0
00622             if (ch == 0)
00623                 if (i == 26)
00624                     if (data[i] != 0)
00625                         console_printf("%i %i i=%i  mdct: (db) %f  %f \n", pplot->frameNum, gr, i,
00626                                        10 * log10(data[i] * data[i]),
00627                                        10 * log10(.33 *
00628                                                   (data[i - 1] * data[i - 1] + data[i] * data[i] +
00629                                                    data[i + 1] * data[i + 1]))
00630                             );
00631 #endif
00632 
00633             ymx = (ycord[i] > ymx) ? ycord[i] : ymx;
00634             ymn = (ycord[i] < ymn) ? ycord[i] : ymn;
00635         }
00636         /*  print the min/max
00637            sprintf(title2,"MDCT%1i %5.2f %5.2f  bits=%i",gr,ymn,ymx,
00638            pplot1->mainbits[gr][ch]);
00639          */
00640         if (gtkinfo.flag123)
00641             bits = pplot1->mainbits[gr][ch];
00642         else
00643             bits = pplot->LAMEmainbits[gr][ch];
00644 
00645 
00646         sprintf(title2, "MDCT%1i(%s) bits=%i ", gr, label, bits);
00647 
00648         xmn = 0;
00649         xmx = n - 1;
00650         ymn = 0;
00651         ymx = 11;
00652         gpk_bargraph_draw(mdctbox[gr], n, xcord, ycord, xmn, ymn, xmx, ymx, 0, title2, 0, barcolor);
00653     }
00654 
00655 
00656 
00657 
00658   /*******************************************************************
00659    * draw the psy model energy spectrum (k space)
00660    * l3psy.c computes pe, en, thm for THIS granule.
00661    *******************************************************************/
00662     if (gtkinfo.kbflag) {
00663         for (gr = 0; gr < mode_gr; gr++) {
00664             n = HBLKSIZE; /* only show half the spectrum */
00665 
00666             data = &pplot->energy[gr][ch][0];
00667 
00668             ymn = 9e20;
00669             ymx = -9e20;
00670             for (i = 0; i < n; i++) {
00671                 xcord[i] = i + 1;
00672                 if (blocktype[gr][ch] == SHORT_TYPE && !subblock_draw[i % 3])
00673                     ycord[i] = 0;
00674                 else
00675                     ycord[i] = log10(MAX(data[i], (double) 1));
00676                 ymx = (ycord[i] > ymx) ? ycord[i] : ymx;
00677                 ymn = (ycord[i] < ymn) ? ycord[i] : ymn;
00678             }
00679             for (en = 0, j = 0; j < BLKSIZE; j++)
00680                 en += pplot->energy[gr][ch][j];
00681 
00682             sprintf(title2, "FFT%1i  pe=%5.2fK  en=%5.2e ", gr, pplot->pe[gr][ch] / 1000, en);
00683 
00684             ymn = 3;
00685             ymx = 15;
00686             xmn = 1;
00687             xmx = n;
00688             gpk_bargraph_draw(enerbox[gr], n, xcord, ycord,
00689                               xmn, ymn, xmx, ymx, 1, title2, 0, barcolor);
00690 
00691         }
00692     }
00693     else {
00694     /*******************************************************************
00695      * draw the psy model energy spectrum (scalefactor bands)
00696      *******************************************************************/
00697         for (gr = 0; gr < mode_gr; gr++) {
00698 
00699             if (blocktype[gr][ch] == 2) {
00700                 n = 3 * SBMAX_s;
00701                 data = &pplot->en_s[gr][ch][0];
00702                 data2 = &pplot->thr_s[gr][ch][0];
00703                 data3 = &pplot->xfsf_s[gr][ch][0];
00704             }
00705             else {
00706                 n = SBMAX_l;
00707                 data = &pplot->en[gr][ch][0];
00708                 data2 = &pplot->thr[gr][ch][0];
00709                 data3 = &pplot->xfsf[gr][ch][0];
00710             }
00711             ymn = 9e20;
00712             ymx = -9e20;
00713             for (i = 0; i < n; i++) {
00714                 xcord[i] = i + 1;
00715                 if (blocktype[gr][ch] == SHORT_TYPE && !subblock_draw[i % 3])
00716                     ycord[i] = 0;
00717                 else
00718                     ycord[i] = log10(MAX(data[i], (double) 1));
00719                 /*
00720                    ymx=(ycord[i] > ymx) ? ycord[i] : ymx;
00721                    ymn=(ycord[i] < ymn) ? ycord[i] : ymn;
00722                  */
00723             }
00724 
00725 
00726 
00727             /* en = max energy difference amoung the 3 short FFTs for this granule */
00728             en = pplot->ers[gr][ch];
00729             if (en > 999)
00730                 en = 999;
00731             sprintf(title2,
00732                     "FFT%1i pe=%5.2fK/%3.1f \nnoise ovr_b:%i/max:%3.1f/ovr:%3.1f/tot:%3.1f/ssd:%i",
00733                     gr, pplot->pe[gr][ch] / 1000, en, pplot->over[gr][ch], pplot->max_noise[gr][ch],
00734                     pplot->over_noise[gr][ch], pplot->tot_noise[gr][ch], pplot->over_SSD[gr][ch]);
00735 
00736             barthick = 3;
00737             if (blocktype[gr][ch] == SHORT_TYPE)
00738                 barthick = 2;
00739             if (!(subblock_draw[0] && subblock_draw[1] && subblock_draw[2]))
00740                 barthick = 3;
00741 
00742             ymn = 3;
00743             ymx = 15;
00744             xmn = 1;
00745             xmx = n + 1; /* a little extra because of the bar thickness */
00746             gpk_bargraph_draw(enerbox[gr], n, xcord, ycord,
00747                               xmn, ymn, xmx, ymx, 1, title2, barthick, barcolor);
00748 
00749             for (i = 0; i < n; i++) {
00750                 xcord[i] = i + 1 + .20;
00751                 if (blocktype[gr][ch] == SHORT_TYPE && !subblock_draw[i % 3])
00752                     ycord[i] = 0;
00753                 else
00754                     ycord[i] = log10(MAX(data2[i], (double) 1));
00755             }
00756 
00757             gpk_bargraph_draw(enerbox[gr], n, xcord, ycord,
00758                               xmn, ymn, xmx, ymx, 0, title2, barthick, grcolor[gr]);
00759 
00760             for (i = 0; i < n; i++) {
00761                 xcord[i] = i + 1 + .40;
00762                 if (blocktype[gr][ch] == SHORT_TYPE && !subblock_draw[i % 3])
00763                     ycord[i] = 0;
00764                 else
00765                     ycord[i] = log10(MAX(data3[i], (double) 1));
00766             }
00767             gpk_bargraph_draw(enerbox[gr], n, xcord, ycord,
00768                               xmn, ymn, xmx, ymx, 0, title2, barthick, &red);
00769 
00770         }
00771     }
00772 
00773   /*******************************************************************
00774    * draw scalefactors
00775    *******************************************************************/
00776     for (gr = 0; gr < mode_gr; gr++) {
00777         int     ggain;
00778         if (blocktype[gr][ch] == 2) {
00779             n = 3 * SBMAX_s;
00780             if (gtkinfo.flag123)
00781                 data = pplot1->sfb_s[gr][ch];
00782             else
00783                 data = pplot->LAMEsfb_s[gr][ch];
00784         }
00785         else {
00786             n = SBMAX_l;
00787             if (gtkinfo.flag123)
00788                 data = pplot1->sfb[gr][ch];
00789             else
00790                 data = pplot->LAMEsfb[gr][ch];
00791         }
00792 
00793         ymn = -1;
00794         ymx = 10;
00795         for (i = 0; i < n; i++) {
00796             xcord[i] = i + 1;
00797             if (blocktype[gr][ch] == SHORT_TYPE && !subblock_draw[i % 3])
00798                 ycord[i] = 0;
00799             else
00800                 ycord[i] = -data[i];
00801 
00802             ymx = (ycord[i] > ymx - 2) ? ycord[i] + 2 : ymx;
00803             ymn = (ycord[i] < ymn) ? ycord[i] - 1 : ymn;
00804         }
00805 
00806         if (blocktype[gr][ch] == 2) {
00807             sprintf(label2,
00808                     "SFB scale=%i preflag=%i  %i%i%i",
00809                     pplot1->scalefac_scale[gr][ch],
00810                     pplot1->preflag[gr][ch],
00811                     pplot1->sub_gain[gr][ch][0],
00812                     pplot1->sub_gain[gr][ch][1], pplot1->sub_gain[gr][ch][2]);
00813         }
00814         else {
00815             sprintf(label2, "SFB scale=%i preflag=%i", pplot1->scalefac_scale[gr][ch],
00816                     pplot1->preflag[gr][ch]);
00817         }
00818 
00819         if (gtkinfo.flag123)
00820             ggain = (pplot1->qss[gr][ch]);
00821         else
00822             ggain = (pplot->LAMEqss[gr][ch]);
00823 
00824         sprintf(title2, " ggain=%i", ggain);
00825         strcat(label2, title2);
00826 
00827         xmn = 1;
00828         xmx = n + 1;
00829         gpk_bargraph_draw(sfbbox[gr], n, xcord, ycord,
00830                           xmn, ymn, xmx, ymx, 1, label2, 0, grcolor[gr]);
00831 
00832         ycord[0] = ycord[1] = 0;
00833         xcord[0] = 1;
00834         xcord[1] = n + 1;
00835         gpk_rectangle_draw(sfbbox[gr], xcord, ycord, xmn, ymn, xmx, ymx, &yellow);
00836 
00837 
00838     }
00839 
00840 
00841 }
00842 
00843 
00844 
00845 static void
00846 update_progress(void)
00847 {
00848     char    label[80];
00849 
00850     int     tf = lame_get_totalframes(gfp);
00851     if (gtkinfo.totalframes > 0)
00852         tf = gtkinfo.totalframes;
00853 
00854     sprintf(label, "Frame:%4i/%4i  %6.2fs", pplot->frameNum, (int) tf - 1, pplot->frametime);
00855     gtk_progress_set_value(GTK_PROGRESS(frameprogress), (gdouble) pplot->frameNum);
00856     gtk_label_set_text(GTK_LABEL(framecounter), label);
00857 }
00858 
00859 
00860 
00861 static void
00862 analyze(void)
00863 {
00864     if (idle_keepgoing) {
00865         idle_count = 0;
00866         idle_count_max = 0;
00867         idle_keepgoing = 0;
00868         idle_end = 0;
00869     }
00870     plot_frame();
00871     update_progress();
00872 }
00873 
00874 static void
00875 plotclick(GtkWidget * widget, gpointer data)
00876 {
00877     analyze();
00878 }
00879 
00880 
00881 
00882 
00883 static int
00884 frameadv1(GtkWidget * widget, gpointer data)
00885 {
00886     int     i;
00887     if (idle_keepgoing) {
00888         if (idle_back) {
00889             /* frame displayed is the old frame.  to advance, just swap in new frame */
00890             idle_back--;
00891             pplot = &Pinfo[READ_AHEAD + idle_back];
00892         }
00893         else {
00894             /* advance the frame by reading in a new frame */
00895             pplot = &Pinfo[READ_AHEAD];
00896             if (mp3done) {
00897                 /* dont try to read any more frames, and quit if "finish MP3" was selected */
00898                 /* if (idle_finish) gtk_main_quit(); */
00899                 idle_count_max = 0;
00900                 idle_end = 0;
00901             }
00902             else {
00903                 /* read in the next frame */
00904                 for (i = NUMPINFO - 1; i > 0; i--)
00905                     memcpy(&Pinfo[i], &Pinfo[i - 1], sizeof(plotting_data));
00906                 pinfo = &Pinfo[0];
00907                 pinfo->num_samples = gtkmakeframe();
00908                 if (pinfo->num_samples == 0 && gtkinfo.totalframes == 0)
00909                     /* allow an extra frame to flush decoder buffers */
00910                     gtkinfo.totalframes = pinfo->frameNum + 2;
00911 
00912                 if (pinfo->sampfreq)
00913                     pinfo->frametime = (pinfo->frameNum) * 1152.0 / pinfo->sampfreq;
00914                 else
00915                     pinfo->frametime = 0;
00916 
00917                 /* eof?
00918                    if (!pinfo->num_samples) if (idle_finish) gtk_main_quit();
00919                  */
00920 
00921                 pinfo->totbits = 0;
00922                 {
00923                     int     gr, ch;
00924                     for (gr = 0; gr < 2; gr++)
00925                         for (ch = 0; ch < 2; ch++) {
00926                             gtkinfo.totshort += (pinfo->mpg123blocktype[gr][ch] == 2);
00927                             gtkinfo.totmix += !(pinfo->mixed[gr][ch] == 0);
00928                             gtkinfo.totpreflag += (pinfo->preflag[gr][ch] == 1);
00929                             pinfo->totbits += pinfo->mainbits[gr][ch];
00930                         }
00931                 }
00932                 if (pinfo->frameNum > 0) /* start averaging at second frame */
00933                     gtkinfo.avebits = (gtkinfo.avebits * ((pinfo->frameNum) - 1)
00934                                        + pinfo->totbits) / (pinfo->frameNum);
00935 
00936                 gtkinfo.maxbits = MAX(gtkinfo.maxbits, pinfo->totbits);
00937                 gtkinfo.totemph += !(pinfo->emph == 0);
00938                 gtkinfo.totms += !(pinfo->ms_stereo == 0);
00939                 gtkinfo.totis += !(pinfo->i_stereo == 0);
00940 
00941                 if (gtkinfo.totalframes > 0)
00942                     if (pplot->frameNum >= gtkinfo.totalframes - 1)
00943                         mp3done = 1;
00944             }
00945         }
00946 
00947         idle_count++;
00948         if (gtkinfo.pupdate)
00949             plot_frame();
00950         update_progress();
00951         if ((idle_count >= idle_count_max) && (!idle_end))
00952             analyze();
00953     }
00954     else {
00955         /*no processing to do, sleep in order to not monopolize CPU */
00956         msleep(10);
00957     }
00958     return 1;
00959 }
00960 
00961 
00962 static void
00963 frameadv(GtkWidget * widget, gpointer data)
00964 {
00965     int     adv;
00966 
00967     if (!strcmp((char *) data, "-1")) {
00968         /* ignore if we've already gone back as far as possible */
00969         if (pplot->frameNum == 0 || (idle_back == NUMBACK))
00970             return;
00971         idle_back++;
00972         pplot = &Pinfo[READ_AHEAD + idle_back];
00973         analyze();
00974         return;
00975     }
00976 
00977 
00978     adv = 1;
00979     if (!strcmp((char *) data, "1"))
00980         adv = 1;
00981     if (!strcmp((char *) data, "10"))
00982         adv = 10;
00983     if (!strcmp((char *) data, "100"))
00984         adv = 100;
00985     if (!strcmp((char *) data, "finish"))
00986         idle_end = 1;
00987 
00988 
00989     if (idle_keepgoing) {
00990         /* already running - que up additional frame advance requests */
00991         idle_count_max += adv;
00992     }
00993     else {
00994         /* turn on idleing */
00995         idle_count_max = adv;
00996         idle_count = 0;
00997         idle_keepgoing = 1;
00998     }
00999 }
01000 
01001 
01002 
01003 
01004 /* another callback */
01005 static void
01006 delete_event(GtkWidget * widget, GdkEvent * event, gpointer data)
01007 {
01008     /* set MP3 done flag in case the File/Quit menu item has been selected */
01009     mp3done = 1;
01010 
01011     gtk_main_quit();
01012 }
01013 
01014 
01015 
01016 
01017 
01018 
01019 
01020 static void
01021 channel_option(GtkWidget * widget, gpointer data)
01022 {
01023     long    option;
01024     option = (long) data;
01025     switch (option) {
01026     case 1:
01027         gtkinfo.msflag = 0;
01028         gtkinfo.chflag = 0;
01029         break;
01030     case 2:
01031         gtkinfo.msflag = 0;
01032         gtkinfo.chflag = 1;
01033         break;
01034     case 3:
01035         gtkinfo.msflag = 1;
01036         gtkinfo.chflag = 0;
01037         break;
01038     case 4:
01039         gtkinfo.msflag = 1;
01040         gtkinfo.chflag = 1;
01041     }
01042     analyze();
01043 }
01044 static void
01045 spec_option(GtkWidget * widget, gpointer data)
01046 {
01047     long    option;
01048     option = (long) data;
01049     switch (option) {
01050     case 1:
01051         gtkinfo.kbflag = 0;
01052         break;
01053     case 2:
01054         gtkinfo.kbflag = 1;
01055         break;
01056     case 3:
01057         gtkinfo.flag123 = 0;
01058         break;
01059     case 4:
01060         gtkinfo.flag123 = 1;
01061         break;
01062     case 5:
01063         gtkinfo.pupdate = 1;
01064         break;
01065     case 6:
01066         gtkinfo.pupdate = 0;
01067         break;
01068     case 7:
01069         gtkinfo.sfblines = !gtkinfo.sfblines;
01070         break;
01071     case 8:
01072         gtkinfo.difference = !gtkinfo.difference;
01073         break;
01074     }
01075     analyze();
01076 }
01077 
01078 static  gint
01079 key_press_event(GtkWidget * widget, GdkEventKey * event)
01080 {
01081     /* is a switch() statement in lame forbidden? */
01082     if (event->keyval == '1') {
01083         subblock_draw[0] = 1;
01084         subblock_draw[1] = 0;
01085         subblock_draw[2] = 0;
01086         analyze();
01087     }
01088     else if (event->keyval == '2') {
01089         subblock_draw[0] = 0;
01090         subblock_draw[1] = 1;
01091         subblock_draw[2] = 0;
01092         analyze();
01093     }
01094     else if (event->keyval == '3') {
01095         subblock_draw[0] = 0;
01096         subblock_draw[1] = 0;
01097         subblock_draw[2] = 1;
01098         analyze();
01099     }
01100     else if (event->keyval == '0') {
01101         subblock_draw[0] = 1;
01102         subblock_draw[1] = 1;
01103         subblock_draw[2] = 1;
01104         analyze();
01105     }
01106     /* analyze(); *//* dont redraw entire window for every key! */
01107     return 0;
01108 }
01109 
01110 
01116 const char *
01117 get_mp3x_version(void)
01118 {
01119 #if   MP3X_ALPHA_VERSION > 0
01120     static /*@observer@ */ const char *const str =
01121         XSTR(MP3X_MAJOR_VERSION) "." XSTR(MP3X_MINOR_VERSION)
01122         " (alpha " XSTR(MP3X_ALPHA_VERSION) ", " __DATE__ " " __TIME__ ")";
01123 #elif MP3X_BETA_VERSION > 0
01124     static /*@observer@ */ const char *const str =
01125         XSTR(MP3X_MAJOR_VERSION) "." XSTR(MP3X_MINOR_VERSION)
01126         " (beta " XSTR(MP3X_BETA_VERSION) ", " __DATE__ ")";
01127 #else
01128     static /*@observer@ */ const char *const str =
01129         XSTR(MP3X_MAJOR_VERSION) "." XSTR(MP3X_MINOR_VERSION);
01130 #endif
01131 
01132     return str;
01133 }
01134 
01135 
01136 static void
01137 text_window(GtkWidget * widget, gpointer data)
01138 {
01139     long    option;
01140     GtkWidget *hbox, *vbox, *button, *box;
01141     GtkWidget *textwindow, *vscrollbar;
01142     char    text[256];
01143 
01144     option = (long) data;
01145 
01146     textwindow = gtk_window_new(GTK_WINDOW_DIALOG);
01147     gtk_signal_connect_object(GTK_OBJECT(window), "delete_event",
01148                               GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(textwindow));
01149 
01150     gtk_container_set_border_width(GTK_CONTAINER(textwindow), 0);
01151     vbox = gtk_vbox_new(FALSE, 0);
01152     hbox = gtk_hbox_new(FALSE, 0);
01153 
01154     button = gtk_button_new_with_label("close");
01155     gtk_signal_connect_object(GTK_OBJECT(button), "clicked",
01156                               GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(textwindow));
01157 
01158     box = gtk_text_new(NULL, NULL);
01159     gtk_text_set_editable(GTK_TEXT(box), FALSE);
01160     vscrollbar = gtk_vscrollbar_new(GTK_TEXT(box)->vadj);
01161 
01162 
01163     switch (option) {
01164     case 0:
01165         gtk_window_set_title(GTK_WINDOW(textwindow), "Documentation");
01166         gtk_widget_set_usize(box, 450, 500);
01167         gtk_text_set_word_wrap(GTK_TEXT(box), TRUE);
01168         /* text should be moved outside this function, may be in a separate file */
01169         gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL,
01170                         "Frame header information: "
01171                         "First the bitrate, sampling frequency and mono, stereo or jstereo "
01172                         "indicators are displayed .  If the bitstream is jstereo, then mid/side "
01173                         "stereo or intensity stereo may be on (indicated in red).  If "
01174                         "de-emphasis is used, this is also indicated in red.  The mdb value is "
01175                         "main_data_begin.  The encoded data starts this many bytes *before* the "
01176                         "frame header.  A large value of mdb means the bitstream has saved some "
01177                         "bits into the reservoir, which it may allocate for some future frame. "
01178                         "The two numbers after mdb are the size (in bits) used to encode the "
01179                         "MDCT coefficients for this frame, followed byt the size of the bit "
01180                         "resevoir before encoding this frame.  The maximum frame size and a "
01181                         "running average are given in the Stats pull down menu.  A large "
01182                         "maximum frame size indicates the bitstream has made use of the bit "
01183                         "reservoir. \n\n", -1);
01184 
01185         gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL,
01186                         "PCM data (top graph): "
01187                         "The PCM data is plotted in black.  The layer3 frame is divided into 2 "
01188                         "granules of 576 samples (marked with yellow vertical lines).  In the "
01189                         "case of normal, start and stop blocks, the MDCT coefficients for each "
01190                         "granule are computed using a 1152 sample window centered over the "
01191                         "granule.  In the case of short blocks, the granule is further divided "
01192                         "into 3 blocks of 192 samples (also marked with yellow vertical lines)."
01193                         "The MDCT coefficients for these blocks are computed using 384 sample "
01194                         "windows centered over the 192 sample window.  (This info not available "
01195                         "when analyzing .mp3 files.)  For the psycho-acoustic model, a windowed "
01196                         "FFT is computed for each granule.  The range of these windows "
01197                         "is denoted by the blue and green bars.\n\n", -1);
01198 
01199         gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL,
01200                         "PCM re-synthesis data (second graph): "
01201                         "Same as the PCM window described above.  The data displayed is the "
01202                         "result of encoding and then decoding the original sample. \n\n", -1);
01203 
01204         gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL,
01205                         "MDCT windows: "
01206                         "Shows the energy in the MDCT spectrum for granule 0 (left window) "
01207                         "and granule 1 (right window).  The text also shows the blocktype "
01208                         "used, the number of bits used to encode the coefficients and the "
01209                         "number of extra bits allocated from the reservoir.  The MDCT pull down "
01210                         "window will toggle between the original unquantized MDCT coefficients "
01211                         "and the compressed (quantized) coefficients.\n\n", -1);
01212 
01213         gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL,
01214                         "FFT window: "
01215                         "The gray bars show the energy in the FFT spectrum used by the "
01216                         "psycho-acoustic model.  Granule 0 is in the left window, granule 1 in "
01217                         "the right window.  The green and blue bars show how much distortion is "
01218                         "allowable, as computed by the psycho-acoustic model. The red bars show "
01219                         "the actual distortion after encoding.  There is one FFT for each "
01220                         "granule, computed with a 1024 Hann window centered over the "
01221                         "appropriate granule.  (the range of this 1024 sample window is shown "
01222                         "by the blue and green bars in the PCM data window).  The Spectrum pull "
01223                         "down window will toggle between showing the energy in equally spaced "
01224                         "frequency domain and the scale factor bands used by layer3.  Finally, "
01225                         "the perceptual entropy, total energy and number of scalefactor bands "
01226                         "with audible distortion is shown.  (This info not available when "
01227                         "analyzing .mp3 files.)", -1);
01228 
01229         break;
01230     case 1:
01231         /* Set the about box information */
01232         gtk_window_set_title(GTK_WINDOW(textwindow), "About");
01233         gtk_widget_set_usize(box, 350, 260);
01234 
01235         sprintf(text, "LAME version %s \n%s\n\n", get_lame_version(), get_lame_url());
01236         gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1);
01237 
01238         sprintf(text, "psycho-acoustic model:  GPSYCHO version %s\n", get_psy_version());
01239         gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1);
01240 
01241         sprintf(text, "frame analyzer: MP3x version %s\n\n", get_mp3x_version());
01242         gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1);
01243 
01244         gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL,
01245                         "decoder:  mpg123/mpglib  .59q  \nMichael Hipp (www.mpg123.de)\n\n", -1);
01246 
01247         gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL,
01248                         "Encoder, decoder & psy-models based on ISO\ndemonstration source. ", -1);
01249         break;
01250 
01251     case 2:
01252         gtk_window_set_title(GTK_WINDOW(textwindow), "Statistics");
01253         gtk_widget_set_usize(box, 350, 260);
01254         sprintf(text, "frames processed so far: %i \n", Pinfo[0].frameNum + 1);
01255         gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1);
01256         sprintf(text, "granules processed so far: %i \n\n", 4 * (Pinfo[0].frameNum + 1));
01257         gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1);
01258         sprintf(text, "mean bits/frame (approximate): %i\n", gtkinfo.approxbits);
01259         gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1);
01260         sprintf(text, "mean bits/frame (from LAME): %i\n", 4 * Pinfo[0].mean_bits);
01261         gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1);
01262         sprintf(text, "bitsize of largest frame: %i \n", gtkinfo.maxbits);
01263         gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1);
01264         sprintf(text, "average bits/frame: %3.1f \n\n", gtkinfo.avebits);
01265         gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1);
01266         sprintf(text, "ms_stereo frames: %i \n", gtkinfo.totms);
01267         gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1);
01268         sprintf(text, "i_stereo frames: %i \n", gtkinfo.totis);
01269         gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1);
01270         sprintf(text, "de-emphasis frames: %i \n", gtkinfo.totemph);
01271         gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1);
01272         sprintf(text, "short block granules: %i \n", gtkinfo.totshort);
01273         gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1);
01274         sprintf(text, "mixed block granules: %i \n", gtkinfo.totmix);
01275         gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1);
01276         sprintf(text, "preflag granules: %i \n", gtkinfo.totpreflag);
01277         gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1);
01278         break;
01279     }
01280 
01281 
01282 
01283     gtk_widget_show(vscrollbar);
01284     gtk_widget_show(box);
01285     gtk_widget_show(vbox);
01286     gtk_widget_show(hbox);
01287     gtk_widget_show(button);
01288 
01289     gtk_box_pack_start(GTK_BOX(hbox), box, FALSE, TRUE, 0);
01290     gtk_box_pack_start(GTK_BOX(hbox), vscrollbar, FALSE, FALSE, 0);
01291     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 0);
01292     gtk_box_pack_end(GTK_BOX(vbox), button, FALSE, TRUE, 0);
01293     gtk_container_add(GTK_CONTAINER(textwindow), vbox);
01294     gtk_widget_show(textwindow);
01295 
01296 }
01297 
01298 
01299 
01300 
01301 /* #include <strings.h>*/
01302 
01303 
01304 /* This is the GtkItemFactoryEntry structure used to generate new menus.
01305    Item 1: The menu path. The letter after the underscore indicates an
01306            accelerator key once the menu is open.
01307    Item 2: The accelerator key for the entry
01308    Item 3: The callback function.
01309    Item 4: The callback action.  This changes the parameters with
01310            which the function is called.  The default is 0.
01311    Item 5: The item type, used to define what kind of an item it is.
01312            Here are the possible values:
01313 
01314            NULL               -> "<Item>"
01315            ""                 -> "<Item>"
01316            "<Title>"          -> create a title item
01317            "<Item>"           -> create a simple item
01318            "<CheckItem>"      -> create a check item
01319            "<ToggleItem>"     -> create a toggle item
01320            "<RadioItem>"      -> create a radio item
01321            <path>             -> path of a radio item to link against
01322            "<Separator>"      -> create a separator
01323            "<Branch>"         -> create an item to hold sub items
01324            "<LastBranch>"     -> create a right justified branch
01325 */
01326 
01327 
01328 #define C(chr)       "<control>" #chr
01329 #define func(name)   (GtkItemFactoryCallback) (name)
01330 
01331 static const GtkItemFactoryEntry menu_items[] = {
01332     {"/_File", NULL, NULL, 0, "<Branch>"},
01333 #if 0
01334     {"/File/_New", C(N), func(print_hello), 0, NULL},
01335     {"/File/_Open", C(O), func(print_hello), 0, NULL},
01336     {"/File/_Save", C(S), func(print_hello), 0, NULL},
01337     {"/File/Save _As", NULL, NULL, 0, NULL},
01338     {"/File/sep1", NULL, NULL, 0, "<Separator>"},
01339     {"/File/Quit", C(Q), func(gtk_main_quit), 0, NULL},
01340 #endif
01341     {"/File/_Quit", C(Q), func(delete_event), 0, NULL},
01342 
01343     {"/_Plotting", NULL, NULL, 0, "<Branch>"},
01344     {"/Plotting/_While advancing", NULL, func(spec_option), 5, NULL},
01345     {"/Plotting/_After advancing", NULL, func(spec_option), 6, NULL},
01346     {"/Plotting/Toggle SFB lines", NULL, func(spec_option), 7, NULL},
01347     {"/Plotting/Toggle orig-diff", NULL, func(spec_option), 8, NULL},
01348 
01349     {"/_Channel", NULL, NULL, 0, "<Branch>"},
01350     {"/Channel/show _Left", NULL, func(channel_option), 1, NULL},
01351     {"/Channel/show _Right", NULL, func(channel_option), 2, NULL},
01352     {"/Channel/show _Mid", NULL, func(channel_option), 3, NULL},
01353     {"/Channel/show _Side", NULL, func(channel_option), 4, NULL},
01354 
01355     {"/_Spectrum", NULL, NULL, 0, "<Branch>"},
01356     {"/Spectrum/_Scalefactor bands", NULL, func(spec_option), 1, NULL},
01357     {"/Spectrum/_Wave number", NULL, func(spec_option), 2, NULL},
01358 
01359     {"/_MDCT", NULL, NULL, 0, "<Branch>"},
01360     {"/MDCT/_Original", NULL, func(spec_option), 3, NULL},
01361     {"/MDCT/_Compressed", NULL, func(spec_option), 4, NULL},
01362     {"/MDCT/_Toggle SFB lines", NULL, func(spec_option), 7, NULL},
01363 
01364     {"/_Stats", NULL, NULL, 0, "<Branch>"},
01365     {"/Stats/_Show", NULL, func(text_window), 2, NULL},
01366 
01367     {"/_Help", NULL, NULL, 0, "<LastBranch>"},
01368     {"/_Help/_Documentation", NULL, func(text_window), 0, NULL},
01369     {"/_Help/_About", NULL, func(text_window), 1, NULL},
01370 };
01371 
01372 #undef C
01373 #undef func
01374 
01375 
01376 static void
01377 get_main_menu(GtkWidget * windows, GtkWidget ** menubar)
01378 {
01379     unsigned int nmenu_items = sizeof(menu_items) / sizeof(menu_items[0]);
01380     GtkItemFactory *item_factory;
01381     GtkAccelGroup *accel_group;
01382 
01383     accel_group = gtk_accel_group_new();
01384 
01385     /* This function initializes the item factory.
01386        Param 1: The type of menu - can be GTK_TYPE_MENU_BAR, GTK_TYPE_MENU,
01387        or GTK_TYPE_OPTION_MENU.
01388        Param 2: The path of the menu.
01389        Param 3: A pointer to a gtk_accel_group.  The item factory sets up
01390        the accelerator table while generating menus.
01391      */
01392 
01393     item_factory = gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<main>", accel_group);
01394 
01395     /* This function generates the menu items. Pass the item factory,
01396        the number of items in the array, the array itself, and any
01397        callback data for the the menu items. */
01398     gtk_item_factory_create_items(item_factory, nmenu_items, (GtkItemFactoryEntry *) menu_items,
01399                                   NULL);
01400 
01401     /* Attach the new accelerator group to the window. */
01402     gtk_accel_group_attach(accel_group, GTK_OBJECT(windows));
01403 
01404     if (menubar)
01405         /* Finally, return the actual menu bar created by the item factory. */
01406         *menubar = gtk_item_factory_get_widget(item_factory, "<main>");
01407 }
01408 
01409 
01410 
01411 
01412 
01413 
01414 
01415 
01416 
01417 
01418 
01419 
01420 
01421 
01422 
01423 
01424 int
01425 gtkcontrol(lame_global_flags * gfp2, char *inPath)
01426 {
01427     /* GtkWidget is the storage type for widgets */
01428     GtkWidget *button;
01429     GtkAdjustment *adj;
01430     GtkWidget *mbox;         /* main box */
01431     GtkWidget *box1;         /* frame control buttons go */
01432     GtkWidget *box2;         /* frame counters */
01433     GtkWidget *box3;         /* frame header info */
01434     GtkWidget *table;        /* table for all the plotting areas */
01435     GtkWidget *menubar;
01436 
01437     gint    tableops, graphx, graphy;
01438     char    frameinfo[80];
01439 
01440     graphx = 600;       /* minimum allowed size of pixmap */
01441     graphy = 95;
01442 
01443     gfp = gfp2;
01444     gfc = gfp->internal_flags;
01445 
01446     /* set some global defaults/variables */
01447     gtkinfo.filetype = is_mpeg_file_format(input_format) ? 1 : 0;
01448     gtkinfo.msflag = 0;
01449     gtkinfo.chflag = 0;
01450     gtkinfo.kbflag = 0;
01451     gtkinfo.flag123 = is_mpeg_file_format(input_format) ? 1 : 0; /* MP3 file=use mpg123 output */
01452     gtkinfo.pupdate = 0;
01453     gtkinfo.avebits = 0;
01454     gtkinfo.maxbits = 0;
01455     gtkinfo.approxbits = 0;
01456     gtkinfo.totemph = 0;
01457     gtkinfo.totms = 0;
01458     gtkinfo.totis = 0;
01459     gtkinfo.totshort = 0;
01460     gtkinfo.totmix = 0;
01461     gtkinfo.sfblines = 1;
01462     gtkinfo.difference = 0;
01463     gtkinfo.totalframes = 0;
01464 
01465     memset((char *) Pinfo, 0, sizeof(Pinfo));
01466     pplot = &Pinfo[READ_AHEAD];
01467 
01468     strcpy(frameinfo, "MP3x: ");
01469     strncat(frameinfo, inPath, 70);
01470 
01471     window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
01472     gtk_window_set_title(GTK_WINDOW(window), frameinfo);
01473     gtk_signal_connect(GTK_OBJECT(window), "delete_event", GTK_SIGNAL_FUNC(delete_event), NULL);
01474 
01475     gtk_signal_connect_object(GTK_OBJECT(window), "key_press_event",
01476                               GTK_SIGNAL_FUNC(key_press_event), GTK_OBJECT(window));
01477 
01478     gtk_container_set_border_width(GTK_CONTAINER(window), 0);
01479 
01480 
01481     mbox = gtk_vbox_new(FALSE, 0);
01482 
01483 
01484     /* layout of mbox */
01485     box1 = gtk_hbox_new(FALSE, 0);
01486     box2 = gtk_hbox_new(FALSE, 0);
01487     box3 = gtk_hbox_new(FALSE, 0);
01488     table = gtk_table_new(5, 2, FALSE);
01489     tableops = GTK_FILL | GTK_EXPAND | GTK_SHRINK;
01490     get_main_menu(window, &menubar);
01491 
01492     gtk_box_pack_start(GTK_BOX(mbox), menubar, FALSE, TRUE, 0);
01493     gtk_box_pack_end(GTK_BOX(mbox), box1, FALSE, TRUE, 0);
01494     gtk_box_pack_end(GTK_BOX(mbox), box2, FALSE, TRUE, 0);
01495     gtk_box_pack_start(GTK_BOX(mbox), box3, FALSE, TRUE, 0);
01496     gtk_box_pack_start(GTK_BOX(mbox), table, TRUE, TRUE, 0);
01497     gtk_container_add(GTK_CONTAINER(window), mbox);
01498 
01499 
01500     /*********************************************************************/
01501     /* stuff in box3  frame header info */
01502     /*********************************************************************/
01503     /*
01504        headerbox = gtk_label_new(" ");
01505        gtk_label_set_justify(GTK_LABEL(headerbox),GTK_JUSTIFY_LEFT);
01506      */
01507     headerbox = gtk_text_new(NULL, NULL);
01508     gtk_text_set_editable(GTK_TEXT(headerbox), FALSE);
01509     gtk_widget_set_usize(headerbox, 200, 20);
01510     gtk_widget_show(headerbox);
01511     gtk_box_pack_start(GTK_BOX(box3), headerbox, TRUE, TRUE, 0);
01512 
01513 
01514 
01515     /*********************************************************************/
01516     /* stuff in box2   frame counters  */
01517     /*********************************************************************/
01518     framecounter = gtk_label_new("");
01519     gtk_widget_show(framecounter);
01520     gtk_box_pack_start(GTK_BOX(box2), framecounter, FALSE, TRUE, 0);
01521 
01522     adj = (GtkAdjustment *) gtk_adjustment_new(0, 0, (gint) lame_get_totalframes(gfp) - 1, 0, 0, 0);
01523     frameprogress = gtk_progress_bar_new_with_adjustment(adj);
01524     /* Set the format of the string that can be displayed in the
01525      * trough of the progress bar:
01526      * %p - percentage
01527      * %v - value
01528      * %l - lower range value
01529      * %u - upper range value */
01530     gtk_progress_set_format_string(GTK_PROGRESS(frameprogress), "%p%%");
01531     gtk_progress_set_value(GTK_PROGRESS(frameprogress), (gdouble) 0);
01532     gtk_progress_set_show_text(GTK_PROGRESS(frameprogress), TRUE);
01533     gtk_widget_show(frameprogress);
01534     gtk_box_pack_end(GTK_BOX(box2), frameprogress, FALSE, TRUE, 0);
01535 
01536 
01537 
01538     /*********************************************************************/
01539     /* stuff in box1  buttons along bottom */
01540     /*********************************************************************/
01541     button = gtk_button_new_with_label("-1");
01542     gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(frameadv), (gpointer) "-1");
01543     gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0);
01544     gtk_widget_show(button);
01545 
01546     button = gtk_button_new_with_label("+1");
01547     gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(frameadv), (gpointer) "1");
01548     gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0);
01549     gtk_widget_show(button);
01550 
01551     button = gtk_button_new_with_label("+10");
01552     gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(frameadv), (gpointer) "10");
01553     gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0);
01554     gtk_widget_show(button);
01555 
01556     button = gtk_button_new_with_label("+100");
01557     gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(frameadv), (gpointer) "100");
01558     gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0);
01559     gtk_widget_show(button);
01560 
01561     button = gtk_button_new_with_label("last frame");
01562     gtk_signal_connect(GTK_OBJECT(button), "clicked",
01563                        GTK_SIGNAL_FUNC(frameadv), (gpointer) "finish");
01564     gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0);
01565     gtk_widget_show(button);
01566 
01567     button = gtk_button_new_with_label("stop/plot");
01568     gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(plotclick), NULL);
01569     gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0);
01570     gtk_widget_show(button);
01571 
01572 
01573     /*********************************************************************/
01574     /* stuff in table.  all the plotting windows */
01575     /*********************************************************************/
01576     pcmbox = gpk_plot_new(graphx, graphy);
01577     gtk_table_attach(GTK_TABLE(table), pcmbox, 0, 2, 0, 1, tableops, tableops, 2, 2);
01578     gtk_widget_show(pcmbox);
01579 
01580     winbox = gpk_plot_new(graphy, graphy);
01581     gtk_table_attach(GTK_TABLE(table), winbox, 0, 2, 1, 2, tableops, tableops, 2, 2);
01582     gtk_widget_show(winbox);
01583 
01584 
01585     mdctbox[0] = gpk_plot_new(graphy, graphy);
01586     gtk_table_attach(GTK_TABLE(table), mdctbox[0], 0, 1, 2, 3, tableops, tableops, 2, 2);
01587     gtk_widget_show(mdctbox[0]);
01588 
01589     mdctbox[1] = gpk_plot_new(graphy, graphy);
01590     gtk_table_attach(GTK_TABLE(table), mdctbox[1], 1, 2, 2, 3, tableops, tableops, 2, 2);
01591     gtk_widget_show(mdctbox[1]);
01592 
01593     enerbox[0] = gpk_plot_new(graphy, graphy);
01594     gtk_table_attach(GTK_TABLE(table), enerbox[0], 0, 1, 3, 4, tableops, tableops, 2, 2);
01595     gtk_widget_show(enerbox[0]);
01596 
01597     enerbox[1] = gpk_plot_new(graphy, graphy);
01598     gtk_table_attach(GTK_TABLE(table), enerbox[1], 1, 2, 3, 4, tableops, tableops, 2, 2);
01599     gtk_widget_show(enerbox[1]);
01600 
01601     sfbbox[0] = gpk_plot_new(graphy, graphy);
01602     gtk_table_attach(GTK_TABLE(table), sfbbox[0], 0, 1, 4, 5, tableops, tableops, 2, 2);
01603     gtk_widget_show(sfbbox[0]);
01604 
01605     sfbbox[1] = gpk_plot_new(graphy, graphy);
01606     gtk_table_attach(GTK_TABLE(table), sfbbox[1], 1, 2, 4, 5, tableops, tableops, 2, 2);
01607     gtk_widget_show(sfbbox[1]);
01608 
01609 
01610 
01611 
01612     gtk_idle_add((GtkFunction) frameadv1, NULL);
01613     gtk_widget_show(menubar);
01614     gtk_widget_show(box2);
01615     gtk_widget_show(box3);
01616     gtk_widget_show(table);
01617     gtk_widget_show(box1);
01618     gtk_widget_show(mbox);
01619     gtk_widget_show(window); /* show smallest allowed window */
01620 
01621     /* make window bigger.   */
01622     /* now the user will be able to shrink it, if desired */
01623     /* gtk_widget_set_usize(mbox,500,500);  */
01624     /* gtk_widget_show (window); *//* show smallest allowed window */
01625 
01626 
01627 
01628     idle_keepgoing = 1; /* processing of frames is ON */
01629     idle_count_max = READ_AHEAD + 1; /* number of frames to process before plotting */
01630     idle_count = 0;     /* pause & plot when idle_count=idle_count_max */
01631 
01632     gtk_main();
01633     assert(mp3done);
01634     return (0);
01635 }

Generated on Sun Dec 2 11:34:18 2007 for LAME by  doxygen 1.5.2