2 * GTK plotting routines source file
4 * Copyright (c) 1999 Mark Taylor
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.
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.
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.
22 /* $Id: gtkanal.c,v 1.49 2011/05/07 16:05:17 rbrito Exp $ */
34 #include "lame-analysis.h"
35 #include "get_audio.h"
37 #include "gpkplotting.h"
38 #include "lame_global_flags.h"
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 */
49 # define msleep(t) Sleep(t)
52 # define msleep(t) usleep((t) * 1000)
58 /*! Stringify \a x. */
60 /*! Stringify \a x, perform macro expansion. */
61 #define XSTR(x) STR(x)
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 */
71 plotting_data Pinfo[NUMPINFO];
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 */
84 static int subblock_draw[3] = { 1, 1, 1 };
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 */
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 */
119 static lame_global_flags *gfp;
120 lame_internal_flags *gfc;
123 /**********************************************************************
124 * read one frame and encode it
125 **********************************************************************/
132 static short int Buffer[2][1152];
133 short int mpg123pcm[2][1152];
138 unsigned char mp3buffer[LAME_MAXMP3BUFFER];
139 static int frameNum = 0;
140 int framesize = lame_get_framesize(gfp);
142 channels_out = (lame_get_mode(gfp) == MONO) ? 1 : 2;
144 pinfo->frameNum = frameNum;
145 pinfo->sampfreq = lame_get_out_samplerate(gfp);
146 pinfo->framesize = framesize;
147 pinfo->stereo = channels_out;
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: */
153 hip_set_pinfo(hip, pinfo);
155 if (is_mpeg_file_format(global_reader.input_format)) {
156 hip_set_pinfo(get_hip(), pplot);
157 iread = get_audio16(gfp, Buffer);
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];
169 pinfo->frameNum123 = frameNum - 1;
175 /* feed data to encoder until encoder produces some output */
176 while (lame_get_frameNum(gfp) == pinfo->frameNum) {
182 hip_decode_exit(hip);
184 hip = hip_decode_init();
185 hip_set_pinfo(hip, pinfo);
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.
195 error_printf("Warning: get_audio is returning too much data.\n");
200 mp3count = lame_encode_buffer(gfp, Buffer[0], Buffer[1], iread,
201 mp3buffer, sizeof(mp3buffer));
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 */
207 frameNum = lame_get_frameNum(gfp); /* use the internal MP3 frame counter */
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 */
216 assert(mp3out == pinfo->framesize);
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];
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");
239 pinfo->frameNum123 = -1; /* no frame output */
250 gdouble *xcord, *ycord;
251 gdouble xmx, xmn, ymx, ymn;
252 double *data, *data2, *data3;
254 char label[80], label2[80];
256 plotting_data *pplot1;
257 plotting_data *pplot2 = NULL;
260 /*int sampindex, version = 0;*/
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,
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) {
279 error_printf("input/output pcm syncing problem. should not happen!\n");
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 */
289 /* allocate these GC's only once */
292 /* grcolor[0] = &magenta; */
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);
312 /*******************************************************************
314 *******************************************************************/
315 if (pplot1->sampfreq)
316 samp = pplot1->sampfreq;
319 /*sampindex = SmpFrqIndex((long) samp, &version);*/
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);
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);
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);
344 color = pplot1->emph ? &oncolor : &offcolor;
345 gtk_text_insert(GTK_TEXT(headerbox), NULL, color, NULL, "em ", -1);
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);
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);
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));
363 /*******************************************************************
365 *******************************************************************/
366 for (gr = 0; gr < mode_gr; gr++)
368 blocktype[gr][ch] = pplot1->mpg123blocktype[gr][ch];
370 blocktype[gr][ch] = pplot->blocktype[gr][ch];
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));
382 title = ch ? "Side Channel" : "Mid Channel";
384 title = ch ? "Right Channel" : "Left Channel";
386 sprintf(title2, "%s mask_ratio=%3.2f %3.2f ener_ratio=%3.2f %3.2f",
388 pplot->ms_ratio[0], pplot->ms_ratio[1],
389 pplot->ms_ener_ratio[0], pplot->ms_ener_ratio[1]);
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
403 gpk_graph_draw(pcmbox, 0, xcord, ycord, xmn, ymn, xmx, ymx, 1, title2, &black);
406 /* draw some hash marks dividing the frames */
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);
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);
422 /* bars representing FFT windows */
424 ycord[0] = ymn + 3000;
426 ycord[1] = ymn + 1000;
427 gpk_rectangle_draw(pcmbox, xcord, ycord, xmn, ymn, xmx, ymx, grcolor[0]);
429 ycord[0] = ymn + 2000;
430 xcord[1] = 576 + 1024 - 1;
432 gpk_rectangle_draw(pcmbox, xcord, ycord, xmn, ymn, xmx, ymx, grcolor[1]);
436 for (i = 0; i < n; i++) {
439 ycord[i] = ch ? .5 * (pplot->pcmdata[0][i] - pplot->pcmdata[1][i]) :
440 .5 * (pplot->pcmdata[0][i] + pplot->pcmdata[1][i]);
442 ycord[i] = pplot->pcmdata[ch][i];
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);
451 /*******************************************************************/
452 /* draw the PCM re-synthesis data */
453 /*******************************************************************/
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]);
460 title = "Re-synthesis";
461 if (gtkinfo.difference)
462 title = "Re-synthesis difference (amplified 20db)";
469 gpk_graph_draw(winbox, 0, xcord, ycord, xmn, ymn, xmx, ymx, 1, title, &black);
470 /* draw some hash marks dividing the frames */
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);
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);
487 /* this piece of PCM data from previous frame */
489 for (j = 1152 - n, i = 0; i < n; i++, j++) {
492 ycord[i] = ch ? .5 * (pplot1->pcmdata2[0][j] -
493 pplot1->pcmdata2[1][j]) :
494 .5 * (pplot1->pcmdata2[0][j] + pplot1->pcmdata2[1][j]);
496 ycord[i] = pplot1->pcmdata2[ch][j];
499 /* this piece of PCM data from current frame */
501 for (i = 0; i < n; i++) {
502 xcord[i + 224] = i + 224;
504 ycord[i + 224] = ch ? .5 * (pplot2->pcmdata2[0][i] - pplot2->pcmdata2[1][i]) :
505 .5 * (pplot2->pcmdata2[0][i] + pplot2->pcmdata2[1][i]);
507 ycord[i + 224] = pplot2->pcmdata2[ch][i];
511 if (gtkinfo.difference) {
512 for (i = 0; i < n; i++) {
514 ycord[i] -= ch ? .5 * (pplot->pcmdata[0][i] - pplot->pcmdata[1][i]) :
515 .5 * (pplot->pcmdata[0][i] + pplot->pcmdata[1][i]);
517 ycord[i] -= pplot->pcmdata[ch][i];
523 gpk_graph_draw(winbox, n, xcord, ycord, xmn, ymn, xmx, ymx, 0, title, &black);
529 /*******************************************************************/
530 /* draw the MDCT energy spectrum */
531 /*******************************************************************/
532 for (gr = 0; gr < mode_gr; gr++) {
534 char *blockname = "";
535 switch (blocktype[gr][ch]) {
537 blockname = "normal";
549 strcpy(label, blockname);
550 if (pplot1->mixed[gr][ch])
551 strcat(label, "(mixed)");
557 if (gtkinfo.flag123) {
558 data = pplot1->mpg123xr[gr][0];
559 data2 = pplot1->mpg123xr[gr][1];
562 data = pplot->xr[gr][0];
563 data2 = pplot->xr[gr][1];
572 /* draw title, erase old plot */
573 if (gtkinfo.flag123) {
574 bits = pplot1->mainbits[gr][ch];
575 bits2 = pplot1->sfbits[gr][ch];
578 bits = pplot->LAMEmainbits[gr][ch];
579 bits2 = pplot->LAMEsfbits[gr][ch];
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);
584 /* draw some hash marks showing scalefactor bands */
585 if (gtkinfo.sfblines) {
586 int fac, nsfb, *scalefac;
587 if (blocktype[gr][ch] == SHORT_TYPE) {
591 scalefac = gfc->scalefac_band.s;
597 scalefac = gfc->scalefac_band.l;
599 for (; i < nsfb; i++) {
602 xcord[0] = fac * scalefac[i];
604 gpk_rectangle_draw(mdctbox[gr], xcord, ycord, xmn, ymn, xmx, ymx, &yellow);
612 for (i = 0; i < n; i++) {
615 if (gtkinfo.msflag) {
616 coeff = ch ? .5 * (data[i] - data2[i]) : .5 * (data[i] + data2[i]);
619 coeff = ch ? data2[i] : data[i];
621 if (blocktype[gr][ch] == SHORT_TYPE && !subblock_draw[i % 3])
623 ycord[i] = coeff * coeff * 1e10;
624 ycord[i] = log10(MAX(ycord[i], (double) 1));
630 console_printf("%i %i i=%i mdct: (db) %f %f \n", pplot->frameNum, gr, i,
631 10 * log10(data[i] * data[i]),
633 (data[i - 1] * data[i - 1] + data[i] * data[i] +
634 data[i + 1] * data[i + 1]))
638 ymx = (ycord[i] > ymx) ? ycord[i] : ymx;
639 ymn = (ycord[i] < ymn) ? ycord[i] : ymn;
642 sprintf(title2,"MDCT%1i %5.2f %5.2f bits=%i",gr,ymn,ymx,
643 pplot1->mainbits[gr][ch]);
646 bits = pplot1->mainbits[gr][ch];
648 bits = pplot->LAMEmainbits[gr][ch];
651 sprintf(title2, "MDCT%1i(%s) bits=%i ", gr, label, bits);
657 gpk_bargraph_draw(mdctbox[gr], n, xcord, ycord, xmn, ymn, xmx, ymx, 0, title2, 0, barcolor);
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 */
671 data = &pplot->energy[gr][ch][0];
675 for (i = 0; i < n; i++) {
677 if (blocktype[gr][ch] == SHORT_TYPE && !subblock_draw[i % 3])
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;
684 for (en = 0, j = 0; j < BLKSIZE; j++)
685 en += pplot->energy[gr][ch][j];
687 sprintf(title2, "FFT%1i pe=%5.2fK en=%5.2e ", gr, pplot->pe[gr][ch] / 1000, en);
693 gpk_bargraph_draw(enerbox[gr], n, xcord, ycord,
694 xmn, ymn, xmx, ymx, 1, title2, 0, barcolor);
699 /*******************************************************************
700 * draw the psy model energy spectrum (scalefactor bands)
701 *******************************************************************/
702 for (gr = 0; gr < mode_gr; gr++) {
704 if (blocktype[gr][ch] == 2) {
706 data = &pplot->en_s[gr][ch][0];
707 data2 = &pplot->thr_s[gr][ch][0];
708 data3 = &pplot->xfsf_s[gr][ch][0];
712 data = &pplot->en[gr][ch][0];
713 data2 = &pplot->thr[gr][ch][0];
714 data3 = &pplot->xfsf[gr][ch][0];
718 for (i = 0; i < n; i++) {
720 if (blocktype[gr][ch] == SHORT_TYPE && !subblock_draw[i % 3])
723 ycord[i] = log10(MAX(data[i], (double) 1));
725 ymx=(ycord[i] > ymx) ? ycord[i] : ymx;
726 ymn=(ycord[i] < ymn) ? ycord[i] : ymn;
732 /* en = max energy difference amoung the 3 short FFTs for this granule */
733 en = pplot->ers[gr][ch];
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]);
742 if (blocktype[gr][ch] == SHORT_TYPE)
744 if (!(subblock_draw[0] && subblock_draw[1] && subblock_draw[2]))
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);
754 for (i = 0; i < n; i++) {
755 xcord[i] = i + 1 + .20;
756 if (blocktype[gr][ch] == SHORT_TYPE && !subblock_draw[i % 3])
759 ycord[i] = log10(MAX(data2[i], (double) 1));
762 gpk_bargraph_draw(enerbox[gr], n, xcord, ycord,
763 xmn, ymn, xmx, ymx, 0, title2, barthick, grcolor[gr]);
765 for (i = 0; i < n; i++) {
766 xcord[i] = i + 1 + .40;
767 if (blocktype[gr][ch] == SHORT_TYPE && !subblock_draw[i % 3])
770 ycord[i] = log10(MAX(data3[i], (double) 1));
772 gpk_bargraph_draw(enerbox[gr], n, xcord, ycord,
773 xmn, ymn, xmx, ymx, 0, title2, barthick, &red);
778 /*******************************************************************
780 *******************************************************************/
781 for (gr = 0; gr < mode_gr; gr++) {
783 if (blocktype[gr][ch] == 2) {
786 data = pplot1->sfb_s[gr][ch];
788 data = pplot->LAMEsfb_s[gr][ch];
793 data = pplot1->sfb[gr][ch];
795 data = pplot->LAMEsfb[gr][ch];
800 for (i = 0; i < n; i++) {
802 if (blocktype[gr][ch] == SHORT_TYPE && !subblock_draw[i % 3])
807 ymx = (ycord[i] > ymx - 2) ? ycord[i] + 2 : ymx;
808 ymn = (ycord[i] < ymn) ? ycord[i] - 1 : ymn;
811 if (blocktype[gr][ch] == 2) {
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]);
820 sprintf(label2, "SFB scale=%i preflag=%i", pplot1->scalefac_scale[gr][ch],
821 pplot1->preflag[gr][ch]);
825 ggain = (pplot1->qss[gr][ch]);
827 ggain = (pplot->LAMEqss[gr][ch]);
829 sprintf(title2, " ggain=%i", ggain);
830 strcat(label2, title2);
834 gpk_bargraph_draw(sfbbox[gr], n, xcord, ycord,
835 xmn, ymn, xmx, ymx, 1, label2, 0, grcolor[gr]);
837 ycord[0] = ycord[1] = 0;
840 gpk_rectangle_draw(sfbbox[gr], xcord, ycord, xmn, ymn, xmx, ymx, &yellow);
851 update_progress(void)
855 int tf = lame_get_totalframes(gfp);
856 if (gtkinfo.totalframes > 0)
857 tf = gtkinfo.totalframes;
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);
869 if (idle_keepgoing) {
880 plotclick(GtkWidget * widget, gpointer data)
889 frameadv1(GtkWidget * widget, gpointer data)
892 if (idle_keepgoing) {
894 /* frame displayed is the old frame. to advance, just swap in new frame */
896 pplot = &Pinfo[READ_AHEAD + idle_back];
899 /* advance the frame by reading in a new frame */
900 pplot = &Pinfo[READ_AHEAD];
902 /* dont try to read any more frames, and quit if "finish MP3" was selected */
903 /* if (idle_finish) gtk_main_quit(); */
908 /* read in the next frame */
909 for (i = NUMPINFO - 1; i > 0; i--)
910 memcpy(&Pinfo[i], &Pinfo[i - 1], sizeof(plotting_data));
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;
918 pinfo->frametime = (pinfo->frameNum) * 1152.0 / pinfo->sampfreq;
920 pinfo->frametime = 0;
923 if (!pinfo->num_samples) if (idle_finish) gtk_main_quit();
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];
937 if (pinfo->frameNum > 0) /* start averaging at second frame */
938 gtkinfo.avebits = (gtkinfo.avebits * ((pinfo->frameNum) - 1)
939 + pinfo->totbits) / (pinfo->frameNum);
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);
946 if (gtkinfo.totalframes > 0)
947 if (pplot->frameNum >= gtkinfo.totalframes - 1)
956 if ((idle_count >= idle_count_max) && (!idle_end))
960 /*no processing to do, sleep in order to not monopolize CPU */
968 frameadv(GtkWidget * widget, gpointer data)
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))
977 pplot = &Pinfo[READ_AHEAD + idle_back];
984 if (!strcmp((char *) data, "1"))
986 if (!strcmp((char *) data, "10"))
988 if (!strcmp((char *) data, "100"))
990 if (!strcmp((char *) data, "finish"))
994 if (idle_keepgoing) {
995 /* already running - que up additional frame advance requests */
996 idle_count_max += adv;
999 /* turn on idleing */
1000 idle_count_max = adv;
1009 /* another callback */
1011 delete_event(GtkWidget * widget, GdkEvent * event, gpointer data)
1013 /* set MP3 done flag in case the File/Quit menu item has been selected */
1026 channel_option(GtkWidget * widget, gpointer data)
1029 option = (long) data;
1050 spec_option(GtkWidget * widget, gpointer data)
1053 option = (long) data;
1062 gtkinfo.flag123 = 0;
1065 gtkinfo.flag123 = 1;
1068 gtkinfo.pupdate = 1;
1071 gtkinfo.pupdate = 0;
1074 gtkinfo.sfblines = !gtkinfo.sfblines;
1077 gtkinfo.difference = !gtkinfo.difference;
1084 key_press_event(GtkWidget * widget, GdkEventKey * event)
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;
1093 else if (event->keyval == '2') {
1094 subblock_draw[0] = 0;
1095 subblock_draw[1] = 1;
1096 subblock_draw[2] = 0;
1099 else if (event->keyval == '3') {
1100 subblock_draw[0] = 0;
1101 subblock_draw[1] = 0;
1102 subblock_draw[2] = 1;
1105 else if (event->keyval == '0') {
1106 subblock_draw[0] = 1;
1107 subblock_draw[1] = 1;
1108 subblock_draw[2] = 1;
1111 /* analyze(); */ /* dont redraw entire window for every key! */
1116 /*! Get the mp3x version string. */
1119 \return a pointer to a string which describes the version of mp3x.
1122 get_mp3x_version(void)
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__ ")";
1133 static /*@observer@ */ const char *const str =
1134 XSTR(MP3X_MAJOR_VERSION) "." XSTR(MP3X_MINOR_VERSION);
1142 text_window(GtkWidget * widget, gpointer data)
1145 GtkWidget *hbox, *vbox, *button, *box;
1146 GtkWidget *textwindow, *vscrollbar;
1149 option = (long) data;
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));
1155 gtk_container_set_border_width(GTK_CONTAINER(textwindow), 0);
1156 vbox = gtk_vbox_new(FALSE, 0);
1157 hbox = gtk_hbox_new(FALSE, 0);
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));
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);
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);
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);
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);
1209 gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL,
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);
1218 gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL,
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);
1236 /* Set the about box information */
1237 gtk_window_set_title(GTK_WINDOW(textwindow), "About");
1238 gtk_widget_set_usize(box, 350, 260);
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);
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);
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);
1249 gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL,
1250 "decoder: mpg123/mpglib .59q \nMichael Hipp (www.mpg123.de)\n\n", -1);
1252 gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL,
1253 "Encoder, decoder & psy-models based on ISO\ndemonstration source. ", -1);
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);
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);
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);
1306 /* #include <strings.h>*/
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:
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
1333 #define C(chr) "<control>" #chr
1334 #define func(name) (GtkItemFactoryCallback) (name)
1336 static const GtkItemFactoryEntry menu_items[] = {
1337 {"/_File", NULL, NULL, 0, "<Branch>"},
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},
1346 {"/File/_Quit", C(Q), func(delete_event), 0, NULL},
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},
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},
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},
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},
1369 {"/_Stats", NULL, NULL, 0, "<Branch>"},
1370 {"/Stats/_Show", NULL, func(text_window), 2, NULL},
1372 {"/_Help", NULL, NULL, 0, "<LastBranch>"},
1373 {"/_Help/_Documentation", NULL, func(text_window), 0, NULL},
1374 {"/_Help/_About", NULL, func(text_window), 1, NULL},
1382 get_main_menu(GtkWidget * windows, GtkWidget ** menubar)
1384 unsigned int nmenu_items = sizeof(menu_items) / sizeof(menu_items[0]);
1385 GtkItemFactory *item_factory;
1386 GtkAccelGroup *accel_group;
1388 accel_group = gtk_accel_group_new();
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.
1398 item_factory = gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<main>", accel_group);
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,
1406 /* Attach the new accelerator group to the window. */
1407 gtk_accel_group_attach(accel_group, GTK_OBJECT(windows));
1410 /* Finally, return the actual menu bar created by the item factory. */
1411 *menubar = gtk_item_factory_get_widget(item_factory, "<main>");
1430 gtkcontrol(lame_global_flags * gfp2, char *inPath)
1432 /* GtkWidget is the storage type for widgets */
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 */
1442 gint tableops, graphx, graphy;
1445 graphx = 600; /* minimum allowed size of pixmap */
1449 gfc = gfp->internal_flags;
1451 /* set some global defaults/variables */
1452 gtkinfo.filetype = is_mpeg_file_format(global_reader.input_format) ? 1 : 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;
1464 gtkinfo.totshort = 0;
1466 gtkinfo.sfblines = 1;
1467 gtkinfo.difference = 0;
1468 gtkinfo.totalframes = 0;
1470 memset((char *) Pinfo, 0, sizeof(Pinfo));
1471 pplot = &Pinfo[READ_AHEAD];
1473 strcpy(frameinfo, "MP3x: ");
1474 strncat(frameinfo, inPath, 70);
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);
1480 gtk_signal_connect_object(GTK_OBJECT(window), "key_press_event",
1481 GTK_SIGNAL_FUNC(key_press_event), GTK_OBJECT(window));
1483 gtk_container_set_border_width(GTK_CONTAINER(window), 0);
1486 mbox = gtk_vbox_new(FALSE, 0);
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);
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);
1505 /*********************************************************************/
1506 /* stuff in box3 frame header info */
1507 /*********************************************************************/
1509 headerbox = gtk_label_new(" ");
1510 gtk_label_set_justify(GTK_LABEL(headerbox),GTK_JUSTIFY_LEFT);
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);
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);
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:
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);
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);
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);
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);
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);
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);
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);
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);
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);
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]);
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]);
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]);
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]);
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]);
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]);
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 */
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 */
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 */