1 /*
2  *      GTK plotting routines source file
3  *
4  *      Copyright (c) 1999 Mark Taylor
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21 
22 /* $Id$ */
23 
24 #ifdef HAVE_CONFIG_H
25 # include <config.h>
26 #endif
27 
28 #include <gtk/gtk.h>
29 
30 #include "main.h"
31 #include "lame.h"
32 #include "machine.h"
33 #include "encoder.h"
34 #include "lame-analysis.h"
35 #include "get_audio.h"
36 #include "gtkanal.h"
37 #include "gpkplotting.h"
38 #include "lame_global_flags.h"
39 
40 /* this file should be removed. The few data items accessed in 'gfc'
41    should be made accessable by writing a lame_set_variable() function */
42 #include "util.h"
43 
44 #include "console.h"
45 
46 
47 #ifdef _WIN32
48 #  include <windows.h>
49 #  define msleep(t) Sleep(t)
50 #else
51 #  include <unistd.h>
52 #  define msleep(t) usleep((t) * 1000)
53 #endif
54 
55 
56 
57 
58 /*! Stringify \a x. */
59 #define STR(x)   #x
60 /*! Stringify \a x, perform macro expansion. */
61 #define XSTR(x)  STR(x)
62 
63 #define MP3X_MAJOR_VERSION      0 /* Major version number */
64 #define MP3X_MINOR_VERSION     82 /* Minor version number */
65 #define MP3X_ALPHA_VERSION      0 /* Set number if this is an alpha version, otherwise zero */
66 #define MP3X_BETA_VERSION       0 /* Set number if this is a beta version, otherwise zero */
67 
68 
69 plotting_data *pinfo;
70 plotting_data *pplot;
71 plotting_data Pinfo[NUMPINFO];
72 
73 
74 /* global variables for the state of the system */
75 static gint idle_keepgoing;  /* processing of frames is ON */
76 static gint idle_count_max;  /* number of frames to process before plotting */
77 static gint idle_count;      /* pause & plot when idle_count=idel_count_max */
78 static gint idle_end = 0;    /* process all frames, stop at last frame  */
79 static gint idle_back = 0;   /* set when we are displaying the old data */
80 static int mp3done = 0;      /* last frame has been read */
81 static GtkWidget *frameprogress; /* progress bar */
82 static GtkWidget *framecounter; /* progress counter */
83 
84 static int subblock_draw[3] = { 1, 1, 1 };
85 
86 /* main window */
87 GtkWidget *window;
88 /* Backing pixmap for drawing areas */
89 GtkWidget *pcmbox;           /* PCM data plotted here */
90 GtkWidget *winbox;           /* mpg123 synthesis data plotted here */
91 GtkWidget *enerbox[2];       /* spectrum, gr=0,1 plotted here */
92 GtkWidget *mdctbox[2];       /* mdct coefficients gr=0,1 plotted here */
93 GtkWidget *sfbbox[2];        /* scalefactors gr=0,1 plotted here */
94 GtkWidget *headerbox;        /* mpg123 header info shown here */
95 
96 
97 struct gtkinfostruct {
98     int     filetype;        /* input file type 0=WAV, 1=MP3 */
99     int     msflag;          /* toggle between L&R vs M&S PCM data display */
100     int     chflag;          /* toggle between L & R channels */
101     int     kbflag;          /* toggle between wave # and barks */
102     int     flag123;         /* show mpg123 frame info, OR ISO encoder frame info */
103     double  avebits;         /* running average bits per frame */
104     int     approxbits;      /* (approx) bits per frame */
105     int     maxbits;         /* max bits per frame used so far */
106     int     totemph;         /* total of frames with de-emphasis */
107     int     totms;           /* total frames with ms_stereo */
108     int     totis;           /* total frames with i_stereo */
109     int     totshort;        /* total granules with short blocks */
110     int     totmix;          /* total granules with mixed blocks */
111     int     totpreflag;      /* total granules with preflag */
112     int     pupdate;         /* plot while processing, or only when needed */
113     int     sfblines;        /* plot scalefactor bands in MDCT plot */
114     int     difference;      /* plot original - decoded instead of orig vs. decoded */
115     int     totalframes;
116 } gtkinfo;
117 
118 
119 static lame_global_flags *gfp;
120 lame_internal_flags *gfc;
121 hip_t hip; /* decoder handle of just encoded data */
122 
123 /**********************************************************************
124  * read one frame and encode it
125  **********************************************************************/
126 int
gtkmakeframe(void)127 gtkmakeframe(void)
128 {
129     int     iread = 0;
130     static int init = 0;
131     static int mpglag;
132     static short int Buffer[2][1152];
133     short int mpg123pcm[2][1152];
134     int     ch, j;
135     int     mp3count = 0;
136     int     mp3out = 0;
137     int     channels_out;
138     unsigned char mp3buffer[LAME_MAXMP3BUFFER];
139     static int frameNum = 0;
140     int     framesize = lame_get_framesize(gfp);
141 
142     channels_out = (lame_get_mode(gfp) == MONO) ? 1 : 2;
143 
144     pinfo->frameNum = frameNum;
145     pinfo->sampfreq = lame_get_out_samplerate(gfp);
146     pinfo->framesize = framesize;
147     pinfo->stereo = channels_out;
148 
149     /* If the analsys code is enabled, lame will writes data into gfc->pinfo,
150      * and mpg123 will write data into pinfo.  Set these so
151      * the libraries put this data in the right place: */
152     gfc->pinfo = pinfo;
153     hip_set_pinfo(hip, pinfo);
154 
155     if (is_mpeg_file_format(global_reader.input_format)) {
156         hip_set_pinfo(get_hip(), pplot);
157         iread = get_audio16(gfp, Buffer);
158 
159 
160         /* add a delay of framesize-DECDELAY, which will make the total delay
161          * exactly one frame, so we can sync MP3 output with WAV input */
162         for (ch = 0; ch < channels_out; ch++) {
163             for (j = 0; j < framesize - DECDELAY; j++)
164                 pinfo->pcmdata2[ch][j] = pinfo->pcmdata2[ch][j + framesize];
165             for (j = 0; j < framesize; j++) /*rescale from int to short int */
166                 pinfo->pcmdata2[ch][j + framesize - DECDELAY] = Buffer[ch][j];
167         }
168 
169         pinfo->frameNum123 = frameNum - 1;
170         ++frameNum;
171 
172     }
173     else {
174 
175         /* feed data to encoder until encoder produces some output */
176         while (lame_get_frameNum(gfp) == pinfo->frameNum) {
177 
178             if (!init) {
179                 init = 1;
180                 mpglag = 1;
181                 if (hip) {
182                     hip_decode_exit(hip);
183                 }
184                 hip = hip_decode_init();
185                 hip_set_pinfo(hip, pinfo);
186             }
187 
188             iread = get_audio16(gfp, Buffer);
189             if (iread > framesize) {
190                 /* NOTE: frame analyzer requires that we encode one frame
191                  * for each pass through this loop.  If lame_encode_buffer()
192                  * is feed data too quickly, it will sometimes encode multiple frames
193                  * breaking this loop.
194                  */
195                 error_printf("Warning: get_audio is returning too much data.\n");
196             }
197             if (iread <= 0)
198                 break;  /* eof */
199 
200             mp3count = lame_encode_buffer(gfp, Buffer[0], Buffer[1], iread,
201                                           mp3buffer, sizeof(mp3buffer));
202 
203             assert(!(mp3count > 0 && lame_get_frameNum(gfp) == pinfo->frameNum));
204             /* not possible to produce mp3 data without encoding at least
205              * one frame of data which would increment frameNum */
206         }
207         frameNum = lame_get_frameNum(gfp); /* use the internal MP3 frame counter */
208 
209 
210         /* decode one frame of output */
211         mp3out = hip_decode1(hip, mp3buffer, mp3count, mpg123pcm[0], mpg123pcm[1]); /* re-synthesis to pcm */
212         /* mp3out = 0:  need more data to decode */
213         /* mp3out = -1:  error.  Lets assume 0 pcm output */
214         /* mp3out = number of samples output */
215         if (mp3out > 0)
216             assert(mp3out == pinfo->framesize);
217         if (mp3out != 0) {
218             /* decoded output is for frame pinfo->frameNum123
219              * add a delay of framesize-DECDELAY, which will make the total delay
220              * exactly one frame */
221             pinfo->frameNum123 = pinfo->frameNum - mpglag;
222             for (ch = 0; ch < pinfo->stereo; ch++) {
223                 for (j = 0; j < pinfo->framesize - DECDELAY; j++)
224                     pinfo->pcmdata2[ch][j] = pinfo->pcmdata2[ch][j + pinfo->framesize];
225                 for (j = 0; j < pinfo->framesize; j++) {
226                     pinfo->pcmdata2[ch][j + pinfo->framesize - DECDELAY] =
227                         (mp3out == -1) ? 0 : mpg123pcm[ch][j];
228                 }
229             }
230         }
231         else {
232             if (mpglag == MAXMPGLAG) {
233                 error_printf("READ_AHEAD set too low - not enough frame buffering.\n"
234                              "MP3x display of input and output PCM data out of sync.\n");
235                 error_flush();
236             }
237             else
238                 mpglag++;
239             pinfo->frameNum123 = -1; /* no frame output */
240         }
241     }
242     return iread;
243 }
244 
245 
246 void
plot_frame(void)247 plot_frame(void)
248 {
249     int     i, j, n, ch, gr;
250     gdouble *xcord, *ycord;
251     gdouble xmx, xmn, ymx, ymn;
252     double *data, *data2, *data3;
253     char    title2[80];
254     char    label[80], label2[80];
255     char   *title;
256     plotting_data *pplot1;
257     plotting_data *pplot2 = NULL;
258 
259     double  en, samp;
260     /*int     sampindex, version = 0;*/
261     int     barthick;
262     static int firstcall = 1;
263     static GdkColor *barcolor, *color, *grcolor[2];
264     static GdkColor yellow, gray, cyan, magenta, orange, pink, red, green, blue, black, oncolor,
265         offcolor;
266     int     blocktype[2][2];
267     int     headbits;
268     int     mode_gr = 2;
269 
270     /* find the frame where mpg123 produced output coming from input frame
271      * pinfo.  i.e.:   out_frame + out_frame_lag = input_frame  */
272     for (i = 1; i <= MAXMPGLAG; i++) {
273         if ((pplot - i)->frameNum123 == pplot->frameNum) {
274             pplot2 = pplot - i;
275             break;
276         }
277     }
278     if (i > MAXMPGLAG) {
279         error_printf("input/output pcm syncing problem.  should not happen!\n");
280         pplot2 = pplot - 1;
281     }
282 
283 
284     /* however, the PCM data is delayed by 528 samples in the encoder filterbanks.
285      * We added another 1152-528 delay to this so the PCM data is *exactly* one
286      * frame behind the header & MDCT information */
287     pplot1 = pplot2 + 1; /* back one frame for header info, MDCT */
288 
289     /* allocate these GC's only once */
290     if (firstcall) {
291         firstcall = 0;
292         /*    grcolor[0] = &magenta; */
293         grcolor[0] = &blue;
294         grcolor[1] = &green;
295         barcolor = &gray;
296 
297         setcolor(headerbox, &oncolor, 255, 0, 0);
298         setcolor(headerbox, &offcolor, 175, 175, 175);
299         setcolor(pcmbox, &red, 255, 0, 0);
300         setcolor(pcmbox, &pink, 255, 0, 255);
301         setcolor(pcmbox, &magenta, 255, 0, 100);
302         setcolor(pcmbox, &orange, 255, 127, 0);
303         setcolor(pcmbox, &cyan, 0, 255, 255);
304         setcolor(pcmbox, &green, 0, 255, 0);
305         setcolor(pcmbox, &blue, 0, 0, 255);
306         setcolor(pcmbox, &black, 0, 0, 0);
307         setcolor(pcmbox, &gray, 100, 100, 100);
308         setcolor(pcmbox, &yellow, 255, 255, 0);
309 
310     }
311 
312   /*******************************************************************
313    * frame header info
314    *******************************************************************/
315     if (pplot1->sampfreq)
316         samp = pplot1->sampfreq;
317     else
318         samp = 1;
319     /*sampindex = SmpFrqIndex((long) samp, &version);*/
320 
321     ch = gtkinfo.chflag;
322 
323     headbits = 32 + ((pplot1->stereo == 2) ? 256 : 136);
324     gtkinfo.approxbits = (pplot1->bitrate * 1000 * 1152.0 / samp) - headbits;
325     sprintf(title2, "%3.1fkHz %ikbs ", samp / 1000, pplot1->bitrate);
326     gtk_text_freeze(GTK_TEXT(headerbox));
327     gtk_text_backward_delete(GTK_TEXT(headerbox), gtk_text_get_length(GTK_TEXT(headerbox)));
328     gtk_text_set_point(GTK_TEXT(headerbox), 0);
329     gtk_text_insert(GTK_TEXT(headerbox), NULL, &oncolor, NULL, title2, -1);
330     title = " mono ";
331     if (2 == pplot1->stereo)
332         title = pplot1->js ? " js " : " s ";
333     gtk_text_insert(GTK_TEXT(headerbox), NULL, &oncolor, NULL, title, -1);
334     color = pplot1->ms_stereo ? &oncolor : &offcolor;
335     gtk_text_insert(GTK_TEXT(headerbox), NULL, color, NULL, "ms ", -1);
336     color = pplot1->i_stereo ? &oncolor : &offcolor;
337     gtk_text_insert(GTK_TEXT(headerbox), NULL, color, NULL, "is ", -1);
338 
339     color = pplot1->crc ? &oncolor : &offcolor;
340     gtk_text_insert(GTK_TEXT(headerbox), NULL, color, NULL, "crc ", -1);
341     color = pplot1->padding ? &oncolor : &offcolor;
342     gtk_text_insert(GTK_TEXT(headerbox), NULL, color, NULL, "pad ", -1);
343 
344     color = pplot1->emph ? &oncolor : &offcolor;
345     gtk_text_insert(GTK_TEXT(headerbox), NULL, color, NULL, "em ", -1);
346 
347     sprintf(title2, "bv=%i,%i ", pplot1->big_values[0][ch], pplot1->big_values[1][ch]);
348     gtk_text_insert(GTK_TEXT(headerbox), NULL, &black, NULL, title2, -1);
349 
350     color = pplot1->scfsi[ch] ? &oncolor : &offcolor;
351     sprintf(title2, "scfsi=%i            ", pplot1->scfsi[ch]);
352     gtk_text_insert(GTK_TEXT(headerbox), NULL, color, NULL, title2, -1);
353     if (gtkinfo.filetype)
354         sprintf(title2, " mdb=%i %i/NA", pplot1->maindata, pplot1->totbits);
355     else
356         sprintf(title2, " mdb=%i   %i/%i",
357                 pplot1->maindata, pplot1->totbits, pplot1->totbits + pplot->resvsize);
358     gtk_text_insert(GTK_TEXT(headerbox), NULL, &oncolor, NULL, title2, -1);
359     gtk_text_thaw(GTK_TEXT(headerbox));
360 
361 
362 
363   /*******************************************************************
364    * block type
365    *******************************************************************/
366     for (gr = 0; gr < mode_gr; gr++)
367         if (gtkinfo.flag123)
368             blocktype[gr][ch] = pplot1->mpg123blocktype[gr][ch];
369         else
370             blocktype[gr][ch] = pplot->blocktype[gr][ch];
371 
372 
373   /*******************************************************************
374    * draw the PCM data *
375    *******************************************************************/
376     n = 1600;           /* PCM frame + FFT window:   224 + 1152 + 224  */
377     xcord = g_malloc(n * sizeof(gdouble));
378     ycord = g_malloc(n * sizeof(gdouble));
379 
380 
381     if (gtkinfo.msflag)
382         title = ch ? "Side Channel" : "Mid Channel";
383     else
384         title = ch ? "Right Channel" : "Left Channel";
385 
386     sprintf(title2, "%s  mask_ratio=%3.2f  %3.2f  ener_ratio=%3.2f  %3.2f",
387             title,
388             pplot->ms_ratio[0], pplot->ms_ratio[1],
389             pplot->ms_ener_ratio[0], pplot->ms_ener_ratio[1]);
390 
391 
392     ymn = -32767;
393     ymx = 32767;
394     xmn = 0;
395     xmx = 1600 - 1;
396 
397     /*  0  ... 224      draw in black, connecting to 224 pixel
398      * 1375 .. 1599     draw in black  connecting to 1375 pixel
399      * 224 ... 1375     MP3 frame.  draw in blue
400      */
401 
402     /* draw the title */
403     gpk_graph_draw(pcmbox, 0, xcord, ycord, xmn, ymn, xmx, ymx, 1, title2, &black);
404 
405 
406     /* draw some hash marks dividing the frames */
407     ycord[0] = ymx * .8;
408     ycord[1] = ymn * .8;
409     for (gr = 0; gr <= 2; gr++) {
410         xcord[0] = 223.5 + gr * 576;
411         xcord[1] = 223.5 + gr * 576;
412         gpk_rectangle_draw(pcmbox, xcord, ycord, xmn, ymn, xmx, ymx, &yellow);
413     }
414     for (gr = 0; gr < mode_gr; gr++) {
415         if (blocktype[gr][ch] == 2)
416             for (i = 1; i <= 2; i++) {
417                 xcord[0] = 223.5 + gr * 576 + i * 192;
418                 xcord[1] = 223.5 + gr * 576 + i * 192;
419                 gpk_rectangle_draw(pcmbox, xcord, ycord, xmn, ymn, xmx, ymx, &yellow);
420             }
421     }
422     /* bars representing FFT windows */
423     xcord[0] = 0;
424     ycord[0] = ymn + 3000;
425     xcord[1] = 1024 - 1;
426     ycord[1] = ymn + 1000;
427     gpk_rectangle_draw(pcmbox, xcord, ycord, xmn, ymn, xmx, ymx, grcolor[0]);
428     xcord[0] = 576;
429     ycord[0] = ymn + 2000;
430     xcord[1] = 576 + 1024 - 1;
431     ycord[1] = ymn;
432     gpk_rectangle_draw(pcmbox, xcord, ycord, xmn, ymn, xmx, ymx, grcolor[1]);
433 
434 
435     /* plot PCM data */
436     for (i = 0; i < n; i++) {
437         xcord[i] = i;
438         if (gtkinfo.msflag)
439             ycord[i] = ch ? .5 * (pplot->pcmdata[0][i] - pplot->pcmdata[1][i]) :
440                 .5 * (pplot->pcmdata[0][i] + pplot->pcmdata[1][i]);
441         else
442             ycord[i] = pplot->pcmdata[ch][i];
443     }
444 
445     /* skip plot if we are doing an mp3 file */
446     if (!gtkinfo.filetype) {
447         gpk_graph_draw(pcmbox, n, xcord, ycord, xmn, ymn, xmx, ymx, 0, title2, &black);
448     }
449 
450 
451   /*******************************************************************/
452     /* draw the PCM re-synthesis data */
453   /*******************************************************************/
454     n = 1152;
455     /*
456        sprintf(title2,"Re-synthesis  mask_ratio=%3.2f  %3.2f  ener_ratio=%3.2f  %3.2f",
457        pplot->ms_ratio[0],pplot->ms_ratio[1],
458        pplot->ms_ener_ratio[0],pplot->ms_ener_ratio[1]);
459      */
460     title = "Re-synthesis";
461     if (gtkinfo.difference)
462         title = "Re-synthesis difference (amplified 20db)";
463 
464 
465     ymn = -32767;
466     ymx = 32767;
467     xmn = 0;
468     xmx = 1600 - 1;
469     gpk_graph_draw(winbox, 0, xcord, ycord, xmn, ymn, xmx, ymx, 1, title, &black);
470     /* draw some hash marks dividing the frames */
471     ycord[0] = ymx * .8;
472     ycord[1] = ymn * .8;
473     for (gr = 0; gr <= 2; gr++) {
474         xcord[0] = 223.5 + gr * 576;
475         xcord[1] = 223.5 + gr * 576;
476         gpk_rectangle_draw(winbox, xcord, ycord, xmn, ymn, xmx, ymx, &yellow);
477     }
478     for (gr = 0; gr < 2; gr++) {
479         if (blocktype[gr][ch] == 2)
480             for (i = 1; i <= 2; i++) {
481                 xcord[0] = 223.5 + gr * 576 + i * 192;
482                 xcord[1] = 223.5 + gr * 576 + i * 192;
483                 gpk_rectangle_draw(winbox, xcord, ycord, xmn, ymn, xmx, ymx, &yellow);
484             }
485     }
486 
487     /* this piece of PCM data from previous frame */
488     n = 224;
489     for (j = 1152 - n, i = 0; i < n; i++, j++) {
490         xcord[i] = i;
491         if (gtkinfo.msflag)
492             ycord[i] = ch ? .5 * (pplot1->pcmdata2[0][j] -
493                                   pplot1->pcmdata2[1][j]) :
494                 .5 * (pplot1->pcmdata2[0][j] + pplot1->pcmdata2[1][j]);
495         else
496             ycord[i] = pplot1->pcmdata2[ch][j];
497     }
498 
499     /* this piece of PCM data from current frame */
500     n = 1152;
501     for (i = 0; i < n; i++) {
502         xcord[i + 224] = i + 224;
503         if (gtkinfo.msflag)
504             ycord[i + 224] = ch ? .5 * (pplot2->pcmdata2[0][i] - pplot2->pcmdata2[1][i]) :
505                 .5 * (pplot2->pcmdata2[0][i] + pplot2->pcmdata2[1][i]);
506         else
507             ycord[i + 224] = pplot2->pcmdata2[ch][i];
508     }
509 
510     n = 1152 + 224;
511     if (gtkinfo.difference) {
512         for (i = 0; i < n; i++) {
513             if (gtkinfo.msflag)
514                 ycord[i] -= ch ? .5 * (pplot->pcmdata[0][i] - pplot->pcmdata[1][i]) :
515                     .5 * (pplot->pcmdata[0][i] + pplot->pcmdata[1][i]);
516             else
517                 ycord[i] -= pplot->pcmdata[ch][i];
518         }
519         ycord[i] *= 100;
520     }
521 
522 
523     gpk_graph_draw(winbox, n, xcord, ycord, xmn, ymn, xmx, ymx, 0, title, &black);
524 
525 
526 
527 
528 
529   /*******************************************************************/
530     /* draw the MDCT energy spectrum */
531   /*******************************************************************/
532     for (gr = 0; gr < mode_gr; gr++) {
533         int     bits, bits2;
534         char   *blockname = "";
535         switch (blocktype[gr][ch]) {
536         case 0:
537             blockname = "normal";
538             break;
539         case 1:
540             blockname = "start";
541             break;
542         case 2:
543             blockname = "short";
544             break;
545         case 3:
546             blockname = "end";
547             break;
548         }
549         strcpy(label, blockname);
550         if (pplot1->mixed[gr][ch])
551             strcat(label, "(mixed)");
552 
553 
554 
555 
556         n = 576;
557         if (gtkinfo.flag123) {
558             data = pplot1->mpg123xr[gr][0];
559             data2 = pplot1->mpg123xr[gr][1];
560         }
561         else {
562             data = pplot->xr[gr][0];
563             data2 = pplot->xr[gr][1];
564         }
565 
566 
567         xmn = 0;
568         xmx = n - 1;
569         ymn = 0;
570         ymx = 11;
571 
572         /* draw title, erase old plot */
573         if (gtkinfo.flag123) {
574             bits = pplot1->mainbits[gr][ch];
575             bits2 = pplot1->sfbits[gr][ch];
576         }
577         else {
578             bits = pplot->LAMEmainbits[gr][ch];
579             bits2 = pplot->LAMEsfbits[gr][ch];
580         }
581         sprintf(title2, "MDCT%1i(%s) bits=%i/%i ", gr, label, bits, bits2);
582         gpk_bargraph_draw(mdctbox[gr], 0, xcord, ycord, xmn, ymn, xmx, ymx, 1, title2, 0, barcolor);
583 
584         /* draw some hash marks showing scalefactor bands */
585         if (gtkinfo.sfblines) {
586             int     fac, nsfb, *scalefac;
587             if (blocktype[gr][ch] == SHORT_TYPE) {
588                 nsfb = SBMAX_s;
589                 i = nsfb - 7;
590                 fac = 3;
591                 scalefac = gfc->scalefac_band.s;
592             }
593             else {
594                 nsfb = SBMAX_l;
595                 i = nsfb - 10;
596                 fac = 1;
597                 scalefac = gfc->scalefac_band.l;
598             }
599             for (; i < nsfb; i++) {
600                 ycord[0] = .8 * ymx;
601                 ycord[1] = ymn;
602                 xcord[0] = fac * scalefac[i];
603                 xcord[1] = xcord[0];
604                 gpk_rectangle_draw(mdctbox[gr], xcord, ycord, xmn, ymn, xmx, ymx, &yellow);
605             }
606         }
607 
608 
609 
610         ymn = 9e20;
611         ymx = -9e20;
612         for (i = 0; i < n; i++) {
613             double  coeff;
614             xcord[i] = i;
615             if (gtkinfo.msflag) {
616                 coeff = ch ? .5 * (data[i] - data2[i]) : .5 * (data[i] + data2[i]);
617             }
618             else {
619                 coeff = ch ? data2[i] : data[i];
620             }
621             if (blocktype[gr][ch] == SHORT_TYPE && !subblock_draw[i % 3])
622                 coeff = 0;
623             ycord[i] = coeff * coeff * 1e10;
624             ycord[i] = log10(MAX(ycord[i], (double) 1));
625 
626 #if 0
627             if (ch == 0)
628                 if (i == 26)
629                     if (data[i] != 0)
630                         console_printf("%i %i i=%i  mdct: (db) %f  %f \n", pplot->frameNum, gr, i,
631                                        10 * log10(data[i] * data[i]),
632                                        10 * log10(.33 *
633                                                   (data[i - 1] * data[i - 1] + data[i] * data[i] +
634                                                    data[i + 1] * data[i + 1]))
635                             );
636 #endif
637 
638             ymx = (ycord[i] > ymx) ? ycord[i] : ymx;
639             ymn = (ycord[i] < ymn) ? ycord[i] : ymn;
640         }
641         /*  print the min/max
642            sprintf(title2,"MDCT%1i %5.2f %5.2f  bits=%i",gr,ymn,ymx,
643            pplot1->mainbits[gr][ch]);
644          */
645         if (gtkinfo.flag123)
646             bits = pplot1->mainbits[gr][ch];
647         else
648             bits = pplot->LAMEmainbits[gr][ch];
649 
650 
651         sprintf(title2, "MDCT%1i(%s) bits=%i ", gr, label, bits);
652 
653         xmn = 0;
654         xmx = n - 1;
655         ymn = 0;
656         ymx = 11;
657         gpk_bargraph_draw(mdctbox[gr], n, xcord, ycord, xmn, ymn, xmx, ymx, 0, title2, 0, barcolor);
658     }
659 
660 
661 
662 
663   /*******************************************************************
664    * draw the psy model energy spectrum (k space)
665    * l3psy.c computes pe, en, thm for THIS granule.
666    *******************************************************************/
667     if (gtkinfo.kbflag) {
668         for (gr = 0; gr < mode_gr; gr++) {
669             n = HBLKSIZE; /* only show half the spectrum */
670 
671             data = &pplot->energy[gr][ch][0];
672 
673             ymn = 9e20;
674             ymx = -9e20;
675             for (i = 0; i < n; i++) {
676                 xcord[i] = i + 1;
677                 if (blocktype[gr][ch] == SHORT_TYPE && !subblock_draw[i % 3])
678                     ycord[i] = 0;
679                 else
680                     ycord[i] = log10(MAX(data[i], (double) 1));
681                 ymx = (ycord[i] > ymx) ? ycord[i] : ymx;
682                 ymn = (ycord[i] < ymn) ? ycord[i] : ymn;
683             }
684             for (en = 0, j = 0; j < BLKSIZE; j++)
685                 en += pplot->energy[gr][ch][j];
686 
687             sprintf(title2, "FFT%1i  pe=%5.2fK  en=%5.2e ", gr, pplot->pe[gr][ch] / 1000, en);
688 
689             ymn = 3;
690             ymx = 15;
691             xmn = 1;
692             xmx = n;
693             gpk_bargraph_draw(enerbox[gr], n, xcord, ycord,
694                               xmn, ymn, xmx, ymx, 1, title2, 0, barcolor);
695 
696         }
697     }
698     else {
699     /*******************************************************************
700      * draw the psy model energy spectrum (scalefactor bands)
701      *******************************************************************/
702         for (gr = 0; gr < mode_gr; gr++) {
703 
704             if (blocktype[gr][ch] == 2) {
705                 n = 3 * SBMAX_s;
706                 data = &pplot->en_s[gr][ch][0];
707                 data2 = &pplot->thr_s[gr][ch][0];
708                 data3 = &pplot->xfsf_s[gr][ch][0];
709             }
710             else {
711                 n = SBMAX_l;
712                 data = &pplot->en[gr][ch][0];
713                 data2 = &pplot->thr[gr][ch][0];
714                 data3 = &pplot->xfsf[gr][ch][0];
715             }
716             ymn = 9e20;
717             ymx = -9e20;
718             for (i = 0; i < n; i++) {
719                 xcord[i] = i + 1;
720                 if (blocktype[gr][ch] == SHORT_TYPE && !subblock_draw[i % 3])
721                     ycord[i] = 0;
722                 else
723                     ycord[i] = log10(MAX(data[i], (double) 1));
724                 /*
725                    ymx=(ycord[i] > ymx) ? ycord[i] : ymx;
726                    ymn=(ycord[i] < ymn) ? ycord[i] : ymn;
727                  */
728             }
729 
730 
731 
732             /* en = max energy difference amoung the 3 short FFTs for this granule */
733             en = pplot->ers[gr][ch];
734             if (en > 999)
735                 en = 999;
736             sprintf(title2,
737                     "FFT%1i pe=%5.2fK/%3.1f \nnoise ovr_b:%i/max:%3.1f/ovr:%3.1f/tot:%3.1f/ssd:%i",
738                     gr, pplot->pe[gr][ch] / 1000, en, pplot->over[gr][ch], pplot->max_noise[gr][ch],
739                     pplot->over_noise[gr][ch], pplot->tot_noise[gr][ch], pplot->over_SSD[gr][ch]);
740 
741             barthick = 3;
742             if (blocktype[gr][ch] == SHORT_TYPE)
743                 barthick = 2;
744             if (!(subblock_draw[0] && subblock_draw[1] && subblock_draw[2]))
745                 barthick = 3;
746 
747             ymn = 3;
748             ymx = 15;
749             xmn = 1;
750             xmx = n + 1; /* a little extra because of the bar thickness */
751             gpk_bargraph_draw(enerbox[gr], n, xcord, ycord,
752                               xmn, ymn, xmx, ymx, 1, title2, barthick, barcolor);
753 
754             for (i = 0; i < n; i++) {
755                 xcord[i] = i + 1 + .20;
756                 if (blocktype[gr][ch] == SHORT_TYPE && !subblock_draw[i % 3])
757                     ycord[i] = 0;
758                 else
759                     ycord[i] = log10(MAX(data2[i], (double) 1));
760             }
761 
762             gpk_bargraph_draw(enerbox[gr], n, xcord, ycord,
763                               xmn, ymn, xmx, ymx, 0, title2, barthick, grcolor[gr]);
764 
765             for (i = 0; i < n; i++) {
766                 xcord[i] = i + 1 + .40;
767                 if (blocktype[gr][ch] == SHORT_TYPE && !subblock_draw[i % 3])
768                     ycord[i] = 0;
769                 else
770                     ycord[i] = log10(MAX(data3[i], (double) 1));
771             }
772             gpk_bargraph_draw(enerbox[gr], n, xcord, ycord,
773                               xmn, ymn, xmx, ymx, 0, title2, barthick, &red);
774 
775         }
776     }
777 
778   /*******************************************************************
779    * draw scalefactors
780    *******************************************************************/
781     for (gr = 0; gr < mode_gr; gr++) {
782         int     ggain;
783         if (blocktype[gr][ch] == 2) {
784             n = 3 * SBMAX_s;
785             if (gtkinfo.flag123)
786                 data = pplot1->sfb_s[gr][ch];
787             else
788                 data = pplot->LAMEsfb_s[gr][ch];
789         }
790         else {
791             n = SBMAX_l;
792             if (gtkinfo.flag123)
793                 data = pplot1->sfb[gr][ch];
794             else
795                 data = pplot->LAMEsfb[gr][ch];
796         }
797 
798         ymn = -1;
799         ymx = 10;
800         for (i = 0; i < n; i++) {
801             xcord[i] = i + 1;
802             if (blocktype[gr][ch] == SHORT_TYPE && !subblock_draw[i % 3])
803                 ycord[i] = 0;
804             else
805                 ycord[i] = -data[i];
806 
807             ymx = (ycord[i] > ymx - 2) ? ycord[i] + 2 : ymx;
808             ymn = (ycord[i] < ymn) ? ycord[i] - 1 : ymn;
809         }
810 
811         if (blocktype[gr][ch] == 2) {
812             sprintf(label2,
813                     "SFB scale=%i preflag=%i  %i%i%i",
814                     pplot1->scalefac_scale[gr][ch],
815                     pplot1->preflag[gr][ch],
816                     pplot1->sub_gain[gr][ch][0],
817                     pplot1->sub_gain[gr][ch][1], pplot1->sub_gain[gr][ch][2]);
818         }
819         else {
820             sprintf(label2, "SFB scale=%i preflag=%i", pplot1->scalefac_scale[gr][ch],
821                     pplot1->preflag[gr][ch]);
822         }
823 
824         if (gtkinfo.flag123)
825             ggain = (pplot1->qss[gr][ch]);
826         else
827             ggain = (pplot->LAMEqss[gr][ch]);
828 
829         sprintf(title2, " ggain=%i", ggain);
830         strcat(label2, title2);
831 
832         xmn = 1;
833         xmx = n + 1;
834         gpk_bargraph_draw(sfbbox[gr], n, xcord, ycord,
835                           xmn, ymn, xmx, ymx, 1, label2, 0, grcolor[gr]);
836 
837         ycord[0] = ycord[1] = 0;
838         xcord[0] = 1;
839         xcord[1] = n + 1;
840         gpk_rectangle_draw(sfbbox[gr], xcord, ycord, xmn, ymn, xmx, ymx, &yellow);
841 
842 
843     }
844 
845 
846 }
847 
848 
849 
850 static void
update_progress(void)851 update_progress(void)
852 {
853     char    label[80];
854 
855     int     tf = lame_get_totalframes(gfp);
856     if (gtkinfo.totalframes > 0)
857         tf = gtkinfo.totalframes;
858 
859     sprintf(label, "Frame:%4i/%4i  %6.2fs", pplot->frameNum, (int) tf - 1, pplot->frametime);
860     gtk_progress_set_value(GTK_PROGRESS(frameprogress), (gdouble) pplot->frameNum);
861     gtk_label_set_text(GTK_LABEL(framecounter), label);
862 }
863 
864 
865 
866 static void
analyze(void)867 analyze(void)
868 {
869     if (idle_keepgoing) {
870         idle_count = 0;
871         idle_count_max = 0;
872         idle_keepgoing = 0;
873         idle_end = 0;
874     }
875     plot_frame();
876     update_progress();
877 }
878 
879 static void
plotclick(GtkWidget * widget, gpointer data)880 plotclick(GtkWidget * widget, gpointer data)
881 {
882     analyze();
883 }
884 
885 
886 
887 
888 static int
frameadv1(GtkWidget * widget, gpointer data)889 frameadv1(GtkWidget * widget, gpointer data)
890 {
891     int     i;
892     if (idle_keepgoing) {
893         if (idle_back) {
894             /* frame displayed is the old frame.  to advance, just swap in new frame */
895             idle_back--;
896             pplot = &Pinfo[READ_AHEAD + idle_back];
897         }
898         else {
899             /* advance the frame by reading in a new frame */
900             pplot = &Pinfo[READ_AHEAD];
901             if (mp3done) {
902                 /* dont try to read any more frames, and quit if "finish MP3" was selected */
903                 /* if (idle_finish) gtk_main_quit(); */
904                 idle_count_max = 0;
905                 idle_end = 0;
906             }
907             else {
908                 /* read in the next frame */
909                 for (i = NUMPINFO - 1; i > 0; i--)
910                     memcpy(&Pinfo[i], &Pinfo[i - 1], sizeof(plotting_data));
911                 pinfo = &Pinfo[0];
912                 pinfo->num_samples = gtkmakeframe();
913                 if (pinfo->num_samples == 0 && gtkinfo.totalframes == 0)
914                     /* allow an extra frame to flush decoder buffers */
915                     gtkinfo.totalframes = pinfo->frameNum + 2;
916 
917                 if (pinfo->sampfreq)
918                     pinfo->frametime = (pinfo->frameNum) * 1152.0 / pinfo->sampfreq;
919                 else
920                     pinfo->frametime = 0;
921 
922                 /* eof?
923                    if (!pinfo->num_samples) if (idle_finish) gtk_main_quit();
924                  */
925 
926                 pinfo->totbits = 0;
927                 {
928                     int     gr, ch;
929                     for (gr = 0; gr < 2; gr++)
930                         for (ch = 0; ch < 2; ch++) {
931                             gtkinfo.totshort += (pinfo->mpg123blocktype[gr][ch] == 2);
932                             gtkinfo.totmix += !(pinfo->mixed[gr][ch] == 0);
933                             gtkinfo.totpreflag += (pinfo->preflag[gr][ch] == 1);
934                             pinfo->totbits += pinfo->mainbits[gr][ch];
935                         }
936                 }
937                 if (pinfo->frameNum > 0) /* start averaging at second frame */
938                     gtkinfo.avebits = (gtkinfo.avebits * ((pinfo->frameNum) - 1)
939                                        + pinfo->totbits) / (pinfo->frameNum);
940 
941                 gtkinfo.maxbits = MAX(gtkinfo.maxbits, pinfo->totbits);
942                 gtkinfo.totemph += !(pinfo->emph == 0);
943                 gtkinfo.totms += !(pinfo->ms_stereo == 0);
944                 gtkinfo.totis += !(pinfo->i_stereo == 0);
945 
946                 if (gtkinfo.totalframes > 0)
947                     if (pplot->frameNum >= gtkinfo.totalframes - 1)
948                         mp3done = 1;
949             }
950         }
951 
952         idle_count++;
953         if (gtkinfo.pupdate)
954             plot_frame();
955         update_progress();
956         if ((idle_count >= idle_count_max) && (!idle_end))
957             analyze();
958     }
959     else {
960         /*no processing to do, sleep in order to not monopolize CPU */
961         msleep(10);
962     }
963     return 1;
964 }
965 
966 
967 static void
frameadv(GtkWidget * widget, gpointer data)968 frameadv(GtkWidget * widget, gpointer data)
969 {
970     int     adv;
971 
972     if (!strcmp((char *) data, "-1")) {
973         /* ignore if we've already gone back as far as possible */
974         if (pplot->frameNum == 0 || (idle_back == NUMBACK))
975             return;
976         idle_back++;
977         pplot = &Pinfo[READ_AHEAD + idle_back];
978         analyze();
979         return;
980     }
981 
982 
983     adv = 1;
984     if (!strcmp((char *) data, "1"))
985         adv = 1;
986     if (!strcmp((char *) data, "10"))
987         adv = 10;
988     if (!strcmp((char *) data, "100"))
989         adv = 100;
990     if (!strcmp((char *) data, "finish"))
991         idle_end = 1;
992 
993 
994     if (idle_keepgoing) {
995         /* already running - que up additional frame advance requests */
996         idle_count_max += adv;
997     }
998     else {
999         /* turn on idleing */
1000         idle_count_max = adv;
1001         idle_count = 0;
1002         idle_keepgoing = 1;
1003     }
1004 }
1005 
1006 
1007 
1008 
1009 /* another callback */
1010 static void
delete_event(GtkWidget * widget, GdkEvent * event, gpointer data)1011 delete_event(GtkWidget * widget, GdkEvent * event, gpointer data)
1012 {
1013     /* set MP3 done flag in case the File/Quit menu item has been selected */
1014     mp3done = 1;
1015 
1016     if (hip) {
1017         hip_decode_exit(hip);
1018         hip = 0;
1019     }
1020     gtk_main_quit();
1021 }
1022 
1023 
1024 
1025 
1026 
1027 
1028 
1029 static void
channel_option(GtkWidget * widget, gpointer data)1030 channel_option(GtkWidget * widget, gpointer data)
1031 {
1032     long    option;
1033     option = (long) data;
1034     switch (option) {
1035     case 1:
1036         gtkinfo.msflag = 0;
1037         gtkinfo.chflag = 0;
1038         break;
1039     case 2:
1040         gtkinfo.msflag = 0;
1041         gtkinfo.chflag = 1;
1042         break;
1043     case 3:
1044         gtkinfo.msflag = 1;
1045         gtkinfo.chflag = 0;
1046         break;
1047     case 4:
1048         gtkinfo.msflag = 1;
1049         gtkinfo.chflag = 1;
1050     }
1051     analyze();
1052 }
1053 static void
spec_option(GtkWidget * widget, gpointer data)1054 spec_option(GtkWidget * widget, gpointer data)
1055 {
1056     long    option;
1057     option = (long) data;
1058     switch (option) {
1059     case 1:
1060         gtkinfo.kbflag = 0;
1061         break;
1062     case 2:
1063         gtkinfo.kbflag = 1;
1064         break;
1065     case 3:
1066         gtkinfo.flag123 = 0;
1067         break;
1068     case 4:
1069         gtkinfo.flag123 = 1;
1070         break;
1071     case 5:
1072         gtkinfo.pupdate = 1;
1073         break;
1074     case 6:
1075         gtkinfo.pupdate = 0;
1076         break;
1077     case 7:
1078         gtkinfo.sfblines = !gtkinfo.sfblines;
1079         break;
1080     case 8:
1081         gtkinfo.difference = !gtkinfo.difference;
1082         break;
1083     }
1084     analyze();
1085 }
1086 
1087 static  gint
key_press_event(GtkWidget * widget, GdkEventKey * event)1088 key_press_event(GtkWidget * widget, GdkEventKey * event)
1089 {
1090     /* is a switch() statement in lame forbidden? */
1091     if (event->keyval == '1') {
1092         subblock_draw[0] = 1;
1093         subblock_draw[1] = 0;
1094         subblock_draw[2] = 0;
1095         analyze();
1096     }
1097     else if (event->keyval == '2') {
1098         subblock_draw[0] = 0;
1099         subblock_draw[1] = 1;
1100         subblock_draw[2] = 0;
1101         analyze();
1102     }
1103     else if (event->keyval == '3') {
1104         subblock_draw[0] = 0;
1105         subblock_draw[1] = 0;
1106         subblock_draw[2] = 1;
1107         analyze();
1108     }
1109     else if (event->keyval == '0') {
1110         subblock_draw[0] = 1;
1111         subblock_draw[1] = 1;
1112         subblock_draw[2] = 1;
1113         analyze();
1114     }
1115     /* analyze(); */ /* dont redraw entire window for every key! */
1116     return 0;
1117 }
1118 
1119 
1120 /*! Get the mp3x version string. */
1121 /*!
1122   \param void
1123   \return a pointer to a string which describes the version of mp3x.
1124 */
1125 const char *
get_mp3x_version(void)1126 get_mp3x_version(void)
1127 {
1128 #if   MP3X_ALPHA_VERSION > 0
1129     static /*@observer@ */ const char *const str =
1130         XSTR(MP3X_MAJOR_VERSION) "." XSTR(MP3X_MINOR_VERSION)
1131         " (alpha " XSTR(MP3X_ALPHA_VERSION) ", " __DATE__ " " __TIME__ ")";
1132 #elif MP3X_BETA_VERSION > 0
1133     static /*@observer@ */ const char *const str =
1134         XSTR(MP3X_MAJOR_VERSION) "." XSTR(MP3X_MINOR_VERSION)
1135         " (beta " XSTR(MP3X_BETA_VERSION) ", " __DATE__ ")";
1136 #else
1137     static /*@observer@ */ const char *const str =
1138         XSTR(MP3X_MAJOR_VERSION) "." XSTR(MP3X_MINOR_VERSION);
1139 #endif
1140 
1141     return str;
1142 }
1143 
1144 
1145 static void
text_window(GtkWidget * widget, gpointer data)1146 text_window(GtkWidget * widget, gpointer data)
1147 {
1148     long    option;
1149     GtkWidget *hbox, *vbox, *button, *box;
1150     GtkWidget *textwindow, *vscrollbar;
1151     char    text[256];
1152 
1153     option = (long) data;
1154 
1155     textwindow = gtk_window_new(GTK_WINDOW_DIALOG);
1156     gtk_signal_connect_object(GTK_OBJECT(window), "delete_event",
1157                               GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(textwindow));
1158 
1159     gtk_container_set_border_width(GTK_CONTAINER(textwindow), 0);
1160     vbox = gtk_vbox_new(FALSE, 0);
1161     hbox = gtk_hbox_new(FALSE, 0);
1162 
1163     button = gtk_button_new_with_label("close");
1164     gtk_signal_connect_object(GTK_OBJECT(button), "clicked",
1165                               GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(textwindow));
1166 
1167     box = gtk_text_new(NULL, NULL);
1168     gtk_text_set_editable(GTK_TEXT(box), FALSE);
1169     vscrollbar = gtk_vscrollbar_new(GTK_TEXT(box)->vadj);
1170 
1171 
1172     switch (option) {
1173     case 0:
1174         gtk_window_set_title(GTK_WINDOW(textwindow), "Documentation");
1175         gtk_widget_set_usize(box, 450, 500);
1176         gtk_text_set_word_wrap(GTK_TEXT(box), TRUE);
1177         /* text should be moved outside this function, may be in a separate file */
1178         gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL,
1179                         "Frame header information: "
1180                         "First the bitrate, sampling frequency and mono, stereo or jstereo "
1181                         "indicators are displayed .  If the bitstream is jstereo, then mid/side "
1182                         "stereo or intensity stereo may be on (indicated in red).  If "
1183                         "de-emphasis is used, this is also indicated in red.  The mdb value is "
1184                         "main_data_begin.  The encoded data starts this many bytes *before* the "
1185                         "frame header.  A large value of mdb means the bitstream has saved some "
1186                         "bits into the reservoir, which it may allocate for some future frame. "
1187                         "The two numbers after mdb are the size (in bits) used to encode the "
1188                         "MDCT coefficients for this frame, followed byt the size of the bit "
1189                         "resevoir before encoding this frame.  The maximum frame size and a "
1190                         "running average are given in the Stats pull down menu.  A large "
1191                         "maximum frame size indicates the bitstream has made use of the bit "
1192                         "reservoir. \n\n", -1);
1193 
1194         gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL,
1195                         "PCM data (top graph): "
1196                         "The PCM data is plotted in black.  The layer3 frame is divided into 2 "
1197                         "granules of 576 samples (marked with yellow vertical lines).  In the "
1198                         "case of normal, start and stop blocks, the MDCT coefficients for each "
1199                         "granule are computed using a 1152 sample window centered over the "
1200                         "granule.  In the case of short blocks, the granule is further divided "
1201                         "into 3 blocks of 192 samples (also marked with yellow vertical lines)."
1202                         "The MDCT coefficients for these blocks are computed using 384 sample "
1203                         "windows centered over the 192 sample window.  (This info not available "
1204                         "when analyzing .mp3 files.)  For the psycho-acoustic model, a windowed "
1205                         "FFT is computed for each granule.  The range of these windows "
1206                         "is denoted by the blue and green bars.\n\n", -1);
1207 
1208         gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL,
1209                         "PCM re-synthesis data (second graph): "
1210                         "Same as the PCM window described above.  The data displayed is the "
1211                         "result of encoding and then decoding the original sample. \n\n", -1);
1212 
1213         gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL,
1214                         "MDCT windows: "
1215                         "Shows the energy in the MDCT spectrum for granule 0 (left window) "
1216                         "and granule 1 (right window).  The text also shows the blocktype "
1217                         "used, the number of bits used to encode the coefficients and the "
1218                         "number of extra bits allocated from the reservoir.  The MDCT pull down "
1219                         "window will toggle between the original unquantized MDCT coefficients "
1220                         "and the compressed (quantized) coefficients.\n\n", -1);
1221 
1222         gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL,
1223                         "FFT window: "
1224                         "The gray bars show the energy in the FFT spectrum used by the "
1225                         "psycho-acoustic model.  Granule 0 is in the left window, granule 1 in "
1226                         "the right window.  The green and blue bars show how much distortion is "
1227                         "allowable, as computed by the psycho-acoustic model. The red bars show "
1228                         "the actual distortion after encoding.  There is one FFT for each "
1229                         "granule, computed with a 1024 Hann window centered over the "
1230                         "appropriate granule.  (the range of this 1024 sample window is shown "
1231                         "by the blue and green bars in the PCM data window).  The Spectrum pull "
1232                         "down window will toggle between showing the energy in equally spaced "
1233                         "frequency domain and the scale factor bands used by layer3.  Finally, "
1234                         "the perceptual entropy, total energy and number of scalefactor bands "
1235                         "with audible distortion is shown.  (This info not available when "
1236                         "analyzing .mp3 files.)", -1);
1237 
1238         break;
1239     case 1:
1240         /* Set the about box information */
1241         gtk_window_set_title(GTK_WINDOW(textwindow), "About");
1242         gtk_widget_set_usize(box, 350, 260);
1243 
1244         sprintf(text, "LAME version %s \n%s\n\n", get_lame_version(), get_lame_url());
1245         gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1);
1246 
1247         sprintf(text, "psycho-acoustic model:  GPSYCHO version %s\n", get_psy_version());
1248         gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1);
1249 
1250         sprintf(text, "frame analyzer: MP3x version %s\n\n", get_mp3x_version());
1251         gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1);
1252 
1253         gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL,
1254                         "decoder:  mpg123/mpglib  .59q  \nMichael Hipp (www.mpg123.de)\n\n", -1);
1255 
1256         gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL,
1257                         "Encoder, decoder & psy-models based on ISO\ndemonstration source. ", -1);
1258         break;
1259 
1260     case 2:
1261         gtk_window_set_title(GTK_WINDOW(textwindow), "Statistics");
1262         gtk_widget_set_usize(box, 350, 260);
1263         sprintf(text, "frames processed so far: %i \n", Pinfo[0].frameNum + 1);
1264         gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1);
1265         sprintf(text, "granules processed so far: %i \n\n", 4 * (Pinfo[0].frameNum + 1));
1266         gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1);
1267         sprintf(text, "mean bits/frame (approximate): %i\n", gtkinfo.approxbits);
1268         gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1);
1269         sprintf(text, "mean bits/frame (from LAME): %i\n", 4 * Pinfo[0].mean_bits);
1270         gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1);
1271         sprintf(text, "bitsize of largest frame: %i \n", gtkinfo.maxbits);
1272         gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1);
1273         sprintf(text, "average bits/frame: %3.1f \n\n", gtkinfo.avebits);
1274         gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1);
1275         sprintf(text, "ms_stereo frames: %i \n", gtkinfo.totms);
1276         gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1);
1277         sprintf(text, "i_stereo frames: %i \n", gtkinfo.totis);
1278         gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1);
1279         sprintf(text, "de-emphasis frames: %i \n", gtkinfo.totemph);
1280         gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1);
1281         sprintf(text, "short block granules: %i \n", gtkinfo.totshort);
1282         gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1);
1283         sprintf(text, "mixed block granules: %i \n", gtkinfo.totmix);
1284         gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1);
1285         sprintf(text, "preflag granules: %i \n", gtkinfo.totpreflag);
1286         gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1);
1287         break;
1288     }
1289 
1290 
1291 
1292     gtk_widget_show(vscrollbar);
1293     gtk_widget_show(box);
1294     gtk_widget_show(vbox);
1295     gtk_widget_show(hbox);
1296     gtk_widget_show(button);
1297 
1298     gtk_box_pack_start(GTK_BOX(hbox), box, FALSE, TRUE, 0);
1299     gtk_box_pack_start(GTK_BOX(hbox), vscrollbar, FALSE, FALSE, 0);
1300     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 0);
1301     gtk_box_pack_end(GTK_BOX(vbox), button, FALSE, TRUE, 0);
1302     gtk_container_add(GTK_CONTAINER(textwindow), vbox);
1303     gtk_widget_show(textwindow);
1304 
1305 }
1306 
1307 
1308 
1309 
1310 /* #include <strings.h>*/
1311 
1312 
1313 /* This is the GtkItemFactoryEntry structure used to generate new menus.
1314    Item 1: The menu path. The letter after the underscore indicates an
1315            accelerator key once the menu is open.
1316    Item 2: The accelerator key for the entry
1317    Item 3: The callback function.
1318    Item 4: The callback action.  This changes the parameters with
1319            which the function is called.  The default is 0.
1320    Item 5: The item type, used to define what kind of an item it is.
1321            Here are the possible values:
1322 
1323            NULL               -> "<Item>"
1324            ""                 -> "<Item>"
1325            "<Title>"          -> create a title item
1326            "<Item>"           -> create a simple item
1327            "<CheckItem>"      -> create a check item
1328            "<ToggleItem>"     -> create a toggle item
1329            "<RadioItem>"      -> create a radio item
1330            <path>             -> path of a radio item to link against
1331            "<Separator>"      -> create a separator
1332            "<Branch>"         -> create an item to hold sub items
1333            "<LastBranch>"     -> create a right justified branch
1334 */
1335 
1336 
1337 #define C(chr)       "<control>" #chr
1338 #define func(name)   (GtkItemFactoryCallback) (name)
1339 
1340 static const GtkItemFactoryEntry menu_items[] = {
1341     {"/_File", NULL, NULL, 0, "<Branch>"},
1342 #if 0
1343     {"/File/_New", C(N), func(print_hello), 0, NULL},
1344     {"/File/_Open", C(O), func(print_hello), 0, NULL},
1345     {"/File/_Save", C(S), func(print_hello), 0, NULL},
1346     {"/File/Save _As", NULL, NULL, 0, NULL},
1347     {"/File/sep1", NULL, NULL, 0, "<Separator>"},
1348     {"/File/Quit", C(Q), func(gtk_main_quit), 0, NULL},
1349 #endif
1350     {"/File/_Quit", C(Q), func(delete_event), 0, NULL},
1351 
1352     {"/_Plotting", NULL, NULL, 0, "<Branch>"},
1353     {"/Plotting/_While advancing", NULL, func(spec_option), 5, NULL},
1354     {"/Plotting/_After advancing", NULL, func(spec_option), 6, NULL},
1355     {"/Plotting/Toggle SFB lines", NULL, func(spec_option), 7, NULL},
1356     {"/Plotting/Toggle orig-diff", NULL, func(spec_option), 8, NULL},
1357 
1358     {"/_Channel", NULL, NULL, 0, "<Branch>"},
1359     {"/Channel/show _Left", NULL, func(channel_option), 1, NULL},
1360     {"/Channel/show _Right", NULL, func(channel_option), 2, NULL},
1361     {"/Channel/show _Mid", NULL, func(channel_option), 3, NULL},
1362     {"/Channel/show _Side", NULL, func(channel_option), 4, NULL},
1363 
1364     {"/_Spectrum", NULL, NULL, 0, "<Branch>"},
1365     {"/Spectrum/_Scalefactor bands", NULL, func(spec_option), 1, NULL},
1366     {"/Spectrum/_Wave number", NULL, func(spec_option), 2, NULL},
1367 
1368     {"/_MDCT", NULL, NULL, 0, "<Branch>"},
1369     {"/MDCT/_Original", NULL, func(spec_option), 3, NULL},
1370     {"/MDCT/_Compressed", NULL, func(spec_option), 4, NULL},
1371     {"/MDCT/_Toggle SFB lines", NULL, func(spec_option), 7, NULL},
1372 
1373     {"/_Stats", NULL, NULL, 0, "<Branch>"},
1374     {"/Stats/_Show", NULL, func(text_window), 2, NULL},
1375 
1376     {"/_Help", NULL, NULL, 0, "<LastBranch>"},
1377     {"/_Help/_Documentation", NULL, func(text_window), 0, NULL},
1378     {"/_Help/_About", NULL, func(text_window), 1, NULL},
1379 };
1380 
1381 #undef C
1382 #undef func
1383 
1384 
1385 static void
get_main_menu(GtkWidget * windows, GtkWidget ** menubar)1386 get_main_menu(GtkWidget * windows, GtkWidget ** menubar)
1387 {
1388     unsigned int nmenu_items = sizeof(menu_items) / sizeof(menu_items[0]);
1389     GtkItemFactory *item_factory;
1390     GtkAccelGroup *accel_group;
1391 
1392     accel_group = gtk_accel_group_new();
1393 
1394     /* This function initializes the item factory.
1395        Param 1: The type of menu - can be GTK_TYPE_MENU_BAR, GTK_TYPE_MENU,
1396        or GTK_TYPE_OPTION_MENU.
1397        Param 2: The path of the menu.
1398        Param 3: A pointer to a gtk_accel_group.  The item factory sets up
1399        the accelerator table while generating menus.
1400      */
1401 
1402     item_factory = gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<main>", accel_group);
1403 
1404     /* This function generates the menu items. Pass the item factory,
1405        the number of items in the array, the array itself, and any
1406        callback data for the the menu items. */
1407     gtk_item_factory_create_items(item_factory, nmenu_items, (GtkItemFactoryEntry *) menu_items,
1408                                   NULL);
1409 
1410     /* Attach the new accelerator group to the window. */
1411     gtk_accel_group_attach(accel_group, GTK_OBJECT(windows));
1412 
1413     if (menubar)
1414         /* Finally, return the actual menu bar created by the item factory. */
1415         *menubar = gtk_item_factory_get_widget(item_factory, "<main>");
1416 }
1417 
1418 
1419 
1420 
1421 
1422 
1423 
1424 
1425 
1426 
1427 
1428 
1429 
1430 
1431 
1432 
1433 int
gtkcontrol(lame_global_flags * gfp2, char *inPath)1434 gtkcontrol(lame_global_flags * gfp2, char *inPath)
1435 {
1436     /* GtkWidget is the storage type for widgets */
1437     GtkWidget *button;
1438     GtkAdjustment *adj;
1439     GtkWidget *mbox;         /* main box */
1440     GtkWidget *box1;         /* frame control buttons go */
1441     GtkWidget *box2;         /* frame counters */
1442     GtkWidget *box3;         /* frame header info */
1443     GtkWidget *table;        /* table for all the plotting areas */
1444     GtkWidget *menubar;
1445 
1446     gint    tableops, graphx, graphy;
1447     char    frameinfo[80];
1448 
1449     graphx = 600;       /* minimum allowed size of pixmap */
1450     graphy = 95;
1451 
1452     gfp = gfp2;
1453     gfc = gfp->internal_flags;
1454 
1455     /* set some global defaults/variables */
1456     gtkinfo.filetype = is_mpeg_file_format(global_reader.input_format) ? 1 : 0;
1457     gtkinfo.msflag = 0;
1458     gtkinfo.chflag = 0;
1459     gtkinfo.kbflag = 0;
1460     gtkinfo.flag123 = is_mpeg_file_format(global_reader.input_format) ? 1 : 0; /* MP3 file=use mpg123 output */
1461     gtkinfo.pupdate = 0;
1462     gtkinfo.avebits = 0;
1463     gtkinfo.maxbits = 0;
1464     gtkinfo.approxbits = 0;
1465     gtkinfo.totemph = 0;
1466     gtkinfo.totms = 0;
1467     gtkinfo.totis = 0;
1468     gtkinfo.totshort = 0;
1469     gtkinfo.totmix = 0;
1470     gtkinfo.sfblines = 1;
1471     gtkinfo.difference = 0;
1472     gtkinfo.totalframes = 0;
1473 
1474     memset((char *) Pinfo, 0, sizeof(Pinfo));
1475     pplot = &Pinfo[READ_AHEAD];
1476 
1477     strcpy(frameinfo, "MP3x: ");
1478     strncat(frameinfo, inPath, 70);
1479 
1480     window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
1481     gtk_window_set_title(GTK_WINDOW(window), frameinfo);
1482     gtk_signal_connect(GTK_OBJECT(window), "delete_event", GTK_SIGNAL_FUNC(delete_event), NULL);
1483 
1484     gtk_signal_connect_object(GTK_OBJECT(window), "key_press_event",
1485                               GTK_SIGNAL_FUNC(key_press_event), GTK_OBJECT(window));
1486 
1487     gtk_container_set_border_width(GTK_CONTAINER(window), 0);
1488 
1489 
1490     mbox = gtk_vbox_new(FALSE, 0);
1491 
1492 
1493     /* layout of mbox */
1494     box1 = gtk_hbox_new(FALSE, 0);
1495     box2 = gtk_hbox_new(FALSE, 0);
1496     box3 = gtk_hbox_new(FALSE, 0);
1497     table = gtk_table_new(5, 2, FALSE);
1498     tableops = GTK_FILL | GTK_EXPAND | GTK_SHRINK;
1499     get_main_menu(window, &menubar);
1500 
1501     gtk_box_pack_start(GTK_BOX(mbox), menubar, FALSE, TRUE, 0);
1502     gtk_box_pack_end(GTK_BOX(mbox), box1, FALSE, TRUE, 0);
1503     gtk_box_pack_end(GTK_BOX(mbox), box2, FALSE, TRUE, 0);
1504     gtk_box_pack_start(GTK_BOX(mbox), box3, FALSE, TRUE, 0);
1505     gtk_box_pack_start(GTK_BOX(mbox), table, TRUE, TRUE, 0);
1506     gtk_container_add(GTK_CONTAINER(window), mbox);
1507 
1508 
1509     /*********************************************************************/
1510     /* stuff in box3  frame header info */
1511     /*********************************************************************/
1512     /*
1513        headerbox = gtk_label_new(" ");
1514        gtk_label_set_justify(GTK_LABEL(headerbox),GTK_JUSTIFY_LEFT);
1515      */
1516     headerbox = gtk_text_new(NULL, NULL);
1517     gtk_text_set_editable(GTK_TEXT(headerbox), FALSE);
1518     gtk_widget_set_usize(headerbox, 200, 20);
1519     gtk_widget_show(headerbox);
1520     gtk_box_pack_start(GTK_BOX(box3), headerbox, TRUE, TRUE, 0);
1521 
1522 
1523 
1524     /*********************************************************************/
1525     /* stuff in box2   frame counters  */
1526     /*********************************************************************/
1527     framecounter = gtk_label_new("");
1528     gtk_widget_show(framecounter);
1529     gtk_box_pack_start(GTK_BOX(box2), framecounter, FALSE, TRUE, 0);
1530 
1531     adj = (GtkAdjustment *) gtk_adjustment_new(0, 0, (gint) lame_get_totalframes(gfp) - 1, 0, 0, 0);
1532     frameprogress = gtk_progress_bar_new_with_adjustment(adj);
1533     /* Set the format of the string that can be displayed in the
1534      * trough of the progress bar:
1535      * %p - percentage
1536      * %v - value
1537      * %l - lower range value
1538      * %u - upper range value */
1539     gtk_progress_set_format_string(GTK_PROGRESS(frameprogress), "%p%%");
1540     gtk_progress_set_value(GTK_PROGRESS(frameprogress), (gdouble) 0);
1541     gtk_progress_set_show_text(GTK_PROGRESS(frameprogress), TRUE);
1542     gtk_widget_show(frameprogress);
1543     gtk_box_pack_end(GTK_BOX(box2), frameprogress, FALSE, TRUE, 0);
1544 
1545 
1546 
1547     /*********************************************************************/
1548     /* stuff in box1  buttons along bottom */
1549     /*********************************************************************/
1550     button = gtk_button_new_with_label("-1");
1551     gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(frameadv), (gpointer) "-1");
1552     gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0);
1553     gtk_widget_show(button);
1554 
1555     button = gtk_button_new_with_label("+1");
1556     gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(frameadv), (gpointer) "1");
1557     gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0);
1558     gtk_widget_show(button);
1559 
1560     button = gtk_button_new_with_label("+10");
1561     gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(frameadv), (gpointer) "10");
1562     gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0);
1563     gtk_widget_show(button);
1564 
1565     button = gtk_button_new_with_label("+100");
1566     gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(frameadv), (gpointer) "100");
1567     gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0);
1568     gtk_widget_show(button);
1569 
1570     button = gtk_button_new_with_label("last frame");
1571     gtk_signal_connect(GTK_OBJECT(button), "clicked",
1572                        GTK_SIGNAL_FUNC(frameadv), (gpointer) "finish");
1573     gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0);
1574     gtk_widget_show(button);
1575 
1576     button = gtk_button_new_with_label("stop/plot");
1577     gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(plotclick), NULL);
1578     gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0);
1579     gtk_widget_show(button);
1580 
1581 
1582     /*********************************************************************/
1583     /* stuff in table.  all the plotting windows */
1584     /*********************************************************************/
1585     pcmbox = gpk_plot_new(graphx, graphy);
1586     gtk_table_attach(GTK_TABLE(table), pcmbox, 0, 2, 0, 1, tableops, tableops, 2, 2);
1587     gtk_widget_show(pcmbox);
1588 
1589     winbox = gpk_plot_new(graphy, graphy);
1590     gtk_table_attach(GTK_TABLE(table), winbox, 0, 2, 1, 2, tableops, tableops, 2, 2);
1591     gtk_widget_show(winbox);
1592 
1593 
1594     mdctbox[0] = gpk_plot_new(graphy, graphy);
1595     gtk_table_attach(GTK_TABLE(table), mdctbox[0], 0, 1, 2, 3, tableops, tableops, 2, 2);
1596     gtk_widget_show(mdctbox[0]);
1597 
1598     mdctbox[1] = gpk_plot_new(graphy, graphy);
1599     gtk_table_attach(GTK_TABLE(table), mdctbox[1], 1, 2, 2, 3, tableops, tableops, 2, 2);
1600     gtk_widget_show(mdctbox[1]);
1601 
1602     enerbox[0] = gpk_plot_new(graphy, graphy);
1603     gtk_table_attach(GTK_TABLE(table), enerbox[0], 0, 1, 3, 4, tableops, tableops, 2, 2);
1604     gtk_widget_show(enerbox[0]);
1605 
1606     enerbox[1] = gpk_plot_new(graphy, graphy);
1607     gtk_table_attach(GTK_TABLE(table), enerbox[1], 1, 2, 3, 4, tableops, tableops, 2, 2);
1608     gtk_widget_show(enerbox[1]);
1609 
1610     sfbbox[0] = gpk_plot_new(graphy, graphy);
1611     gtk_table_attach(GTK_TABLE(table), sfbbox[0], 0, 1, 4, 5, tableops, tableops, 2, 2);
1612     gtk_widget_show(sfbbox[0]);
1613 
1614     sfbbox[1] = gpk_plot_new(graphy, graphy);
1615     gtk_table_attach(GTK_TABLE(table), sfbbox[1], 1, 2, 4, 5, tableops, tableops, 2, 2);
1616     gtk_widget_show(sfbbox[1]);
1617 
1618 
1619 
1620 
1621     gtk_idle_add((GtkFunction) frameadv1, NULL);
1622     gtk_widget_show(menubar);
1623     gtk_widget_show(box2);
1624     gtk_widget_show(box3);
1625     gtk_widget_show(table);
1626     gtk_widget_show(box1);
1627     gtk_widget_show(mbox);
1628     gtk_widget_show(window); /* show smallest allowed window */
1629 
1630     /* make window bigger.   */
1631     /* now the user will be able to shrink it, if desired */
1632     /* gtk_widget_set_usize(mbox,500,500);  */
1633     /* gtk_widget_show (window); */ /* show smallest allowed window */
1634 
1635 
1636 
1637     idle_keepgoing = 1; /* processing of frames is ON */
1638     idle_count_max = READ_AHEAD + 1; /* number of frames to process before plotting */
1639     idle_count = 0;     /* pause & plot when idle_count=idle_count_max */
1640 
1641     gtk_main();
1642 
1643     assert(mp3done);
1644     return (0);
1645 }
1646