home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 24 / AACD 24.iso / AACD / Sound / LAME / WarpOS / src / frontend / brhist.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-03-26  |  11.4 KB  |  359 lines

  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.36 2001/03/26 00:38:15 markt 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 <stdlib.h>
  42. # include <string.h>
  43. #else
  44. # ifndef HAVE_STRCHR
  45. #  define strchr index
  46. #  define strrchr rindex
  47. # endif
  48. char *strchr (), *strrchr ();
  49. # ifndef HAVE_MEMCPY
  50. #  define memcpy(d, s, n) bcopy ((s), (d), (n))
  51. #  define memmove(d, s, n) bcopy ((s), (d), (n))
  52. # endif
  53. #endif
  54.  
  55.  
  56. #if defined(HAVE_TERMCAP)
  57. #if defined(HAVE_TERMCAP_H)
  58. # include <termcap.h>
  59. #elif defined(HAVE_NCURSES_TERMCAP_H)
  60. # include <ncurses/termcap.h>
  61. #endif
  62. #endif
  63.  
  64. #include "brhist.h"
  65.  
  66. #ifdef WITH_DMALLOC
  67. #include <dmalloc.h>
  68. #endif
  69.  
  70. /* Structure holding all data related to the Console I/O 
  71.  * may be this should be a more global frontend structure. So it
  72.  * makes sense to print all files instead with
  73.  * printf ( "blah\n") with printf ( "blah%s\n", Console_IO.str_clreoln );
  74.  */
  75.  
  76. Console_IO_t Console_IO;
  77.  
  78. static struct {
  79.     int     vbr_bitrate_min_index;
  80.     int     vbr_bitrate_max_index;
  81.     int     kbps [BRHIST_WIDTH];
  82.     int     hist_printed_lines;
  83.     char    bar_asterisk [512 + 1];    /* buffer filled up with a lot of '*' to print a bar     */
  84.     char    bar_percent  [512 + 1];    /* buffer filled up with a lot of '%' to print a bar     */
  85. } brhist;
  86.  
  87. static int calculate_index ( const int* const array, const int len, const int value )
  88. {
  89.     int i;
  90.     
  91.     for ( i = 0; i < len; i++ )
  92.         if ( array [i] == value )
  93.         return i;
  94.     return -1;
  95. }
  96.  
  97. int  brhist_init ( const lame_global_flags* gf, const int bitrate_kbps_min, const int bitrate_kbps_max )
  98. {
  99. #ifdef HAVE_TERMCAP
  100.     char         term_buff [2048];  // see 1)
  101.     const char*  term_name;
  102.     char*        tp;
  103.     char         tc [10];
  104.     int          val;
  105. #endif
  106.  
  107.     /* setup basics of brhist I/O channels */
  108.     Console_IO.disp_width  = 80;
  109.     Console_IO.disp_height = 25;
  110.     brhist.hist_printed_lines = 0;
  111.     Console_IO.Console_fp  = stderr;
  112.     Console_IO.Error_fp    = stderr;
  113.     Console_IO.Report_fp   = stderr;
  114.  
  115.     setvbuf ( Console_IO.Console_fp, Console_IO.Console_buff, _IOFBF, sizeof (Console_IO.Console_buff) );
  116. //  setvbuf ( Console_IO.Error_fp  , NULL                   , _IONBF, 0                                );
  117.  
  118. #if defined(_WIN32)  &&  !defined(__CYGWIN__) 
  119.     Console_IO.Console_Handle = GetStdHandle (STD_ERROR_HANDLE);
  120. #endif
  121.  
  122.     strcpy ( Console_IO.str_up, "\033[A" );
  123.     
  124.     /* some internal checks */
  125.     if ( bitrate_kbps_min > bitrate_kbps_max ) {
  126.     fprintf ( Console_IO.Error_fp, "lame internal error: VBR min %d kbps > VBR max %d kbps.\n", bitrate_kbps_min, bitrate_kbps_max );
  127.     return -1;
  128.     }
  129.     if ( bitrate_kbps_min < 8  ||  bitrate_kbps_max > 320 ) {
  130.     fprintf ( Console_IO.Error_fp, "lame internal error: VBR min %d kbps or VBR max %d kbps out of range.\n", bitrate_kbps_min, bitrate_kbps_max );
  131.     return -1;
  132.     }
  133.  
  134.     /* initialize histogramming data structure */
  135.     lame_bitrate_kbps ( gf, brhist.kbps );
  136.     brhist.vbr_bitrate_min_index = calculate_index ( brhist.kbps, BRHIST_WIDTH, bitrate_kbps_min );
  137.     brhist.vbr_bitrate_max_index = calculate_index ( brhist.kbps, BRHIST_WIDTH, bitrate_kbps_max );
  138.  
  139.     if ( brhist.vbr_bitrate_min_index >= BRHIST_WIDTH  ||  
  140.          brhist.vbr_bitrate_max_index >= BRHIST_WIDTH ) {
  141.     fprintf ( Console_IO.Error_fp, "lame internal error: VBR min %d kbps or VBR max %d kbps not allowed.\n", bitrate_kbps_min, bitrate_kbps_max );
  142.     return -1;
  143.     }
  144.  
  145.     memset (brhist.bar_asterisk, '*', sizeof (brhist.bar_asterisk)-1 );
  146.     memset (brhist.bar_percent , '%', sizeof (brhist.bar_percent) -1 );
  147.  
  148. #ifdef HAVE_TERMCAP
  149.     /* try to catch additional information about special console sequences */
  150.     
  151.     if ((term_name = getenv("TERM")) == NULL) {
  152.     fprintf ( Console_IO.Error_fp, "LAME: Can't get \"TERM\" environment string.\n" );
  153.     return -1;
  154.     }
  155.     if ( tgetent (term_buff, term_name) != 1 ) {
  156.     fprintf ( Console_IO.Error_fp, "LAME: Can't find termcap entry for terminal \"%s\"\n", term_name );
  157.     return -1;
  158.     }
  159.     
  160.     val = tgetnum ("co");
  161.     if ( val >= 40  &&  val <= 512 )
  162.         Console_IO.disp_width   = val;
  163.     val = tgetnum ("li");
  164.     if ( val >= 16  &&  val <= 256 )
  165.         Console_IO.disp_height  = val;
  166.         
  167.     *(tp = tc) = '\0';
  168.     tp = tgetstr ("up", &tp);
  169.     if (tp != NULL)
  170.         strcpy ( Console_IO.str_up, tp );
  171.  
  172.     *(tp = tc) = '\0';
  173.     tp = tgetstr ("ce", &tp);
  174.     if (tp != NULL)
  175.         strcpy ( Console_IO.str_clreoln, tp );
  176.  
  177.     *(tp = tc) = '\0';
  178.     tp = tgetstr ("md", &tp);
  179.     if (tp != NULL)
  180.         strcpy ( Console_IO.str_emph, tp );
  181.  
  182.     *(tp = tc) = '\0';
  183.     tp = tgetstr ("me", &tp);
  184.     if (tp != NULL)
  185.         strcpy ( Console_IO.str_norm, tp );
  186.         
  187. #endif /* HAVE_TERMCAP */
  188.  
  189.     return 0;
  190. }
  191.  
  192. static int  digits ( unsigned number )
  193. {
  194.     int  ret = 1;
  195.     
  196.     if ( number >= 100000000 ) { ret += 8; number /= 100000000; }
  197.     if ( number >=     10000 ) { ret += 4; number /=     10000; }
  198.     if ( number >=       100 ) { ret += 2; number /=       100; }
  199.     if ( number >=        10 ) { ret += 1;                      }
  200.     
  201.     return ret;
  202. }
  203.  
  204.  
  205. static void  brhist_disp_line ( const lame_global_flags*  gf, int i, int br_hist_TOT, int br_hist_LR, int full, int frames )
  206. {
  207.     char    brppt [14];  /* [%] and max. 10 characters for kbps */
  208.     int     barlen_TOT;
  209.     int     barlen_LR;
  210.     int     ppt  = 0;
  211.  
  212.     if ( full != 0 ) {
  213.         // some problems when br_hist_TOT \approx br_hist_LR: You can't see that there are still MS frames
  214.         barlen_TOT = (br_hist_TOT * (Console_IO.disp_width-BRHIST_RES) + full-1 ) / full;  /* round up */
  215.         barlen_LR  = (br_hist_LR  * (Console_IO.disp_width-BRHIST_RES) + full-1 ) / full;  /* round up */
  216.     } else {
  217.         barlen_TOT = barlen_LR = 0;
  218.     }
  219.  
  220.     if (frames > 0)
  221.         ppt = (1000 * br_hist_TOT + frames/2) / frames;                                  /* round nearest */
  222.  
  223.     // bar graph gives a visual indication of percentages.
  224.     // so lets not print perswitched back 
  225.     // mt 11/00
  226. #if 0
  227.     if ( br_hist_TOT == 0 )
  228.         sprintf ( brppt,  " [   ]" );
  229.     else if ( ppt < br_hist_TOT/10000 )
  230.         sprintf ( brppt," [%%..]" );
  231.     else if ( ppt <  10 )
  232.         sprintf ( brppt," [%%.%1u]", ppt );
  233.     else if ( ppt < 995 )
  234.         sprintf ( brppt, " [%2u%%]", (ppt+5)/10 );
  235.     else
  236.         sprintf ( brppt, "[%3u%%]", (ppt+5)/10 );
  237. #else
  238.     sprintf ( brppt, " [%*i]", digits(frames), br_hist_TOT );
  239. #endif
  240.           
  241.     if ( Console_IO.str_clreoln [0] ) /* ClearEndOfLine available */
  242.         fprintf ( Console_IO.Console_fp, "\n%3d%s %.*s%.*s%s", 
  243.               brhist.kbps [i], brppt, 
  244.                   barlen_LR, brhist.bar_percent, 
  245.                   barlen_TOT - barlen_LR, brhist.bar_asterisk, 
  246.           Console_IO.str_clreoln );
  247.     else
  248.         fprintf ( Console_IO.Console_fp, "\n%3d%s %.*s%.*s%*s", 
  249.               brhist.kbps [i], brppt, 
  250.                   barlen_LR, brhist.bar_percent, 
  251.                   barlen_TOT - barlen_LR, brhist.bar_asterisk, 
  252.           Console_IO.disp_width - BRHIST_RES - barlen_TOT, "" );
  253.           
  254.     brhist.hist_printed_lines++;
  255. }
  256.  
  257.  
  258. /* Yes, not very good */
  259. #define LR  0
  260. #define MS  2
  261.  
  262. void  brhist_disp ( const lame_global_flags*  gf )
  263. {
  264.     int   i;
  265.     int   br_hist [BRHIST_WIDTH];       /* how often a frame size was used */
  266.     int   br_sm_hist [BRHIST_WIDTH] [4];/* how often a special frame size/stereo mode commbination was used */
  267.     int   frames;                       /* total number of encoded frames */
  268.     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 */
  269.     
  270.     brhist.hist_printed_lines = 0;  /* printed number of lines for the brhist functionality, used to skip back the right number of lines */
  271.     
  272.     lame_bitrate_hist             ( gf, br_hist    );
  273.     lame_bitrate_stereo_mode_hist ( gf, br_sm_hist );
  274.  
  275.     frames = most_often = 0;
  276.     for (i = 0; i < BRHIST_WIDTH; i++) {
  277.         frames += br_hist[i];
  278.         if (most_often < br_hist[i]) most_often = br_hist[i];
  279.     }
  280.  
  281.     for ( i = 0; i < BRHIST_WIDTH; i++ )
  282.         if ( br_hist [i]  ||  (i >= brhist.vbr_bitrate_min_index  &&  i <= brhist.vbr_bitrate_max_index) )
  283.             brhist_disp_line ( gf, i, br_hist [i], br_sm_hist [i][LR], most_often, frames );
  284.  
  285.     fputs ( "\r", Console_IO.Console_fp );
  286.     fflush ( Console_IO.Console_fp );   /* fflush is ALSO needed for Windows! */
  287. }
  288.  
  289. void brhist_jump_back( void )
  290. {
  291. #if defined(_WIN32)  &&  !defined(__CYGWIN__) 
  292.     if ( GetFileType (Console_IO.Console_Handle) != FILE_TYPE_PIPE ) {
  293.         COORD                       Pos;
  294.         CONSOLE_SCREEN_BUFFER_INFO  CSBI;
  295.     
  296.         GetConsoleScreenBufferInfo ( Console_IO.Console_Handle, &CSBI );
  297.         Pos.Y = CSBI.dwCursorPosition.Y - brhist.hist_printed_lines ;
  298.         Pos.X = 0;
  299.         SetConsoleCursorPosition ( Console_IO.Console_Handle, Pos );
  300.     }
  301. #else
  302.     while ( brhist.hist_printed_lines-- > 0 )
  303.         fputs ( Console_IO.str_up, Console_IO.Console_fp );
  304. #endif
  305. }
  306.  
  307.  
  308. void  brhist_disp_total ( const lame_global_flags* gf )
  309. {
  310.     int i;
  311.     int br_hist [BRHIST_WIDTH];
  312.     int st_mode [4];
  313.     int st_frames = 0;
  314.     int br_frames = 0;
  315.     double sum = 0.;
  316.     
  317.     lame_stereo_mode_hist ( gf, st_mode );
  318.     lame_bitrate_hist     ( gf, br_hist );
  319.     
  320.     for (i = 0; i < BRHIST_WIDTH; i++) {
  321.         br_frames += br_hist[i];
  322.     sum       += br_hist[i] * brhist.kbps[i];
  323.     }
  324.  
  325.     for (i = 0; i < 4; i++) {
  326.         st_frames += st_mode[i];
  327.     }
  328.  
  329.     if (0==br_frames) return;
  330.  
  331.     fprintf ( Console_IO.Console_fp, "\naverage: %5.1f kbps", sum / br_frames);
  332.  
  333.     // I'm very unhappy because this is only printed out in VBR modes
  334.     if (st_frames > 0) {
  335.         if ( st_mode[LR] > 0 )
  336.             fprintf ( Console_IO.Console_fp, "   LR: %d (%#5.4g%%)", st_mode[LR], 100. * st_mode[LR] / st_frames );
  337.         else
  338.             fprintf ( Console_IO.Console_fp, "                 " );
  339.         if ( st_mode[MS] > 0 )
  340.             fprintf ( Console_IO.Console_fp, "   MS: %d (%#5.4g%%)", st_mode[MS], 100. * st_mode[MS] / st_frames );
  341.     }
  342.     fprintf ( Console_IO.Console_fp, "\n" );
  343.     fflush  ( Console_IO.Console_fp );
  344. }
  345.  
  346. /* 
  347.  * 1)
  348.  *
  349.  * Taken from Termcap_Manual.html:
  350.  *
  351.  * With the Unix version of termcap, you must allocate space for the description yourself and pass
  352.  * the address of the space as the argument buffer. There is no way you can tell how much space is
  353.  * needed, so the convention is to allocate a buffer 2048 characters long and assume that is
  354.  * enough.  (Formerly the convention was to allocate 1024 characters and assume that was enough.
  355.  * But one day, for one kind of terminal, that was not enough.)
  356.  */
  357.  
  358. /* end of brhist.c */
  359.