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