This is the patch I wrote to allow the user to set a target compression ratio (rather 
than a bitrate) for determining the bitrate & stereo mode (regular Stereo vs Joint 
Stereo). I thought this would be useful for batch encoding when the source files are a 
mixture of mono & stereo, &/or of varying sample rates, which would of course be a 
pain in the butt to have to set separately.

So, if we were to use a command line like "lame.exe --compression 5.2 infile.wav 
outfile.mp3", it would (should) encode all stereo 44kHz WAVs at 256kBit/sec, mono 
32kHz WAVs at 96kBit/sec, & stereo 24kHz WAVs at 144kBit/sec, etc, without having to 
change the command line.

Notes-
1- The altered files are lame.c & parse.c. I downloaded v3.70 just a few hours ago & 
retyped everything to that. I noticed there were some slight changes since v3.65 which 
is what I have on my home computer, but I think they're fine. I haven't altered any 
other files, including lame.h & parse.h, so I've probably missed something there.
2- I noticed how the arguments used "gfp->" at the start. I thought it would be best 
to use that for the extra arg, but I've never seen that before. I found the place 
where I *think* they've all been declared, so the variable I needed to use was 
included there. I hope it behaves.
3- Since this changes only "brate" & compression_ratio", I'd expect that 
"--compression floatval" would be freely interchangeable with "-b intval" in setting 
the low bitrate limit for VBR encodings. You could go as far as doing something 
similar for the maximum bitrate (by setting a minimum compression ratio) but I haven't 
done it.
4- I've probably forgotten a semicolon somewhere ;-) amongst other things, since I 
can't compile Lame on my home computer.

Hope it works!

Shawn
-----

Start of patch
ŻŻŻŻŻŻŻŻŻŻŻŻŻŻ


/******************\
Purpose - To parse a new argument allowing the program set a compression ratio (by 
using "--compression floatval")
Function - lame_parse_args()
File - parse.c
\******************/



                if (argUsed>genre_last) { 
                  argUsed=255; 
                  fprintf(stderr,"Unknown genre: %s.  Specifiy genre number \n", 
nextArg);
                }
                argUsed &= 255; c=(char)(argUsed);

                id3tag.used=1; argUsed = 1;
                strncpy(id3tag.genre, &c, 1);
               }
++ /*
++ If the user specifies a compression ratio, it will set the bitrate & stereo mode 
+(unless already specified)
++ Old frontends for Lame will probably set the bitrate ever ime, & this should be 
+able to overrule any bitrates set by them.
++ */
++  else if (!strcmp(token, "lowpass") {
++    argUsed=1;
++    gfp->user_comp_ratio = atof( nextArg); /* to avoid rounding errors */
++
++    if (gfp->user_comp_ratio < 0.01) {
++      fprintf(stderr, "If you specify a compression ratio, it has to be positive. 
+You can also use \"1\" for the maximum bitrate.\n");
++      exit(1)
++    }
++  }

        else if (strcmp(token, "lowpass")==0) {
          argUsed=1;
          gfp->lowpassfreq =  (( 1000.0 * atof( nextArg ) ) + 0.5);
          if (gfp->lowpassfreq  < 1) {
            fprintf(stderr,"Must specify lowpass with --lowpass freq, freq >= 0.001 
kHz\n");
            exit(1);
          }
        }




/******************\
Purpose - To call a function which selects a valid bitrate based on input compression 
ratio.
Function - lame_init_params()
File - lame.c
\******************/



  gfp->mode_gr = (gfp->out_samplerate <= 24000) ? 1 : 2;  /* mode_gr = 2 */
  gfp->encoder_delay = ENCDELAY;
  gfp->framesize = gfp->mode_gr*576;

++  if (gfp->user_comp_ratio > 0.01) CalcBRFromCR(&gf);  /* is this right? */
++  /* If the user specified a compression ratio, it needs to set the bitrate here. if 
+the "-b" switch was used on the command line, it will be ignored. */

--  if (gfp->brate==0) { /* user didn't specify a bitrate, use default */
++  if (gfp->brate==0) { /* User didn't specify a bitrate, nor a compression ratio. 
+Use default. */
    gfp->brate=128;
    if (gfp->mode_gr==1) gfp->brate=64;
  }

  gfp->resample_ratio=1;
  if (gfp->out_samplerate != gfp->in_samplerate) gfp->resample_ratio = 
(FLOAT)gfp->in_samplerate/(FLOAT)gfp->out_samplerate;




/******************\
Purpose - To select a bitrate from the given compression ratio
Function - New function added - "CalcBRFromCR()"
File - lame.c
Notes-
1- Add this entire section somewhere useful within lame.c (probably near the end).
2- By the time we get here, we have a valid input & compression ratio & sample rate. 
This function assumes that. It also assumes that it's okay to change the bitrate.
3- This is the big kahuna for this patch. It's probably not very efficient though. At 
least this only has to happen once per file, however, if Lame is made to encode 
streams in which the sample rate keeps changing, it might be useful to call upon this 
function each time it changes so the compression quality stays about the same 
throughout.
\******************/



void CalcBRFromCR(lame_global_flags *gfp) {
/* Initialise constants & variables */
  const int BRTableSize = 15;
  const int bitrate_table[2][BRTableSize] = {
    {0,8,16,24,32,40,48,56,64,80,96,112,128,144,160}
    {0,32,40,48,56,64,80,96,112,128,160,192,224,256,320}};
  /* I copied that table (above) from the start of "util.c". It should be consistent 
with the table in "util.c".
     (Perhaps that table should be set somewhere as a global constant) */
  float AvailableBitrate = 0.0;
  int ClosestBitrate = 0;
  int UseTableRow = 0;

/* Find out the bitrate needed... */
  float RequestedBitrate = 
gfp->out_samplerate*16&gfp->stereo/(1000.0*gfp->user_comp_ratio);

/* Find out which table row to use... */
  if (gfp->out_samplerate==32000 || gfp->out_samplerate==44100 || 
gfp->out_samplerate==48000)
    UseTableRow = 1;

/* Search through the table to find the bitrate with the closest match... */
  int BRNumber = 1;
  float BRDeviation[2] = {0.0, 0.0};  /* Stores the ratio between the requested & 
available bitrate - first is current, second is previous. */
  for (BRNumber = 1; BRNumber < BRTableSize; BRNumber++) {
    AvailableBitrate = bitrate_table[UseTableRow][BRNumber];
    BRDeviation[1] = BRDeviation [0]  /* Shuffle current to previous to make room for 
next */
    BRDeviation[0] = RequestedBitrate / AvailableBitrate;
    if (RequestedBitrate < AvailableBitrate) break;  /* Break if we've found the 
nearest bitrates. */
    }
  }

/* Decide which valid bitrate is closest to preferred & select it... */
  if (BRDeviation[1] < 0.01)
    /* "Previous" deviation value is unchanged. Lowest bitrate isn't low enough, so 
the lowest bitrate has to do */
    gfp->brate = bitrate_table[UseTableRow][1];

  else if (BRDeviation > 1.00)
    /* We ran out of bitrates - Highest bitrate isn't high enough, so the highest will 
have to do. */
    gfp-brate = bitrate_tabl[UseTableRow][BrTableSize - 1];

  else {
    /* Looped once or more - preferred bitrate is somewhere between lowest & highest 
(usual) */
    if ((BRDeviation[0] * BRDeviation[1] < 1)
      /* Lower bitrate was closer */
      gfp->brate = bitrate_table[UseTableRow][BRNumber - 1];
    else
      /* Higher bitrate was closer */
      gfp->brate = bitrate_table[UseTableRow][BRNumber];

/* Now, having calculated the new bitrate, we should recalculate the compression 
ratio. */
  compression_ratio = gfp->out_samplerate*16*gfp->stereo/(1000.0*gfp->brate);

} /* End of "CalcBRFromCR()"




/******************\
Purpose - To show a message indicating use of the "--compression" switch"
Function - lame_print_config()
File - lame.c
Note - Someone's gonna have to fix this up, 'cause I've never used these "%" 
doohickeys before
\******************/



  if (gfp->resample_ratio!=1) {
    fprintf(stderr,"Resampling:  input=%ikHz  output=%ikHz\n",
            (int)in_samplerate,(int)out_samplerate);
  }
++  if(gfp->user_comp_ratio > 0.01)
++    fprintf(stderr, "Compression ratio of %.1fx requested. Using closest available 
+bitrate & ignoring \"-b\" switch.\n", /* This line could be a bit long... */
++    gfp->user_comp_ratio);
  if (gfp->highpass2>0.0)
    fprintf(stderr, "Using polyphase highpass filter, transition band: %.0f Hz -  %.0f 
Hz\n",
            gfp->highpass1*out_samplerate*500,
            gfp->highpass2*out_samplerate*500);




/******************\
Purpose - To declare this variable we need to hold the compression ratio
Function - lame_init()
File - lame.c
Note - This seems to be dealing with integer values. "user_comp_ratio" has to be a 
float!
\******************/



  gfp->version = 1;   /* =1   Default: MPEG-1 */
  gfp->mode = MPG_MD_JOINT_STEREO;
  gfp->mode_fixed=0;
  gfp->force_ms=0;
  gfp->brate=0;
  gfp->copyright=0;
  gfp->original=1;
  gfp->extension=0;
  gfp->error_protection=0;
  gfp->emphasis=0;
  gfp->in_samplerate=1000*44.1;
  gfp->out_samplerate=0;
  gfp->num_channels=2;
  gfp->num_samples=MAX_U_32_NUM;
++  gfp->user_comp_ratio = 0.0;

  gfp->inPath=NULL;
  gfp->outPath=NULL;
  id3tag.used=0;


____________
End of patch
--
MP3 ENCODER mailing list ( http://geek.rcc.se/mp3encoder/ )

Reply via email to