2 * Bitrate histogram source file
4 * Copyright (c) 2000 Mark Taylor
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
22 /* $Id: brhist.c,v 1.57 2011/05/07 16:05:17 rbrito Exp $ */
31 # define BRHIST_WIDTH 14
34 # define BRHIST_RES 14
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 );
60 extern Console_IO_t Console_IO;
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 */
74 calculate_index(const int *const array, const int len, const int value)
78 for (i = 0; i < len; i++)
79 if (array[i] == value)
85 brhist_init(const lame_global_flags * gf, const int bitrate_kbps_min, const int bitrate_kbps_max)
87 brhist.hist_printed_lines = 0;
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);
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);
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);
110 digits(unsigned number)
114 if (number >= 100000000) {
118 if (number >= 10000) {
135 brhist_disp_line(int i, int br_hist_TOT, int br_hist_LR, int full, int frames)
137 char brppt[14]; /* [%] and max. 10 characters for kbps */
140 int res = digits(frames) + 3 + 4 + 1;
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 */
148 barlen_TOT = barlen_LR = 0;
151 sprintf(brppt, " [%*i]", digits(frames), br_hist_TOT);
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);
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, "");
165 brhist.hist_printed_lines++;
171 progress_line(const lame_global_flags * gf, int full, int frames)
174 int barlen_TOT = 0, barlen_COD = 0, barlen_RST = 0;
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);
185 time_in_sec = (float)(full - frames);
186 time_in_sec *= fsize;
187 time_in_sec /= srate;
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;
196 sprintf(rst, "%*d:%02u:%02u", digits(hour), hour, min, sec);
197 res += digits(hour) + 1 + 5;
200 sprintf(rst, "%02u:%02u", min, sec);
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);
212 barlen_TOT = barlen_COD = barlen_RST = 0;
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);
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,
225 brhist.hist_printed_lines++;
230 stats_value(double x)
233 console_printf(" %5.1f", x);
240 stats_head(double x, const char *txt)
251 stats_line(double *stat)
254 console_printf("\n kbps ");
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(" %% ");
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);
271 console_printf("%*s", Console_IO.disp_width - n, "");
273 brhist.hist_printed_lines++;
276 console_printf("\n %5.1f ", stat[0]);
278 n += stats_value(stat[1]);
279 n += stats_value(stat[2]);
280 n += stats_value(stat[3]);
281 n += stats_value(stat[4]);
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);
292 console_printf("%*s", Console_IO.disp_width - n, "");
294 brhist.hist_printed_lines++;
298 /* Yes, not very good */
303 brhist_disp(const lame_global_flags * gf)
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 */
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 */
314 double stat[9] = { 0 };
318 brhist.hist_printed_lines = 0; /* printed number of lines for the brhist functionality, used to skip back the right number of lines */
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);
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];
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);
341 for (i = 0; i < 4; i++) {
342 st_frames += st_mode[i];
345 stat[0] = sum / frames;
346 stat[1] = 100. * (frames - st_frames) / frames;
350 stat[3] = 100. * st_mode[LR] / st_frames;
351 stat[4] = 100. * st_mode[MS] / st_frames;
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];
359 progress_line(gf, lame_get_totalframes(gf), frames);
364 brhist_jump_back(void)
366 console_up(brhist.hist_printed_lines);
367 brhist.hist_printed_lines = 0;
373 * Taken from Termcap_Manual.html:
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.)