]> 4ch.mooo.com Git - 16.git/blob - src/lib/doslib/ext/lame/gtkanal.c
0c925819c0e5cb2991d4a25b9dc8ae1457413ce0
[16.git] / src / lib / doslib / ext / lame / gtkanal.c
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: gtkanal.c,v 1.49 2011/05/07 16:05:17 rbrito Exp $ */
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;
122
123 /**********************************************************************
124  * read one frame and encode it
125  **********************************************************************/
126 int
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
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
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
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
880 plotclick(GtkWidget * widget, gpointer data)
881 {
882     analyze();
883 }
884
885
886
887
888 static int
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
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
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     gtk_main_quit();
1017 }
1018
1019
1020
1021
1022
1023
1024
1025 static void
1026 channel_option(GtkWidget * widget, gpointer data)
1027 {
1028     long    option;
1029     option = (long) data;
1030     switch (option) {
1031     case 1:
1032         gtkinfo.msflag = 0;
1033         gtkinfo.chflag = 0;
1034         break;
1035     case 2:
1036         gtkinfo.msflag = 0;
1037         gtkinfo.chflag = 1;
1038         break;
1039     case 3:
1040         gtkinfo.msflag = 1;
1041         gtkinfo.chflag = 0;
1042         break;
1043     case 4:
1044         gtkinfo.msflag = 1;
1045         gtkinfo.chflag = 1;
1046     }
1047     analyze();
1048 }
1049 static void
1050 spec_option(GtkWidget * widget, gpointer data)
1051 {
1052     long    option;
1053     option = (long) data;
1054     switch (option) {
1055     case 1:
1056         gtkinfo.kbflag = 0;
1057         break;
1058     case 2:
1059         gtkinfo.kbflag = 1;
1060         break;
1061     case 3:
1062         gtkinfo.flag123 = 0;
1063         break;
1064     case 4:
1065         gtkinfo.flag123 = 1;
1066         break;
1067     case 5:
1068         gtkinfo.pupdate = 1;
1069         break;
1070     case 6:
1071         gtkinfo.pupdate = 0;
1072         break;
1073     case 7:
1074         gtkinfo.sfblines = !gtkinfo.sfblines;
1075         break;
1076     case 8:
1077         gtkinfo.difference = !gtkinfo.difference;
1078         break;
1079     }
1080     analyze();
1081 }
1082
1083 static  gint
1084 key_press_event(GtkWidget * widget, GdkEventKey * event)
1085 {
1086     /* is a switch() statement in lame forbidden? */
1087     if (event->keyval == '1') {
1088         subblock_draw[0] = 1;
1089         subblock_draw[1] = 0;
1090         subblock_draw[2] = 0;
1091         analyze();
1092     }
1093     else if (event->keyval == '2') {
1094         subblock_draw[0] = 0;
1095         subblock_draw[1] = 1;
1096         subblock_draw[2] = 0;
1097         analyze();
1098     }
1099     else if (event->keyval == '3') {
1100         subblock_draw[0] = 0;
1101         subblock_draw[1] = 0;
1102         subblock_draw[2] = 1;
1103         analyze();
1104     }
1105     else if (event->keyval == '0') {
1106         subblock_draw[0] = 1;
1107         subblock_draw[1] = 1;
1108         subblock_draw[2] = 1;
1109         analyze();
1110     }
1111     /* analyze(); */ /* dont redraw entire window for every key! */
1112     return 0;
1113 }
1114
1115
1116 /*! Get the mp3x version string. */
1117 /*!
1118   \param void
1119   \return a pointer to a string which describes the version of mp3x.
1120 */
1121 const char *
1122 get_mp3x_version(void)
1123 {
1124 #if   MP3X_ALPHA_VERSION > 0
1125     static /*@observer@ */ const char *const str =
1126         XSTR(MP3X_MAJOR_VERSION) "." XSTR(MP3X_MINOR_VERSION)
1127         " (alpha " XSTR(MP3X_ALPHA_VERSION) ", " __DATE__ " " __TIME__ ")";
1128 #elif MP3X_BETA_VERSION > 0
1129     static /*@observer@ */ const char *const str =
1130         XSTR(MP3X_MAJOR_VERSION) "." XSTR(MP3X_MINOR_VERSION)
1131         " (beta " XSTR(MP3X_BETA_VERSION) ", " __DATE__ ")";
1132 #else
1133     static /*@observer@ */ const char *const str =
1134         XSTR(MP3X_MAJOR_VERSION) "." XSTR(MP3X_MINOR_VERSION);
1135 #endif
1136
1137     return str;
1138 }
1139
1140
1141 static void
1142 text_window(GtkWidget * widget, gpointer data)
1143 {
1144     long    option;
1145     GtkWidget *hbox, *vbox, *button, *box;
1146     GtkWidget *textwindow, *vscrollbar;
1147     char    text[256];
1148
1149     option = (long) data;
1150
1151     textwindow = gtk_window_new(GTK_WINDOW_DIALOG);
1152     gtk_signal_connect_object(GTK_OBJECT(window), "delete_event",
1153                               GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(textwindow));
1154
1155     gtk_container_set_border_width(GTK_CONTAINER(textwindow), 0);
1156     vbox = gtk_vbox_new(FALSE, 0);
1157     hbox = gtk_hbox_new(FALSE, 0);
1158
1159     button = gtk_button_new_with_label("close");
1160     gtk_signal_connect_object(GTK_OBJECT(button), "clicked",
1161                               GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(textwindow));
1162
1163     box = gtk_text_new(NULL, NULL);
1164     gtk_text_set_editable(GTK_TEXT(box), FALSE);
1165     vscrollbar = gtk_vscrollbar_new(GTK_TEXT(box)->vadj);
1166
1167
1168     switch (option) {
1169     case 0:
1170         gtk_window_set_title(GTK_WINDOW(textwindow), "Documentation");
1171         gtk_widget_set_usize(box, 450, 500);
1172         gtk_text_set_word_wrap(GTK_TEXT(box), TRUE);
1173         /* text should be moved outside this function, may be in a separate file */
1174         gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL,
1175                         "Frame header information: "
1176                         "First the bitrate, sampling frequency and mono, stereo or jstereo "
1177                         "indicators are displayed .  If the bitstream is jstereo, then mid/side "
1178                         "stereo or intensity stereo may be on (indicated in red).  If "
1179                         "de-emphasis is used, this is also indicated in red.  The mdb value is "
1180                         "main_data_begin.  The encoded data starts this many bytes *before* the "
1181                         "frame header.  A large value of mdb means the bitstream has saved some "
1182                         "bits into the reservoir, which it may allocate for some future frame. "
1183                         "The two numbers after mdb are the size (in bits) used to encode the "
1184                         "MDCT coefficients for this frame, followed byt the size of the bit "
1185                         "resevoir before encoding this frame.  The maximum frame size and a "
1186                         "running average are given in the Stats pull down menu.  A large "
1187                         "maximum frame size indicates the bitstream has made use of the bit "
1188                         "reservoir. \n\n", -1);
1189
1190         gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL,
1191                         "PCM data (top graph): "
1192                         "The PCM data is plotted in black.  The layer3 frame is divided into 2 "
1193                         "granules of 576 samples (marked with yellow vertical lines).  In the "
1194                         "case of normal, start and stop blocks, the MDCT coefficients for each "
1195                         "granule are computed using a 1152 sample window centered over the "
1196                         "granule.  In the case of short blocks, the granule is further divided "
1197                         "into 3 blocks of 192 samples (also marked with yellow vertical lines)."
1198                         "The MDCT coefficients for these blocks are computed using 384 sample "
1199                         "windows centered over the 192 sample window.  (This info not available "
1200                         "when analyzing .mp3 files.)  For the psycho-acoustic model, a windowed "
1201                         "FFT is computed for each granule.  The range of these windows "
1202                         "is denoted by the blue and green bars.\n\n", -1);
1203
1204         gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL,
1205                         "PCM re-synthesis data (second graph): "
1206                         "Same as the PCM window described above.  The data displayed is the "
1207                         "result of encoding and then decoding the original sample. \n\n", -1);
1208
1209         gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL,
1210                         "MDCT windows: "
1211                         "Shows the energy in the MDCT spectrum for granule 0 (left window) "
1212                         "and granule 1 (right window).  The text also shows the blocktype "
1213                         "used, the number of bits used to encode the coefficients and the "
1214                         "number of extra bits allocated from the reservoir.  The MDCT pull down "
1215                         "window will toggle between the original unquantized MDCT coefficients "
1216                         "and the compressed (quantized) coefficients.\n\n", -1);
1217
1218         gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL,
1219                         "FFT window: "
1220                         "The gray bars show the energy in the FFT spectrum used by the "
1221                         "psycho-acoustic model.  Granule 0 is in the left window, granule 1 in "
1222                         "the right window.  The green and blue bars show how much distortion is "
1223                         "allowable, as computed by the psycho-acoustic model. The red bars show "
1224                         "the actual distortion after encoding.  There is one FFT for each "
1225                         "granule, computed with a 1024 Hann window centered over the "
1226                         "appropriate granule.  (the range of this 1024 sample window is shown "
1227                         "by the blue and green bars in the PCM data window).  The Spectrum pull "
1228                         "down window will toggle between showing the energy in equally spaced "
1229                         "frequency domain and the scale factor bands used by layer3.  Finally, "
1230                         "the perceptual entropy, total energy and number of scalefactor bands "
1231                         "with audible distortion is shown.  (This info not available when "
1232                         "analyzing .mp3 files.)", -1);
1233
1234         break;
1235     case 1:
1236         /* Set the about box information */
1237         gtk_window_set_title(GTK_WINDOW(textwindow), "About");
1238         gtk_widget_set_usize(box, 350, 260);
1239
1240         sprintf(text, "LAME version %s \n%s\n\n", get_lame_version(), get_lame_url());
1241         gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1);
1242
1243         sprintf(text, "psycho-acoustic model:  GPSYCHO version %s\n", get_psy_version());
1244         gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1);
1245
1246         sprintf(text, "frame analyzer: MP3x version %s\n\n", get_mp3x_version());
1247         gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1);
1248
1249         gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL,
1250                         "decoder:  mpg123/mpglib  .59q  \nMichael Hipp (www.mpg123.de)\n\n", -1);
1251
1252         gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL,
1253                         "Encoder, decoder & psy-models based on ISO\ndemonstration source. ", -1);
1254         break;
1255
1256     case 2:
1257         gtk_window_set_title(GTK_WINDOW(textwindow), "Statistics");
1258         gtk_widget_set_usize(box, 350, 260);
1259         sprintf(text, "frames processed so far: %i \n", Pinfo[0].frameNum + 1);
1260         gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1);
1261         sprintf(text, "granules processed so far: %i \n\n", 4 * (Pinfo[0].frameNum + 1));
1262         gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1);
1263         sprintf(text, "mean bits/frame (approximate): %i\n", gtkinfo.approxbits);
1264         gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1);
1265         sprintf(text, "mean bits/frame (from LAME): %i\n", 4 * Pinfo[0].mean_bits);
1266         gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1);
1267         sprintf(text, "bitsize of largest frame: %i \n", gtkinfo.maxbits);
1268         gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1);
1269         sprintf(text, "average bits/frame: %3.1f \n\n", gtkinfo.avebits);
1270         gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1);
1271         sprintf(text, "ms_stereo frames: %i \n", gtkinfo.totms);
1272         gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1);
1273         sprintf(text, "i_stereo frames: %i \n", gtkinfo.totis);
1274         gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1);
1275         sprintf(text, "de-emphasis frames: %i \n", gtkinfo.totemph);
1276         gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1);
1277         sprintf(text, "short block granules: %i \n", gtkinfo.totshort);
1278         gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1);
1279         sprintf(text, "mixed block granules: %i \n", gtkinfo.totmix);
1280         gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1);
1281         sprintf(text, "preflag granules: %i \n", gtkinfo.totpreflag);
1282         gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1);
1283         break;
1284     }
1285
1286
1287
1288     gtk_widget_show(vscrollbar);
1289     gtk_widget_show(box);
1290     gtk_widget_show(vbox);
1291     gtk_widget_show(hbox);
1292     gtk_widget_show(button);
1293
1294     gtk_box_pack_start(GTK_BOX(hbox), box, FALSE, TRUE, 0);
1295     gtk_box_pack_start(GTK_BOX(hbox), vscrollbar, FALSE, FALSE, 0);
1296     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 0);
1297     gtk_box_pack_end(GTK_BOX(vbox), button, FALSE, TRUE, 0);
1298     gtk_container_add(GTK_CONTAINER(textwindow), vbox);
1299     gtk_widget_show(textwindow);
1300
1301 }
1302
1303
1304
1305
1306 /* #include <strings.h>*/
1307
1308
1309 /* This is the GtkItemFactoryEntry structure used to generate new menus.
1310    Item 1: The menu path. The letter after the underscore indicates an
1311            accelerator key once the menu is open.
1312    Item 2: The accelerator key for the entry
1313    Item 3: The callback function.
1314    Item 4: The callback action.  This changes the parameters with
1315            which the function is called.  The default is 0.
1316    Item 5: The item type, used to define what kind of an item it is.
1317            Here are the possible values:
1318
1319            NULL               -> "<Item>"
1320            ""                 -> "<Item>"
1321            "<Title>"          -> create a title item
1322            "<Item>"           -> create a simple item
1323            "<CheckItem>"      -> create a check item
1324            "<ToggleItem>"     -> create a toggle item
1325            "<RadioItem>"      -> create a radio item
1326            <path>             -> path of a radio item to link against
1327            "<Separator>"      -> create a separator
1328            "<Branch>"         -> create an item to hold sub items
1329            "<LastBranch>"     -> create a right justified branch
1330 */
1331
1332
1333 #define C(chr)       "<control>" #chr
1334 #define func(name)   (GtkItemFactoryCallback) (name)
1335
1336 static const GtkItemFactoryEntry menu_items[] = {
1337     {"/_File", NULL, NULL, 0, "<Branch>"},
1338 #if 0
1339     {"/File/_New", C(N), func(print_hello), 0, NULL},
1340     {"/File/_Open", C(O), func(print_hello), 0, NULL},
1341     {"/File/_Save", C(S), func(print_hello), 0, NULL},
1342     {"/File/Save _As", NULL, NULL, 0, NULL},
1343     {"/File/sep1", NULL, NULL, 0, "<Separator>"},
1344     {"/File/Quit", C(Q), func(gtk_main_quit), 0, NULL},
1345 #endif
1346     {"/File/_Quit", C(Q), func(delete_event), 0, NULL},
1347
1348     {"/_Plotting", NULL, NULL, 0, "<Branch>"},
1349     {"/Plotting/_While advancing", NULL, func(spec_option), 5, NULL},
1350     {"/Plotting/_After advancing", NULL, func(spec_option), 6, NULL},
1351     {"/Plotting/Toggle SFB lines", NULL, func(spec_option), 7, NULL},
1352     {"/Plotting/Toggle orig-diff", NULL, func(spec_option), 8, NULL},
1353
1354     {"/_Channel", NULL, NULL, 0, "<Branch>"},
1355     {"/Channel/show _Left", NULL, func(channel_option), 1, NULL},
1356     {"/Channel/show _Right", NULL, func(channel_option), 2, NULL},
1357     {"/Channel/show _Mid", NULL, func(channel_option), 3, NULL},
1358     {"/Channel/show _Side", NULL, func(channel_option), 4, NULL},
1359
1360     {"/_Spectrum", NULL, NULL, 0, "<Branch>"},
1361     {"/Spectrum/_Scalefactor bands", NULL, func(spec_option), 1, NULL},
1362     {"/Spectrum/_Wave number", NULL, func(spec_option), 2, NULL},
1363
1364     {"/_MDCT", NULL, NULL, 0, "<Branch>"},
1365     {"/MDCT/_Original", NULL, func(spec_option), 3, NULL},
1366     {"/MDCT/_Compressed", NULL, func(spec_option), 4, NULL},
1367     {"/MDCT/_Toggle SFB lines", NULL, func(spec_option), 7, NULL},
1368
1369     {"/_Stats", NULL, NULL, 0, "<Branch>"},
1370     {"/Stats/_Show", NULL, func(text_window), 2, NULL},
1371
1372     {"/_Help", NULL, NULL, 0, "<LastBranch>"},
1373     {"/_Help/_Documentation", NULL, func(text_window), 0, NULL},
1374     {"/_Help/_About", NULL, func(text_window), 1, NULL},
1375 };
1376
1377 #undef C
1378 #undef func
1379
1380
1381 static void
1382 get_main_menu(GtkWidget * windows, GtkWidget ** menubar)
1383 {
1384     unsigned int nmenu_items = sizeof(menu_items) / sizeof(menu_items[0]);
1385     GtkItemFactory *item_factory;
1386     GtkAccelGroup *accel_group;
1387
1388     accel_group = gtk_accel_group_new();
1389
1390     /* This function initializes the item factory.
1391        Param 1: The type of menu - can be GTK_TYPE_MENU_BAR, GTK_TYPE_MENU,
1392        or GTK_TYPE_OPTION_MENU.
1393        Param 2: The path of the menu.
1394        Param 3: A pointer to a gtk_accel_group.  The item factory sets up
1395        the accelerator table while generating menus.
1396      */
1397
1398     item_factory = gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<main>", accel_group);
1399
1400     /* This function generates the menu items. Pass the item factory,
1401        the number of items in the array, the array itself, and any
1402        callback data for the the menu items. */
1403     gtk_item_factory_create_items(item_factory, nmenu_items, (GtkItemFactoryEntry *) menu_items,
1404                                   NULL);
1405
1406     /* Attach the new accelerator group to the window. */
1407     gtk_accel_group_attach(accel_group, GTK_OBJECT(windows));
1408
1409     if (menubar)
1410         /* Finally, return the actual menu bar created by the item factory. */
1411         *menubar = gtk_item_factory_get_widget(item_factory, "<main>");
1412 }
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429 int
1430 gtkcontrol(lame_global_flags * gfp2, char *inPath)
1431 {
1432     /* GtkWidget is the storage type for widgets */
1433     GtkWidget *button;
1434     GtkAdjustment *adj;
1435     GtkWidget *mbox;         /* main box */
1436     GtkWidget *box1;         /* frame control buttons go */
1437     GtkWidget *box2;         /* frame counters */
1438     GtkWidget *box3;         /* frame header info */
1439     GtkWidget *table;        /* table for all the plotting areas */
1440     GtkWidget *menubar;
1441
1442     gint    tableops, graphx, graphy;
1443     char    frameinfo[80];
1444
1445     graphx = 600;       /* minimum allowed size of pixmap */
1446     graphy = 95;
1447
1448     gfp = gfp2;
1449     gfc = gfp->internal_flags;
1450
1451     /* set some global defaults/variables */
1452     gtkinfo.filetype = is_mpeg_file_format(global_reader.input_format) ? 1 : 0;
1453     gtkinfo.msflag = 0;
1454     gtkinfo.chflag = 0;
1455     gtkinfo.kbflag = 0;
1456     gtkinfo.flag123 = is_mpeg_file_format(global_reader.input_format) ? 1 : 0; /* MP3 file=use mpg123 output */
1457     gtkinfo.pupdate = 0;
1458     gtkinfo.avebits = 0;
1459     gtkinfo.maxbits = 0;
1460     gtkinfo.approxbits = 0;
1461     gtkinfo.totemph = 0;
1462     gtkinfo.totms = 0;
1463     gtkinfo.totis = 0;
1464     gtkinfo.totshort = 0;
1465     gtkinfo.totmix = 0;
1466     gtkinfo.sfblines = 1;
1467     gtkinfo.difference = 0;
1468     gtkinfo.totalframes = 0;
1469
1470     memset((char *) Pinfo, 0, sizeof(Pinfo));
1471     pplot = &Pinfo[READ_AHEAD];
1472
1473     strcpy(frameinfo, "MP3x: ");
1474     strncat(frameinfo, inPath, 70);
1475
1476     window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
1477     gtk_window_set_title(GTK_WINDOW(window), frameinfo);
1478     gtk_signal_connect(GTK_OBJECT(window), "delete_event", GTK_SIGNAL_FUNC(delete_event), NULL);
1479
1480     gtk_signal_connect_object(GTK_OBJECT(window), "key_press_event",
1481                               GTK_SIGNAL_FUNC(key_press_event), GTK_OBJECT(window));
1482
1483     gtk_container_set_border_width(GTK_CONTAINER(window), 0);
1484
1485
1486     mbox = gtk_vbox_new(FALSE, 0);
1487
1488
1489     /* layout of mbox */
1490     box1 = gtk_hbox_new(FALSE, 0);
1491     box2 = gtk_hbox_new(FALSE, 0);
1492     box3 = gtk_hbox_new(FALSE, 0);
1493     table = gtk_table_new(5, 2, FALSE);
1494     tableops = GTK_FILL | GTK_EXPAND | GTK_SHRINK;
1495     get_main_menu(window, &menubar);
1496
1497     gtk_box_pack_start(GTK_BOX(mbox), menubar, FALSE, TRUE, 0);
1498     gtk_box_pack_end(GTK_BOX(mbox), box1, FALSE, TRUE, 0);
1499     gtk_box_pack_end(GTK_BOX(mbox), box2, FALSE, TRUE, 0);
1500     gtk_box_pack_start(GTK_BOX(mbox), box3, FALSE, TRUE, 0);
1501     gtk_box_pack_start(GTK_BOX(mbox), table, TRUE, TRUE, 0);
1502     gtk_container_add(GTK_CONTAINER(window), mbox);
1503
1504
1505     /*********************************************************************/
1506     /* stuff in box3  frame header info */
1507     /*********************************************************************/
1508     /*
1509        headerbox = gtk_label_new(" ");
1510        gtk_label_set_justify(GTK_LABEL(headerbox),GTK_JUSTIFY_LEFT);
1511      */
1512     headerbox = gtk_text_new(NULL, NULL);
1513     gtk_text_set_editable(GTK_TEXT(headerbox), FALSE);
1514     gtk_widget_set_usize(headerbox, 200, 20);
1515     gtk_widget_show(headerbox);
1516     gtk_box_pack_start(GTK_BOX(box3), headerbox, TRUE, TRUE, 0);
1517
1518
1519
1520     /*********************************************************************/
1521     /* stuff in box2   frame counters  */
1522     /*********************************************************************/
1523     framecounter = gtk_label_new("");
1524     gtk_widget_show(framecounter);
1525     gtk_box_pack_start(GTK_BOX(box2), framecounter, FALSE, TRUE, 0);
1526
1527     adj = (GtkAdjustment *) gtk_adjustment_new(0, 0, (gint) lame_get_totalframes(gfp) - 1, 0, 0, 0);
1528     frameprogress = gtk_progress_bar_new_with_adjustment(adj);
1529     /* Set the format of the string that can be displayed in the
1530      * trough of the progress bar:
1531      * %p - percentage
1532      * %v - value
1533      * %l - lower range value
1534      * %u - upper range value */
1535     gtk_progress_set_format_string(GTK_PROGRESS(frameprogress), "%p%%");
1536     gtk_progress_set_value(GTK_PROGRESS(frameprogress), (gdouble) 0);
1537     gtk_progress_set_show_text(GTK_PROGRESS(frameprogress), TRUE);
1538     gtk_widget_show(frameprogress);
1539     gtk_box_pack_end(GTK_BOX(box2), frameprogress, FALSE, TRUE, 0);
1540
1541
1542
1543     /*********************************************************************/
1544     /* stuff in box1  buttons along bottom */
1545     /*********************************************************************/
1546     button = gtk_button_new_with_label("-1");
1547     gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(frameadv), (gpointer) "-1");
1548     gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0);
1549     gtk_widget_show(button);
1550
1551     button = gtk_button_new_with_label("+1");
1552     gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(frameadv), (gpointer) "1");
1553     gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0);
1554     gtk_widget_show(button);
1555
1556     button = gtk_button_new_with_label("+10");
1557     gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(frameadv), (gpointer) "10");
1558     gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0);
1559     gtk_widget_show(button);
1560
1561     button = gtk_button_new_with_label("+100");
1562     gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(frameadv), (gpointer) "100");
1563     gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0);
1564     gtk_widget_show(button);
1565
1566     button = gtk_button_new_with_label("last frame");
1567     gtk_signal_connect(GTK_OBJECT(button), "clicked",
1568                        GTK_SIGNAL_FUNC(frameadv), (gpointer) "finish");
1569     gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0);
1570     gtk_widget_show(button);
1571
1572     button = gtk_button_new_with_label("stop/plot");
1573     gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(plotclick), NULL);
1574     gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0);
1575     gtk_widget_show(button);
1576
1577
1578     /*********************************************************************/
1579     /* stuff in table.  all the plotting windows */
1580     /*********************************************************************/
1581     pcmbox = gpk_plot_new(graphx, graphy);
1582     gtk_table_attach(GTK_TABLE(table), pcmbox, 0, 2, 0, 1, tableops, tableops, 2, 2);
1583     gtk_widget_show(pcmbox);
1584
1585     winbox = gpk_plot_new(graphy, graphy);
1586     gtk_table_attach(GTK_TABLE(table), winbox, 0, 2, 1, 2, tableops, tableops, 2, 2);
1587     gtk_widget_show(winbox);
1588
1589
1590     mdctbox[0] = gpk_plot_new(graphy, graphy);
1591     gtk_table_attach(GTK_TABLE(table), mdctbox[0], 0, 1, 2, 3, tableops, tableops, 2, 2);
1592     gtk_widget_show(mdctbox[0]);
1593
1594     mdctbox[1] = gpk_plot_new(graphy, graphy);
1595     gtk_table_attach(GTK_TABLE(table), mdctbox[1], 1, 2, 2, 3, tableops, tableops, 2, 2);
1596     gtk_widget_show(mdctbox[1]);
1597
1598     enerbox[0] = gpk_plot_new(graphy, graphy);
1599     gtk_table_attach(GTK_TABLE(table), enerbox[0], 0, 1, 3, 4, tableops, tableops, 2, 2);
1600     gtk_widget_show(enerbox[0]);
1601
1602     enerbox[1] = gpk_plot_new(graphy, graphy);
1603     gtk_table_attach(GTK_TABLE(table), enerbox[1], 1, 2, 3, 4, tableops, tableops, 2, 2);
1604     gtk_widget_show(enerbox[1]);
1605
1606     sfbbox[0] = gpk_plot_new(graphy, graphy);
1607     gtk_table_attach(GTK_TABLE(table), sfbbox[0], 0, 1, 4, 5, tableops, tableops, 2, 2);
1608     gtk_widget_show(sfbbox[0]);
1609
1610     sfbbox[1] = gpk_plot_new(graphy, graphy);
1611     gtk_table_attach(GTK_TABLE(table), sfbbox[1], 1, 2, 4, 5, tableops, tableops, 2, 2);
1612     gtk_widget_show(sfbbox[1]);
1613
1614
1615
1616
1617     gtk_idle_add((GtkFunction) frameadv1, NULL);
1618     gtk_widget_show(menubar);
1619     gtk_widget_show(box2);
1620     gtk_widget_show(box3);
1621     gtk_widget_show(table);
1622     gtk_widget_show(box1);
1623     gtk_widget_show(mbox);
1624     gtk_widget_show(window); /* show smallest allowed window */
1625
1626     /* make window bigger.   */
1627     /* now the user will be able to shrink it, if desired */
1628     /* gtk_widget_set_usize(mbox,500,500);  */
1629     /* gtk_widget_show (window); */ /* show smallest allowed window */
1630
1631
1632
1633     idle_keepgoing = 1; /* processing of frames is ON */
1634     idle_count_max = READ_AHEAD + 1; /* number of frames to process before plotting */
1635     idle_count = 0;     /* pause & plot when idle_count=idle_count_max */
1636
1637     gtk_main();
1638     assert(mp3done);
1639     return (0);
1640 }