initial revision
[swftools.git] / lib / lame / lame.c
diff --git a/lib/lame/lame.c b/lib/lame/lame.c
new file mode 100644 (file)
index 0000000..df4fdac
--- /dev/null
@@ -0,0 +1,2239 @@
+/* -*- mode: C; mode: fold -*- */
+/*
+ *     LAME MP3 encoding engine
+ *
+ *     Copyright (c) 1999 Mark Taylor
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/* $Id: lame.c,v 1.1 2002/04/28 17:30:20 kramm Exp $ */
+
+#include "config_static.h"
+
+
+#include <assert.h>
+#include "lame-analysis.h"
+#include "lame.h"
+#include "util.h"
+#include "bitstream.h"
+#include "version.h"
+#include "tables.h"
+#include "quantize_pvt.h"
+#include "VbrTag.h"
+
+#if defined(__FreeBSD__) && !defined(__alpha__)
+#include <floatingpoint.h>
+#endif
+#ifdef __riscos__
+#include "asmstuff.h"
+#endif
+
+#ifdef WITH_DMALLOC
+#include <dmalloc.h>
+#endif
+
+
+static void
+lame_init_params_ppflt_lowpass(FLOAT8 amp_lowpass[32], FLOAT lowpass1,
+                               FLOAT lowpass2, int *lowpass_band,
+                               int *minband, int *maxband)
+{
+    int     band;
+    FLOAT8  freq;
+
+    for (band = 0; band <= 31; band++) {
+        freq = band / 31.0;
+        amp_lowpass[band] = 1;
+        /* this band and above will be zeroed: */
+        if (freq >= lowpass2) {
+            *lowpass_band = Min(*lowpass_band, band);
+            amp_lowpass[band] = 0;
+        }
+        if (lowpass1 < freq && freq < lowpass2) {
+            *minband = Min(*minband, band);
+            *maxband = Max(*maxband, band);
+            amp_lowpass[band] = cos((PI / 2) *
+                                    (lowpass1 - freq) / (lowpass2 - lowpass1));
+        }
+        /*
+         * DEBUGF("lowpass band=%i  amp=%f \n",
+         *      band, gfc->amp_lowpass[band]);
+         */
+    }
+}
+
+/* lame_init_params_ppflt */
+
+/*}}}*/
+/* static void   lame_init_params_ppflt         (lame_internal_flags *gfc)                                                                                        *//*{{{ */
+
+static void
+lame_init_params_ppflt(lame_global_flags * gfp)
+{
+    lame_internal_flags *gfc = gfp->internal_flags;
+  /***************************************************************/
+    /* compute info needed for polyphase filter (filter type==0, default) */
+  /***************************************************************/
+
+    int     band, maxband, minband;
+    FLOAT8  freq;
+
+    if (gfc->lowpass1 > 0) {
+        minband = 999;
+        maxband = -1;
+        lame_init_params_ppflt_lowpass(gfc->amp_lowpass,
+                                       gfc->lowpass1, gfc->lowpass2,
+                                       &gfc->lowpass_band, &minband, &maxband);
+        /* compute the *actual* transition band implemented by
+         * the polyphase filter */
+        if (minband == 999) {
+            gfc->lowpass1 = (gfc->lowpass_band - .75) / 31.0;
+        }
+        else {
+            gfc->lowpass1 = (minband - .75) / 31.0;
+        }
+        gfc->lowpass2 = gfc->lowpass_band / 31.0;
+
+        gfc->lowpass_start_band = minband;
+        gfc->lowpass_end_band = maxband;
+
+        /* as the lowpass may have changed above
+         * calculate the amplification here again
+         */
+        for (band = minband; band <= maxband; band++) {
+            freq = band / 31.0;
+            gfc->amp_lowpass[band] =
+                cos((PI / 2) * (gfc->lowpass1 - freq) /
+                    (gfc->lowpass2 - gfc->lowpass1));
+        }
+    }
+    else {
+        gfc->lowpass_start_band = 0;
+        gfc->lowpass_end_band = -1; /* do not to run into for-loops */
+    }
+
+    /* make sure highpass filter is within 90% of what the effective
+     * highpass frequency will be */
+    if (gfc->highpass2 > 0) {
+        if (gfc->highpass2 < .9 * (.75 / 31.0)) {
+            gfc->highpass1 = 0;
+            gfc->highpass2 = 0;
+            MSGF(gfc, "Warning: highpass filter disabled.  "
+                 "highpass frequency too small\n");
+        }
+    }
+
+    if (gfc->highpass2 > 0) {
+        minband = 999;
+        maxband = -1;
+        for (band = 0; band <= 31; band++) {
+            freq = band / 31.0;
+            gfc->amp_highpass[band] = 1;
+            /* this band and below will be zereod */
+            if (freq <= gfc->highpass1) {
+                gfc->highpass_band = Max(gfc->highpass_band, band);
+                gfc->amp_highpass[band] = 0;
+            }
+            if (gfc->highpass1 < freq && freq < gfc->highpass2) {
+                minband = Min(minband, band);
+                maxband = Max(maxband, band);
+                gfc->amp_highpass[band] =
+                    cos((PI / 2) *
+                        (gfc->highpass2 - freq) /
+                        (gfc->highpass2 - gfc->highpass1));
+            }
+            /*
+               DEBUGF("highpass band=%i  amp=%f \n",
+               band, gfc->amp_highpass[band]);
+             */
+        }
+        /* compute the *actual* transition band implemented by
+         * the polyphase filter */
+        gfc->highpass1 = gfc->highpass_band / 31.0;
+        if (maxband == -1) {
+            gfc->highpass2 = (gfc->highpass_band + .75) / 31.0;
+        }
+        else {
+            gfc->highpass2 = (maxband + .75) / 31.0;
+        }
+
+        gfc->highpass_start_band = minband;
+        gfc->highpass_end_band = maxband;
+
+        /* as the highpass may have changed above
+         * calculate the amplification here again
+         */
+        for (band = minband; band <= maxband; band++) {
+            freq = band / 31.0;
+            gfc->amp_highpass[band] =
+                cos((PI / 2) * (gfc->highpass2 - freq) /
+                    (gfc->highpass2 - gfc->highpass1));
+        }
+    }
+    else {
+        gfc->highpass_start_band = 0;
+        gfc->highpass_end_band = -1; /* do not to run into for-loops */
+    }
+    /*
+       DEBUGF("lowpass band with amp=0:  %i \n",gfc->lowpass_band);
+       DEBUGF("highpass band with amp=0:  %i \n",gfc->highpass_band);
+       DEBUGF("lowpass band start:  %i \n",gfc->lowpass_start_band);
+       DEBUGF("lowpass band end:    %i \n",gfc->lowpass_end_band);
+       DEBUGF("highpass band start:  %i \n",gfc->highpass_start_band);
+       DEBUGF("highpass band end:    %i \n",gfc->highpass_end_band);
+     */
+}
+
+/*}}}*/
+
+
+static void
+optimum_bandwidth(double *const lowerlimit,
+                  double *const upperlimit,
+                  const unsigned bitrate,
+                  const int samplefreq,
+                  const double channels)
+{
+/* 
+ *  Input:
+ *      bitrate     total bitrate in bps
+ *      samplefreq  output sampling frequency in Hz
+ *      channels    1 for mono, 2+epsilon for MS stereo, 3 for LR stereo
+ *                  epsilon is the percentage of LR frames for typical audio
+ *                  (I use 'Fade to Gray' by Metallica)
+ *
+ *   Output:
+ *      lowerlimit: best lowpass frequency limit for input filter in Hz
+ *      upperlimit: best highpass frequency limit for input filter in Hz
+ */
+    double  f_low;
+    double  f_high;
+    double  br;
+
+    assert(bitrate >= 8000 && bitrate <= 320000);
+    assert(samplefreq >= 8000 && samplefreq <= 48000);
+    assert(channels == 1 || (channels >= 2 && channels <= 3));
+
+    if (samplefreq >= 32000)
+        br =
+            bitrate - (channels ==
+                       1 ? (17 + 4) * 8 : (32 + 4) * 8) * samplefreq / 1152;
+    else
+        br =
+            bitrate - (channels ==
+                       1 ? (9 + 4) * 8 : (17 + 4) * 8) * samplefreq / 576;
+
+    if (channels >= 2.)
+        br /= 1.75 + 0.25 * (channels - 2.); // MS needs 1.75x mono, LR needs 2.00x mono (experimental data of a lot of albums)
+
+    br *= 0.5;          // the sine and cosine term must share the bitrate
+
+/* 
+ *  So, now we have the bitrate for every spectral line.
+ *  Let's look at the current settings:
+ *
+ *    Bitrate   limit    bits/line
+ *     8 kbps   0.34 kHz  4.76
+ *    16 kbps   1.9 kHz   2.06
+ *    24 kbps   2.8 kHz   2.21
+ *    32 kbps   3.85 kHz  2.14
+ *    40 kbps   5.1 kHz   2.06
+ *    48 kbps   5.6 kHz   2.21
+ *    56 kbps   7.0 kHz   2.10
+ *    64 kbps   7.7 kHz   2.14
+ *    80 kbps  10.1 kHz   2.08
+ *    96 kbps  11.2 kHz   2.24
+ *   112 kbps  14.0 kHz   2.12
+ *   128 kbps  15.4 kHz   2.17
+ *   160 kbps  18.2 kHz   2.05
+ *   192 kbps  21.1 kHz   2.14
+ *   224 kbps  22.0 kHz   2.41
+ *   256 kbps  22.0 kHz   2.78
+ *
+ *   What can we see?
+ *       Value for 8 kbps is nonsense (although 8 kbps and stereo is nonsense)
+ *       Values are between 2.05 and 2.24 for 16...192 kbps
+ *       Some bitrate lack the following bitrates have: 16, 40, 80, 160 kbps
+ *       A lot of bits per spectral line have: 24, 48, 96 kbps
+ *
+ *   What I propose?
+ *       A slightly with the bitrate increasing bits/line function. It is
+ *       better to decrease NMR for low bitrates to get a little bit more
+ *       bandwidth. So we have a better trade off between twickling and
+ *       muffled sound.
+ */
+
+    f_low = br / log10(br * 4.425e-3); // Tests with 8, 16, 32, 64, 112 and 160 kbps
+/*
+GB 04/04/01
+sfb21 is a huge bitrate consumer in vbr with the new ath.
+Need to reduce the lowpass to more reasonable values. This extra lowpass
+won't reduce quality over 3.87 as the previous ath was doing this lowpass
+*/
+/*GB 22/05/01
+I'm also extending this to CBR as tests showed that a
+limited bandwidth is increasing quality
+*/
+    if (f_low>18400)
+           f_low = 18400+(f_low-18400)/4;
+
+/*
+ *  What we get now?
+ *
+ *    Bitrate       limit  bits/line   difference
+ *     8 kbps (8)  1.89 kHz  0.86          +1.6 kHz
+ *    16 kbps (8)  3.16 kHz  1.24          +1.2 kHz
+ *    32 kbps(16)  5.08 kHz  1.54          +1.2 kHz
+ *    56 kbps(22)  7.88 kHz  1.80          +0.9 kHz
+ *    64 kbps(22)  8.83 kHz  1.86          +1.1 kHz
+ *   112 kbps(32) 14.02 kHz  2.12           0.0 kHz
+ *   112 kbps(44) 13.70 kHz  2.11          -0.3 kHz
+ *   128 kbps     15.40 kHz  2.17           0.0 kHz
+ *   160 kbps     16.80 kHz  2.22          -1.4 kHz 
+ *   192 kbps     19.66 kHz  2.30          -1.4 kHz
+ *   256 kbps     22.05 kHz  2.78           0.0 kHz
+ */
+
+
+/*
+ *  Now we try to choose a good high pass filtering frequency.
+ *  This value is currently not used.
+ *    For fu < 16 kHz:  sqrt(fu*fl) = 560 Hz
+ *    For fu = 18 kHz:  no high pass filtering
+ *  This gives:
+ *
+ *   2 kHz => 160 Hz
+ *   3 kHz => 107 Hz
+ *   4 kHz =>  80 Hz
+ *   8 kHz =>  40 Hz
+ *  16 kHz =>  20 Hz
+ *  17 kHz =>  10 Hz
+ *  18 kHz =>   0 Hz
+ *
+ *  These are ad hoc values and these can be optimized if a high pass is available.
+ */
+    if (f_low <= 16000)
+        f_high = 16000. * 20. / f_low;
+    else if (f_low <= 18000)
+        f_high = 180. - 0.01 * f_low;
+    else
+        f_high = 0.;
+
+    /*  
+     *  When we sometimes have a good highpass filter, we can add the highpass
+     *  frequency to the lowpass frequency
+     */
+
+    if (lowerlimit != NULL)
+        *lowerlimit = (f_low>0.5 * samplefreq ? 0.5 * samplefreq : f_low); // roel - fixes mono "-b320 -a"
+    if (upperlimit != NULL)
+        *upperlimit = f_high;
+/*
+ * Now the weak points:
+ *
+ *   - the formula f_low=br/log10(br*4.425e-3) is an ad hoc formula
+ *     (but has a physical background and is easy to tune)
+ *   - the switch to the ATH based bandwidth selecting is the ad hoc
+ *     value of 128 kbps
+ */
+}
+
+static int
+optimum_samplefreq(int lowpassfreq, int input_samplefreq)
+{
+/*
+ * Rules:
+ *
+ *  - output sample frequency should NOT be decreased by more than 3% if lowpass allows this
+ *  - if possible, sfb21 should NOT be used
+ *
+ *  Problem: Switches to 32 kHz at 112 kbps
+ */
+    if (input_samplefreq <= 8000 * 1.03 || lowpassfreq <= 3622)
+        return 8000;
+    if (input_samplefreq <= 11025 * 1.03 || lowpassfreq <= 4991)
+        return 11025;
+    if (input_samplefreq <= 12000 * 1.03 || lowpassfreq <= 5620)
+        return 12000;
+    if (input_samplefreq <= 16000 * 1.03 || lowpassfreq <= 7244)
+        return 16000;
+    if (input_samplefreq <= 22050 * 1.03 || lowpassfreq <= 9982)
+        return 22050;
+    if (input_samplefreq <= 24000 * 1.03 || lowpassfreq <= 11240)
+        return 24000;
+    if (input_samplefreq <= 32000 * 1.03 || lowpassfreq <= 15264)
+        return 32000;
+    if (input_samplefreq <= 44100 * 1.03)
+        return 44100;
+    return 48000;
+}
+
+
+/* set internal feature flags.  USER should not access these since
+ * some combinations will produce strange results */
+void
+lame_init_qval(lame_global_flags * gfp)
+{
+    lame_internal_flags *gfc = gfp->internal_flags;
+
+    switch (gfp->quality) {
+    case 9:            /* no psymodel, no noise shaping */
+        gfc->filter_type = 0;
+        gfc->psymodel = 0;
+        gfc->quantization = 0;
+        gfc->noise_shaping = 0;
+        gfc->noise_shaping_amp = 0;
+        gfc->noise_shaping_stop = 0;
+        gfc->use_best_huffman = 0;
+        break;
+
+    case 8:
+        gfp->quality = 7;
+    case 7:            /* use psymodel (for short block and m/s switching), but no noise shapping */
+        gfc->filter_type = 0;
+        gfc->psymodel = 1;
+        gfc->quantization = 0;
+        gfc->noise_shaping = 0;
+        gfc->noise_shaping_amp = 0;
+        gfc->noise_shaping_stop = 0;
+        gfc->use_best_huffman = 0;
+        break;
+
+    case 6:
+        gfp->quality = 5;
+    case 5:            /* the default */
+        gfc->filter_type = 0;
+        gfc->psymodel = 1;
+        gfc->quantization = 0;
+        gfc->noise_shaping = 1;
+         /**/ gfc->noise_shaping_amp = 0;
+        gfc->noise_shaping_stop = 0;
+        gfc->use_best_huffman = 0;
+        break;
+
+    case 4:
+        gfp->quality = 3;
+    case 3:
+        gfc->filter_type = 0;
+        gfc->psymodel = 1;
+        gfc->quantization = 1;
+        gfc->noise_shaping = 1;
+        gfc->noise_shaping_amp = 0;
+        gfc->noise_shaping_stop = 0;
+        gfc->use_best_huffman = 1;
+        break;
+
+    case 2:
+        gfc->filter_type = 0;
+        gfc->psymodel = 1;
+        gfc->quantization = 1;
+        gfc->noise_shaping = 1;
+        gfc->noise_shaping_amp = 1;
+        gfc->noise_shaping_stop = 1;
+        gfc->use_best_huffman = 1;
+        break;
+
+    case 1:
+        gfc->filter_type = 0;
+        gfc->psymodel = 1;
+        gfc->quantization = 1;
+        gfc->noise_shaping = 1;
+        gfc->noise_shaping_amp = 2;
+        gfc->noise_shaping_stop = 1;
+        gfc->use_best_huffman = 1;
+        break;
+
+    case 0:            /* 0..1 quality */
+        gfc->filter_type = 0; /* 1 not yet coded */
+        gfc->psymodel = 1;
+        gfc->quantization = 1;
+        gfc->noise_shaping = 1; /* 2=usually lowers quality */
+        gfc->noise_shaping_amp = 3;
+        gfc->noise_shaping_stop = 1;
+        gfc->use_best_huffman = 1; /* 2 not yet coded */
+    }
+
+    /* modifications to the above rules: */
+
+    /* -Z option toggles scalefactor_scale: */
+    if ( (gfp->experimentalZ & 1) > 0) {
+        gfc->noise_shaping = 2;
+    }
+}
+
+
+
+
+
+
+
+/* int           lame_init_params               (lame_global_flags *gfp)                                                                                          *//*{{{ */
+
+/********************************************************************
+ *   initialize internal params based on data in gf
+ *   (globalflags struct filled in by calling program)
+ *
+ *  OUTLINE:
+ *
+ * We first have some complex code to determine bitrate, 
+ * output samplerate and mode.  It is complicated by the fact
+ * that we allow the user to set some or all of these parameters,
+ * and need to determine best possible values for the rest of them:
+ *
+ *  1. set some CPU related flags
+ *  2. check if we are mono->mono, stereo->mono or stereo->stereo
+ *  3.  compute bitrate and output samplerate:
+ *          user may have set compression ratio
+ *          user may have set a bitrate  
+ *          user may have set a output samplerate
+ *  4. set some options which depend on output samplerate
+ *  5. compute the actual compression ratio
+ *  6. set mode based on compression ratio
+ *
+ *  The remaining code is much simpler - it just sets options
+ *  based on the mode & compression ratio: 
+ *   
+ *   set allow_diff_short based on mode
+ *   select lowpass filter based on compression ratio & mode
+ *   set the bitrate index, and min/max bitrates for VBR modes
+ *   disable VBR tag if it is not appropriate
+ *   initialize the bitstream
+ *   initialize scalefac_band data
+ *   set sideinfo_len (based on channels, CRC, out_samplerate)
+ *   write an id3v2 tag into the bitstream
+ *   write VBR tag into the bitstream
+ *   set mpeg1/2 flag
+ *   estimate the number of frames (based on a lot of data)
+ *         
+ *   now we set more flags:
+ *   nspsytune:
+ *      see code
+ *   VBR modes
+ *      see code      
+ *   CBR/ABR
+ *      see code   
+ *
+ *  Finally, we set the algorithm flags based on the gfp->quality value
+ *  lame_init_qval(gfp);
+ *
+ ********************************************************************/
+int
+lame_init_params(lame_global_flags * const gfp)
+{
+
+    int     i;
+    int     j;
+    lame_internal_flags *gfc = gfp->internal_flags;
+
+    gfc->gfp = gfp;
+
+    gfc->Class_ID = 0;
+
+    /* report functions */
+    gfc->report.msgf   = gfp->report.msgf;
+    gfc->report.debugf = gfp->report.debugf;
+    gfc->report.errorf = gfp->report.errorf;
+
+    gfc->CPU_features.i387 = has_i387();
+    gfc->CPU_features.AMD_3DNow = has_3DNow();
+    gfc->CPU_features.MMX = has_MMX();
+    gfc->CPU_features.SIMD = has_SIMD();
+    gfc->CPU_features.SIMD2 = has_SIMD2();
+
+
+    if (NULL == gfc->ATH)
+        gfc->ATH = calloc(1, sizeof(ATH_t));
+
+    if (NULL == gfc->ATH)
+        return -2;  // maybe error codes should be enumerated in lame.h ??
+
+    if (NULL == gfc->VBR)
+        gfc->VBR = calloc(1, sizeof(VBR_t));
+    if (NULL == gfc->VBR)
+        return -2;
+        
+    if (NULL == gfc->PSY)
+        gfc->PSY = calloc(1, sizeof(PSY_t));
+    if (NULL == gfc->PSY)
+        return -2;
+        
+#ifdef KLEMM_44
+    /* Select the fastest functions for this CPU */
+    init_scalar_functions(gfc);
+#endif
+
+    gfc->channels_in = gfp->num_channels;
+    if (gfc->channels_in == 1)
+        gfp->mode = MONO;
+    gfc->channels_out = (gfp->mode == MONO) ? 1 : 2;
+    gfc->mode_ext = MPG_MD_LR_LR;
+    if (gfp->mode == MONO)
+        gfp->force_ms = 0; // don't allow forced mid/side stereo for mono output
+
+
+    if (gfp->VBR != vbr_off) {
+        gfp->free_format = 0; /* VBR can't be mixed with free format */
+    }
+
+    if (gfp->VBR == vbr_off && gfp->brate == 0) {
+        /* no bitrate or compression ratio specified, use a compression ratio of 11.025 */
+        if (gfp->compression_ratio == 0)
+            gfp->compression_ratio = 11.025; /* rate to compress a CD down to exactly 128000 bps */
+    }
+
+
+    if (gfp->VBR == vbr_off && gfp->brate == 0) {
+        /* no bitrate or compression ratio specified, use 11.025 */
+        if (gfp->compression_ratio == 0)
+            gfp->compression_ratio = 11.025; /* rate to compress a CD down to exactly 128000 bps */
+    }
+
+    /* find bitrate if user specify a compression ratio */
+    if (gfp->VBR == vbr_off && gfp->compression_ratio > 0) {
+
+        if (gfp->out_samplerate == 0)
+            gfp->out_samplerate = map2MP3Frequency( (int)( 0.97 * gfp->in_samplerate ) ); /* round up with a margin of 3% */
+
+        /* choose a bitrate for the output samplerate which achieves
+         * specified compression ratio 
+         */
+        gfp->brate =
+            gfp->out_samplerate * 16 * gfc->channels_out / (1.e3 *
+                                                            gfp->
+                                                            compression_ratio);
+
+        /* we need the version for the bitrate table look up */
+        gfc->samplerate_index = SmpFrqIndex(gfp->out_samplerate, &gfp->version);
+
+        if (!gfp->free_format) /* for non Free Format find the nearest allowed bitrate */
+            gfp->brate =
+                FindNearestBitrate(gfp->brate, gfp->version,
+                                   gfp->out_samplerate);
+    }
+
+    if (gfp->VBR != vbr_off && gfp->brate >= 320)
+        gfp->VBR = vbr_off; /* at 160 kbps (MPEG-2/2.5)/ 320 kbps (MPEG-1) only Free format or CBR are possible, no VBR */
+
+
+    if (gfp->out_samplerate == 0) { /* if output sample frequency is not given, find an useful value */
+        gfp->out_samplerate = map2MP3Frequency( (int)( 0.97 * gfp->in_samplerate ) );
+
+
+        /* check if user specified bitrate requires downsampling, if compression    */
+        /* ratio is > 13, choose a new samplerate to get the ratio down to about 10 */
+
+        if (gfp->VBR == vbr_off && gfp->brate > 0) {
+            gfp->compression_ratio =
+                gfp->out_samplerate * 16 * gfc->channels_out / (1.e3 *
+                                                                gfp->brate);
+            if (gfp->compression_ratio > 13.)
+                gfp->out_samplerate =
+                    map2MP3Frequency( (int)( (10. * 1.e3 * gfp->brate) /
+                                     (16 * gfc->channels_out)));
+        }
+        if (gfp->VBR == vbr_abr) {
+            gfp->compression_ratio =
+                gfp->out_samplerate * 16 * gfc->channels_out / (1.e3 *
+                                                                gfp->
+                                                                VBR_mean_bitrate_kbps);
+            if (gfp->compression_ratio > 13.)
+                gfp->out_samplerate =
+                    map2MP3Frequency((int)((10. * 1.e3 * gfp->VBR_mean_bitrate_kbps) /
+                                     (16 * gfc->channels_out)));
+        }
+    }
+
+    if (gfp->ogg) {
+        gfp->framesize = 1024;
+        gfp->encoder_delay = ENCDELAY;
+        gfc->coding = coding_Ogg_Vorbis;
+    }
+    else {
+        gfc->mode_gr = gfp->out_samplerate <= 24000 ? 1 : 2; // Number of granules per frame
+        gfp->framesize = 576 * gfc->mode_gr;
+        gfp->encoder_delay = ENCDELAY;
+        gfc->coding = coding_MPEG_Layer_3;
+    }
+
+    gfc->frame_size = gfp->framesize;
+
+    gfc->resample_ratio = (double) gfp->in_samplerate / gfp->out_samplerate;
+
+    /* 
+     *  sample freq       bitrate     compression ratio
+     *     [kHz]      [kbps/channel]   for 16 bit input
+     *     44.1            56               12.6
+     *     44.1            64               11.025
+     *     44.1            80                8.82
+     *     22.05           24               14.7
+     *     22.05           32               11.025
+     *     22.05           40                8.82
+     *     16              16               16.0
+     *     16              24               10.667
+     *
+     */
+    /* 
+     *  For VBR, take a guess at the compression_ratio. 
+     *  For example:
+     *
+     *    VBR_q    compression     like
+     *     -        4.4         320 kbps/44 kHz
+     *   0...1      5.5         256 kbps/44 kHz
+     *     2        7.3         192 kbps/44 kHz
+     *     4        8.8         160 kbps/44 kHz
+     *     6       11           128 kbps/44 kHz
+     *     9       14.7          96 kbps
+     *
+     *  for lower bitrates, downsample with --resample
+     */
+
+    switch (gfp->VBR) {
+    case vbr_mt:
+    case vbr_rh:
+    case vbr_mtrh:
+        {
+            FLOAT8  cmp[] = { 5.7, 6.5, 7.3, 8.2, 9.1, 10, 11, 12, 13, 14 };
+            gfp->compression_ratio = cmp[gfp->VBR_q];
+        }
+        break;
+    case vbr_abr:
+        gfp->compression_ratio =
+            gfp->out_samplerate * 16 * gfc->channels_out / (1.e3 *
+                                                            gfp->
+                                                            VBR_mean_bitrate_kbps);
+        break;
+    default:
+        gfp->compression_ratio =
+            gfp->out_samplerate * 16 * gfc->channels_out / (1.e3 * gfp->brate);
+        break;
+    }
+
+
+    /* mode = -1 (not set by user) or 
+     * mode = MONO (because of only 1 input channel).  
+     * If mode has been set, then select between STEREO or J-STEREO
+     * At higher quality (lower compression) use STEREO instead of J-STEREO.
+     * (unless the user explicitly specified a mode)
+     *
+     * The threshold to switch to STEREO is:
+     *    48 kHz:   171 kbps (used at 192+)
+     *    44.1 kHz: 160 kbps (used at 160+)
+     *    32 kHz:   119 kbps (used at 128+)
+     *
+     *   Note, that for 32 kHz/128 kbps J-STEREO FM recordings sound much
+     *   better than STEREO, so I'm not so very happy with that. 
+     *   fs < 32 kHz I have not tested.
+     */
+    if (gfp->mode == NOT_SET) {
+        if (gfp->compression_ratio < 8)
+            gfp->mode = STEREO;
+        else
+            gfp->mode = JOINT_STEREO;
+    }
+
+    /* KLEMM's jstereo with ms threshold adjusted via compression ratio */
+    if (gfp->mode_automs) {
+        if (gfp->mode != MONO && gfp->compression_ratio < 6.6)
+            gfp->mode = STEREO;
+    }
+
+
+
+
+
+
+  /****************************************************************/
+  /* if a filter has not been enabled, see if we should add one: */
+  /****************************************************************/
+    if (gfp->lowpassfreq == 0) {
+        double  lowpass;
+        double  highpass;
+        double  channels;
+
+        switch (gfp->mode) {
+        case MONO:
+            channels = 1.;
+            break;
+        case JOINT_STEREO:
+            channels = 2. + 0.00;
+            break;
+        case DUAL_CHANNEL:
+        case STEREO:
+            channels = 3.;
+            break;
+        default:    
+            channels = 1.;  // just to make data flow analysis happy :-)
+            assert(0);
+            break;
+        }
+
+        optimum_bandwidth(&lowpass,
+                          &highpass,
+                          gfp->out_samplerate * 16 * gfc->channels_out /
+                          gfp->compression_ratio, gfp->out_samplerate, channels);
+                       
+/*  roel - is this still needed?
+               if (lowpass > 0.5 * gfp->out_samplerate) {
+            //MSGF(gfc,"Lowpass @ %7.1f Hz\n", lowpass);
+            gfc->lowpass1 = gfc->lowpass2 =
+                lowpass / (0.5 * gfp->out_samplerate);
+        }
+*/
+        gfp->lowpassfreq = lowpass;
+
+#if 0
+        if (gfp->out_samplerate !=
+            optimum_samplefreq(lowpass, gfp->in_samplerate)) {
+            MSGF(gfc,
+                 "I would suggest to use %u Hz instead of %u Hz sample frequency\n",
+                 optimum_samplefreq(lowpass, gfp->in_samplerate),
+                 gfp->out_samplerate);
+        }
+        fflush(stderr);
+#endif
+    }
+
+    /* apply user driven high pass filter */
+    if (gfp->highpassfreq > 0) {
+        gfc->highpass1 = 2. * gfp->highpassfreq / gfp->out_samplerate; /* will always be >=0 */
+        if (gfp->highpasswidth >= 0)
+            gfc->highpass2 =
+                2. * (gfp->highpassfreq +
+                      gfp->highpasswidth) / gfp->out_samplerate;
+        else            /* 0% above on default */
+            gfc->highpass2 =
+                (1 + 0.00) * 2. * gfp->highpassfreq / gfp->out_samplerate;
+    }
+
+    /* apply user driven low pass filter */
+    if (gfp->lowpassfreq > 0) {
+        gfc->lowpass2 = 2. * gfp->lowpassfreq / gfp->out_samplerate; /* will always be >=0 */
+        if (gfp->lowpasswidth >= 0) {
+            gfc->lowpass1 =
+                2. * (gfp->lowpassfreq -
+                      gfp->lowpasswidth) / gfp->out_samplerate;
+            if (gfc->lowpass1 < 0) /* has to be >= 0 */
+                gfc->lowpass1 = 0;
+        }
+        else {          /* 0% below on default */
+            gfc->lowpass1 =
+                (1 - 0.00) * 2. * gfp->lowpassfreq / gfp->out_samplerate;
+        }
+    }
+
+
+
+
+  /**********************************************************************/
+  /* compute info needed for polyphase filter (filter type==0, default) */
+  /**********************************************************************/
+    lame_init_params_ppflt(gfp);
+
+
+  /*******************************************************/
+  /* compute info needed for FIR filter (filter_type==1) */
+  /*******************************************************/
+   /* not yet coded */
+
+
+
+  /*******************************************************
+   * samplerate and bitrate index
+   *******************************************************/
+    gfc->samplerate_index = SmpFrqIndex(gfp->out_samplerate, &gfp->version);
+    if (gfc->samplerate_index < 0)
+        return -1;
+
+    if (gfp->VBR == vbr_off) {
+        if (gfp->free_format) {
+            gfc->bitrate_index = 0;
+        }
+        else {
+            gfc->bitrate_index = BitrateIndex(gfp->brate, gfp->version,
+                                              gfp->out_samplerate);
+            if (gfc->bitrate_index < 0)
+                return -1;
+        }
+    }
+    else {              /* choose a min/max bitrate for VBR */
+        /* if the user didn't specify VBR_max_bitrate: */
+        gfc->VBR_min_bitrate = 1; /* default: allow   8 kbps (MPEG-2) or  32 kbps (MPEG-1) */
+        gfc->VBR_max_bitrate = 14; /* default: allow 160 kbps (MPEG-2) or 320 kbps (MPEG-1) */
+
+        if (gfp->VBR_min_bitrate_kbps)
+            if (
+                (gfc->VBR_min_bitrate =
+                 BitrateIndex(gfp->VBR_min_bitrate_kbps, gfp->version,
+                              gfp->out_samplerate)) < 0) return -1;
+        if (gfp->VBR_max_bitrate_kbps)
+            if (
+                (gfc->VBR_max_bitrate =
+                 BitrateIndex(gfp->VBR_max_bitrate_kbps, gfp->version,
+                              gfp->out_samplerate)) < 0) return -1;
+
+        gfp->VBR_min_bitrate_kbps =
+            bitrate_table[gfp->version][gfc->VBR_min_bitrate];
+        gfp->VBR_max_bitrate_kbps =
+            bitrate_table[gfp->version][gfc->VBR_max_bitrate];
+
+        gfp->VBR_mean_bitrate_kbps =
+            Min(bitrate_table[gfp->version][gfc->VBR_max_bitrate],
+                gfp->VBR_mean_bitrate_kbps);
+        gfp->VBR_mean_bitrate_kbps =
+            Max(bitrate_table[gfp->version][gfc->VBR_min_bitrate],
+                gfp->VBR_mean_bitrate_kbps);
+
+
+    }
+
+    /* for CBR, we will write an "info" tag. */
+    //    if ((gfp->VBR == vbr_off)) 
+    //  gfp->bWriteVbrTag = 0;
+
+    if (gfp->ogg)
+        gfp->bWriteVbrTag = 0;
+#if defined(HAVE_GTK)
+    if (gfp->analysis)
+        gfp->bWriteVbrTag = 0;
+#endif
+
+    /* some file options not allowed if output is: not specified or stdout */
+    if (gfc->pinfo != NULL)
+        gfp->bWriteVbrTag = 0; /* disable Xing VBR tag */
+
+    init_bit_stream_w(gfc);
+
+    j =
+        gfc->samplerate_index + (3 * gfp->version) + 6 * (gfp->out_samplerate <
+                                                          16000);
+    for (i = 0; i < SBMAX_l + 1; i++)
+        gfc->scalefac_band.l[i] = sfBandIndex[j].l[i];
+    for (i = 0; i < SBMAX_s + 1; i++)
+        gfc->scalefac_band.s[i] = sfBandIndex[j].s[i];
+
+    /* determine the mean bitrate for main data */
+    if (gfp->version == 1) /* MPEG 1 */
+        gfc->sideinfo_len = (gfc->channels_out == 1) ? 4 + 17 : 4 + 32;
+    else                /* MPEG 2 */
+        gfc->sideinfo_len = (gfc->channels_out == 1) ? 4 + 9 : 4 + 17;
+
+    if (gfp->error_protection)
+        gfc->sideinfo_len += 2;
+
+    lame_init_bitstream(gfp);
+
+
+    if (gfp->version == 1) /* 0 indicates use lower sample freqs algorithm */
+        gfc->is_mpeg1 = 1; /* yes */
+    else
+        gfc->is_mpeg1 = 0; /* no */
+
+    gfc->Class_ID = LAME_ID;
+
+
+    if (gfp->exp_nspsytune & 1) {
+        int     i,j;
+
+        gfc->nsPsy.use = 1;
+        gfc->nsPsy.safejoint = (gfp->exp_nspsytune & 2) != 0;
+        for (i = 0; i < 19; i++)
+            gfc->nsPsy.pefirbuf[i] = 700;
+
+        if (gfp->ATHtype == -1)
+            gfp->ATHtype = 4;
+
+        gfc->nsPsy.bass = gfc->nsPsy.alto = gfc->nsPsy.treble = 0;
+
+        i = (gfp->exp_nspsytune >> 2) & 63;
+        if (i >= 32)
+            i -= 64;
+        gfc->nsPsy.bass = pow(10, i / 4.0 / 10.0);
+        i = (gfp->exp_nspsytune >> 8) & 63;
+        if (i >= 32)
+            i -= 64;
+        gfc->nsPsy.alto = pow(10, i / 4.0 / 10.0);
+        i = (gfp->exp_nspsytune >> 14) & 63;
+        if (i >= 32)
+            i -= 64;
+        gfc->nsPsy.treble = pow(10, i / 4.0 / 10.0);
+        /*  to be compatible with Naoki's original code, the next 6 bits
+         *  define only the amount of changing treble for sfb21 */
+        j = (gfp->exp_nspsytune >> 20) & 63;
+        if (j >= 32)
+            j -= 64;
+        gfc->nsPsy.sfb21 = pow(10, (i+j) / 4.0 / 10.0);
+    }
+
+    assert( gfp->VBR_q <= 9 );
+    assert( gfp->VBR_q >= 0 );
+    
+    gfc->PSY->tonalityPatch = 0;
+  
+    switch (gfp->VBR) {
+
+    case vbr_mt:
+        gfp->VBR = vbr_mtrh;
+        
+    case vbr_mtrh:
+
+        if (gfp->ATHtype < 0) gfp->ATHtype = 4;
+        if (gfp->quality < 0) gfp->quality = 2;
+        if (gfp->quality > 7) {
+            gfp->quality = 7;     // needs psymodel
+            ERRORF( gfc, "VBR needs a psymodel, switching to quality level 7\n");
+        }
+
+        /*  tonality
+         */
+        if (gfp->cwlimit <= 0) gfp->cwlimit = 0.42 * gfp->out_samplerate;
+        gfc->PSY->tonalityPatch = 1;
+
+        if ( gfp->experimentalX <= 4 && gfp->experimentalX >= 0 )
+        {   /* map experimentalX settings to internal secltions */
+            static char const map[] = {2,1,0,3,6};
+            gfc->VBR->quality = map[gfp->experimentalX];
+        }
+        else    /* defaulting to */
+        {
+            gfc->VBR->quality = 2;
+        }   
+        if ( gfc->VBR->quality > 5 ) {
+            static float const dbQ[10] = { -6,-4.75,-3.5,-2.25,-1,.25,1.5,2.75,4,5.25 };
+            gfc->VBR->mask_adjust = dbQ[gfp->VBR_q];
+            gfc->VBR->smooth = 1;   // not finally
+        }
+        else {
+            static const float dbQ[10]={-2.,-1.0,-.66,-.33,0.,0.33,.66,1.0,1.33,1.66};
+            gfc->VBR->mask_adjust = dbQ[gfp->VBR_q];
+            gfc->VBR->smooth = 1;
+        }
+        if ( gfc->VBR->quality == 1 ) {
+            static float const dbQ[10] = { -2., -1.4, -.7, 0, .7, 1.5, 2.3, 3.1, 4., 5 };
+            gfc->VBR->mask_adjust = dbQ[gfp->VBR_q];
+            gfc->VBR->smooth = 0;    
+        }
+        if ( gfc->VBR->quality == 0 ) {
+            static float const dbQ[10] = { -1., -.6, -.3, 0, 1, 2, 3, 4, 5, 6};
+            gfc->VBR->mask_adjust = dbQ[gfp->VBR_q];
+            gfc->VBR->smooth = 0;    
+            gfc->PSY->tonalityPatch = 0;
+        }
+        
+        gfc->VBR->bitpressure = 1;
+        
+        if (gfp->experimentalY)
+            gfc->sfb21_extra = 0;
+        else
+            gfc->sfb21_extra = (gfp->out_samplerate > 44000);
+        
+        if ( gfp->athaa_type < 0 )
+            gfc->ATH->use_adjust = 3;
+        else
+            gfc->ATH->use_adjust = gfp->athaa_type;
+        
+        break;
+        
+
+    case vbr_rh:
+
+        if (gfp->VBR == vbr_rh) /* because of above fall thru */
+        {   static const FLOAT8 dbQ[10]={-2.,-1.0,-.66,-.33,0.,0.33,.66,1.0,1.33,1.66};
+            static const FLOAT8 dbQns[10]={- 4,- 3,-2,-1,0,0.7,1.4,2.1,2.8,3.5};
+            /*static const FLOAT8 atQns[10]={-16,-12,-8,-4,0,  1,  2,  3,  4,  5};*/
+            if ( gfc->nsPsy.use )
+                gfc->VBR->mask_adjust = dbQns[gfp->VBR_q];
+            else {
+                gfc->PSY->tonalityPatch = 1;
+                gfc->VBR->mask_adjust = dbQ[gfp->VBR_q]; 
+            }
+        }
+        gfc->VBR->bitpressure = 1;
+        
+        /*  use Gabriel's adaptative ATH shape for VBR by default
+         */
+        if (gfp->ATHtype == -1)
+            gfp->ATHtype = 4;
+
+        /*  automatic ATH adjustment on, VBR modes need it
+         */
+        if ( gfp->athaa_type < 0 )
+            gfc->ATH->use_adjust = 3;
+        else
+            gfc->ATH->use_adjust = gfp->athaa_type;
+
+        /*  sfb21 extra only with MPEG-1 at higher sampling rates
+         */
+        if ( gfp->experimentalY )
+            gfc->sfb21_extra = 0;
+        else 
+            gfc->sfb21_extra = (gfp->out_samplerate > 44000);
+
+        /*  VBR needs at least the output of GPSYCHO,
+         *  so we have to garantee that by setting a minimum 
+         *  quality level, actually level 5 does it.
+         *  the -v and -V x settings switch the quality to level 2
+         *  you would have to add a -q 5 to reduce the quality
+         *  down to level 5
+         */
+        if (gfp->quality > 5)
+            gfp->quality = 5;
+
+
+        /*  default quality setting is 2
+         */
+        if (gfp->quality < 0)
+            gfp->quality = 2;
+
+        break;
+
+    default:
+
+        if (gfp->ATHtype == -1)
+            gfp->ATHtype = 2;
+
+        /*  automatic ATH adjustment off by default
+         *  not so important for CBR code?
+         */
+        if ( gfp->athaa_type < 0 )
+            gfc->ATH->use_adjust = 0;
+        else
+            gfc->ATH->use_adjust = gfp->athaa_type;
+
+
+        /*  no sfb21 extra with CBR code
+         */
+        gfc->sfb21_extra = 0;
+
+        /*  default quality setting for CBR/ABR is 5
+         */
+        if (gfp->quality < 0)
+            gfp->quality = 5;
+
+        break;
+    }
+    /*  just another daily changing developer switch  */
+    if ( gfp->tune ) gfc->VBR->mask_adjust = gfp->tune_value_a;
+
+    /* initialize internal qval settings */
+    lame_init_qval(gfp);
+
+#ifdef KLEMM_44
+    gfc->mfbuf[0] = (sample_t *) calloc(sizeof(sample_t), MFSIZE);
+    gfc->mfbuf[1] = (sample_t *) calloc(sizeof(sample_t), MFSIZE);
+    gfc->sampfreq_in = unround_samplefrequency(gfp->in_samplerate);
+    gfc->sampfreq_out = gfp->out_samplerate;
+    gfc->resample_in = resample_open(gfc->sampfreq_in,
+                                     gfc->sampfreq_out, -1.0 /* Auto */, 32);
+#endif
+
+    /* initialize internal adaptive ATH settings  -jd */
+    gfc->athaa_sensitivity_p = pow( 10.0, gfp->athaa_sensitivity / -10.0 );
+
+
+    gfc->PSY->cwlimit = gfp->cwlimit <= 0 ? 8871.7f : gfp->cwlimit;
+    
+    if (gfp->short_blocks == short_block_not_set) {
+        gfp->short_blocks =  short_block_allowed;
+    }
+    if (gfp->short_blocks == short_block_allowed && gfp->mode == JOINT_STEREO) {
+        gfp->short_blocks =  short_block_coupled;
+    }    
+    
+    if ( gfp->athaa_loudapprox < 0 ) gfp->athaa_loudapprox = 2;
+    
+    if (gfp->useTemporal < 0 ) gfp->useTemporal = 1;  // on by default
+
+
+    if ( gfp->experimentalY )
+        MSGF(gfc,"\n *** WARNING *** the meaning of the experimental -Y has changed!\n"
+                   "                 now it tells LAME to ignore sfb21 noise shaping (VBR)\n\n");
+
+    if ( gfp->preset_expopts && gfc->presetTune.use < 1 )
+        MSGF(gfc,"\n*** WARNING ***\n\n"
+                        "Specialized tunings for the preset you are using have been deactivated.\n"
+                 "This is *NOT* recommended and will lead to a decrease in quality!\n"
+                    "\n*** WARNING ***\n\n");
+
+    return 0;
+}
+
+/*}}}*/
+/* void          lame_print_config              (lame_global_flags *gfp)                                                                                          *//*{{{ */
+
+/*
+ *  print_config
+ *
+ *  Prints some selected information about the coding parameters via 
+ *  the macro command MSGF(), which is currently mapped to lame_errorf 
+ *  (reports via a error function?), which is a printf-like function 
+ *  for <stderr>.
+ */
+
+void
+lame_print_config(const lame_global_flags * gfp)
+{
+    lame_internal_flags *gfc = gfp->internal_flags;
+    double  out_samplerate = gfp->out_samplerate;
+    double  in_samplerate = gfp->out_samplerate * gfc->resample_ratio;
+
+    MSGF(gfc, "LAME version %s (%s)\n", get_lame_version(), get_lame_url());
+
+    if (gfc->CPU_features.MMX
+        || gfc->CPU_features.AMD_3DNow
+        || gfc->CPU_features.SIMD || gfc->CPU_features.SIMD2) {
+        MSGF(gfc, "CPU features:");
+
+        if (gfc->CPU_features.i387)
+            MSGF(gfc, " i387");
+        if (gfc->CPU_features.MMX)
+#ifdef MMX_choose_table
+            MSGF(gfc, ", MMX (ASM used)");
+#else
+            MSGF(gfc, ", MMX");
+#endif
+        if (gfc->CPU_features.AMD_3DNow)
+            MSGF(gfc, ", 3DNow!");
+        if (gfc->CPU_features.SIMD)
+            MSGF(gfc, ", SIMD");
+        if (gfc->CPU_features.SIMD2)
+            MSGF(gfc, ", SIMD2");
+        MSGF(gfc, "\n");
+    }
+
+    if (gfp->num_channels == 2 && gfc->channels_out == 1 /* mono */ ) {
+        MSGF
+            (gfc,
+             "Autoconverting from stereo to mono. Setting encoding to mono mode.\n");
+    }
+
+    if (gfc->resample_ratio != 1.) {
+        MSGF(gfc, "Resampling:  input %g kHz  output %g kHz\n",
+             1.e-3 * in_samplerate, 1.e-3 * out_samplerate);
+    }
+
+    if (gfc->filter_type == 0) {
+        if (gfc->highpass2 > 0.)
+            MSGF
+                (gfc,
+                 "Using polyphase highpass filter, transition band: %5.0f Hz - %5.0f Hz\n",
+                 0.5 * gfc->highpass1 * out_samplerate,
+                 0.5 * gfc->highpass2 * out_samplerate);
+        if (gfc->lowpass1 > 0.) {
+            MSGF
+                (gfc,
+                 "Using polyphase lowpass  filter, transition band: %5.0f Hz - %5.0f Hz\n",
+                 0.5 * gfc->lowpass1 * out_samplerate,
+                 0.5 * gfc->lowpass2 * out_samplerate);
+        }
+        else {
+            MSGF(gfc, "polyphase lowpass filter disabled\n");
+        }
+    }
+    else {
+        MSGF(gfc, "polyphase filters disabled\n");
+    }
+
+    if (gfp->free_format) {
+        MSGF(gfc,
+             "Warning: many decoders cannot handle free format bitstreams\n");
+        if (gfp->brate > 320) {
+            MSGF
+                (gfc,
+                 "Warning: many decoders cannot handle free format bitrates >320 kbps (see documentation)\n");
+        }
+    }
+}
+
+
+/**     rh:
+ *      some pretty printing is very welcome at this point!
+ *      so, if someone is willing to do so, please do it!
+ *      add more, if you see more...
+ */
+void 
+lame_print_internals( const lame_global_flags * gfp )
+{
+    lame_internal_flags *gfc = gfp->internal_flags;
+    const char * pc = "";
+
+    /*  compiler/processor optimizations, operational, etc.
+     */
+    MSGF( gfc, "\nmisc:\n\n" );
+    
+    MSGF( gfc, "\tscaling: %f\n", gfp->scale );
+    MSGF( gfc, "\tch0 (left) scaling: %f\n", gfp->scale_left );
+    MSGF( gfc, "\tch1 (right) scaling: %f\n", gfp->scale_right );
+    MSGF( gfc, "\tfilter type: %d\n", gfc->filter_type );
+    pc = gfc->quantization ? "xr^3/4" : "ISO";
+    MSGF( gfc, "\tquantization: %s\n", pc );
+    switch( gfc->use_best_huffman ) {
+    default: pc = "normal"; break;
+    case  1: pc = "best (outside loop)"; break;
+    case  2: pc = "best (inside loop, slow)"; break;
+    } 
+    MSGF( gfc, "\thuffman search: %s\n", pc ); 
+    MSGF( gfc, "\texperimental X=%d Y=%d Z=%d\n", gfp->experimentalX, gfp->experimentalY, gfp->experimentalZ );
+    MSGF( gfc, "\t...\n" );
+
+    /*  everything controlling the stream format 
+     */
+    MSGF( gfc, "\nstream format:\n\n" );
+    switch ( gfp->version ) {
+    case 0:  pc = "2.5"; break;
+    case 1:  pc = "1";   break;
+    case 2:  pc = "2";   break;
+    default: pc = "?";   break;
+    }
+    MSGF( gfc, "\tMPEG-%s Layer 3\n", pc );
+    switch ( gfp->mode ) {
+    case JOINT_STEREO: pc = "joint stereo";   break;
+    case STEREO      : pc = "stereo";         break;
+    case DUAL_CHANNEL: pc = "dual channel";   break;
+    case MONO        : pc = "mono";           break;
+    case NOT_SET     : pc = "not set (error)"; break;
+    default          : pc = "unknown (error)"; break;
+    }
+    MSGF( gfc, "\t%d channel - %s\n", gfc->channels_out, pc );
+    switch ( gfp->padding_type ) {
+    case PAD_NO    : pc = "off";    break;
+    case PAD_ALL   : pc = "all";    break;
+    case PAD_ADJUST: pc = "auto";   break;
+    default        : pc = "(error)"; break;
+    }
+    MSGF( gfc, "\tpadding: %s\n", pc );
+    
+    if ( vbr_default == gfp->VBR )  pc = "(default)";
+    else if ( gfp->free_format )    pc = "(free format)";
+    else pc = "";
+    switch ( gfp->VBR ) {
+    case vbr_off : MSGF( gfc, "\tconstant bitrate - CBR %s\n",      pc ); break;
+    case vbr_abr : MSGF( gfc, "\tvariable bitrate - ABR %s\n",      pc ); break;
+    case vbr_rh  : MSGF( gfc, "\tvariable bitrate - VBR rh %s\n",   pc ); break;
+    case vbr_mt  : MSGF( gfc, "\tvariable bitrate - VBR mt %s\n",   pc ); break;
+    case vbr_mtrh: MSGF( gfc, "\tvariable bitrate - VBR mtrh %s\n", pc ); break; 
+    default      : MSGF( gfc, "\t ?? oops, some new one ?? \n" );         break;
+    }
+    if (gfp->bWriteVbrTag) 
+    MSGF( gfc, "\tusing LAME Tag\n" );
+    MSGF( gfc, "\t...\n" );
+    
+    /*  everything controlling psychoacoustic settings, like ATH, etc.
+     */
+    MSGF( gfc, "\npsychoacoustic:\n\n" );
+    
+    MSGF( gfc, "\ttonality estimation limit: %f Hz\n", gfc->PSY->cwlimit );
+    switch ( gfp->short_blocks ) {
+    default:
+    case short_block_not_set:   pc = "?";               break;
+    case short_block_allowed:   pc = "allowed";         break;
+    case short_block_coupled:   pc = "channel coupled"; break;
+    case short_block_dispensed: pc = "dispensed";       break;
+    case short_block_forced:    pc = "forced";          break;
+    }
+    MSGF( gfc, "\tusing short blocks: %s\n", pc );    
+    MSGF( gfc, "\tadjust masking: %f dB\n", gfc->VBR->mask_adjust );
+    MSGF( gfc, "\tpsymodel: %d\n", gfc->psymodel );
+    MSGF( gfc, "\tnoise shaping: %d\n", gfc->noise_shaping );
+    MSGF( gfc, "\t ^ amplification: %d\n", gfc->noise_shaping_amp );
+    MSGF( gfc, "\t ^ stopping: %d\n", gfc->noise_shaping_stop );
+    
+    pc = "using";
+    if ( gfp->ATHshort ) pc = "the only masking for short blocks";
+    if ( gfp->ATHonly  ) pc = "the only masking";
+    if ( gfp->noATH    ) pc = "not used";
+    MSGF( gfc, "\tATH: %s\n", pc );
+    MSGF( gfc, "\t ^ type: %d\n", gfp->ATHtype );
+    MSGF( gfc, "\t ^ adjust type: %d\n", gfc->ATH->use_adjust );
+    MSGF( gfc, "\t ^ adapt threshold type: %d\n", gfp->athaa_loudapprox );
+    
+    if ( gfc->nsPsy.use ) {
+    MSGF( gfc, "\texperimental psy tunings by Naoki Shibata\n" ); 
+    MSGF( gfc, "\t   adjust masking bass=%g dB, alto=%g dB, treble=%g dB, sfb21=%g dB\n", 
+        10*log10(gfc->nsPsy.bass),   10*log10(gfc->nsPsy.alto), 
+        10*log10(gfc->nsPsy.treble), 10*log10(gfc->nsPsy.sfb21) );
+    }
+    pc = gfp->useTemporal ? "yes" : "no";
+    MSGF( gfc, "\tusing temporal masking effect: %s\n", pc );
+    MSGF( gfc, "\t...\n" );
+    
+    /*  that's all ?
+     */
+    MSGF( gfc, "\n" );
+    return;
+}
+
+
+
+/* int           lame_encode_frame              (lame_global_flags *gfp, sample_t inbuf_l[],sample_t inbuf_r[], char *mp3buf, int mp3buf_size)                    *//*{{{ */
+
+/* routine to feed exactly one frame (gfp->framesize) worth of data to the 
+encoding engine.  All buffering, resampling, etc, handled by calling
+program.  
+*/
+int
+lame_encode_frame(lame_global_flags * gfp,
+                  sample_t inbuf_l[], sample_t inbuf_r[],
+                  unsigned char *mp3buf, int mp3buf_size)
+{
+    int     ret;
+    if (gfp->ogg) {
+#ifdef HAVE_VORBIS_ENCODER
+        ret = lame_encode_ogg_frame(gfp, inbuf_l, inbuf_r, mp3buf, mp3buf_size);
+#else
+        return -5;      /* wanna encode ogg without vorbis */
+#endif
+    }
+    else {
+        ret = lame_encode_mp3_frame(gfp, inbuf_l, inbuf_r, mp3buf, mp3buf_size);
+    }
+
+
+
+    gfp->frameNum++;
+    return ret;
+}
+
+/*}}}*/
+/* int           lame_encode_buffer             (lame_global_flags* gfp, short int buffer_l[], short int buffer_r[], int nsamples, char* mp3buf, int mp3buf_size )*//*{{{ */
+
+
+
+/*
+ * THE MAIN LAME ENCODING INTERFACE
+ * mt 3/00
+ *
+ * input pcm data, output (maybe) mp3 frames.
+ * This routine handles all buffering, resampling and filtering for you.
+ * The required mp3buffer_size can be computed from num_samples,
+ * samplerate and encoding rate, but here is a worst case estimate:
+ *
+ * mp3buffer_size in bytes = 1.25*num_samples + 7200
+ *
+ * return code = number of bytes output in mp3buffer.  can be 0
+*/
+int
+lame_encode_buffer_sample_t(lame_global_flags * gfp,
+                   sample_t buffer_l[],
+                   sample_t buffer_r[],
+                   int nsamples, unsigned char *mp3buf, const int mp3buf_size)
+{
+    lame_internal_flags *gfc = gfp->internal_flags;
+    int     mp3size = 0, ret, i, ch, mf_needed;
+    int mp3out;
+    sample_t *mfbuf[2];
+    sample_t *in_buffer[2];
+
+    if (gfc->Class_ID != LAME_ID)
+        return -3;
+
+    if (nsamples == 0)
+        return 0;
+
+    /* copy out any tags that may have been written into bitstream */
+    mp3out = copy_buffer(gfc,mp3buf,mp3buf_size,0);
+    if (mp3out<0) return mp3out;  // not enough buffer space
+    mp3buf += mp3out;
+    mp3size += mp3out;
+
+
+    in_buffer[0]=buffer_l;
+    in_buffer[1]=buffer_r;  
+
+
+    /* some sanity checks */
+#if ENCDELAY < MDCTDELAY
+# error ENCDELAY is less than MDCTDELAY, see encoder.h
+#endif
+#if FFTOFFSET > BLKSIZE
+# error FFTOFFSET is greater than BLKSIZE, see encoder.h
+#endif
+
+    mf_needed = BLKSIZE + gfp->framesize - FFTOFFSET; /* amount needed for FFT */
+    mf_needed = Max(mf_needed, 286 + 576 * (1 + gfc->mode_gr)); /* amount needed for MDCT/filterbank */
+    assert(MFSIZE >= mf_needed);
+
+    mfbuf[0] = gfc->mfbuf[0];
+    mfbuf[1] = gfc->mfbuf[1];
+
+    if (gfp->num_channels == 2 && gfc->channels_out == 1) {
+        /* downsample to mono */
+        for (i = 0; i < nsamples; ++i) {
+            in_buffer[0][i] =
+                0.5 * ((FLOAT8) in_buffer[0][i] + in_buffer[1][i]);
+            in_buffer[1][i] = 0.0;
+        }
+    }
+
+
+    while (nsamples > 0) {
+        int     n_in = 0;    /* number of input samples processed with fill_buffer */
+        int     n_out = 0;   /* number of samples output with fill_buffer */
+        /* n_in <> n_out if we are resampling */
+
+        /* copy in new samples into mfbuf, with resampling & scaling if necessary */
+        fill_buffer(gfp, mfbuf, in_buffer, nsamples, &n_in, &n_out);
+
+        /* update in_buffer counters */
+        nsamples -= n_in;
+        in_buffer[0] += n_in;
+        if (gfc->channels_out == 2)
+            in_buffer[1] += n_in;
+
+        /* update mfbuf[] counters */
+        gfc->mf_size += n_out;
+        assert(gfc->mf_size <= MFSIZE);
+        gfc->mf_samples_to_encode += n_out;
+
+
+        if (gfc->mf_size >= mf_needed) {
+            /* encode the frame.  */
+            // mp3buf              = pointer to current location in buffer
+            // mp3buf_size         = size of original mp3 output buffer
+            //                     = 0 if we should not worry about the
+            //                       buffer size because calling program is 
+            //                       to lazy to compute it
+            // mp3size             = size of data written to buffer so far
+            // mp3buf_size-mp3size = amount of space avalable 
+
+            int buf_size=mp3buf_size - mp3size;
+            if (mp3buf_size==0) buf_size=0;
+
+            ret =
+                lame_encode_frame(gfp, mfbuf[0], mfbuf[1], mp3buf,buf_size);
+
+            if (ret < 0) goto retr;
+            mp3buf += ret;
+            mp3size += ret;
+
+            /* shift out old samples */
+            gfc->mf_size -= gfp->framesize;
+            gfc->mf_samples_to_encode -= gfp->framesize;
+            for (ch = 0; ch < gfc->channels_out; ch++)
+                for (i = 0; i < gfc->mf_size; i++)
+                    mfbuf[ch][i] = mfbuf[ch][i + gfp->framesize];
+        }
+    }
+    assert(nsamples == 0);
+    ret = mp3size;
+
+  retr:
+    return ret;
+}
+
+
+int
+lame_encode_buffer(lame_global_flags * gfp,
+                   const short int buffer_l[],
+                   const short int buffer_r[],
+                   const int nsamples, unsigned char *mp3buf, const int mp3buf_size)
+{
+    lame_internal_flags *gfc = gfp->internal_flags;
+    int     ret, i;
+    sample_t *in_buffer[2];
+
+    if (gfc->Class_ID != LAME_ID)
+        return -7; //-3
+
+    if (nsamples == 0)
+        return 0;
+
+    in_buffer[0] = calloc(sizeof(sample_t), nsamples);
+    in_buffer[1] = calloc(sizeof(sample_t), nsamples);
+
+    if (in_buffer[0] == NULL || in_buffer[1] == NULL) {
+        ERRORF(gfc, "Error: can't allocate in_buffer buffer\n");
+        return -2;
+    }
+
+    /* make a copy of input buffer, changing type to sample_t */
+    for (i = 0; i < nsamples; i++) {
+        in_buffer[0][i] = buffer_l[i];
+        in_buffer[1][i] = buffer_r[i];
+    }
+
+    ret = lame_encode_buffer_sample_t(gfp,in_buffer[0],in_buffer[1],
+                                     nsamples, mp3buf, mp3buf_size);
+    
+    free(in_buffer[0]);
+    free(in_buffer[1]);
+    return ret;
+}
+
+
+int
+lame_encode_buffer_float(lame_global_flags * gfp,
+                   const float buffer_l[],
+                   const float buffer_r[],
+                   const int nsamples, unsigned char *mp3buf, const int mp3buf_size)
+{
+    lame_internal_flags *gfc = gfp->internal_flags;
+    int     ret, i;
+    sample_t *in_buffer[2];
+
+    if (gfc->Class_ID != LAME_ID)
+        return -3;
+
+    if (nsamples == 0)
+        return 0;
+
+    in_buffer[0] = calloc(sizeof(sample_t), nsamples);
+    in_buffer[1] = calloc(sizeof(sample_t), nsamples);
+
+    if (in_buffer[0] == NULL || in_buffer[1] == NULL) {
+        ERRORF(gfc, "Error: can't allocate in_buffer buffer\n");
+        return -2;
+    }
+
+    /* make a copy of input buffer, changing type to sample_t */
+    for (i = 0; i < nsamples; i++) {
+        in_buffer[0][i] = buffer_l[i];
+        in_buffer[1][i] = buffer_r[i];
+    }
+
+    ret = lame_encode_buffer_sample_t(gfp,in_buffer[0],in_buffer[1],
+                                     nsamples, mp3buf, mp3buf_size);
+    
+    free(in_buffer[0]);
+    free(in_buffer[1]);
+    return ret;
+}
+
+
+
+int
+lame_encode_buffer_int(lame_global_flags * gfp,
+                   const int buffer_l[],
+                   const int buffer_r[],
+                   const int nsamples, unsigned char *mp3buf, const int mp3buf_size)
+{
+    lame_internal_flags *gfc = gfp->internal_flags;
+    int     ret, i;
+    sample_t *in_buffer[2];
+
+    if (gfc->Class_ID != LAME_ID)
+        return -3;
+
+    if (nsamples == 0)
+        return 0;
+
+    in_buffer[0] = calloc(sizeof(sample_t), nsamples);
+    in_buffer[1] = calloc(sizeof(sample_t), nsamples);
+
+    if (in_buffer[0] == NULL || in_buffer[1] == NULL) {
+        ERRORF(gfc, "Error: can't allocate in_buffer buffer\n");
+        return -2;
+    }
+
+    /* make a copy of input buffer, changing type to sample_t */
+    for (i = 0; i < nsamples; i++) {
+                                /* internal code expects +/- 32768.0 */
+      in_buffer[0][i] = buffer_l[i] * (1.0 / ( 1 << (8 * sizeof(int) - 16)));
+      in_buffer[1][i] = buffer_r[i] * (1.0 / ( 1 << (8 * sizeof(int) - 16)));
+    }
+
+    ret = lame_encode_buffer_sample_t(gfp,in_buffer[0],in_buffer[1],
+                                     nsamples, mp3buf, mp3buf_size);
+    
+    free(in_buffer[0]);
+    free(in_buffer[1]);
+    return ret;
+
+}
+
+
+
+
+int
+lame_encode_buffer_long2(lame_global_flags * gfp,
+                   const long buffer_l[],
+                   const long buffer_r[],
+                   const int nsamples, unsigned char *mp3buf, const int mp3buf_size)
+{
+    lame_internal_flags *gfc = gfp->internal_flags;
+    int     ret, i;
+    sample_t *in_buffer[2];
+
+    if (gfc->Class_ID != LAME_ID)
+        return -3;
+
+    if (nsamples == 0)
+        return 0;
+
+    in_buffer[0] = calloc(sizeof(sample_t), nsamples);
+    in_buffer[1] = calloc(sizeof(sample_t), nsamples);
+
+    if (in_buffer[0] == NULL || in_buffer[1] == NULL) {
+        ERRORF(gfc, "Error: can't allocate in_buffer buffer\n");
+        return -2;
+    }
+
+    /* make a copy of input buffer, changing type to sample_t */
+    for (i = 0; i < nsamples; i++) {
+                                /* internal code expects +/- 32768.0 */
+      in_buffer[0][i] = buffer_l[i] * (1.0 / ( 1 << (8 * sizeof(long) - 16)));
+      in_buffer[1][i] = buffer_r[i] * (1.0 / ( 1 << (8 * sizeof(long) - 16)));
+    }
+
+    ret = lame_encode_buffer_sample_t(gfp,in_buffer[0],in_buffer[1],
+                                     nsamples, mp3buf, mp3buf_size);
+    
+    free(in_buffer[0]);
+    free(in_buffer[1]);
+    return ret;
+
+}
+
+
+
+int
+lame_encode_buffer_long(lame_global_flags * gfp,
+                   const long buffer_l[],
+                   const long buffer_r[],
+                   const int nsamples, unsigned char *mp3buf, const int mp3buf_size)
+{
+    lame_internal_flags *gfc = gfp->internal_flags;
+    int     ret, i;
+    sample_t *in_buffer[2];
+
+    if (gfc->Class_ID != LAME_ID)
+        return -3;
+
+    if (nsamples == 0)
+        return 0;
+
+    in_buffer[0] = calloc(sizeof(sample_t), nsamples);
+    in_buffer[1] = calloc(sizeof(sample_t), nsamples);
+
+    if (in_buffer[0] == NULL || in_buffer[1] == NULL) {
+        ERRORF(gfc, "Error: can't allocate in_buffer buffer\n");
+        return -2;
+    }
+
+    /* make a copy of input buffer, changing type to sample_t */
+    for (i = 0; i < nsamples; i++) {
+        in_buffer[0][i] = buffer_l[i];
+        in_buffer[1][i] = buffer_r[i];
+    }
+
+    ret = lame_encode_buffer_sample_t(gfp,in_buffer[0],in_buffer[1],
+                                     nsamples, mp3buf, mp3buf_size);
+    
+    free(in_buffer[0]);
+    free(in_buffer[1]);
+    return ret;
+}
+
+
+
+
+
+
+
+
+
+
+
+int
+lame_encode_buffer_interleaved(lame_global_flags * gfp,
+                               short int buffer[],
+                               int nsamples,
+                               unsigned char *mp3buf, int mp3buf_size)
+{
+    int     ret, i;
+    short int *buffer_l;
+    short int *buffer_r;
+
+    buffer_l = malloc(sizeof(short int) * nsamples);
+    buffer_r = malloc(sizeof(short int) * nsamples);
+    if (buffer_l == NULL || buffer_r == NULL) {
+        return -2;
+    }
+    for (i = 0; i < nsamples; i++) {
+        buffer_l[i] = buffer[2 * i];
+        buffer_r[i] = buffer[2 * i + 1];
+    }
+    ret =
+        lame_encode_buffer(gfp, buffer_l, buffer_r, nsamples, mp3buf,
+                           mp3buf_size);
+    free(buffer_l);
+    free(buffer_r);
+    return ret;
+
+}
+
+
+/*}}}*/
+/* int           lame_encode                    (lame_global_flags* gfp, short int in_buffer[2][1152], char* mp3buf, int size )                                   *//*{{{ */
+
+
+/* old LAME interface.  use lame_encode_buffer instead */
+
+int
+lame_encode(lame_global_flags * const gfp,
+            const short int in_buffer[2][1152],
+            unsigned char *const mp3buf, const int size)
+{
+    lame_internal_flags *gfc = gfp->internal_flags;
+
+    if (gfc->Class_ID != LAME_ID)
+        return -3;
+
+    return lame_encode_buffer(gfp, in_buffer[0], in_buffer[1], gfp->framesize,
+                              mp3buf, size);
+}
+
+/*}}}*/
+/* int           lame_encode_flush              (lame_global_flags* gfp, char* mp3buffer, int mp3buffer_size )                                                    *//*{{{ */
+
+
+
+/*****************************************************************
+ Flush mp3 buffer, pad with ancillary data so last frame is complete.
+ Reset reservoir size to 0                  
+ but keep all PCM samples and MDCT data in memory             
+ This option is used to break a large file into several mp3 files 
+ that when concatenated together will decode with no gaps         
+ Because we set the reservoir=0, they will also decode seperately 
+ with no errors. 
+*********************************************************************/
+int
+lame_encode_flush_nogap(lame_global_flags * gfp,
+                  unsigned char *mp3buffer, int mp3buffer_size)
+{
+    lame_internal_flags *gfc = gfp->internal_flags;
+    flush_bitstream(gfp);
+    return copy_buffer(gfc,mp3buffer, mp3buffer_size,1);
+}
+
+
+/* called by lame_init_params.  You can also call this after flush_nogap 
+   if you want to write new id3v2 and Xing VBR tags into the bitstream */
+int
+lame_init_bitstream(lame_global_flags * gfp)
+{
+    lame_internal_flags *gfc = gfp->internal_flags;
+    int i;
+    gfp->frameNum=0;
+
+    if (!gfp->ogg)
+       id3tag_write_v2(gfp);
+
+    /* initialize histogram data optionally used by frontend */
+    for ( i = 0; i < 16; i++ ) 
+       gfc->bitrate_stereoMode_Hist [i] [0] =
+           gfc->bitrate_stereoMode_Hist [i] [1] =
+           gfc->bitrate_stereoMode_Hist [i] [2] =
+           gfc->bitrate_stereoMode_Hist [i] [3] =
+           gfc->bitrate_stereoMode_Hist [i] [4] = 0;
+
+    /* Write initial VBR Header to bitstream and init VBR data */
+    if (gfp->bWriteVbrTag)
+        InitVbrTag(gfp);
+
+    
+    return 0;
+}
+
+
+/*****************************************************************/
+/* flush internal PCM sample buffers, then mp3 buffers           */
+/* then write id3 v1 tags into bitstream.                        */
+/*****************************************************************/
+
+int
+lame_encode_flush(lame_global_flags * gfp,
+                  unsigned char *mp3buffer, int mp3buffer_size)
+{
+    lame_internal_flags *gfc = gfp->internal_flags;
+    short int buffer[2][1152];
+    int     imp3 = 0, mp3count, mp3buffer_size_remaining;
+
+    /* we always add POSTDELAY=288 padding to make sure granule with real
+     * data can be complety decoded (because of 50% overlap with next granule */
+    int end_padding=POSTDELAY;  
+
+    memset(buffer, 0, sizeof(buffer));
+    mp3count = 0;
+
+
+    while (gfc->mf_samples_to_encode > 0) {
+
+        mp3buffer_size_remaining = mp3buffer_size - mp3count;
+
+        /* if user specifed buffer size = 0, dont check size */
+        if (mp3buffer_size == 0)
+            mp3buffer_size_remaining = 0;
+
+        /* send in a frame of 0 padding until all internal sample buffers
+         * are flushed 
+         */
+        imp3 = lame_encode_buffer(gfp, buffer[0], buffer[1], gfp->framesize,
+                                  mp3buffer, mp3buffer_size_remaining);
+
+        /* don't count the above padding: */
+        gfc->mf_samples_to_encode -= gfp->framesize;
+        if (gfc->mf_samples_to_encode < 0) {
+            /* we added extra padding to the end */
+            end_padding += -gfc->mf_samples_to_encode;  
+        }
+
+
+        if (imp3 < 0) {
+            /* some type of fatal error */
+            return imp3;
+        }
+        mp3buffer += imp3;
+        mp3count += imp3;
+    }
+
+    mp3buffer_size_remaining = mp3buffer_size - mp3count;
+    /* if user specifed buffer size = 0, dont check size */
+    if (mp3buffer_size == 0)
+        mp3buffer_size_remaining = 0;
+
+    if (gfp->ogg) {
+#ifdef HAVE_VORBIS_ENCODER
+        /* ogg related stuff */
+        imp3 = lame_encode_ogg_finish(gfp, mp3buffer, mp3buffer_size_remaining);
+#endif
+    }
+    else {
+        /* mp3 related stuff.  bit buffer might still contain some mp3 data */
+        flush_bitstream(gfp);
+        imp3 = copy_buffer(gfc,mp3buffer, mp3buffer_size_remaining, 1);
+        if (imp3 < 0) {
+            /* some type of fatal error */
+            return imp3;
+        }
+        mp3buffer += imp3;
+        mp3count += imp3;
+        mp3buffer_size_remaining = mp3buffer_size - mp3count;
+        /* if user specifed buffer size = 0, dont check size */
+        if (mp3buffer_size == 0)
+            mp3buffer_size_remaining = 0;
+
+
+        /* write a id3 tag to the bitstream */
+        id3tag_write_v1(gfp);
+        imp3 = copy_buffer(gfc,mp3buffer, mp3buffer_size_remaining, 0);
+    }
+
+    if (imp3 < 0) {
+        return imp3;
+    }
+    mp3count += imp3;
+    gfp->encoder_padding=end_padding;
+    return mp3count;
+}
+
+/*}}}*/
+/* void          lame_close                     (lame_global_flags *gfp)                                                                                          *//*{{{ */
+
+/***********************************************************************
+ *
+ *      lame_close ()
+ *
+ *  frees internal buffers
+ *
+ ***********************************************************************/
+
+int
+lame_close(lame_global_flags * gfp)
+{
+    lame_internal_flags *gfc = gfp->internal_flags;
+
+    if (gfc->Class_ID != LAME_ID)
+        return -3;
+
+    gfc->Class_ID = 0;
+
+    // this routien will free all malloc'd data in gfc, and then free gfc:
+    freegfc(gfc);
+
+    gfp->internal_flags = NULL;
+
+    if (gfp->lame_allocated_gfp)
+        free(gfp);
+
+    return 0;
+}
+
+
+/*}}}*/
+/* int           lame_encode_finish             (lame_global_flags* gfp, char* mp3buffer, int mp3buffer_size )                                                    *//*{{{ */
+
+
+/*****************************************************************/
+/* flush internal mp3 buffers, and free internal buffers         */
+/*****************************************************************/
+
+int
+lame_encode_finish(lame_global_flags * gfp,
+                   unsigned char *mp3buffer, int mp3buffer_size)
+{
+    int     ret = lame_encode_flush(gfp, mp3buffer, mp3buffer_size);
+
+    lame_close(gfp);
+
+    return ret;
+}
+
+/*}}}*/
+/* void          lame_mp3_tags_fid              (lame_global_flags *gfp,FILE *fpStream)                                                                           *//*{{{ */
+
+/*****************************************************************/
+/* write VBR Xing header, and ID3 version 1 tag, if asked for    */
+/*****************************************************************/
+void
+lame_mp3_tags_fid(lame_global_flags * gfp, FILE * fpStream)
+{
+    if (gfp->bWriteVbrTag) {
+        /* Map VBR_q to Xing quality value: 0=worst, 100=best */
+        int     nQuality = ((9-gfp->VBR_q) * 100) / 9;
+
+        /* Write Xing header again */
+        if (fpStream && !fseek(fpStream, 0, SEEK_SET))
+            PutVbrTag(gfp, fpStream, nQuality);
+    }
+
+
+}
+/*}}}*/
+/* lame_global_flags *lame_init                 (void)                                                                                                            *//*{{{ */
+
+lame_global_flags *
+lame_init(void)
+{
+    lame_global_flags *gfp;
+    int     ret;
+
+    gfp = calloc(1, sizeof(lame_global_flags));
+    if (gfp == NULL)
+        return NULL;
+
+    ret = lame_init_old(gfp);
+    if (ret != 0) {
+        free(gfp);
+        return NULL;
+    }
+
+    gfp->lame_allocated_gfp = 1;
+    return gfp;
+}
+
+/*}}}*/
+/* int           lame_init_old                  (lame_global_flags *gfp)                                                                                          *//*{{{ */
+
+/* initialize mp3 encoder */
+int
+lame_init_old(lame_global_flags * gfp)
+{
+    lame_internal_flags *gfc;
+
+    disable_FPE();      // disable floating point exceptions
+
+    memset(gfp, 0, sizeof(lame_global_flags));
+
+    if (NULL ==
+        (gfc = gfp->internal_flags =
+         calloc(1, sizeof(lame_internal_flags)))) return -1;
+
+    /* Global flags.  set defaults here for non-zero values */
+    /* see lame.h for description */
+    /* set integer values to -1 to mean that LAME will compute the
+     * best value, UNLESS the calling program as set it
+     * (and the value is no longer -1)
+     */
+
+
+    gfp->mode = NOT_SET;
+    gfp->original = 1;
+    gfp->in_samplerate = 1000 * 44.1;
+    gfp->num_channels = 2;
+    gfp->num_samples = MAX_U_32_NUM;
+
+    gfp->bWriteVbrTag = 1;
+    gfp->quality = -1;
+    gfp->short_blocks = short_block_not_set;
+
+    gfp->lowpassfreq = 0;
+    gfp->highpassfreq = 0;
+    gfp->lowpasswidth = -1;
+    gfp->highpasswidth = -1;
+
+    gfp->padding_type = PAD_ADJUST;
+    gfp->VBR = vbr_off;
+    gfp->VBR_q = 4;
+    gfp->VBR_mean_bitrate_kbps = 128;
+    gfp->VBR_min_bitrate_kbps = 0;
+    gfp->VBR_max_bitrate_kbps = 0;
+    gfp->VBR_hard_min = 0;
+
+
+    gfc->resample_ratio = 1;
+    gfc->lowpass_band = 32;
+    gfc->highpass_band = -1;
+    gfc->VBR_min_bitrate = 1; /* not  0 ????? */
+    gfc->VBR_max_bitrate = 13; /* not 14 ????? */
+
+    gfc->OldValue[0] = 180;
+    gfc->OldValue[1] = 180;
+    gfc->CurrentStep = 4;
+    gfc->masking_lower = 1;
+
+    gfp->athaa_type = -1;
+    gfp->ATHtype = -1;  /* default = -1 = set in lame_init_params */
+    gfp->athaa_loudapprox = -1;        /* 1 = flat loudness approx. (total energy) */
+                                /* 2 = equal loudness curve */
+    gfp->athaa_sensitivity = 0.0; /* no offset */
+    gfp->useTemporal = -1;
+
+    /* The reason for
+     *       int mf_samples_to_encode = ENCDELAY + POSTDELAY;
+     * ENCDELAY = internal encoder delay.  And then we have to add POSTDELAY=288
+     * because of the 50% MDCT overlap.  A 576 MDCT granule decodes to
+     * 1152 samples.  To synthesize the 576 samples centered under this granule
+     * we need the previous granule for the first 288 samples (no problem), and
+     * the next granule for the next 288 samples (not possible if this is last
+     * granule).  So we need to pad with 288 samples to make sure we can
+     * encode the 576 samples we are interested in.
+     */
+    gfc->mf_samples_to_encode = ENCDELAY + POSTDELAY;
+    gfp->encoder_padding = 0;
+    gfc->mf_size = ENCDELAY - MDCTDELAY; /* we pad input with this many 0's */
+
+#ifdef KLEMM_44
+    /* XXX: this wasn't protectes by KLEMM_44 initially! */
+    gfc->last_ampl = gfc->ampl = +1.0;
+#endif
+    return 0;
+}
+
+/*}}}*/
+
+/***********************************************************************
+ *
+ *  some simple statistics
+ *
+ *  Robert Hegemann 2000-10-11
+ *
+ ***********************************************************************/
+
+/*  histogram of used bitrate indexes:
+ *  One has to weight them to calculate the average bitrate in kbps
+ *
+ *  bitrate indices:
+ *  there are 14 possible bitrate indices, 0 has the special meaning 
+ *  "free format" which is not possible to mix with VBR and 15 is forbidden
+ *  anyway.
+ *
+ *  stereo modes:
+ *  0: LR   number of left-right encoded frames
+ *  1: LR-I number of left-right and intensity encoded frames
+ *  2: MS   number of mid-side encoded frames
+ *  3: MS-I number of mid-side and intensity encoded frames
+ *
+ *  4: number of encoded frames
+ *
+ */
+
+void
+lame_bitrate_hist(const lame_global_flags * const gfp, int bitrate_count[14])
+{
+    const lame_internal_flags *gfc;
+    int     i;
+
+    if (NULL == bitrate_count)
+        return;
+    if (NULL == gfp)
+        return;
+    gfc = gfp->internal_flags;
+    if (NULL == gfc)
+        return;
+
+    for (i = 0; i < 14; i++)
+        bitrate_count[i] = gfc->bitrate_stereoMode_Hist[i + 1][4];
+}
+
+
+void
+lame_bitrate_kbps(const lame_global_flags * const gfp, int bitrate_kbps[14])
+{
+    const lame_internal_flags *gfc;
+    int     i;
+
+    if (NULL == bitrate_kbps)
+        return;
+    if (NULL == gfp)
+        return;
+    gfc = gfp->internal_flags;
+    if (NULL == gfc)
+        return;
+
+    for (i = 0; i < 14; i++)
+        bitrate_kbps[i] = bitrate_table[gfp->version][i + 1];
+}
+
+
+
+void
+lame_stereo_mode_hist(const lame_global_flags * const gfp, int stmode_count[4])
+{
+    const lame_internal_flags *gfc;
+    int     i;
+
+    if (NULL == stmode_count)
+        return;
+    if (NULL == gfp)
+        return;
+    gfc = gfp->internal_flags;
+    if (NULL == gfc)
+        return;
+
+    for (i = 0; i < 4; i++) {
+        int     j, sum = 0;
+        for (j = 0; j < 14; j++)
+            sum += gfc->bitrate_stereoMode_Hist[j + 1][i];
+        stmode_count[i] = sum;
+    }
+}
+
+
+
+void
+lame_bitrate_stereo_mode_hist(const lame_global_flags * const gfp,
+                              int bitrate_stmode_count[14][4])
+{
+    const lame_internal_flags *gfc;
+    int     i;
+    int     j;
+
+    if (NULL == bitrate_stmode_count)
+        return;
+    if (NULL == gfp)
+        return;
+    gfc = gfp->internal_flags;
+    if (NULL == gfc)
+        return;
+
+    for (j = 0; j < 14; j++)
+        for (i = 0; i < 4; i++)
+            bitrate_stmode_count[j][i] = gfc->bitrate_stereoMode_Hist[j + 1][i];
+}
+
+/* end of lame.c */