X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=lib%2Flame%2Flame.c;fp=lib%2Flame%2Flame.c;h=df4fdac467cda39361ac8acd25907c958139c68c;hb=698acf324aaa52147b1486646f6549ffd95804da;hp=0000000000000000000000000000000000000000;hpb=f8d07c79494e8536e682da73cee2057740a0e4db;p=swftools.git diff --git a/lib/lame/lame.c b/lib/lame/lame.c new file mode 100644 index 0000000..df4fdac --- /dev/null +++ b/lib/lame/lame.c @@ -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 +#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 +#endif +#ifdef __riscos__ +#include "asmstuff.h" +#endif + +#ifdef WITH_DMALLOC +#include +#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 . + */ + +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 */