]> 4ch.mooo.com Git - 16.git/blob - brhist.c
dcf858fb22b8a6cc68547914deb0b66c8a5a99d1
[16.git] / brhist.c
1 /*
2  *      Bitrate histogram source file
3  *
4  *      Copyright (c) 2000 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: brhist.c,v 1.57 2011/05/07 16:05:17 rbrito Exp $ */
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 /* basic #define's */
29
30 #ifndef BRHIST_WIDTH
31 # define BRHIST_WIDTH    14
32 #endif
33 #ifndef BRHIST_RES
34 # define BRHIST_RES      14
35 #endif
36
37
38 /* #includes */
39
40 #ifdef STDC_HEADERS
41 # include <stdio.h>
42 # include <stdlib.h>
43 # include <string.h>
44 #endif
45
46 #include "brhist.h"
47 #include "console.h"
48
49 #ifdef WITH_DMALLOC
50 #include <dmalloc.h>
51 #endif
52
53
54 /* Structure holding all data related to the Console I/O
55  * may be this should be a more global frontend structure. So it
56  * makes sense to print all files instead with
57  * printf ( "blah\n") with printf ( "blah%s\n", Console_IO.str_clreoln );
58  */
59
60 extern Console_IO_t Console_IO;
61
62 static struct brhist_struct {
63     int     vbr_bitrate_min_index;
64     int     vbr_bitrate_max_index;
65     int     kbps[BRHIST_WIDTH];
66     int     hist_printed_lines;
67     char    bar_asterisk[512 + 1]; /* buffer filled up with a lot of '*' to print a bar     */
68     char    bar_percent[512 + 1]; /* buffer filled up with a lot of '%' to print a bar     */
69     char    bar_coded[512 + 1]; /* buffer filled up with a lot of ' ' to print a bar     */
70     char    bar_space[512 + 1]; /* buffer filled up with a lot of ' ' to print a bar     */
71 } brhist;
72
73 static int
74 calculate_index(const int *const array, const int len, const int value)
75 {
76     int     i;
77
78     for (i = 0; i < len; i++)
79         if (array[i] == value)
80             return i;
81     return -1;
82 }
83
84 int
85 brhist_init(const lame_global_flags * gf, const int bitrate_kbps_min, const int bitrate_kbps_max)
86 {
87     brhist.hist_printed_lines = 0;
88
89     /* initialize histogramming data structure */
90     lame_bitrate_kbps(gf, brhist.kbps);
91     brhist.vbr_bitrate_min_index = calculate_index(brhist.kbps, BRHIST_WIDTH, bitrate_kbps_min);
92     brhist.vbr_bitrate_max_index = calculate_index(brhist.kbps, BRHIST_WIDTH, bitrate_kbps_max);
93
94     if (brhist.vbr_bitrate_min_index >= BRHIST_WIDTH ||
95         brhist.vbr_bitrate_max_index >= BRHIST_WIDTH) {
96         error_printf("lame internal error: VBR min %d kbps or VBR max %d kbps not allowed.\n",
97                      bitrate_kbps_min, bitrate_kbps_max);
98         return -1;
99     }
100
101     memset(brhist.bar_asterisk, '*', sizeof(brhist.bar_asterisk) - 1);
102     memset(brhist.bar_percent, '%', sizeof(brhist.bar_percent) - 1);
103     memset(brhist.bar_space, '-', sizeof(brhist.bar_space) - 1);
104     memset(brhist.bar_coded, '-', sizeof(brhist.bar_space) - 1);
105
106     return 0;
107 }
108
109 static int
110 digits(unsigned number)
111 {
112     int     ret = 1;
113
114     if (number >= 100000000) {
115         ret += 8;
116         number /= 100000000;
117     }
118     if (number >= 10000) {
119         ret += 4;
120         number /= 10000;
121     }
122     if (number >= 100) {
123         ret += 2;
124         number /= 100;
125     }
126     if (number >= 10) {
127         ret += 1;
128     }
129
130     return ret;
131 }
132
133
134 static void
135 brhist_disp_line(int i, int br_hist_TOT, int br_hist_LR, int full, int frames)
136 {
137     char    brppt[14];       /* [%] and max. 10 characters for kbps */
138     int     barlen_TOT;
139     int     barlen_LR;
140     int     res = digits(frames) + 3 + 4 + 1;
141
142     if (full != 0) {
143         /* some problems when br_hist_TOT \approx br_hist_LR: You can't see that there are still MS frames */
144         barlen_TOT = (br_hist_TOT * (Console_IO.disp_width - res) + full - 1) / full; /* round up */
145         barlen_LR = (br_hist_LR * (Console_IO.disp_width - res) + full - 1) / full; /* round up */
146     }
147     else {
148         barlen_TOT = barlen_LR = 0;
149     }
150
151     sprintf(brppt, " [%*i]", digits(frames), br_hist_TOT);
152
153     if (Console_IO.str_clreoln[0]) /* ClearEndOfLine available */
154         console_printf("\n%3d%s %.*s%.*s%s",
155                        brhist.kbps[i], brppt,
156                        barlen_LR, brhist.bar_percent,
157                        barlen_TOT - barlen_LR, brhist.bar_asterisk, Console_IO.str_clreoln);
158     else
159         console_printf("\n%3d%s %.*s%.*s%*s",
160                        brhist.kbps[i], brppt,
161                        barlen_LR, brhist.bar_percent,
162                        barlen_TOT - barlen_LR, brhist.bar_asterisk,
163                        Console_IO.disp_width - res - barlen_TOT, "");
164
165     brhist.hist_printed_lines++;
166 }
167
168
169
170 static void
171 progress_line(const lame_global_flags * gf, int full, int frames)
172 {
173     char    rst[20] = "\0";
174     int     barlen_TOT = 0, barlen_COD = 0, barlen_RST = 0;
175     int     res = 1;
176     float   time_in_sec = 0;
177     unsigned int hour, min, sec;
178     int     fsize = lame_get_framesize(gf);
179     int     srate = lame_get_out_samplerate(gf);
180
181     if (full < frames) {
182         full = frames;
183     }
184     if (srate > 0) {
185         time_in_sec = (float)(full - frames);
186         time_in_sec *= fsize;
187         time_in_sec /= srate;
188     }
189     hour = (unsigned int)(time_in_sec / 3600);
190     time_in_sec -= hour * 3600;
191     min = (unsigned int)(time_in_sec / 60);
192     time_in_sec -= min * 60;
193     sec = (unsigned int)time_in_sec;
194     if (full != 0) {
195         if (hour > 0) {
196             sprintf(rst, "%*d:%02u:%02u", digits(hour), hour, min, sec);
197             res += digits(hour) + 1 + 5;
198         }
199         else {
200             sprintf(rst, "%02u:%02u", min, sec);
201             res += 5;
202         }
203         /* some problems when br_hist_TOT \approx br_hist_LR: You can't see that there are still MS frames */
204         barlen_TOT = (full * (Console_IO.disp_width - res) + full - 1) / full; /* round up */
205         barlen_COD = (frames * (Console_IO.disp_width - res) + full - 1) / full; /* round up */
206         barlen_RST = barlen_TOT - barlen_COD;
207         if (barlen_RST == 0) {
208             sprintf(rst, "%.*s", res - 1, brhist.bar_coded);
209         }
210     }
211     else {
212         barlen_TOT = barlen_COD = barlen_RST = 0;
213     }
214     if (Console_IO.str_clreoln[0]) { /* ClearEndOfLine available */
215         console_printf("\n%.*s%s%.*s%s",
216                        barlen_COD, brhist.bar_coded,
217                        rst, barlen_RST, brhist.bar_space, Console_IO.str_clreoln);
218     }
219     else {
220         console_printf("\n%.*s%s%.*s%*s",
221                        barlen_COD, brhist.bar_coded,
222                        rst, barlen_RST, brhist.bar_space, Console_IO.disp_width - res - barlen_TOT,
223                        "");
224     }
225     brhist.hist_printed_lines++;
226 }
227
228
229 static int
230 stats_value(double x)
231 {
232     if (x > 0.0) {
233         console_printf(" %5.1f", x);
234         return 6;
235     }
236     return 0;
237 }
238
239 static int
240 stats_head(double x, const char *txt)
241 {
242     if (x > 0.0) {
243         console_printf(txt);
244         return 6;
245     }
246     return 0;
247 }
248
249
250 static void
251 stats_line(double *stat)
252 {
253     int     n = 1;
254     console_printf("\n   kbps     ");
255     n += 12;
256     n += stats_head(stat[1], "  mono");
257     n += stats_head(stat[2], "   IS ");
258     n += stats_head(stat[3], "   LR ");
259     n += stats_head(stat[4], "   MS ");
260     console_printf(" %%    ");
261     n += 6;
262     n += stats_head(stat[5], " long ");
263     n += stats_head(stat[6], "switch");
264     n += stats_head(stat[7], " short");
265     n += stats_head(stat[8], " mixed");
266     n += console_printf(" %%");
267     if (Console_IO.str_clreoln[0]) { /* ClearEndOfLine available */
268         console_printf("%s", Console_IO.str_clreoln);
269     }
270     else {
271         console_printf("%*s", Console_IO.disp_width - n, "");
272     }
273     brhist.hist_printed_lines++;
274
275     n = 1;
276     console_printf("\n  %5.1f     ", stat[0]);
277     n += 12;
278     n += stats_value(stat[1]);
279     n += stats_value(stat[2]);
280     n += stats_value(stat[3]);
281     n += stats_value(stat[4]);
282     console_printf("      ");
283     n += 6;
284     n += stats_value(stat[5]);
285     n += stats_value(stat[6]);
286     n += stats_value(stat[7]);
287     n += stats_value(stat[8]);
288     if (Console_IO.str_clreoln[0]) { /* ClearEndOfLine available */
289         console_printf("%s", Console_IO.str_clreoln);
290     }
291     else {
292         console_printf("%*s", Console_IO.disp_width - n, "");
293     }
294     brhist.hist_printed_lines++;
295 }
296
297
298 /* Yes, not very good */
299 #define LR  0
300 #define MS  2
301
302 void
303 brhist_disp(const lame_global_flags * gf)
304 {
305     int     i, lines_used = 0;
306     int     br_hist[BRHIST_WIDTH]; /* how often a frame size was used */
307     int     br_sm_hist[BRHIST_WIDTH][4]; /* how often a special frame size/stereo mode commbination was used */
308     int     st_mode[4];
309     int     bl_type[6];
310     int     frames;          /* total number of encoded frames */
311     int     most_often;      /* usage count of the most often used frame size, but not smaller than Console_IO.disp_width-BRHIST_RES (makes this sense?) and 1 */
312     double  sum = 0.;
313
314     double  stat[9] = { 0 };
315     int     st_frames = 0;
316
317
318     brhist.hist_printed_lines = 0; /* printed number of lines for the brhist functionality, used to skip back the right number of lines */
319
320     lame_bitrate_stereo_mode_hist(gf, br_sm_hist);
321     lame_bitrate_hist(gf, br_hist);
322     lame_stereo_mode_hist(gf, st_mode);
323     lame_block_type_hist(gf, bl_type);
324
325     frames = most_often = 0;
326     for (i = 0; i < BRHIST_WIDTH; i++) {
327         frames += br_hist[i];
328         sum += br_hist[i] * brhist.kbps[i];
329         if (most_often < br_hist[i])
330             most_often = br_hist[i];
331         if (br_hist[i])
332             ++lines_used;
333     }
334
335     for (i = 0; i < BRHIST_WIDTH; i++) {
336         int     show = br_hist[i];
337         show = show && (lines_used > 1);
338         if (show || (i >= brhist.vbr_bitrate_min_index && i <= brhist.vbr_bitrate_max_index))
339             brhist_disp_line(i, br_hist[i], br_sm_hist[i][LR], most_often, frames);
340     }
341     for (i = 0; i < 4; i++) {
342         st_frames += st_mode[i];
343     }
344     if (frames > 0) {
345         stat[0] = sum / frames;
346         stat[1] = 100. * (frames - st_frames) / frames;
347     }
348     if (st_frames > 0) {
349         stat[2] = 0.0;
350         stat[3] = 100. * st_mode[LR] / st_frames;
351         stat[4] = 100. * st_mode[MS] / st_frames;
352     }
353     if (bl_type[5] > 0) {
354         stat[5] = 100. * bl_type[0] / bl_type[5];
355         stat[6] = 100. * (bl_type[1] + bl_type[3]) / bl_type[5];
356         stat[7] = 100. * bl_type[2] / bl_type[5];
357         stat[8] = 100. * bl_type[4] / bl_type[5];
358     }
359     progress_line(gf, lame_get_totalframes(gf), frames);
360     stats_line(stat);
361 }
362
363 void
364 brhist_jump_back(void)
365 {
366     console_up(brhist.hist_printed_lines);
367     brhist.hist_printed_lines = 0;
368 }
369
370 /*
371  * 1)
372  *
373  * Taken from Termcap_Manual.html:
374  *
375  * With the Unix version of termcap, you must allocate space for the description yourself and pass
376  * the address of the space as the argument buffer. There is no way you can tell how much space is
377  * needed, so the convention is to allocate a buffer 2048 characters long and assume that is
378  * enough.  (Formerly the convention was to allocate 1024 characters and assume that was enough.
379  * But one day, for one kind of terminal, that was not enough.)
380  */
381
382