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 "lame-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
gtkmakeframe(void)127 gtkmakeframe(void)
128 {
129 int iread = 0;
130 static int init = 0;
131 static int mpglag;
132 static short int Buffer[2][1152];
133 short int mpg123pcm[2][1152];
134 int ch, j;
135 int mp3count = 0;
136 int mp3out = 0;
137 int channels_out;
138 unsigned char mp3buffer[LAME_MAXMP3BUFFER];
139 static int frameNum = 0;
140 int framesize = lame_get_framesize(gfp);
141
142 channels_out = (lame_get_mode(gfp) == MONO) ? 1 : 2;
143
144 pinfo->frameNum = frameNum;
145 pinfo->sampfreq = lame_get_out_samplerate(gfp);
146 pinfo->framesize = framesize;
147 pinfo->stereo = channels_out;
148
149 /* If the analsys code is enabled, lame will writes data into gfc->pinfo,
150 * and mpg123 will write data into pinfo. Set these so
151 * the libraries put this data in the right place: */
152 gfc->pinfo = pinfo;
153 hip_set_pinfo(hip, pinfo);
154
155 if (is_mpeg_file_format(global_reader.input_format)) {
156 hip_set_pinfo(get_hip(), pplot);
157 iread = get_audio16(gfp, Buffer);
158
159
160 /* add a delay of framesize-DECDELAY, which will make the total delay
161 * exactly one frame, so we can sync MP3 output with WAV input */
162 for (ch = 0; ch < channels_out; ch++) {
163 for (j = 0; j < framesize - DECDELAY; j++)
164 pinfo->pcmdata2[ch][j] = pinfo->pcmdata2[ch][j + framesize];
165 for (j = 0; j < framesize; j++) /*rescale from int to short int */
166 pinfo->pcmdata2[ch][j + framesize - DECDELAY] = Buffer[ch][j];
167 }
168
169 pinfo->frameNum123 = frameNum - 1;
170 ++frameNum;
171
172 }
173 else {
174
175 /* feed data to encoder until encoder produces some output */
176 while (lame_get_frameNum(gfp) == pinfo->frameNum) {
177
178 if (!init) {
179 init = 1;
180 mpglag = 1;
181 if (hip) {
182 hip_decode_exit(hip);
183 }
184 hip = hip_decode_init();
185 hip_set_pinfo(hip, pinfo);
186 }
187
188 iread = get_audio16(gfp, Buffer);
189 if (iread > framesize) {
190 /* NOTE: frame analyzer requires that we encode one frame
191 * for each pass through this loop. If lame_encode_buffer()
192 * is feed data too quickly, it will sometimes encode multiple frames
193 * breaking this loop.
194 */
195 error_printf("Warning: get_audio is returning too much data.\n");
196 }
197 if (iread <= 0)
198 break; /* eof */
199
200 mp3count = lame_encode_buffer(gfp, Buffer[0], Buffer[1], iread,
201 mp3buffer, sizeof(mp3buffer));
202
203 assert(!(mp3count > 0 && lame_get_frameNum(gfp) == pinfo->frameNum));
204 /* not possible to produce mp3 data without encoding at least
205 * one frame of data which would increment frameNum */
206 }
207 frameNum = lame_get_frameNum(gfp); /* use the internal MP3 frame counter */
208
209
210 /* decode one frame of output */
211 mp3out = hip_decode1(hip, mp3buffer, mp3count, mpg123pcm[0], mpg123pcm[1]); /* re-synthesis to pcm */
212 /* mp3out = 0: need more data to decode */
213 /* mp3out = -1: error. Lets assume 0 pcm output */
214 /* mp3out = number of samples output */
215 if (mp3out > 0)
216 assert(mp3out == pinfo->framesize);
217 if (mp3out != 0) {
218 /* decoded output is for frame pinfo->frameNum123
219 * add a delay of framesize-DECDELAY, which will make the total delay
220 * exactly one frame */
221 pinfo->frameNum123 = pinfo->frameNum - mpglag;
222 for (ch = 0; ch < pinfo->stereo; ch++) {
223 for (j = 0; j < pinfo->framesize - DECDELAY; j++)
224 pinfo->pcmdata2[ch][j] = pinfo->pcmdata2[ch][j + pinfo->framesize];
225 for (j = 0; j < pinfo->framesize; j++) {
226 pinfo->pcmdata2[ch][j + pinfo->framesize - DECDELAY] =
227 (mp3out == -1) ? 0 : mpg123pcm[ch][j];
228 }
229 }
230 }
231 else {
232 if (mpglag == MAXMPGLAG) {
233 error_printf("READ_AHEAD set too low - not enough frame buffering.\n"
234 "MP3x display of input and output PCM data out of sync.\n");
235 error_flush();
236 }
237 else
238 mpglag++;
239 pinfo->frameNum123 = -1; /* no frame output */
240 }
241 }
242 return iread;
243 }
244
245
246 void
plot_frame(void)247 plot_frame(void)
248 {
249 int i, j, n, ch, gr;
250 gdouble *xcord, *ycord;
251 gdouble xmx, xmn, ymx, ymn;
252 double *data, *data2, *data3;
253 char title2[80];
254 char label[80], label2[80];
255 char *title;
256 plotting_data *pplot1;
257 plotting_data *pplot2 = NULL;
258
259 double en, samp;
260 /*int sampindex, version = 0;*/
261 int barthick;
262 static int firstcall = 1;
263 static GdkColor *barcolor, *color, *grcolor[2];
264 static GdkColor yellow, gray, cyan, magenta, orange, pink, red, green, blue, black, oncolor,
265 offcolor;
266 int blocktype[2][2];
267 int headbits;
268 int mode_gr = 2;
269
270 /* find the frame where mpg123 produced output coming from input frame
271 * pinfo. i.e.: out_frame + out_frame_lag = input_frame */
272 for (i = 1; i <= MAXMPGLAG; i++) {
273 if ((pplot - i)->frameNum123 == pplot->frameNum) {
274 pplot2 = pplot - i;
275 break;
276 }
277 }
278 if (i > MAXMPGLAG) {
279 error_printf("input/output pcm syncing problem. should not happen!\n");
280 pplot2 = pplot - 1;
281 }
282
283
284 /* however, the PCM data is delayed by 528 samples in the encoder filterbanks.
285 * We added another 1152-528 delay to this so the PCM data is *exactly* one
286 * frame behind the header & MDCT information */
287 pplot1 = pplot2 + 1; /* back one frame for header info, MDCT */
288
289 /* allocate these GC's only once */
290 if (firstcall) {
291 firstcall = 0;
292 /* grcolor[0] = &magenta; */
293 grcolor[0] = &blue;
294 grcolor[1] = &green;
295 barcolor = &gray;
296
297 setcolor(headerbox, &oncolor, 255, 0, 0);
298 setcolor(headerbox, &offcolor, 175, 175, 175);
299 setcolor(pcmbox, &red, 255, 0, 0);
300 setcolor(pcmbox, &pink, 255, 0, 255);
301 setcolor(pcmbox, &magenta, 255, 0, 100);
302 setcolor(pcmbox, &orange, 255, 127, 0);
303 setcolor(pcmbox, &cyan, 0, 255, 255);
304 setcolor(pcmbox, &green, 0, 255, 0);
305 setcolor(pcmbox, &blue, 0, 0, 255);
306 setcolor(pcmbox, &black, 0, 0, 0);
307 setcolor(pcmbox, &gray, 100, 100, 100);
308 setcolor(pcmbox, &yellow, 255, 255, 0);
309
310 }
311
312 /*******************************************************************
313 * frame header info
314 *******************************************************************/
315 if (pplot1->sampfreq)
316 samp = pplot1->sampfreq;
317 else
318 samp = 1;
319 /*sampindex = SmpFrqIndex((long) samp, &version);*/
320
321 ch = gtkinfo.chflag;
322
323 headbits = 32 + ((pplot1->stereo == 2) ? 256 : 136);
324 gtkinfo.approxbits = (pplot1->bitrate * 1000 * 1152.0 / samp) - headbits;
325 sprintf(title2, "%3.1fkHz %ikbs ", samp / 1000, pplot1->bitrate);
326 gtk_text_freeze(GTK_TEXT(headerbox));
327 gtk_text_backward_delete(GTK_TEXT(headerbox), gtk_text_get_length(GTK_TEXT(headerbox)));
328 gtk_text_set_point(GTK_TEXT(headerbox), 0);
329 gtk_text_insert(GTK_TEXT(headerbox), NULL, &oncolor, NULL, title2, -1);
330 title = " mono ";
331 if (2 == pplot1->stereo)
332 title = pplot1->js ? " js " : " s ";
333 gtk_text_insert(GTK_TEXT(headerbox), NULL, &oncolor, NULL, title, -1);
334 color = pplot1->ms_stereo ? &oncolor : &offcolor;
335 gtk_text_insert(GTK_TEXT(headerbox), NULL, color, NULL, "ms ", -1);
336 color = pplot1->i_stereo ? &oncolor : &offcolor;
337 gtk_text_insert(GTK_TEXT(headerbox), NULL, color, NULL, "is ", -1);
338
339 color = pplot1->crc ? &oncolor : &offcolor;
340 gtk_text_insert(GTK_TEXT(headerbox), NULL, color, NULL, "crc ", -1);
341 color = pplot1->padding ? &oncolor : &offcolor;
342 gtk_text_insert(GTK_TEXT(headerbox), NULL, color, NULL, "pad ", -1);
343
344 color = pplot1->emph ? &oncolor : &offcolor;
345 gtk_text_insert(GTK_TEXT(headerbox), NULL, color, NULL, "em ", -1);
346
347 sprintf(title2, "bv=%i,%i ", pplot1->big_values[0][ch], pplot1->big_values[1][ch]);
348 gtk_text_insert(GTK_TEXT(headerbox), NULL, &black, NULL, title2, -1);
349
350 color = pplot1->scfsi[ch] ? &oncolor : &offcolor;
351 sprintf(title2, "scfsi=%i ", pplot1->scfsi[ch]);
352 gtk_text_insert(GTK_TEXT(headerbox), NULL, color, NULL, title2, -1);
353 if (gtkinfo.filetype)
354 sprintf(title2, " mdb=%i %i/NA", pplot1->maindata, pplot1->totbits);
355 else
356 sprintf(title2, " mdb=%i %i/%i",
357 pplot1->maindata, pplot1->totbits, pplot1->totbits + pplot->resvsize);
358 gtk_text_insert(GTK_TEXT(headerbox), NULL, &oncolor, NULL, title2, -1);
359 gtk_text_thaw(GTK_TEXT(headerbox));
360
361
362
363 /*******************************************************************
364 * block type
365 *******************************************************************/
366 for (gr = 0; gr < mode_gr; gr++)
367 if (gtkinfo.flag123)
368 blocktype[gr][ch] = pplot1->mpg123blocktype[gr][ch];
369 else
370 blocktype[gr][ch] = pplot->blocktype[gr][ch];
371
372
373 /*******************************************************************
374 * draw the PCM data *
375 *******************************************************************/
376 n = 1600; /* PCM frame + FFT window: 224 + 1152 + 224 */
377 xcord = g_malloc(n * sizeof(gdouble));
378 ycord = g_malloc(n * sizeof(gdouble));
379
380
381 if (gtkinfo.msflag)
382 title = ch ? "Side Channel" : "Mid Channel";
383 else
384 title = ch ? "Right Channel" : "Left Channel";
385
386 sprintf(title2, "%s mask_ratio=%3.2f %3.2f ener_ratio=%3.2f %3.2f",
387 title,
388 pplot->ms_ratio[0], pplot->ms_ratio[1],
389 pplot->ms_ener_ratio[0], pplot->ms_ener_ratio[1]);
390
391
392 ymn = -32767;
393 ymx = 32767;
394 xmn = 0;
395 xmx = 1600 - 1;
396
397 /* 0 ... 224 draw in black, connecting to 224 pixel
398 * 1375 .. 1599 draw in black connecting to 1375 pixel
399 * 224 ... 1375 MP3 frame. draw in blue
400 */
401
402 /* draw the title */
403 gpk_graph_draw(pcmbox, 0, xcord, ycord, xmn, ymn, xmx, ymx, 1, title2, &black);
404
405
406 /* draw some hash marks dividing the frames */
407 ycord[0] = ymx * .8;
408 ycord[1] = ymn * .8;
409 for (gr = 0; gr <= 2; gr++) {
410 xcord[0] = 223.5 + gr * 576;
411 xcord[1] = 223.5 + gr * 576;
412 gpk_rectangle_draw(pcmbox, xcord, ycord, xmn, ymn, xmx, ymx, &yellow);
413 }
414 for (gr = 0; gr < mode_gr; gr++) {
415 if (blocktype[gr][ch] == 2)
416 for (i = 1; i <= 2; i++) {
417 xcord[0] = 223.5 + gr * 576 + i * 192;
418 xcord[1] = 223.5 + gr * 576 + i * 192;
419 gpk_rectangle_draw(pcmbox, xcord, ycord, xmn, ymn, xmx, ymx, &yellow);
420 }
421 }
422 /* bars representing FFT windows */
423 xcord[0] = 0;
424 ycord[0] = ymn + 3000;
425 xcord[1] = 1024 - 1;
426 ycord[1] = ymn + 1000;
427 gpk_rectangle_draw(pcmbox, xcord, ycord, xmn, ymn, xmx, ymx, grcolor[0]);
428 xcord[0] = 576;
429 ycord[0] = ymn + 2000;
430 xcord[1] = 576 + 1024 - 1;
431 ycord[1] = ymn;
432 gpk_rectangle_draw(pcmbox, xcord, ycord, xmn, ymn, xmx, ymx, grcolor[1]);
433
434
435 /* plot PCM data */
436 for (i = 0; i < n; i++) {
437 xcord[i] = i;
438 if (gtkinfo.msflag)
439 ycord[i] = ch ? .5 * (pplot->pcmdata[0][i] - pplot->pcmdata[1][i]) :
440 .5 * (pplot->pcmdata[0][i] + pplot->pcmdata[1][i]);
441 else
442 ycord[i] = pplot->pcmdata[ch][i];
443 }
444
445 /* skip plot if we are doing an mp3 file */
446 if (!gtkinfo.filetype) {
447 gpk_graph_draw(pcmbox, n, xcord, ycord, xmn, ymn, xmx, ymx, 0, title2, &black);
448 }
449
450
451 /*******************************************************************/
452 /* draw the PCM re-synthesis data */
453 /*******************************************************************/
454 n = 1152;
455 /*
456 sprintf(title2,"Re-synthesis mask_ratio=%3.2f %3.2f ener_ratio=%3.2f %3.2f",
457 pplot->ms_ratio[0],pplot->ms_ratio[1],
458 pplot->ms_ener_ratio[0],pplot->ms_ener_ratio[1]);
459 */
460 title = "Re-synthesis";
461 if (gtkinfo.difference)
462 title = "Re-synthesis difference (amplified 20db)";
463
464
465 ymn = -32767;
466 ymx = 32767;
467 xmn = 0;
468 xmx = 1600 - 1;
469 gpk_graph_draw(winbox, 0, xcord, ycord, xmn, ymn, xmx, ymx, 1, title, &black);
470 /* draw some hash marks dividing the frames */
471 ycord[0] = ymx * .8;
472 ycord[1] = ymn * .8;
473 for (gr = 0; gr <= 2; gr++) {
474 xcord[0] = 223.5 + gr * 576;
475 xcord[1] = 223.5 + gr * 576;
476 gpk_rectangle_draw(winbox, xcord, ycord, xmn, ymn, xmx, ymx, &yellow);
477 }
478 for (gr = 0; gr < 2; gr++) {
479 if (blocktype[gr][ch] == 2)
480 for (i = 1; i <= 2; i++) {
481 xcord[0] = 223.5 + gr * 576 + i * 192;
482 xcord[1] = 223.5 + gr * 576 + i * 192;
483 gpk_rectangle_draw(winbox, xcord, ycord, xmn, ymn, xmx, ymx, &yellow);
484 }
485 }
486
487 /* this piece of PCM data from previous frame */
488 n = 224;
489 for (j = 1152 - n, i = 0; i < n; i++, j++) {
490 xcord[i] = i;
491 if (gtkinfo.msflag)
492 ycord[i] = ch ? .5 * (pplot1->pcmdata2[0][j] -
493 pplot1->pcmdata2[1][j]) :
494 .5 * (pplot1->pcmdata2[0][j] + pplot1->pcmdata2[1][j]);
495 else
496 ycord[i] = pplot1->pcmdata2[ch][j];
497 }
498
499 /* this piece of PCM data from current frame */
500 n = 1152;
501 for (i = 0; i < n; i++) {
502 xcord[i + 224] = i + 224;
503 if (gtkinfo.msflag)
504 ycord[i + 224] = ch ? .5 * (pplot2->pcmdata2[0][i] - pplot2->pcmdata2[1][i]) :
505 .5 * (pplot2->pcmdata2[0][i] + pplot2->pcmdata2[1][i]);
506 else
507 ycord[i + 224] = pplot2->pcmdata2[ch][i];
508 }
509
510 n = 1152 + 224;
511 if (gtkinfo.difference) {
512 for (i = 0; i < n; i++) {
513 if (gtkinfo.msflag)
514 ycord[i] -= ch ? .5 * (pplot->pcmdata[0][i] - pplot->pcmdata[1][i]) :
515 .5 * (pplot->pcmdata[0][i] + pplot->pcmdata[1][i]);
516 else
517 ycord[i] -= pplot->pcmdata[ch][i];
518 }
519 ycord[i] *= 100;
520 }
521
522
523 gpk_graph_draw(winbox, n, xcord, ycord, xmn, ymn, xmx, ymx, 0, title, &black);
524
525
526
527
528
529 /*******************************************************************/
530 /* draw the MDCT energy spectrum */
531 /*******************************************************************/
532 for (gr = 0; gr < mode_gr; gr++) {
533 int bits, bits2;
534 char *blockname = "";
535 switch (blocktype[gr][ch]) {
536 case 0:
537 blockname = "normal";
538 break;
539 case 1:
540 blockname = "start";
541 break;
542 case 2:
543 blockname = "short";
544 break;
545 case 3:
546 blockname = "end";
547 break;
548 }
549 strcpy(label, blockname);
550 if (pplot1->mixed[gr][ch])
551 strcat(label, "(mixed)");
552
553
554
555
556 n = 576;
557 if (gtkinfo.flag123) {
558 data = pplot1->mpg123xr[gr][0];
559 data2 = pplot1->mpg123xr[gr][1];
560 }
561 else {
562 data = pplot->xr[gr][0];
563 data2 = pplot->xr[gr][1];
564 }
565
566
567 xmn = 0;
568 xmx = n - 1;
569 ymn = 0;
570 ymx = 11;
571
572 /* draw title, erase old plot */
573 if (gtkinfo.flag123) {
574 bits = pplot1->mainbits[gr][ch];
575 bits2 = pplot1->sfbits[gr][ch];
576 }
577 else {
578 bits = pplot->LAMEmainbits[gr][ch];
579 bits2 = pplot->LAMEsfbits[gr][ch];
580 }
581 sprintf(title2, "MDCT%1i(%s) bits=%i/%i ", gr, label, bits, bits2);
582 gpk_bargraph_draw(mdctbox[gr], 0, xcord, ycord, xmn, ymn, xmx, ymx, 1, title2, 0, barcolor);
583
584 /* draw some hash marks showing scalefactor bands */
585 if (gtkinfo.sfblines) {
586 int fac, nsfb, *scalefac;
587 if (blocktype[gr][ch] == SHORT_TYPE) {
588 nsfb = SBMAX_s;
589 i = nsfb - 7;
590 fac = 3;
591 scalefac = gfc->scalefac_band.s;
592 }
593 else {
594 nsfb = SBMAX_l;
595 i = nsfb - 10;
596 fac = 1;
597 scalefac = gfc->scalefac_band.l;
598 }
599 for (; i < nsfb; i++) {
600 ycord[0] = .8 * ymx;
601 ycord[1] = ymn;
602 xcord[0] = fac * scalefac[i];
603 xcord[1] = xcord[0];
604 gpk_rectangle_draw(mdctbox[gr], xcord, ycord, xmn, ymn, xmx, ymx, &yellow);
605 }
606 }
607
608
609
610 ymn = 9e20;
611 ymx = -9e20;
612 for (i = 0; i < n; i++) {
613 double coeff;
614 xcord[i] = i;
615 if (gtkinfo.msflag) {
616 coeff = ch ? .5 * (data[i] - data2[i]) : .5 * (data[i] + data2[i]);
617 }
618 else {
619 coeff = ch ? data2[i] : data[i];
620 }
621 if (blocktype[gr][ch] == SHORT_TYPE && !subblock_draw[i % 3])
622 coeff = 0;
623 ycord[i] = coeff * coeff * 1e10;
624 ycord[i] = log10(MAX(ycord[i], (double) 1));
625
626 #if 0
627 if (ch == 0)
628 if (i == 26)
629 if (data[i] != 0)
630 console_printf("%i %i i=%i mdct: (db) %f %f \n", pplot->frameNum, gr, i,
631 10 * log10(data[i] * data[i]),
632 10 * log10(.33 *
633 (data[i - 1] * data[i - 1] + data[i] * data[i] +
634 data[i + 1] * data[i + 1]))
635 );
636 #endif
637
638 ymx = (ycord[i] > ymx) ? ycord[i] : ymx;
639 ymn = (ycord[i] < ymn) ? ycord[i] : ymn;
640 }
641 /* print the min/max
642 sprintf(title2,"MDCT%1i %5.2f %5.2f bits=%i",gr,ymn,ymx,
643 pplot1->mainbits[gr][ch]);
644 */
645 if (gtkinfo.flag123)
646 bits = pplot1->mainbits[gr][ch];
647 else
648 bits = pplot->LAMEmainbits[gr][ch];
649
650
651 sprintf(title2, "MDCT%1i(%s) bits=%i ", gr, label, bits);
652
653 xmn = 0;
654 xmx = n - 1;
655 ymn = 0;
656 ymx = 11;
657 gpk_bargraph_draw(mdctbox[gr], n, xcord, ycord, xmn, ymn, xmx, ymx, 0, title2, 0, barcolor);
658 }
659
660
661
662
663 /*******************************************************************
664 * draw the psy model energy spectrum (k space)
665 * l3psy.c computes pe, en, thm for THIS granule.
666 *******************************************************************/
667 if (gtkinfo.kbflag) {
668 for (gr = 0; gr < mode_gr; gr++) {
669 n = HBLKSIZE; /* only show half the spectrum */
670
671 data = &pplot->energy[gr][ch][0];
672
673 ymn = 9e20;
674 ymx = -9e20;
675 for (i = 0; i < n; i++) {
676 xcord[i] = i + 1;
677 if (blocktype[gr][ch] == SHORT_TYPE && !subblock_draw[i % 3])
678 ycord[i] = 0;
679 else
680 ycord[i] = log10(MAX(data[i], (double) 1));
681 ymx = (ycord[i] > ymx) ? ycord[i] : ymx;
682 ymn = (ycord[i] < ymn) ? ycord[i] : ymn;
683 }
684 for (en = 0, j = 0; j < BLKSIZE; j++)
685 en += pplot->energy[gr][ch][j];
686
687 sprintf(title2, "FFT%1i pe=%5.2fK en=%5.2e ", gr, pplot->pe[gr][ch] / 1000, en);
688
689 ymn = 3;
690 ymx = 15;
691 xmn = 1;
692 xmx = n;
693 gpk_bargraph_draw(enerbox[gr], n, xcord, ycord,
694 xmn, ymn, xmx, ymx, 1, title2, 0, barcolor);
695
696 }
697 }
698 else {
699 /*******************************************************************
700 * draw the psy model energy spectrum (scalefactor bands)
701 *******************************************************************/
702 for (gr = 0; gr < mode_gr; gr++) {
703
704 if (blocktype[gr][ch] == 2) {
705 n = 3 * SBMAX_s;
706 data = &pplot->en_s[gr][ch][0];
707 data2 = &pplot->thr_s[gr][ch][0];
708 data3 = &pplot->xfsf_s[gr][ch][0];
709 }
710 else {
711 n = SBMAX_l;
712 data = &pplot->en[gr][ch][0];
713 data2 = &pplot->thr[gr][ch][0];
714 data3 = &pplot->xfsf[gr][ch][0];
715 }
716 ymn = 9e20;
717 ymx = -9e20;
718 for (i = 0; i < n; i++) {
719 xcord[i] = i + 1;
720 if (blocktype[gr][ch] == SHORT_TYPE && !subblock_draw[i % 3])
721 ycord[i] = 0;
722 else
723 ycord[i] = log10(MAX(data[i], (double) 1));
724 /*
725 ymx=(ycord[i] > ymx) ? ycord[i] : ymx;
726 ymn=(ycord[i] < ymn) ? ycord[i] : ymn;
727 */
728 }
729
730
731
732 /* en = max energy difference amoung the 3 short FFTs for this granule */
733 en = pplot->ers[gr][ch];
734 if (en > 999)
735 en = 999;
736 sprintf(title2,
737 "FFT%1i pe=%5.2fK/%3.1f \nnoise ovr_b:%i/max:%3.1f/ovr:%3.1f/tot:%3.1f/ssd:%i",
738 gr, pplot->pe[gr][ch] / 1000, en, pplot->over[gr][ch], pplot->max_noise[gr][ch],
739 pplot->over_noise[gr][ch], pplot->tot_noise[gr][ch], pplot->over_SSD[gr][ch]);
740
741 barthick = 3;
742 if (blocktype[gr][ch] == SHORT_TYPE)
743 barthick = 2;
744 if (!(subblock_draw[0] && subblock_draw[1] && subblock_draw[2]))
745 barthick = 3;
746
747 ymn = 3;
748 ymx = 15;
749 xmn = 1;
750 xmx = n + 1; /* a little extra because of the bar thickness */
751 gpk_bargraph_draw(enerbox[gr], n, xcord, ycord,
752 xmn, ymn, xmx, ymx, 1, title2, barthick, barcolor);
753
754 for (i = 0; i < n; i++) {
755 xcord[i] = i + 1 + .20;
756 if (blocktype[gr][ch] == SHORT_TYPE && !subblock_draw[i % 3])
757 ycord[i] = 0;
758 else
759 ycord[i] = log10(MAX(data2[i], (double) 1));
760 }
761
762 gpk_bargraph_draw(enerbox[gr], n, xcord, ycord,
763 xmn, ymn, xmx, ymx, 0, title2, barthick, grcolor[gr]);
764
765 for (i = 0; i < n; i++) {
766 xcord[i] = i + 1 + .40;
767 if (blocktype[gr][ch] == SHORT_TYPE && !subblock_draw[i % 3])
768 ycord[i] = 0;
769 else
770 ycord[i] = log10(MAX(data3[i], (double) 1));
771 }
772 gpk_bargraph_draw(enerbox[gr], n, xcord, ycord,
773 xmn, ymn, xmx, ymx, 0, title2, barthick, &red);
774
775 }
776 }
777
778 /*******************************************************************
779 * draw scalefactors
780 *******************************************************************/
781 for (gr = 0; gr < mode_gr; gr++) {
782 int ggain;
783 if (blocktype[gr][ch] == 2) {
784 n = 3 * SBMAX_s;
785 if (gtkinfo.flag123)
786 data = pplot1->sfb_s[gr][ch];
787 else
788 data = pplot->LAMEsfb_s[gr][ch];
789 }
790 else {
791 n = SBMAX_l;
792 if (gtkinfo.flag123)
793 data = pplot1->sfb[gr][ch];
794 else
795 data = pplot->LAMEsfb[gr][ch];
796 }
797
798 ymn = -1;
799 ymx = 10;
800 for (i = 0; i < n; i++) {
801 xcord[i] = i + 1;
802 if (blocktype[gr][ch] == SHORT_TYPE && !subblock_draw[i % 3])
803 ycord[i] = 0;
804 else
805 ycord[i] = -data[i];
806
807 ymx = (ycord[i] > ymx - 2) ? ycord[i] + 2 : ymx;
808 ymn = (ycord[i] < ymn) ? ycord[i] - 1 : ymn;
809 }
810
811 if (blocktype[gr][ch] == 2) {
812 sprintf(label2,
813 "SFB scale=%i preflag=%i %i%i%i",
814 pplot1->scalefac_scale[gr][ch],
815 pplot1->preflag[gr][ch],
816 pplot1->sub_gain[gr][ch][0],
817 pplot1->sub_gain[gr][ch][1], pplot1->sub_gain[gr][ch][2]);
818 }
819 else {
820 sprintf(label2, "SFB scale=%i preflag=%i", pplot1->scalefac_scale[gr][ch],
821 pplot1->preflag[gr][ch]);
822 }
823
824 if (gtkinfo.flag123)
825 ggain = (pplot1->qss[gr][ch]);
826 else
827 ggain = (pplot->LAMEqss[gr][ch]);
828
829 sprintf(title2, " ggain=%i", ggain);
830 strcat(label2, title2);
831
832 xmn = 1;
833 xmx = n + 1;
834 gpk_bargraph_draw(sfbbox[gr], n, xcord, ycord,
835 xmn, ymn, xmx, ymx, 1, label2, 0, grcolor[gr]);
836
837 ycord[0] = ycord[1] = 0;
838 xcord[0] = 1;
839 xcord[1] = n + 1;
840 gpk_rectangle_draw(sfbbox[gr], xcord, ycord, xmn, ymn, xmx, ymx, &yellow);
841
842
843 }
844
845
846 }
847
848
849
850 static void
update_progress(void)851 update_progress(void)
852 {
853 char label[80];
854
855 int tf = lame_get_totalframes(gfp);
856 if (gtkinfo.totalframes > 0)
857 tf = gtkinfo.totalframes;
858
859 sprintf(label, "Frame:%4i/%4i %6.2fs", pplot->frameNum, (int) tf - 1, pplot->frametime);
860 gtk_progress_set_value(GTK_PROGRESS(frameprogress), (gdouble) pplot->frameNum);
861 gtk_label_set_text(GTK_LABEL(framecounter), label);
862 }
863
864
865
866 static void
analyze(void)867 analyze(void)
868 {
869 if (idle_keepgoing) {
870 idle_count = 0;
871 idle_count_max = 0;
872 idle_keepgoing = 0;
873 idle_end = 0;
874 }
875 plot_frame();
876 update_progress();
877 }
878
879 static void
plotclick(GtkWidget * widget,gpointer data)880 plotclick(GtkWidget * widget, gpointer data)
881 {
882 analyze();
883 }
884
885
886
887
888 static int
frameadv1(GtkWidget * widget,gpointer data)889 frameadv1(GtkWidget * widget, gpointer data)
890 {
891 int i;
892 if (idle_keepgoing) {
893 if (idle_back) {
894 /* frame displayed is the old frame. to advance, just swap in new frame */
895 idle_back--;
896 pplot = &Pinfo[READ_AHEAD + idle_back];
897 }
898 else {
899 /* advance the frame by reading in a new frame */
900 pplot = &Pinfo[READ_AHEAD];
901 if (mp3done) {
902 /* dont try to read any more frames, and quit if "finish MP3" was selected */
903 /* if (idle_finish) gtk_main_quit(); */
904 idle_count_max = 0;
905 idle_end = 0;
906 }
907 else {
908 /* read in the next frame */
909 for (i = NUMPINFO - 1; i > 0; i--)
910 memcpy(&Pinfo[i], &Pinfo[i - 1], sizeof(plotting_data));
911 pinfo = &Pinfo[0];
912 pinfo->num_samples = gtkmakeframe();
913 if (pinfo->num_samples == 0 && gtkinfo.totalframes == 0)
914 /* allow an extra frame to flush decoder buffers */
915 gtkinfo.totalframes = pinfo->frameNum + 2;
916
917 if (pinfo->sampfreq)
918 pinfo->frametime = (pinfo->frameNum) * 1152.0 / pinfo->sampfreq;
919 else
920 pinfo->frametime = 0;
921
922 /* eof?
923 if (!pinfo->num_samples) if (idle_finish) gtk_main_quit();
924 */
925
926 pinfo->totbits = 0;
927 {
928 int gr, ch;
929 for (gr = 0; gr < 2; gr++)
930 for (ch = 0; ch < 2; ch++) {
931 gtkinfo.totshort += (pinfo->mpg123blocktype[gr][ch] == 2);
932 gtkinfo.totmix += !(pinfo->mixed[gr][ch] == 0);
933 gtkinfo.totpreflag += (pinfo->preflag[gr][ch] == 1);
934 pinfo->totbits += pinfo->mainbits[gr][ch];
935 }
936 }
937 if (pinfo->frameNum > 0) /* start averaging at second frame */
938 gtkinfo.avebits = (gtkinfo.avebits * ((pinfo->frameNum) - 1)
939 + pinfo->totbits) / (pinfo->frameNum);
940
941 gtkinfo.maxbits = MAX(gtkinfo.maxbits, pinfo->totbits);
942 gtkinfo.totemph += !(pinfo->emph == 0);
943 gtkinfo.totms += !(pinfo->ms_stereo == 0);
944 gtkinfo.totis += !(pinfo->i_stereo == 0);
945
946 if (gtkinfo.totalframes > 0)
947 if (pplot->frameNum >= gtkinfo.totalframes - 1)
948 mp3done = 1;
949 }
950 }
951
952 idle_count++;
953 if (gtkinfo.pupdate)
954 plot_frame();
955 update_progress();
956 if ((idle_count >= idle_count_max) && (!idle_end))
957 analyze();
958 }
959 else {
960 /*no processing to do, sleep in order to not monopolize CPU */
961 msleep(10);
962 }
963 return 1;
964 }
965
966
967 static void
frameadv(GtkWidget * widget,gpointer data)968 frameadv(GtkWidget * widget, gpointer data)
969 {
970 int adv;
971
972 if (!strcmp((char *) data, "-1")) {
973 /* ignore if we've already gone back as far as possible */
974 if (pplot->frameNum == 0 || (idle_back == NUMBACK))
975 return;
976 idle_back++;
977 pplot = &Pinfo[READ_AHEAD + idle_back];
978 analyze();
979 return;
980 }
981
982
983 adv = 1;
984 if (!strcmp((char *) data, "1"))
985 adv = 1;
986 if (!strcmp((char *) data, "10"))
987 adv = 10;
988 if (!strcmp((char *) data, "100"))
989 adv = 100;
990 if (!strcmp((char *) data, "finish"))
991 idle_end = 1;
992
993
994 if (idle_keepgoing) {
995 /* already running - que up additional frame advance requests */
996 idle_count_max += adv;
997 }
998 else {
999 /* turn on idleing */
1000 idle_count_max = adv;
1001 idle_count = 0;
1002 idle_keepgoing = 1;
1003 }
1004 }
1005
1006
1007
1008
1009 /* another callback */
1010 static void
delete_event(GtkWidget * widget,GdkEvent * event,gpointer data)1011 delete_event(GtkWidget * widget, GdkEvent * event, gpointer data)
1012 {
1013 /* set MP3 done flag in case the File/Quit menu item has been selected */
1014 mp3done = 1;
1015
1016 gtk_main_quit();
1017 }
1018
1019
1020
1021
1022
1023
1024
1025 static void
channel_option(GtkWidget * widget,gpointer data)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
spec_option(GtkWidget * widget,gpointer data)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
key_press_event(GtkWidget * widget,GdkEventKey * event)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 *
get_mp3x_version(void)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
text_window(GtkWidget * widget,gpointer data)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
get_main_menu(GtkWidget * windows,GtkWidget ** menubar)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
gtkcontrol(lame_global_flags * gfp2,char * inPath)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 }
1641