mirror of
				https://github.com/cookiengineer/audacity
				synced 2025-10-31 14:13:50 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			2666 lines
		
	
	
		
			83 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			2666 lines
		
	
	
		
			83 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* -*- mode: C; mode: fold -*- */
 | |
| /*
 | |
|  *      LAME MP3 encoding engine
 | |
|  *
 | |
|  *      Copyright (c) 1999-2000 Mark Taylor
 | |
|  *      Copyright (c) 2000-2005 Takehiro Tominaga
 | |
|  *      Copyright (c) 2000-2017 Robert Hegemann
 | |
|  *      Copyright (c) 2000-2005 Gabriel Bouvigne
 | |
|  *      Copyright (c) 2000-2004 Alexander Leidinger
 | |
|  *
 | |
|  * 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.377 2017/09/26 12:14:02 robert Exp $ */
 | |
| 
 | |
| #ifdef HAVE_CONFIG_H
 | |
| # include <config.h>
 | |
| #endif
 | |
| 
 | |
| 
 | |
| #include "lame.h"
 | |
| #include "machine.h"
 | |
| 
 | |
| #include "encoder.h"
 | |
| #include "util.h"
 | |
| #include "lame_global_flags.h"
 | |
| #include "gain_analysis.h"
 | |
| #include "bitstream.h"
 | |
| #include "quantize_pvt.h"
 | |
| #include "set_get.h"
 | |
| #include "quantize.h"
 | |
| #include "psymodel.h"
 | |
| #include "version.h"
 | |
| #include "VbrTag.h"
 | |
| #include "tables.h"
 | |
| 
 | |
| 
 | |
| #if defined(__FreeBSD__) && !defined(__alpha__)
 | |
| #include <floatingpoint.h>
 | |
| #endif
 | |
| #ifdef __riscos__
 | |
| #include "asmstuff.h"
 | |
| #endif
 | |
| 
 | |
| #ifdef __sun__
 | |
| /* woraround for SunOS 4.x, it has SEEK_* defined here */
 | |
| #include <unistd.h>
 | |
| #endif
 | |
| 
 | |
| 
 | |
| #define LAME_DEFAULT_QUALITY 3
 | |
| 
 | |
| 
 | |
| 
 | |
| int
 | |
| is_lame_global_flags_valid(const lame_global_flags * gfp)
 | |
| {
 | |
|     if (gfp == NULL)
 | |
|         return 0;
 | |
|     if (gfp->class_id != LAME_ID)
 | |
|         return 0;
 | |
|     return 1;
 | |
| }
 | |
| 
 | |
| 
 | |
| int
 | |
| is_lame_internal_flags_valid(const lame_internal_flags * gfc)
 | |
| {
 | |
|     if (gfc == NULL)
 | |
|         return 0;
 | |
|     if (gfc->class_id != LAME_ID)
 | |
|         return 0;
 | |
|     if (gfc->lame_init_params_successful <=0)
 | |
|         return 0;
 | |
|     return 1;
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| static  FLOAT
 | |
| filter_coef(FLOAT x)
 | |
| {
 | |
|     if (x > 1.0)
 | |
|         return 0.0;
 | |
|     if (x <= 0.0)
 | |
|         return 1.0;
 | |
| 
 | |
|     return cos(PI / 2 * x);
 | |
| }
 | |
| 
 | |
| static void
 | |
| lame_init_params_ppflt(lame_internal_flags * gfc)
 | |
| {
 | |
|     SessionConfig_t *const cfg = &gfc->cfg;
 | |
|     
 | |
|     /***************************************************************/
 | |
|     /* compute info needed for polyphase filter (filter type==0, default) */
 | |
|     /***************************************************************/
 | |
| 
 | |
|     int     band, maxband, minband;
 | |
|     FLOAT   freq;
 | |
|     int     lowpass_band = 32;
 | |
|     int     highpass_band = -1;
 | |
| 
 | |
|     if (cfg->lowpass1 > 0) {
 | |
|         minband = 999;
 | |
|         for (band = 0; band <= 31; band++) {
 | |
|             freq = band / 31.0;
 | |
|             /* this band and above will be zeroed: */
 | |
|             if (freq >= cfg->lowpass2) {
 | |
|                 lowpass_band = Min(lowpass_band, band);
 | |
|             }
 | |
|             if (cfg->lowpass1 < freq && freq < cfg->lowpass2) {
 | |
|                 minband = Min(minband, band);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /* compute the *actual* transition band implemented by
 | |
|          * the polyphase filter */
 | |
|         if (minband == 999) {
 | |
|             cfg->lowpass1 = (lowpass_band - .75) / 31.0;
 | |
|         }
 | |
|         else {
 | |
|             cfg->lowpass1 = (minband - .75) / 31.0;
 | |
|         }
 | |
|         cfg->lowpass2 = lowpass_band / 31.0;
 | |
|     }
 | |
| 
 | |
|     /* make sure highpass filter is within 90% of what the effective
 | |
|      * highpass frequency will be */
 | |
|     if (cfg->highpass2 > 0) {
 | |
|         if (cfg->highpass2 < .9 * (.75 / 31.0)) {
 | |
|             cfg->highpass1 = 0;
 | |
|             cfg->highpass2 = 0;
 | |
|             MSGF(gfc, "Warning: highpass filter disabled.  " "highpass frequency too small\n");
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if (cfg->highpass2 > 0) {
 | |
|         maxband = -1;
 | |
|         for (band = 0; band <= 31; band++) {
 | |
|             freq = band / 31.0;
 | |
|             /* this band and below will be zereod */
 | |
|             if (freq <= cfg->highpass1) {
 | |
|                 highpass_band = Max(highpass_band, band);
 | |
|             }
 | |
|             if (cfg->highpass1 < freq && freq < cfg->highpass2) {
 | |
|                 maxband = Max(maxband, band);
 | |
|             }
 | |
|         }
 | |
|         /* compute the *actual* transition band implemented by
 | |
|          * the polyphase filter */
 | |
|         cfg->highpass1 = highpass_band / 31.0;
 | |
|         if (maxband == -1) {
 | |
|             cfg->highpass2 = (highpass_band + .75) / 31.0;
 | |
|         }
 | |
|         else {
 | |
|             cfg->highpass2 = (maxband + .75) / 31.0;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     for (band = 0; band < 32; band++) {
 | |
|         FLOAT fc1, fc2;
 | |
|         freq = band / 31.0f;
 | |
|         if (cfg->highpass2 > cfg->highpass1) {
 | |
|             fc1 = filter_coef((cfg->highpass2 - freq) / (cfg->highpass2 - cfg->highpass1 + 1e-20));
 | |
|         }
 | |
|         else {
 | |
|             fc1 = 1.0f;
 | |
|         }
 | |
|         if (cfg->lowpass2 > cfg->lowpass1) {
 | |
|             fc2 = filter_coef((freq - cfg->lowpass1)  / (cfg->lowpass2 - cfg->lowpass1 + 1e-20));
 | |
|         }
 | |
|         else {
 | |
|             fc2 = 1.0f;
 | |
|         }
 | |
|         gfc->sv_enc.amp_filter[band] = fc1 * fc2;
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| static void
 | |
| optimum_bandwidth(double *const lowerlimit, double *const upperlimit, const unsigned bitrate)
 | |
| {
 | |
| /*
 | |
|  *  Input:
 | |
|  *      bitrate     total bitrate in kbps
 | |
|  *
 | |
|  *   Output:
 | |
|  *      lowerlimit: best lowpass frequency limit for input filter in Hz
 | |
|  *      upperlimit: best highpass frequency limit for input filter in Hz
 | |
|  */
 | |
|     int     table_index;
 | |
| 
 | |
|     typedef struct {
 | |
|         int     bitrate;     /* only indicative value */
 | |
|         int     lowpass;
 | |
|     } band_pass_t;
 | |
| 
 | |
|     const band_pass_t freq_map[] = {
 | |
|         {8, 2000},
 | |
|         {16, 3700},
 | |
|         {24, 3900},
 | |
|         {32, 5500},
 | |
|         {40, 7000},
 | |
|         {48, 7500},
 | |
|         {56, 10000},
 | |
|         {64, 11000},
 | |
|         {80, 13500},
 | |
|         {96, 15100},
 | |
|         {112, 15600},
 | |
|         {128, 17000},
 | |
|         {160, 17500},
 | |
|         {192, 18600},
 | |
|         {224, 19400},
 | |
|         {256, 19700},
 | |
|         {320, 20500}
 | |
|     };
 | |
| 
 | |
| 
 | |
|     table_index = nearestBitrateFullIndex(bitrate);
 | |
| 
 | |
|     (void) freq_map[table_index].bitrate;
 | |
|     *lowerlimit = freq_map[table_index].lowpass;
 | |
| 
 | |
| 
 | |
| /*
 | |
|  *  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 (upperlimit != NULL)
 | |
|      *upperlimit = f_high;*/
 | |
|     (void) upperlimit;
 | |
| }
 | |
| 
 | |
| 
 | |
| static int
 | |
| optimum_samplefreq(int lowpassfreq, int input_samplefreq)
 | |
| {
 | |
| /*
 | |
|  * Rules:
 | |
|  *  - if possible, sfb21 should NOT be used
 | |
|  *
 | |
|  */
 | |
|     int     suggested_samplefreq = 44100;
 | |
| 
 | |
|     if (input_samplefreq >= 48000)
 | |
|         suggested_samplefreq = 48000;
 | |
|     else if (input_samplefreq >= 44100)
 | |
|         suggested_samplefreq = 44100;
 | |
|     else if (input_samplefreq >= 32000)
 | |
|         suggested_samplefreq = 32000;
 | |
|     else if (input_samplefreq >= 24000)
 | |
|         suggested_samplefreq = 24000;
 | |
|     else if (input_samplefreq >= 22050)
 | |
|         suggested_samplefreq = 22050;
 | |
|     else if (input_samplefreq >= 16000)
 | |
|         suggested_samplefreq = 16000;
 | |
|     else if (input_samplefreq >= 12000)
 | |
|         suggested_samplefreq = 12000;
 | |
|     else if (input_samplefreq >= 11025)
 | |
|         suggested_samplefreq = 11025;
 | |
|     else if (input_samplefreq >= 8000)
 | |
|         suggested_samplefreq = 8000;
 | |
| 
 | |
|     if (lowpassfreq == -1)
 | |
|         return suggested_samplefreq;
 | |
| 
 | |
|     if (lowpassfreq <= 15960)
 | |
|         suggested_samplefreq = 44100;
 | |
|     if (lowpassfreq <= 15250)
 | |
|         suggested_samplefreq = 32000;
 | |
|     if (lowpassfreq <= 11220)
 | |
|         suggested_samplefreq = 24000;
 | |
|     if (lowpassfreq <= 9970)
 | |
|         suggested_samplefreq = 22050;
 | |
|     if (lowpassfreq <= 7230)
 | |
|         suggested_samplefreq = 16000;
 | |
|     if (lowpassfreq <= 5420)
 | |
|         suggested_samplefreq = 12000;
 | |
|     if (lowpassfreq <= 4510)
 | |
|         suggested_samplefreq = 11025;
 | |
|     if (lowpassfreq <= 3970)
 | |
|         suggested_samplefreq = 8000;
 | |
| 
 | |
|     if (input_samplefreq < suggested_samplefreq) {
 | |
|         /* choose a valid MPEG sample frequency above the input sample frequency
 | |
|            to avoid SFB21/12 bitrate bloat
 | |
|            rh 061115
 | |
|          */
 | |
|         if (input_samplefreq > 44100) {
 | |
|             return 48000;
 | |
|         }
 | |
|         if (input_samplefreq > 32000) {
 | |
|             return 44100;
 | |
|         }
 | |
|         if (input_samplefreq > 24000) {
 | |
|             return 32000;
 | |
|         }
 | |
|         if (input_samplefreq > 22050) {
 | |
|             return 24000;
 | |
|         }
 | |
|         if (input_samplefreq > 16000) {
 | |
|             return 22050;
 | |
|         }
 | |
|         if (input_samplefreq > 12000) {
 | |
|             return 16000;
 | |
|         }
 | |
|         if (input_samplefreq > 11025) {
 | |
|             return 12000;
 | |
|         }
 | |
|         if (input_samplefreq > 8000) {
 | |
|             return 11025;
 | |
|         }
 | |
|         return 8000;
 | |
|     }
 | |
|     return suggested_samplefreq;
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| /* set internal feature flags.  USER should not access these since
 | |
|  * some combinations will produce strange results */
 | |
| static void
 | |
| lame_init_qval(lame_global_flags * gfp)
 | |
| {
 | |
|     lame_internal_flags *const gfc = gfp->internal_flags;
 | |
|     SessionConfig_t *const cfg = &gfc->cfg;
 | |
| 
 | |
|     switch (gfp->quality) {
 | |
|     default:
 | |
|     case 9:            /* no psymodel, no noise shaping */
 | |
|         cfg->noise_shaping = 0;
 | |
|         cfg->noise_shaping_amp = 0;
 | |
|         cfg->noise_shaping_stop = 0;
 | |
|         cfg->use_best_huffman = 0;
 | |
|         cfg->full_outer_loop = 0;
 | |
|         break;
 | |
| 
 | |
|     case 8:
 | |
|         gfp->quality = 7;
 | |
|         /*lint --fallthrough */
 | |
|     case 7:            /* use psymodel (for short block and m/s switching), but no noise shapping */
 | |
|         cfg->noise_shaping = 0;
 | |
|         cfg->noise_shaping_amp = 0;
 | |
|         cfg->noise_shaping_stop = 0;
 | |
|         cfg->use_best_huffman = 0;
 | |
|         cfg->full_outer_loop = 0;
 | |
|         if (cfg->vbr == vbr_mt || cfg->vbr == vbr_mtrh) {
 | |
|             cfg->full_outer_loop  = -1;
 | |
|         }
 | |
|         break;
 | |
| 
 | |
|     case 6:
 | |
|         if (cfg->noise_shaping == 0)
 | |
|             cfg->noise_shaping = 1;
 | |
|         cfg->noise_shaping_amp = 0;
 | |
|         cfg->noise_shaping_stop = 0;
 | |
|         if (cfg->subblock_gain == -1)
 | |
|             cfg->subblock_gain = 1;
 | |
|         cfg->use_best_huffman = 0;
 | |
|         cfg->full_outer_loop = 0;
 | |
|         break;
 | |
| 
 | |
|     case 5:
 | |
|         if (cfg->noise_shaping == 0)
 | |
|             cfg->noise_shaping = 1;
 | |
|         cfg->noise_shaping_amp = 0;
 | |
|         cfg->noise_shaping_stop = 0;
 | |
|         if (cfg->subblock_gain == -1)
 | |
|             cfg->subblock_gain = 1;
 | |
|         cfg->use_best_huffman = 0;
 | |
|         cfg->full_outer_loop = 0;
 | |
|         break;
 | |
| 
 | |
|     case 4:
 | |
|         if (cfg->noise_shaping == 0)
 | |
|             cfg->noise_shaping = 1;
 | |
|         cfg->noise_shaping_amp = 0;
 | |
|         cfg->noise_shaping_stop = 0;
 | |
|         if (cfg->subblock_gain == -1)
 | |
|             cfg->subblock_gain = 1;
 | |
|         cfg->use_best_huffman = 1;
 | |
|         cfg->full_outer_loop = 0;
 | |
|         break;
 | |
| 
 | |
|     case 3:
 | |
|         if (cfg->noise_shaping == 0)
 | |
|             cfg->noise_shaping = 1;
 | |
|         cfg->noise_shaping_amp = 1;
 | |
|         cfg->noise_shaping_stop = 1;
 | |
|         if (cfg->subblock_gain == -1)
 | |
|             cfg->subblock_gain = 1;
 | |
|         cfg->use_best_huffman = 1;
 | |
|         cfg->full_outer_loop = 0;
 | |
|         break;
 | |
| 
 | |
|     case 2:
 | |
|         if (cfg->noise_shaping == 0)
 | |
|             cfg->noise_shaping = 1;
 | |
|         if (gfc->sv_qnt.substep_shaping == 0)
 | |
|             gfc->sv_qnt.substep_shaping = 2;
 | |
|         cfg->noise_shaping_amp = 1;
 | |
|         cfg->noise_shaping_stop = 1;
 | |
|         if (cfg->subblock_gain == -1)
 | |
|             cfg->subblock_gain = 1;
 | |
|         cfg->use_best_huffman = 1; /* inner loop */
 | |
|         cfg->full_outer_loop = 0;
 | |
|         break;
 | |
| 
 | |
|     case 1:
 | |
|         if (cfg->noise_shaping == 0)
 | |
|             cfg->noise_shaping = 1;
 | |
|         if (gfc->sv_qnt.substep_shaping == 0)
 | |
|             gfc->sv_qnt.substep_shaping = 2;
 | |
|         cfg->noise_shaping_amp = 2;
 | |
|         cfg->noise_shaping_stop = 1;
 | |
|         if (cfg->subblock_gain == -1)
 | |
|             cfg->subblock_gain = 1;
 | |
|         cfg->use_best_huffman = 1;
 | |
|         cfg->full_outer_loop = 0;
 | |
|         break;
 | |
| 
 | |
|     case 0:
 | |
|         if (cfg->noise_shaping == 0)
 | |
|             cfg->noise_shaping = 1;
 | |
|         if (gfc->sv_qnt.substep_shaping == 0)
 | |
|             gfc->sv_qnt.substep_shaping = 2;
 | |
|         cfg->noise_shaping_amp = 2;
 | |
|         cfg->noise_shaping_stop = 1;
 | |
|         if (cfg->subblock_gain == -1)
 | |
|             cfg->subblock_gain = 1;
 | |
|         cfg->use_best_huffman = 1; /*type 2 disabled because of it slowness,
 | |
|                                       in favor of full outer loop search */
 | |
|         cfg->full_outer_loop = 1;
 | |
|         break;
 | |
|     }
 | |
| 
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| static double
 | |
| linear_int(double a, double b, double m)
 | |
| {
 | |
|     return a + m * (b - a);
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| /********************************************************************
 | |
|  *   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 * gfp)
 | |
| {
 | |
| 
 | |
|     int     i;
 | |
|     int     j;
 | |
|     lame_internal_flags *gfc;
 | |
|     SessionConfig_t *cfg;
 | |
| 
 | |
|     if (!is_lame_global_flags_valid(gfp)) 
 | |
|         return -1;
 | |
| 
 | |
|     gfc = gfp->internal_flags;
 | |
|     if (gfc == 0) 
 | |
|         return -1;
 | |
| 
 | |
|     if (is_lame_internal_flags_valid(gfc))
 | |
|         return -1; /* already initialized */
 | |
| 
 | |
|     /* start updating lame internal flags */
 | |
|     gfc->class_id = LAME_ID;
 | |
|     gfc->lame_init_params_successful = 0; /* will be set to one, when we get through until the end */
 | |
| 
 | |
|     if (gfp->samplerate_in < 1)
 | |
|         return -1; /* input sample rate makes no sense */
 | |
|     if (gfp->num_channels < 1 || 2 < gfp->num_channels)
 | |
|         return -1; /* number of input channels makes no sense */
 | |
|     if (gfp->samplerate_out != 0) {
 | |
|         int   v=0;
 | |
|         if (SmpFrqIndex(gfp->samplerate_out, &v) < 0)
 | |
|             return -1; /* output sample rate makes no sense */
 | |
|     }
 | |
| 
 | |
|     cfg = &gfc->cfg;
 | |
| 
 | |
|     cfg->enforce_min_bitrate = gfp->VBR_hard_min;
 | |
|     cfg->analysis = gfp->analysis;
 | |
|     if (cfg->analysis)
 | |
|         gfp->write_lame_tag = 0;
 | |
| 
 | |
|     /* some file options not allowed if output is: not specified or stdout */
 | |
|     if (gfc->pinfo != NULL)
 | |
|         gfp->write_lame_tag = 0; /* disable Xing VBR tag */
 | |
| 
 | |
|     /* report functions */
 | |
|     gfc->report_msg = gfp->report.msgf;
 | |
|     gfc->report_dbg = gfp->report.debugf;
 | |
|     gfc->report_err = gfp->report.errorf;
 | |
| 
 | |
|     if (gfp->asm_optimizations.amd3dnow)
 | |
|         gfc->CPU_features.AMD_3DNow = has_3DNow();
 | |
|     else
 | |
|         gfc->CPU_features.AMD_3DNow = 0;
 | |
| 
 | |
|     if (gfp->asm_optimizations.mmx)
 | |
|         gfc->CPU_features.MMX = has_MMX();
 | |
|     else
 | |
|         gfc->CPU_features.MMX = 0;
 | |
| 
 | |
|     if (gfp->asm_optimizations.sse) {
 | |
|         gfc->CPU_features.SSE = has_SSE();
 | |
|         gfc->CPU_features.SSE2 = has_SSE2();
 | |
|     }
 | |
|     else {
 | |
|         gfc->CPU_features.SSE = 0;
 | |
|         gfc->CPU_features.SSE2 = 0;
 | |
|     }
 | |
| 
 | |
| 
 | |
|     cfg->vbr = gfp->VBR;
 | |
|     cfg->error_protection = gfp->error_protection;
 | |
|     cfg->copyright = gfp->copyright;
 | |
|     cfg->original = gfp->original;
 | |
|     cfg->extension = gfp->extension;
 | |
|     cfg->emphasis = gfp->emphasis;
 | |
| 
 | |
|     cfg->channels_in = gfp->num_channels;
 | |
|     if (cfg->channels_in == 1)
 | |
|         gfp->mode = MONO;
 | |
|     cfg->channels_out = (gfp->mode == MONO) ? 1 : 2;
 | |
|     if (gfp->mode != JOINT_STEREO)
 | |
|         gfp->force_ms = 0; /* forced mid/side stereo for j-stereo only */
 | |
|     cfg->force_ms = gfp->force_ms;
 | |
| 
 | |
|     if (cfg->vbr == vbr_off && gfp->VBR_mean_bitrate_kbps != 128 && gfp->brate == 0)
 | |
|         gfp->brate = gfp->VBR_mean_bitrate_kbps;
 | |
| 
 | |
|     switch (cfg->vbr) {
 | |
|     case vbr_off:
 | |
|     case vbr_mtrh:
 | |
|     case vbr_mt:
 | |
|         /* these modes can handle free format condition */
 | |
|         break;
 | |
|     default:
 | |
|         gfp->free_format = 0; /* mode can't be mixed with free format */
 | |
|         break;
 | |
|     }
 | |
| 
 | |
|     cfg->free_format = gfp->free_format;
 | |
| 
 | |
|     if (cfg->vbr == vbr_off && gfp->brate == 0) {
 | |
|         /* no bitrate or compression ratio specified, use 11.025 */
 | |
|         if (EQ(gfp->compression_ratio, 0.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 (cfg->vbr == vbr_off && gfp->compression_ratio > 0) {
 | |
| 
 | |
|         if (gfp->samplerate_out == 0)
 | |
|             gfp->samplerate_out = map2MP3Frequency((int) (0.97 * gfp->samplerate_in)); /* round up with a margin of 3% */
 | |
| 
 | |
|         /* choose a bitrate for the output samplerate which achieves
 | |
|          * specified compression ratio
 | |
|          */
 | |
|         gfp->brate = gfp->samplerate_out * 16 * cfg->channels_out / (1.e3 * gfp->compression_ratio);
 | |
| 
 | |
|         /* we need the version for the bitrate table look up */
 | |
|         cfg->samplerate_index = SmpFrqIndex(gfp->samplerate_out, &cfg->version);
 | |
|         assert(cfg->samplerate_index >=0);
 | |
| 
 | |
|         if (!cfg->free_format) /* for non Free Format find the nearest allowed bitrate */
 | |
|             gfp->brate = FindNearestBitrate(gfp->brate, cfg->version, gfp->samplerate_out);
 | |
|     }
 | |
|     if (gfp->samplerate_out) {
 | |
|         if (gfp->samplerate_out < 16000) {
 | |
|             gfp->VBR_mean_bitrate_kbps = Max(gfp->VBR_mean_bitrate_kbps, 8);
 | |
|             gfp->VBR_mean_bitrate_kbps = Min(gfp->VBR_mean_bitrate_kbps, 64);
 | |
|         }
 | |
|         else if (gfp->samplerate_out < 32000) {
 | |
|             gfp->VBR_mean_bitrate_kbps = Max(gfp->VBR_mean_bitrate_kbps, 8);
 | |
|             gfp->VBR_mean_bitrate_kbps = Min(gfp->VBR_mean_bitrate_kbps, 160);
 | |
|         }
 | |
|         else {
 | |
|             gfp->VBR_mean_bitrate_kbps = Max(gfp->VBR_mean_bitrate_kbps, 32);
 | |
|             gfp->VBR_mean_bitrate_kbps = Min(gfp->VBR_mean_bitrate_kbps, 320);
 | |
|         }
 | |
|     }
 | |
|     /* WORK IN PROGRESS */
 | |
|     /* mapping VBR scale to internal VBR quality settings */
 | |
|     if (gfp->samplerate_out == 0 && (cfg->vbr == vbr_mt || cfg->vbr == vbr_mtrh)) {
 | |
|         float const qval = gfp->VBR_q + gfp->VBR_q_frac;
 | |
|         struct q_map { int sr_a; float qa, qb, ta, tb; int lp; };
 | |
|         struct q_map const m[9]
 | |
|         = { {48000, 0.0,6.5,  0.0,6.5, 23700}
 | |
|           , {44100, 0.0,6.5,  0.0,6.5, 21780}
 | |
|           , {32000, 6.5,8.0,  5.2,6.5, 15800}
 | |
|           , {24000, 8.0,8.5,  5.2,6.0, 11850}
 | |
|           , {22050, 8.5,9.01, 5.2,6.5, 10892}
 | |
|           , {16000, 9.01,9.4, 4.9,6.5,  7903}
 | |
|           , {12000, 9.4,9.6,  4.5,6.0,  5928}
 | |
|           , {11025, 9.6,9.9,  5.1,6.5,  5446}
 | |
|           , { 8000, 9.9,10.,  4.9,6.5,  3952}
 | |
|         };
 | |
|         for (i = 2; i < 9; ++i) {
 | |
|             if (gfp->samplerate_in == m[i].sr_a) {
 | |
|                 if (qval < m[i].qa) {
 | |
|                     double d = qval / m[i].qa;
 | |
|                     d = d * m[i].ta;
 | |
|                     gfp->VBR_q = (int)d;
 | |
|                     gfp->VBR_q_frac = d - gfp->VBR_q;
 | |
|                 }
 | |
|             }
 | |
|             if (gfp->samplerate_in >= m[i].sr_a) {
 | |
|                 if (m[i].qa <= qval && qval < m[i].qb) {
 | |
|                     float const q_ = m[i].qb-m[i].qa;
 | |
|                     float const t_ = m[i].tb-m[i].ta;
 | |
|                     double d = m[i].ta + t_ * (qval-m[i].qa) / q_;
 | |
|                     gfp->VBR_q = (int)d;
 | |
|                     gfp->VBR_q_frac = d - gfp->VBR_q;
 | |
|                     gfp->samplerate_out = m[i].sr_a;
 | |
|                     if (gfp->lowpassfreq == 0) {
 | |
|                         gfp->lowpassfreq = -1;
 | |
|                     }
 | |
|                     break;
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /****************************************************************/
 | |
|     /* if a filter has not been enabled, see if we should add one: */
 | |
|     /****************************************************************/
 | |
|     if (gfp->lowpassfreq == 0) {
 | |
|         double  lowpass = 16000;
 | |
|         double  highpass;
 | |
| 
 | |
|         switch (cfg->vbr) {
 | |
|         case vbr_off:{
 | |
|                 optimum_bandwidth(&lowpass, &highpass, gfp->brate);
 | |
|                 break;
 | |
|             }
 | |
|         case vbr_abr:{
 | |
|                 optimum_bandwidth(&lowpass, &highpass, gfp->VBR_mean_bitrate_kbps);
 | |
|                 break;
 | |
|             }
 | |
|         case vbr_rh:{
 | |
|                 int const x[11] = {
 | |
|                     19500, 19000, 18600, 18000, 17500, 16000, 15600, 14900, 12500, 10000, 3950
 | |
|                 };
 | |
|                 if (0 <= gfp->VBR_q && gfp->VBR_q <= 9) {
 | |
|                     double  a = x[gfp->VBR_q], b = x[gfp->VBR_q + 1], m = gfp->VBR_q_frac;
 | |
|                     lowpass = linear_int(a, b, m);
 | |
|                 }
 | |
|                 else {
 | |
|                     lowpass = 19500;
 | |
|                 }
 | |
|                 break;
 | |
|             }
 | |
|         case vbr_mtrh:
 | |
|         case vbr_mt:{
 | |
|                 int const x[11] = {
 | |
|                     24000, 19500, 18500, 18000, 17500, 17000, 16500, 15600, 15200, 7230, 3950
 | |
|                 };
 | |
|                 if (0 <= gfp->VBR_q && gfp->VBR_q <= 9) {
 | |
|                     double  a = x[gfp->VBR_q], b = x[gfp->VBR_q + 1], m = gfp->VBR_q_frac;
 | |
|                     lowpass = linear_int(a, b, m);
 | |
|                 }
 | |
|                 else {
 | |
|                     lowpass = 21500;
 | |
|                 }
 | |
|                 break;
 | |
|             }
 | |
|         default:{
 | |
|                 int const x[11] = {
 | |
|                     19500, 19000, 18500, 18000, 17500, 16500, 15500, 14500, 12500, 9500, 3950
 | |
|                 };
 | |
|                 if (0 <= gfp->VBR_q && gfp->VBR_q <= 9) {
 | |
|                     double  a = x[gfp->VBR_q], b = x[gfp->VBR_q + 1], m = gfp->VBR_q_frac;
 | |
|                     lowpass = linear_int(a, b, m);
 | |
|                 }
 | |
|                 else {
 | |
|                     lowpass = 19500;
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         if (gfp->mode == MONO && (cfg->vbr == vbr_off || cfg->vbr == vbr_abr))
 | |
|             lowpass *= 1.5;
 | |
| 
 | |
|         gfp->lowpassfreq = lowpass;
 | |
|     }
 | |
| 
 | |
|     if (gfp->samplerate_out == 0) {
 | |
|         if (2 * gfp->lowpassfreq > gfp->samplerate_in) {
 | |
|             gfp->lowpassfreq = gfp->samplerate_in / 2;
 | |
|         }
 | |
|         gfp->samplerate_out = optimum_samplefreq((int) gfp->lowpassfreq, gfp->samplerate_in);
 | |
|     }
 | |
|     if (cfg->vbr == vbr_mt || cfg->vbr == vbr_mtrh) {
 | |
|         gfp->lowpassfreq = Min(24000, gfp->lowpassfreq);
 | |
|     }
 | |
|     else {
 | |
|         gfp->lowpassfreq = Min(20500, gfp->lowpassfreq);
 | |
|     }
 | |
|     gfp->lowpassfreq = Min(gfp->samplerate_out / 2, gfp->lowpassfreq);
 | |
| 
 | |
|     if (cfg->vbr == vbr_off) {
 | |
|         gfp->compression_ratio = gfp->samplerate_out * 16 * cfg->channels_out / (1.e3 * gfp->brate);
 | |
|     }
 | |
|     if (cfg->vbr == vbr_abr) {
 | |
|         gfp->compression_ratio =
 | |
|             gfp->samplerate_out * 16 * cfg->channels_out / (1.e3 * gfp->VBR_mean_bitrate_kbps);
 | |
|     }
 | |
| 
 | |
|     cfg->disable_reservoir = gfp->disable_reservoir;
 | |
|     cfg->lowpassfreq = gfp->lowpassfreq;
 | |
|     cfg->highpassfreq = gfp->highpassfreq;
 | |
|     cfg->samplerate_in = gfp->samplerate_in;
 | |
|     cfg->samplerate_out = gfp->samplerate_out;
 | |
|     cfg->mode_gr = cfg->samplerate_out <= 24000 ? 1 : 2; /* Number of granules per frame */
 | |
| 
 | |
| 
 | |
|     /*
 | |
|      *  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 (cfg->vbr) {
 | |
|     case vbr_mt:
 | |
|     case vbr_rh:
 | |
|     case vbr_mtrh:
 | |
|         {
 | |
|             /*numbers are a bit strange, but they determine the lowpass value */
 | |
|             FLOAT const cmp[] = { 5.7, 6.5, 7.3, 8.2, 10, 11.9, 13, 14, 15, 16.5 };
 | |
|             gfp->compression_ratio = cmp[gfp->VBR_q];
 | |
|         }
 | |
|         break;
 | |
|     case vbr_abr:
 | |
|         gfp->compression_ratio =
 | |
|             cfg->samplerate_out * 16 * cfg->channels_out / (1.e3 * gfp->VBR_mean_bitrate_kbps);
 | |
|         break;
 | |
|     default:
 | |
|         gfp->compression_ratio = cfg->samplerate_out * 16 * cfg->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 not been set, then select J-STEREO
 | |
|      */
 | |
|     if (gfp->mode == NOT_SET) {
 | |
|         gfp->mode = JOINT_STEREO;
 | |
|     }
 | |
| 
 | |
|     cfg->mode = gfp->mode;
 | |
| 
 | |
| 
 | |
|     /* apply user driven high pass filter */
 | |
|     if (cfg->highpassfreq > 0) {
 | |
|         cfg->highpass1 = 2. * cfg->highpassfreq;
 | |
| 
 | |
|         if (gfp->highpasswidth >= 0)
 | |
|             cfg->highpass2 = 2. * (cfg->highpassfreq + gfp->highpasswidth);
 | |
|         else            /* 0% above on default */
 | |
|             cfg->highpass2 = (1 + 0.00) * 2. * cfg->highpassfreq;
 | |
| 
 | |
|         cfg->highpass1 /= cfg->samplerate_out;
 | |
|         cfg->highpass2 /= cfg->samplerate_out;
 | |
|     }
 | |
|     else {
 | |
|         cfg->highpass1 = 0;
 | |
|         cfg->highpass2 = 0;
 | |
|     }
 | |
|     /* apply user driven low pass filter */
 | |
|     cfg->lowpass1 = 0;
 | |
|     cfg->lowpass2 = 0;
 | |
|     if (cfg->lowpassfreq > 0 && cfg->lowpassfreq < (cfg->samplerate_out / 2) ) {
 | |
|         cfg->lowpass2 = 2. * cfg->lowpassfreq;
 | |
|         if (gfp->lowpasswidth >= 0) {
 | |
|             cfg->lowpass1 = 2. * (cfg->lowpassfreq - gfp->lowpasswidth);
 | |
|             if (cfg->lowpass1 < 0) /* has to be >= 0 */
 | |
|                 cfg->lowpass1 = 0;
 | |
|         }
 | |
|         else {          /* 0% below on default */
 | |
|             cfg->lowpass1 = (1 - 0.00) * 2. * cfg->lowpassfreq;
 | |
|         }
 | |
|         cfg->lowpass1 /= cfg->samplerate_out;
 | |
|         cfg->lowpass2 /= cfg->samplerate_out;
 | |
|     }
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
|   /**********************************************************************/
 | |
|     /* compute info needed for polyphase filter (filter type==0, default) */
 | |
|   /**********************************************************************/
 | |
|     lame_init_params_ppflt(gfc);
 | |
| 
 | |
| 
 | |
|   /*******************************************************
 | |
|    * samplerate and bitrate index
 | |
|    *******************************************************/
 | |
|     cfg->samplerate_index = SmpFrqIndex(cfg->samplerate_out, &cfg->version);
 | |
|     assert(cfg->samplerate_index >= 0);
 | |
| 
 | |
|     if (cfg->vbr == vbr_off) {
 | |
|         if (cfg->free_format) {
 | |
|             gfc->ov_enc.bitrate_index = 0;
 | |
|         }
 | |
|         else {
 | |
|             gfp->brate = FindNearestBitrate(gfp->brate, cfg->version, cfg->samplerate_out);
 | |
|             gfc->ov_enc.bitrate_index = BitrateIndex(gfp->brate, cfg->version, cfg->samplerate_out);
 | |
|             if (gfc->ov_enc.bitrate_index <= 0) {
 | |
|                 /* This never happens, because of preceding FindNearestBitrate!
 | |
|                  * But, set a sane value, just in case
 | |
|                  */
 | |
|                 assert(0);
 | |
|                 gfc->ov_enc.bitrate_index = 8;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     else {
 | |
|         gfc->ov_enc.bitrate_index = 1;
 | |
|     }
 | |
| 
 | |
|     init_bit_stream_w(gfc);
 | |
| 
 | |
|     j = cfg->samplerate_index + (3 * cfg->version) + 6 * (cfg->samplerate_out < 16000);
 | |
|     for (i = 0; i < SBMAX_l + 1; i++)
 | |
|         gfc->scalefac_band.l[i] = sfBandIndex[j].l[i];
 | |
| 
 | |
|     for (i = 0; i < PSFB21 + 1; i++) {
 | |
|         int const size = (gfc->scalefac_band.l[22] - gfc->scalefac_band.l[21]) / PSFB21;
 | |
|         int const start = gfc->scalefac_band.l[21] + i * size;
 | |
|         gfc->scalefac_band.psfb21[i] = start;
 | |
|     }
 | |
|     gfc->scalefac_band.psfb21[PSFB21] = 576;
 | |
| 
 | |
|     for (i = 0; i < SBMAX_s + 1; i++)
 | |
|         gfc->scalefac_band.s[i] = sfBandIndex[j].s[i];
 | |
| 
 | |
|     for (i = 0; i < PSFB12 + 1; i++) {
 | |
|         int const size = (gfc->scalefac_band.s[13] - gfc->scalefac_band.s[12]) / PSFB12;
 | |
|         int const start = gfc->scalefac_band.s[12] + i * size;
 | |
|         gfc->scalefac_band.psfb12[i] = start;
 | |
|     }
 | |
|     gfc->scalefac_band.psfb12[PSFB12] = 192;
 | |
| 
 | |
|     /* determine the mean bitrate for main data */
 | |
|     if (cfg->mode_gr == 2) /* MPEG 1 */
 | |
|         cfg->sideinfo_len = (cfg->channels_out == 1) ? 4 + 17 : 4 + 32;
 | |
|     else                /* MPEG 2 */
 | |
|         cfg->sideinfo_len = (cfg->channels_out == 1) ? 4 + 9 : 4 + 17;
 | |
| 
 | |
|     if (cfg->error_protection)
 | |
|         cfg->sideinfo_len += 2;
 | |
| 
 | |
|     {
 | |
|         int     k;
 | |
| 
 | |
|         for (k = 0; k < 19; k++)
 | |
|             gfc->sv_enc.pefirbuf[k] = 700 * cfg->mode_gr * cfg->channels_out;
 | |
| 
 | |
|         if (gfp->ATHtype == -1)
 | |
|             gfp->ATHtype = 4;
 | |
|     }
 | |
| 
 | |
|     assert(gfp->VBR_q <= 9);
 | |
|     assert(gfp->VBR_q >= 0);
 | |
| 
 | |
|     switch (cfg->vbr) {
 | |
| 
 | |
|     case vbr_mt:
 | |
|     case vbr_mtrh:{
 | |
|             if (gfp->strict_ISO < 0) {
 | |
|                 gfp->strict_ISO = MDB_MAXIMUM;
 | |
|             }
 | |
|             if (gfp->useTemporal < 0) {
 | |
|                 gfp->useTemporal = 0; /* off by default for this VBR mode */
 | |
|             }
 | |
| 
 | |
|             (void) apply_preset(gfp, 500 - (gfp->VBR_q * 10), 0);
 | |
|             /*  The newer VBR code supports only a limited
 | |
|                subset of quality levels:
 | |
|                9-5=5 are the same, uses x^3/4 quantization
 | |
|                4-0=0 are the same  5 plus best huffman divide code
 | |
|              */
 | |
|             if (gfp->quality < 0)
 | |
|                 gfp->quality = LAME_DEFAULT_QUALITY;
 | |
|             if (gfp->quality < 5)
 | |
|                 gfp->quality = 0;
 | |
|             if (gfp->quality > 7)
 | |
|                 gfp->quality = 7;
 | |
| 
 | |
|             /*  sfb21 extra only with MPEG-1 at higher sampling rates
 | |
|              */
 | |
|             if (gfp->experimentalY)
 | |
|                 gfc->sv_qnt.sfb21_extra = 0;
 | |
|             else
 | |
|                 gfc->sv_qnt.sfb21_extra = (cfg->samplerate_out > 44000);
 | |
| 
 | |
|             break;
 | |
| 
 | |
|         }
 | |
|     case vbr_rh:{
 | |
| 
 | |
|             (void) apply_preset(gfp, 500 - (gfp->VBR_q * 10), 0);
 | |
| 
 | |
|             /*  sfb21 extra only with MPEG-1 at higher sampling rates
 | |
|              */
 | |
|             if (gfp->experimentalY)
 | |
|                 gfc->sv_qnt.sfb21_extra = 0;
 | |
|             else
 | |
|                 gfc->sv_qnt.sfb21_extra = (cfg->samplerate_out > 44000);
 | |
| 
 | |
|             /*  VBR needs at least the output of GPSYCHO,
 | |
|              *  so we have to garantee that by setting a minimum
 | |
|              *  quality level, actually level 6 does it.
 | |
|              *  down to level 6
 | |
|              */
 | |
|             if (gfp->quality > 6)
 | |
|                 gfp->quality = 6;
 | |
| 
 | |
| 
 | |
|             if (gfp->quality < 0)
 | |
|                 gfp->quality = LAME_DEFAULT_QUALITY;
 | |
| 
 | |
|             break;
 | |
|         }
 | |
| 
 | |
|     default:           /* cbr/abr */  {
 | |
| 
 | |
|             /*  no sfb21 extra with CBR code
 | |
|              */
 | |
|             gfc->sv_qnt.sfb21_extra = 0;
 | |
| 
 | |
|             if (gfp->quality < 0)
 | |
|                 gfp->quality = LAME_DEFAULT_QUALITY;
 | |
| 
 | |
| 
 | |
|             if (cfg->vbr == vbr_off)
 | |
|                 (void) lame_set_VBR_mean_bitrate_kbps(gfp, gfp->brate);
 | |
|             /* second, set parameters depending on bitrate */
 | |
|             (void) apply_preset(gfp, gfp->VBR_mean_bitrate_kbps, 0);
 | |
|             gfp->VBR = cfg->vbr;
 | |
| 
 | |
|             break;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /*initialize default values common for all modes */
 | |
| 
 | |
|     gfc->sv_qnt.mask_adjust = gfp->maskingadjust;
 | |
|     gfc->sv_qnt.mask_adjust_short = gfp->maskingadjust_short;
 | |
| 
 | |
|     /*  just another daily changing developer switch  */
 | |
|     if (gfp->tune) {
 | |
|         gfc->sv_qnt.mask_adjust += gfp->tune_value_a;
 | |
|         gfc->sv_qnt.mask_adjust_short += gfp->tune_value_a;
 | |
|     }
 | |
| 
 | |
| 
 | |
|     if (cfg->vbr != vbr_off) { /* choose a min/max bitrate for VBR */
 | |
|         /* if the user didn't specify VBR_max_bitrate: */
 | |
|         cfg->vbr_min_bitrate_index = 1; /* default: allow   8 kbps (MPEG-2) or  32 kbps (MPEG-1) */
 | |
|         cfg->vbr_max_bitrate_index = 14; /* default: allow 160 kbps (MPEG-2) or 320 kbps (MPEG-1) */
 | |
|         if (cfg->samplerate_out < 16000)
 | |
|             cfg->vbr_max_bitrate_index = 8; /* default: allow 64 kbps (MPEG-2.5) */
 | |
|         if (gfp->VBR_min_bitrate_kbps) {
 | |
|             gfp->VBR_min_bitrate_kbps =
 | |
|                 FindNearestBitrate(gfp->VBR_min_bitrate_kbps, cfg->version, cfg->samplerate_out);
 | |
|             cfg->vbr_min_bitrate_index =
 | |
|                 BitrateIndex(gfp->VBR_min_bitrate_kbps, cfg->version, cfg->samplerate_out);
 | |
|             if (cfg->vbr_min_bitrate_index < 0) {
 | |
|                 /* This never happens, because of preceding FindNearestBitrate!
 | |
|                  * But, set a sane value, just in case
 | |
|                  */
 | |
|                 assert(0);
 | |
|                 cfg->vbr_min_bitrate_index = 1;
 | |
|             }
 | |
|         }
 | |
|         if (gfp->VBR_max_bitrate_kbps) {
 | |
|             gfp->VBR_max_bitrate_kbps =
 | |
|                 FindNearestBitrate(gfp->VBR_max_bitrate_kbps, cfg->version, cfg->samplerate_out);
 | |
|             cfg->vbr_max_bitrate_index =
 | |
|                 BitrateIndex(gfp->VBR_max_bitrate_kbps, cfg->version, cfg->samplerate_out);
 | |
|             if (cfg->vbr_max_bitrate_index < 0) {
 | |
|                 /* This never happens, because of preceding FindNearestBitrate!
 | |
|                  * But, set a sane value, just in case
 | |
|                  */
 | |
|                 assert(0);
 | |
|                 cfg->vbr_max_bitrate_index = cfg->samplerate_out < 16000 ? 8 : 14;
 | |
|             }
 | |
|         }
 | |
|         gfp->VBR_min_bitrate_kbps = bitrate_table[cfg->version][cfg->vbr_min_bitrate_index];
 | |
|         gfp->VBR_max_bitrate_kbps = bitrate_table[cfg->version][cfg->vbr_max_bitrate_index];
 | |
|         gfp->VBR_mean_bitrate_kbps =
 | |
|             Min(bitrate_table[cfg->version][cfg->vbr_max_bitrate_index],
 | |
|                 gfp->VBR_mean_bitrate_kbps);
 | |
|         gfp->VBR_mean_bitrate_kbps =
 | |
|             Max(bitrate_table[cfg->version][cfg->vbr_min_bitrate_index],
 | |
|                 gfp->VBR_mean_bitrate_kbps);
 | |
|     }
 | |
| 
 | |
|     cfg->preset = gfp->preset;
 | |
|     cfg->write_lame_tag = gfp->write_lame_tag;
 | |
|     gfc->sv_qnt.substep_shaping = gfp->substep_shaping;
 | |
|     cfg->noise_shaping = gfp->noise_shaping;
 | |
|     cfg->subblock_gain = gfp->subblock_gain;
 | |
|     cfg->use_best_huffman = gfp->use_best_huffman;
 | |
|     cfg->avg_bitrate = gfp->brate;
 | |
|     cfg->vbr_avg_bitrate_kbps = gfp->VBR_mean_bitrate_kbps;
 | |
|     cfg->compression_ratio = gfp->compression_ratio;
 | |
| 
 | |
|     /* initialize internal qval settings */
 | |
|     lame_init_qval(gfp);
 | |
| 
 | |
| 
 | |
|     /*  automatic ATH adjustment on
 | |
|      */
 | |
|     if (gfp->athaa_type < 0)
 | |
|         gfc->ATH->use_adjust = 3;
 | |
|     else
 | |
|         gfc->ATH->use_adjust = gfp->athaa_type;
 | |
| 
 | |
| 
 | |
|     /* initialize internal adaptive ATH settings  -jd */
 | |
|     gfc->ATH->aa_sensitivity_p = pow(10.0, gfp->athaa_sensitivity / -10.0);
 | |
| 
 | |
| 
 | |
|     if (gfp->short_blocks == short_block_not_set) {
 | |
|         gfp->short_blocks = short_block_allowed;
 | |
|     }
 | |
| 
 | |
|     /*Note Jan/2003: Many hardware decoders cannot handle short blocks in regular
 | |
|        stereo mode unless they are coupled (same type in both channels)
 | |
|        it is a rare event (1 frame per min. or so) that LAME would use
 | |
|        uncoupled short blocks, so lets turn them off until we decide
 | |
|        how to handle this.  No other encoders allow uncoupled short blocks,
 | |
|        even though it is in the standard.  */
 | |
|     /* rh 20040217: coupling makes no sense for mono and dual-mono streams
 | |
|      */
 | |
|     if (gfp->short_blocks == short_block_allowed
 | |
|         && (cfg->mode == JOINT_STEREO || cfg->mode == STEREO)) {
 | |
|         gfp->short_blocks = short_block_coupled;
 | |
|     }
 | |
| 
 | |
|     cfg->short_blocks = gfp->short_blocks;
 | |
| 
 | |
| 
 | |
|     if (lame_get_quant_comp(gfp) < 0)
 | |
|         (void) lame_set_quant_comp(gfp, 1);
 | |
|     if (lame_get_quant_comp_short(gfp) < 0)
 | |
|         (void) lame_set_quant_comp_short(gfp, 0);
 | |
| 
 | |
|     if (lame_get_msfix(gfp) < 0)
 | |
|         lame_set_msfix(gfp, 0);
 | |
| 
 | |
|     /* select psychoacoustic model */
 | |
|     (void) lame_set_exp_nspsytune(gfp, lame_get_exp_nspsytune(gfp) | 1);
 | |
| 
 | |
|     if (gfp->ATHtype < 0)
 | |
|         gfp->ATHtype = 4;
 | |
| 
 | |
|     if (gfp->ATHcurve < 0)
 | |
|         gfp->ATHcurve = 4;
 | |
| 
 | |
|     if (gfp->interChRatio < 0)
 | |
|         gfp->interChRatio = 0;
 | |
| 
 | |
|     if (gfp->useTemporal < 0)
 | |
|         gfp->useTemporal = 1; /* on by default */
 | |
| 
 | |
| 
 | |
|     cfg->interChRatio = gfp->interChRatio;
 | |
|     cfg->msfix = gfp->msfix;
 | |
|     cfg->ATH_offset_db = 0-gfp->ATH_lower_db;
 | |
|     cfg->ATH_offset_factor = powf(10.f, cfg->ATH_offset_db * 0.1f);
 | |
|     cfg->ATHcurve = gfp->ATHcurve;
 | |
|     cfg->ATHtype = gfp->ATHtype;
 | |
|     cfg->ATHonly = gfp->ATHonly;
 | |
|     cfg->ATHshort = gfp->ATHshort;
 | |
|     cfg->noATH = gfp->noATH;
 | |
| 
 | |
|     cfg->quant_comp = gfp->quant_comp;
 | |
|     cfg->quant_comp_short = gfp->quant_comp_short;
 | |
| 
 | |
|     cfg->use_temporal_masking_effect = gfp->useTemporal;
 | |
|     if (cfg->mode == JOINT_STEREO) {
 | |
|         cfg->use_safe_joint_stereo = gfp->exp_nspsytune & 2;
 | |
|     }
 | |
|     else {
 | |
|         cfg->use_safe_joint_stereo = 0;
 | |
|     }
 | |
|     {
 | |
|         cfg->adjust_bass_db = (gfp->exp_nspsytune >> 2) & 63;
 | |
|         if (cfg->adjust_bass_db >= 32.f)
 | |
|             cfg->adjust_bass_db -= 64.f;
 | |
|         cfg->adjust_bass_db *= 0.25f;
 | |
| 
 | |
|         cfg->adjust_alto_db = (gfp->exp_nspsytune >> 8) & 63;
 | |
|         if (cfg->adjust_alto_db >= 32.f)
 | |
|             cfg->adjust_alto_db -= 64.f;
 | |
|         cfg->adjust_alto_db *= 0.25f;
 | |
| 
 | |
|         cfg->adjust_treble_db = (gfp->exp_nspsytune >> 14) & 63;
 | |
|         if (cfg->adjust_treble_db >= 32.f)
 | |
|             cfg->adjust_treble_db -= 64.f;
 | |
|         cfg->adjust_treble_db *= 0.25f;
 | |
| 
 | |
|         /*  to be compatible with Naoki's original code, the next 6 bits
 | |
|          *  define only the amount of changing treble for sfb21 */
 | |
|         cfg->adjust_sfb21_db = (gfp->exp_nspsytune >> 20) & 63;
 | |
|         if (cfg->adjust_sfb21_db >= 32.f)
 | |
|             cfg->adjust_sfb21_db -= 64.f;
 | |
|         cfg->adjust_sfb21_db *= 0.25f;
 | |
|         cfg->adjust_sfb21_db += cfg->adjust_treble_db;
 | |
|     }
 | |
| 
 | |
|     /* Setting up the PCM input data transform matrix, to apply 
 | |
|      * user defined re-scaling, and or two-to-one channel downmix.
 | |
|      */
 | |
|     {
 | |
|         FLOAT   m[2][2] = { {1.0f, 0.0f}, {0.0f, 1.0f} };
 | |
| 
 | |
|         /* user selected scaling of the samples */
 | |
|         m[0][0] *= gfp->scale;
 | |
|         m[0][1] *= gfp->scale;
 | |
|         m[1][0] *= gfp->scale;
 | |
|         m[1][1] *= gfp->scale;
 | |
|         /* user selected scaling of the channel 0 (left) samples */
 | |
|         m[0][0] *= gfp->scale_left;
 | |
|         m[0][1] *= gfp->scale_left;
 | |
|         /* user selected scaling of the channel 1 (right) samples */
 | |
|         m[1][0] *= gfp->scale_right;
 | |
|         m[1][1] *= gfp->scale_right;
 | |
|         /* Downsample to Mono if 2 channels in and 1 channel out */
 | |
|         if (cfg->channels_in == 2 && cfg->channels_out == 1) {
 | |
|             m[0][0] = 0.5f * (m[0][0] + m[1][0]);
 | |
|             m[0][1] = 0.5f * (m[0][1] + m[1][1]);
 | |
|             m[1][0] = 0;
 | |
|             m[1][1] = 0;
 | |
|         }
 | |
|         cfg->pcm_transform[0][0] = m[0][0];
 | |
|         cfg->pcm_transform[0][1] = m[0][1];
 | |
|         cfg->pcm_transform[1][0] = m[1][0];
 | |
|         cfg->pcm_transform[1][1] = m[1][1];
 | |
|     }
 | |
| 
 | |
|     /* padding method as described in
 | |
|      * "MPEG-Layer3 / Bitstream Syntax and Decoding"
 | |
|      * by Martin Sieler, Ralph Sperschneider
 | |
|      *
 | |
|      * note: there is no padding for the very first frame
 | |
|      *
 | |
|      * Robert Hegemann 2000-06-22
 | |
|      */
 | |
|     gfc->sv_enc.slot_lag = gfc->sv_enc.frac_SpF = 0;
 | |
|     if (cfg->vbr == vbr_off)
 | |
|         gfc->sv_enc.slot_lag = gfc->sv_enc.frac_SpF
 | |
|             = ((cfg->version + 1) * 72000L * cfg->avg_bitrate) % cfg->samplerate_out;
 | |
| 
 | |
|     (void) lame_init_bitstream(gfp);
 | |
| 
 | |
|     iteration_init(gfc);
 | |
|     (void) psymodel_init(gfp);
 | |
| 
 | |
|     cfg->buffer_constraint = get_max_frame_buffer_size_by_constraint(cfg, gfp->strict_ISO);
 | |
| 
 | |
| 
 | |
|     cfg->findReplayGain = gfp->findReplayGain;
 | |
|     cfg->decode_on_the_fly = gfp->decode_on_the_fly;
 | |
| 
 | |
|     if (cfg->decode_on_the_fly)
 | |
|         cfg->findPeakSample = 1;
 | |
| 
 | |
|     if (cfg->findReplayGain) {
 | |
|         if (InitGainAnalysis(gfc->sv_rpg.rgdata, cfg->samplerate_out) == INIT_GAIN_ANALYSIS_ERROR) {
 | |
|             /* Actually this never happens, our samplerates are the ones RG accepts!
 | |
|              * But just in case, turn RG off
 | |
|              */
 | |
|             assert(0);
 | |
|             cfg->findReplayGain = 0;
 | |
|         }
 | |
|     }
 | |
| 
 | |
| #ifdef DECODE_ON_THE_FLY
 | |
|     if (cfg->decode_on_the_fly && !gfp->decode_only) {
 | |
|         if (gfc->hip) {
 | |
|             hip_decode_exit(gfc->hip);
 | |
|         }
 | |
|         gfc->hip = hip_decode_init();
 | |
|         /* report functions */
 | |
|         hip_set_errorf(gfc->hip, gfp->report.errorf);
 | |
|         hip_set_debugf(gfc->hip, gfp->report.debugf);
 | |
|         hip_set_msgf(gfc->hip, gfp->report.msgf);
 | |
|     }
 | |
| #endif
 | |
|     /* updating lame internal flags finished successful */
 | |
|     gfc->lame_init_params_successful = 1;
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| static void
 | |
| concatSep(char* dest, char const* sep, char const* str)
 | |
| {
 | |
|     if (*dest != 0) strcat(dest, sep);
 | |
|     strcat(dest, str);
 | |
| }
 | |
| 
 | |
| /*
 | |
|  *  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 const *const gfc = gfp->internal_flags;
 | |
|     SessionConfig_t const *const cfg = &gfc->cfg;
 | |
|     double const out_samplerate = cfg->samplerate_out;
 | |
|     double const in_samplerate = cfg->samplerate_in;
 | |
| 
 | |
|     MSGF(gfc, "LAME %s %s (%s)\n", get_lame_version(), get_lame_os_bitness(), get_lame_url());
 | |
| 
 | |
| #if (LAME_ALPHA_VERSION)
 | |
|     MSGF(gfc, "warning: alpha versions should be used for testing only\n");
 | |
| #endif
 | |
|     if (gfc->CPU_features.MMX
 | |
|         || gfc->CPU_features.AMD_3DNow || gfc->CPU_features.SSE || gfc->CPU_features.SSE2) {
 | |
|         char    text[256] = { 0 };
 | |
|         int     fft_asm_used = 0;
 | |
| #ifdef HAVE_NASM
 | |
|         if (gfc->CPU_features.AMD_3DNow) {
 | |
|             fft_asm_used = 1;
 | |
|         }
 | |
|         else if (gfc->CPU_features.SSE) {
 | |
|             fft_asm_used = 2;
 | |
|         }
 | |
| #else
 | |
| # if defined( HAVE_XMMINTRIN_H ) && defined( MIN_ARCH_SSE )
 | |
|         {
 | |
|             fft_asm_used = 3;
 | |
|         }
 | |
| # endif
 | |
| #endif
 | |
|         if (gfc->CPU_features.MMX) {
 | |
| #ifdef MMX_choose_table
 | |
|             concatSep(text, ", ", "MMX (ASM used)");
 | |
| #else
 | |
|             concatSep(text, ", ", "MMX");
 | |
| #endif
 | |
|         }
 | |
|         if (gfc->CPU_features.AMD_3DNow) {
 | |
|             concatSep(text, ", ", (fft_asm_used == 1) ? "3DNow! (ASM used)" : "3DNow!");
 | |
|         }
 | |
|         if (gfc->CPU_features.SSE) {
 | |
| #if defined(HAVE_XMMINTRIN_H)
 | |
|             concatSep(text, ", ", "SSE (ASM used)");
 | |
| #else
 | |
|             concatSep(text, ", ", (fft_asm_used == 2) ? "SSE (ASM used)" : "SSE");
 | |
| #endif
 | |
|         }
 | |
|         if (gfc->CPU_features.SSE2) {
 | |
|             concatSep(text, ", ", (fft_asm_used == 3) ? "SSE2 (ASM used)" : "SSE2");
 | |
|         }
 | |
|         MSGF(gfc, "CPU features: %s\n", text);
 | |
|     }
 | |
| 
 | |
|     if (cfg->channels_in == 2 && cfg->channels_out == 1 /* mono */ ) {
 | |
|         MSGF(gfc, "Autoconverting from stereo to mono. Setting encoding to mono mode.\n");
 | |
|     }
 | |
| 
 | |
|     if (isResamplingNecessary(cfg)) {
 | |
|         MSGF(gfc, "Resampling:  input %g kHz  output %g kHz\n",
 | |
|              1.e-3 * in_samplerate, 1.e-3 * out_samplerate);
 | |
|     }
 | |
| 
 | |
|     if (cfg->highpass2 > 0.)
 | |
|         MSGF(gfc,
 | |
|              "Using polyphase highpass filter, transition band: %5.0f Hz - %5.0f Hz\n",
 | |
|              0.5 * cfg->highpass1 * out_samplerate, 0.5 * cfg->highpass2 * out_samplerate);
 | |
|     if (0. < cfg->lowpass1 || 0. < cfg->lowpass2) {
 | |
|         MSGF(gfc,
 | |
|              "Using polyphase lowpass filter, transition band: %5.0f Hz - %5.0f Hz\n",
 | |
|              0.5 * cfg->lowpass1 * out_samplerate, 0.5 * cfg->lowpass2 * out_samplerate);
 | |
|     }
 | |
|     else {
 | |
|         MSGF(gfc, "polyphase lowpass filter disabled\n");
 | |
|     }
 | |
| 
 | |
|     if (cfg->free_format) {
 | |
|         MSGF(gfc, "Warning: many decoders cannot handle free format bitstreams\n");
 | |
|         if (cfg->avg_bitrate > 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 const *const gfc = gfp->internal_flags;
 | |
|     SessionConfig_t const *const cfg = &gfc->cfg;
 | |
|     const char *pc = "";
 | |
| 
 | |
|     /*  compiler/processor optimizations, operational, etc.
 | |
|      */
 | |
|     MSGF(gfc, "\nmisc:\n\n");
 | |
| 
 | |
|     MSGF(gfc, "\tscaling: %g\n", gfp->scale);
 | |
|     MSGF(gfc, "\tch0 (left) scaling: %g\n", gfp->scale_left);
 | |
|     MSGF(gfc, "\tch1 (right) scaling: %g\n", gfp->scale_right);
 | |
|     switch (cfg->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 Y=%d\n", gfp->experimentalY);
 | |
|     MSGF(gfc, "\t...\n");
 | |
| 
 | |
|     /*  everything controlling the stream format
 | |
|      */
 | |
|     MSGF(gfc, "\nstream format:\n\n");
 | |
|     switch (cfg->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 (cfg->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", cfg->channels_out, pc);
 | |
| 
 | |
|     switch (cfg->vbr) {
 | |
|     case vbr_off:
 | |
|         pc = "off";
 | |
|         break;
 | |
|     default:
 | |
|         pc = "all";
 | |
|         break;
 | |
|     }
 | |
|     MSGF(gfc, "\tpadding: %s\n", pc);
 | |
| 
 | |
|     if (vbr_default == cfg->vbr)
 | |
|         pc = "(default)";
 | |
|     else if (cfg->free_format)
 | |
|         pc = "(free format)";
 | |
|     else
 | |
|         pc = "";
 | |
|     switch (cfg->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 (cfg->write_lame_tag)
 | |
|         MSGF(gfc, "\tusing LAME Tag\n");
 | |
|     MSGF(gfc, "\t...\n");
 | |
| 
 | |
|     /*  everything controlling psychoacoustic settings, like ATH, etc.
 | |
|      */
 | |
|     MSGF(gfc, "\npsychoacoustic:\n\n");
 | |
| 
 | |
|     switch (cfg->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, "\tsubblock gain: %d\n", cfg->subblock_gain);
 | |
|     MSGF(gfc, "\tadjust masking: %g dB\n", gfc->sv_qnt.mask_adjust);
 | |
|     MSGF(gfc, "\tadjust masking short: %g dB\n", gfc->sv_qnt.mask_adjust_short);
 | |
|     MSGF(gfc, "\tquantization comparison: %d\n", cfg->quant_comp);
 | |
|     MSGF(gfc, "\t ^ comparison short blocks: %d\n", cfg->quant_comp_short);
 | |
|     MSGF(gfc, "\tnoise shaping: %d\n", cfg->noise_shaping);
 | |
|     MSGF(gfc, "\t ^ amplification: %d\n", cfg->noise_shaping_amp);
 | |
|     MSGF(gfc, "\t ^ stopping: %d\n", cfg->noise_shaping_stop);
 | |
| 
 | |
|     pc = "using";
 | |
|     if (cfg->ATHshort)
 | |
|         pc = "the only masking for short blocks";
 | |
|     if (cfg->ATHonly)
 | |
|         pc = "the only masking";
 | |
|     if (cfg->noATH)
 | |
|         pc = "not used";
 | |
|     MSGF(gfc, "\tATH: %s\n", pc);
 | |
|     MSGF(gfc, "\t ^ type: %d\n", cfg->ATHtype);
 | |
|     MSGF(gfc, "\t ^ shape: %g%s\n", cfg->ATHcurve, " (only for type 4)");
 | |
|     MSGF(gfc, "\t ^ level adjustement: %g dB\n", cfg->ATH_offset_db);
 | |
|     MSGF(gfc, "\t ^ adjust type: %d\n", gfc->ATH->use_adjust);
 | |
|     MSGF(gfc, "\t ^ adjust sensitivity power: %f\n", gfc->ATH->aa_sensitivity_p);
 | |
| 
 | |
|     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->sv_qnt.longfact[0]),
 | |
|          10 * log10(gfc->sv_qnt.longfact[7]),
 | |
|          10 * log10(gfc->sv_qnt.longfact[14]), 10 * log10(gfc->sv_qnt.longfact[21]));
 | |
| 
 | |
|     pc = cfg->use_temporal_masking_effect ? "yes" : "no";
 | |
|     MSGF(gfc, "\tusing temporal masking effect: %s\n", pc);
 | |
|     MSGF(gfc, "\tinterchannel masking ratio: %g\n", cfg->interChRatio);
 | |
|     MSGF(gfc, "\t...\n");
 | |
| 
 | |
|     /*  that's all ?
 | |
|      */
 | |
|     MSGF(gfc, "\n");
 | |
|     return;
 | |
| }
 | |
| 
 | |
| 
 | |
| static void
 | |
| save_gain_values(lame_internal_flags * gfc)
 | |
| {
 | |
|     SessionConfig_t const *const cfg = &gfc->cfg;
 | |
|     RpgStateVar_t const *const rsv = &gfc->sv_rpg;
 | |
|     RpgResult_t *const rov = &gfc->ov_rpg;
 | |
|     /* save the ReplayGain value */
 | |
|     if (cfg->findReplayGain) {
 | |
|         FLOAT const RadioGain = (FLOAT) GetTitleGain(rsv->rgdata);
 | |
|         if (NEQ(RadioGain, (float)GAIN_NOT_ENOUGH_SAMPLES)) {
 | |
|             rov->RadioGain = (int) floor(RadioGain * 10.0 + 0.5); /* round to nearest */
 | |
|         }
 | |
|         else {
 | |
|             rov->RadioGain = 0;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /* find the gain and scale change required for no clipping */
 | |
|     if (cfg->findPeakSample) {
 | |
|         rov->noclipGainChange = (int) ceil(log10(rov->PeakSample / 32767.0) * 20.0 * 10.0); /* round up */
 | |
| 
 | |
|         if (rov->noclipGainChange > 0) { /* clipping occurs */
 | |
|             rov->noclipScale = floor((32767.0f / rov->PeakSample) * 100.0f) / 100.0f; /* round down */
 | |
|         }
 | |
|         else            /* no clipping */
 | |
|             rov->noclipScale = -1.0f;
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| static int
 | |
| update_inbuffer_size(lame_internal_flags * gfc, const int nsamples)
 | |
| {
 | |
|     EncStateVar_t *const esv = &gfc->sv_enc;
 | |
|     if (esv->in_buffer_0 == 0 || esv->in_buffer_nsamples < nsamples) {
 | |
|         if (esv->in_buffer_0) {
 | |
|             free(esv->in_buffer_0);
 | |
|         }
 | |
|         if (esv->in_buffer_1) {
 | |
|             free(esv->in_buffer_1);
 | |
|         }
 | |
|         esv->in_buffer_0 = lame_calloc(sample_t, nsamples);
 | |
|         esv->in_buffer_1 = lame_calloc(sample_t, nsamples);
 | |
|         esv->in_buffer_nsamples = nsamples;
 | |
|     }
 | |
|     if (esv->in_buffer_0 == NULL || esv->in_buffer_1 == NULL) {
 | |
|         if (esv->in_buffer_0) {
 | |
|             free(esv->in_buffer_0);
 | |
|         }
 | |
|         if (esv->in_buffer_1) {
 | |
|             free(esv->in_buffer_1);
 | |
|         }
 | |
|         esv->in_buffer_0 = 0;
 | |
|         esv->in_buffer_1 = 0;
 | |
|         esv->in_buffer_nsamples = 0;
 | |
|         ERRORF(gfc, "Error: can't allocate in_buffer buffer\n");
 | |
|         return -2;
 | |
|     }
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| 
 | |
| static int
 | |
| calcNeeded(SessionConfig_t const * cfg)
 | |
| {
 | |
|     int     mf_needed;
 | |
|     int     pcm_samples_per_frame = 576 * cfg->mode_gr;
 | |
| 
 | |
|     /* 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 + pcm_samples_per_frame - FFTOFFSET; /* amount needed for FFT */
 | |
|     /*mf_needed = Max(mf_needed, 286 + 576 * (1 + gfc->mode_gr)); */
 | |
|     mf_needed = Max(mf_needed, 512 + pcm_samples_per_frame - 32);
 | |
| 
 | |
|     assert(MFSIZE >= mf_needed);
 | |
|     
 | |
|     return mf_needed;
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * 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
 | |
|  *
 | |
|  * NOTE: this routine uses LAME's internal PCM data representation,
 | |
|  * 'sample_t'.  It should not be used by any application.
 | |
|  * applications should use lame_encode_buffer(),
 | |
|  *                         lame_encode_buffer_float()
 | |
|  *                         lame_encode_buffer_int()
 | |
|  * etc... depending on what type of data they are working with.
 | |
| */
 | |
| static int
 | |
| lame_encode_buffer_sample_t(lame_internal_flags * gfc,
 | |
|                             int nsamples, unsigned char *mp3buf, const int mp3buf_size)
 | |
| {
 | |
|     SessionConfig_t const *const cfg = &gfc->cfg;
 | |
|     EncStateVar_t *const esv = &gfc->sv_enc;
 | |
|     int     pcm_samples_per_frame = 576 * cfg->mode_gr;
 | |
|     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 */
 | |
|     {   /* if user specifed buffer size = 0, dont check size */
 | |
|         int const buf_size = mp3buf_size == 0 ? INT_MAX : mp3buf_size;
 | |
|         mp3out = copy_buffer(gfc, mp3buf, buf_size, 0);
 | |
|     }
 | |
|     if (mp3out < 0)
 | |
|         return mp3out;  /* not enough buffer space */
 | |
|     mp3buf += mp3out;
 | |
|     mp3size += mp3out;
 | |
| 
 | |
|     in_buffer[0] = esv->in_buffer_0;
 | |
|     in_buffer[1] = esv->in_buffer_1;
 | |
| 
 | |
|     mf_needed = calcNeeded(cfg);
 | |
| 
 | |
|     mfbuf[0] = esv->mfbuf[0];
 | |
|     mfbuf[1] = esv->mfbuf[1];
 | |
| 
 | |
|     while (nsamples > 0) {
 | |
|         sample_t const *in_buffer_ptr[2];
 | |
|         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 */
 | |
| 
 | |
|         in_buffer_ptr[0] = in_buffer[0];
 | |
|         in_buffer_ptr[1] = in_buffer[1];
 | |
|         /* copy in new samples into mfbuf, with resampling */
 | |
|         fill_buffer(gfc, mfbuf, &in_buffer_ptr[0], nsamples, &n_in, &n_out);
 | |
| 
 | |
|         /* compute ReplayGain of resampled input if requested */
 | |
|         if (cfg->findReplayGain && !cfg->decode_on_the_fly)
 | |
|             if (AnalyzeSamples
 | |
|                 (gfc->sv_rpg.rgdata, &mfbuf[0][esv->mf_size], &mfbuf[1][esv->mf_size], n_out,
 | |
|                  cfg->channels_out) == GAIN_ANALYSIS_ERROR)
 | |
|                 return -6;
 | |
| 
 | |
| 
 | |
| 
 | |
|         /* update in_buffer counters */
 | |
|         nsamples -= n_in;
 | |
|         in_buffer[0] += n_in;
 | |
|         if (cfg->channels_out == 2)
 | |
|             in_buffer[1] += n_in;
 | |
| 
 | |
|         /* update mfbuf[] counters */
 | |
|         esv->mf_size += n_out;
 | |
|         assert(esv->mf_size <= MFSIZE);
 | |
|         
 | |
|         /* lame_encode_flush may have set gfc->mf_sample_to_encode to 0
 | |
|          * so we have to reinitialize it here when that happened.
 | |
|          */
 | |
|         if (esv->mf_samples_to_encode < 1) {
 | |
|             esv->mf_samples_to_encode = ENCDELAY + POSTDELAY;
 | |
|         }        
 | |
|         esv->mf_samples_to_encode += n_out;
 | |
| 
 | |
| 
 | |
|         if (esv->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 = INT_MAX;
 | |
| 
 | |
|             ret = lame_encode_mp3_frame(gfc, mfbuf[0], mfbuf[1], mp3buf, buf_size);
 | |
| 
 | |
|             if (ret < 0)
 | |
|                 return ret;
 | |
|             mp3buf += ret;
 | |
|             mp3size += ret;
 | |
| 
 | |
|             /* shift out old samples */
 | |
|             esv->mf_size -= pcm_samples_per_frame;
 | |
|             esv->mf_samples_to_encode -= pcm_samples_per_frame;
 | |
|             for (ch = 0; ch < cfg->channels_out; ch++)
 | |
|                 for (i = 0; i < esv->mf_size; i++)
 | |
|                     mfbuf[ch][i] = mfbuf[ch][i + pcm_samples_per_frame];
 | |
|         }
 | |
|     }
 | |
|     assert(nsamples == 0);
 | |
| 
 | |
|     return mp3size;
 | |
| }
 | |
| 
 | |
| enum PCMSampleType 
 | |
| {   pcm_short_type
 | |
| ,   pcm_int_type
 | |
| ,   pcm_long_type
 | |
| ,   pcm_float_type
 | |
| ,   pcm_double_type
 | |
| };
 | |
| 
 | |
| static void
 | |
| lame_copy_inbuffer(lame_internal_flags* gfc, 
 | |
|                    void const* l, void const* r, int nsamples,
 | |
|                    enum PCMSampleType pcm_type, int jump, FLOAT s)
 | |
| {
 | |
|     SessionConfig_t const *const cfg = &gfc->cfg;
 | |
|     EncStateVar_t *const esv = &gfc->sv_enc;
 | |
|     sample_t* ib0 = esv->in_buffer_0;
 | |
|     sample_t* ib1 = esv->in_buffer_1;
 | |
|     FLOAT   m[2][2];
 | |
| 
 | |
|     /* Apply user defined re-scaling */
 | |
|     m[0][0] = s * cfg->pcm_transform[0][0];
 | |
|     m[0][1] = s * cfg->pcm_transform[0][1];
 | |
|     m[1][0] = s * cfg->pcm_transform[1][0];
 | |
|     m[1][1] = s * cfg->pcm_transform[1][1];
 | |
| 
 | |
|     /* make a copy of input buffer, changing type to sample_t */
 | |
| #define COPY_AND_TRANSFORM(T) \
 | |
| { \
 | |
|     T const *bl = l, *br = r; \
 | |
|     int     i; \
 | |
|     for (i = 0; i < nsamples; i++) { \
 | |
|         sample_t const xl = *bl; \
 | |
|         sample_t const xr = *br; \
 | |
|         sample_t const u = xl * m[0][0] + xr * m[0][1]; \
 | |
|         sample_t const v = xl * m[1][0] + xr * m[1][1]; \
 | |
|         ib0[i] = u; \
 | |
|         ib1[i] = v; \
 | |
|         bl += jump; \
 | |
|         br += jump; \
 | |
|     } \
 | |
| }
 | |
|     switch ( pcm_type ) {
 | |
|     case pcm_short_type: 
 | |
|         COPY_AND_TRANSFORM(short int);
 | |
|         break;
 | |
|     case pcm_int_type:
 | |
|         COPY_AND_TRANSFORM(int);
 | |
|         break;
 | |
|     case pcm_long_type:
 | |
|         COPY_AND_TRANSFORM(long int);
 | |
|         break;
 | |
|     case pcm_float_type:
 | |
|         COPY_AND_TRANSFORM(float);
 | |
|         break;
 | |
|     case pcm_double_type:
 | |
|         COPY_AND_TRANSFORM(double);
 | |
|         break;
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| static int
 | |
| lame_encode_buffer_template(lame_global_flags * gfp,
 | |
|                             void const* buffer_l, void const* buffer_r, const int nsamples,
 | |
|                             unsigned char *mp3buf, const int mp3buf_size, enum PCMSampleType pcm_type, int aa, FLOAT norm)
 | |
| {
 | |
|     if (is_lame_global_flags_valid(gfp)) {
 | |
|         lame_internal_flags *const gfc = gfp->internal_flags;
 | |
|         if (is_lame_internal_flags_valid(gfc)) {
 | |
|             SessionConfig_t const *const cfg = &gfc->cfg;
 | |
| 
 | |
|             if (nsamples == 0)
 | |
|                 return 0;
 | |
| 
 | |
|             if (update_inbuffer_size(gfc, nsamples) != 0) {
 | |
|                 return -2;
 | |
|             }
 | |
|             /* make a copy of input buffer, changing type to sample_t */
 | |
|             if (cfg->channels_in > 1) {
 | |
|                 if (buffer_l == 0 || buffer_r == 0) {
 | |
|                     return 0;
 | |
|                 }
 | |
|                 lame_copy_inbuffer(gfc, buffer_l, buffer_r, nsamples, pcm_type, aa, norm);
 | |
|             }
 | |
|             else {
 | |
|                 if (buffer_l == 0) {
 | |
|                     return 0;
 | |
|                 }
 | |
|                 lame_copy_inbuffer(gfc, buffer_l, buffer_l, nsamples, pcm_type, aa, norm);
 | |
|             }
 | |
| 
 | |
|             return lame_encode_buffer_sample_t(gfc, nsamples, mp3buf, mp3buf_size);
 | |
|         }
 | |
|     }
 | |
|     return -3;
 | |
| }
 | |
| 
 | |
| int
 | |
| lame_encode_buffer(lame_global_flags * gfp,
 | |
|                    const short int pcm_l[], const short int pcm_r[], const int nsamples,
 | |
|                    unsigned char *mp3buf, const int mp3buf_size)
 | |
| {
 | |
|     return lame_encode_buffer_template(gfp, pcm_l, pcm_r, nsamples, mp3buf, mp3buf_size, pcm_short_type, 1, 1.0);
 | |
| }
 | |
| 
 | |
| 
 | |
| int
 | |
| lame_encode_buffer_float(lame_global_flags * gfp,
 | |
|                          const float pcm_l[], const float pcm_r[], const int nsamples,
 | |
|                          unsigned char *mp3buf, const int mp3buf_size)
 | |
| {
 | |
|     /* input is assumed to be normalized to +/- 32768 for full scale */
 | |
|     return lame_encode_buffer_template(gfp, pcm_l, pcm_r, nsamples, mp3buf, mp3buf_size, pcm_float_type, 1, 1.0);
 | |
| }
 | |
| 
 | |
| 
 | |
| int
 | |
| lame_encode_buffer_ieee_float(lame_t gfp,
 | |
|                          const float pcm_l[], const float pcm_r[], const int nsamples,
 | |
|                          unsigned char *mp3buf, const int mp3buf_size)
 | |
| {
 | |
|     /* input is assumed to be normalized to +/- 1.0 for full scale */
 | |
|     return lame_encode_buffer_template(gfp, pcm_l, pcm_r, nsamples, mp3buf, mp3buf_size, pcm_float_type, 1, 32767.0);
 | |
| }
 | |
| 
 | |
| 
 | |
| int
 | |
| lame_encode_buffer_interleaved_ieee_float(lame_t gfp,
 | |
|                          const float pcm[], const int nsamples,
 | |
|                          unsigned char *mp3buf, const int mp3buf_size)
 | |
| {
 | |
|     /* input is assumed to be normalized to +/- 1.0 for full scale */
 | |
|     return lame_encode_buffer_template(gfp, pcm, pcm+1, nsamples, mp3buf, mp3buf_size, pcm_float_type, 2, 32767.0);
 | |
| }
 | |
| 
 | |
| 
 | |
| int
 | |
| lame_encode_buffer_ieee_double(lame_t gfp,
 | |
|                          const double pcm_l[], const double pcm_r[], const int nsamples,
 | |
|                          unsigned char *mp3buf, const int mp3buf_size)
 | |
| {
 | |
|     /* input is assumed to be normalized to +/- 1.0 for full scale */
 | |
|     return lame_encode_buffer_template(gfp, pcm_l, pcm_r, nsamples, mp3buf, mp3buf_size, pcm_double_type, 1, 32767.0);
 | |
| }
 | |
| 
 | |
| 
 | |
| int
 | |
| lame_encode_buffer_interleaved_ieee_double(lame_t gfp,
 | |
|                          const double pcm[], const int nsamples,
 | |
|                          unsigned char *mp3buf, const int mp3buf_size)
 | |
| {
 | |
|     /* input is assumed to be normalized to +/- 1.0 for full scale */
 | |
|     return lame_encode_buffer_template(gfp, pcm, pcm+1, nsamples, mp3buf, mp3buf_size, pcm_double_type, 2, 32767.0);
 | |
| }
 | |
| 
 | |
| 
 | |
| int
 | |
| lame_encode_buffer_int(lame_global_flags * gfp,
 | |
|                        const int pcm_l[], const int pcm_r[], const int nsamples,
 | |
|                        unsigned char *mp3buf, const int mp3buf_size)
 | |
| {
 | |
|     /* input is assumed to be normalized to +/- MAX_INT for full scale */
 | |
|     FLOAT const norm = (1.0 / (1L << (8 * sizeof(int) - 16)));
 | |
|     return lame_encode_buffer_template(gfp, pcm_l, pcm_r, nsamples, mp3buf, mp3buf_size, pcm_int_type, 1, norm);
 | |
| }
 | |
| 
 | |
| 
 | |
| int
 | |
| lame_encode_buffer_long2(lame_global_flags * gfp,
 | |
|                          const long pcm_l[],  const long pcm_r[], const int nsamples,
 | |
|                          unsigned char *mp3buf, const int mp3buf_size)
 | |
| {
 | |
|     /* input is assumed to be normalized to +/- MAX_LONG for full scale */
 | |
|     FLOAT const norm = (1.0 / (1L << (8 * sizeof(long) - 16)));
 | |
|     return lame_encode_buffer_template(gfp, pcm_l, pcm_r, nsamples, mp3buf, mp3buf_size, pcm_long_type, 1, norm);
 | |
| }
 | |
| 
 | |
| 
 | |
| int
 | |
| lame_encode_buffer_long(lame_global_flags * gfp,
 | |
|                         const long pcm_l[], const long pcm_r[], const int nsamples,
 | |
|                         unsigned char *mp3buf, const int mp3buf_size)
 | |
| {
 | |
|     /* input is assumed to be normalized to +/- 32768 for full scale */
 | |
|     return lame_encode_buffer_template(gfp, pcm_l, pcm_r, nsamples, mp3buf, mp3buf_size, pcm_long_type, 1, 1.0);
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| int
 | |
| lame_encode_buffer_interleaved(lame_global_flags * gfp,
 | |
|                                short int pcm[], int nsamples,
 | |
|                                unsigned char *mp3buf, int mp3buf_size)
 | |
| {
 | |
|     /* input is assumed to be normalized to +/- MAX_SHORT for full scale */
 | |
|     return lame_encode_buffer_template(gfp, pcm, pcm+1, nsamples, mp3buf, mp3buf_size, pcm_short_type, 2, 1.0);
 | |
| }
 | |
| 
 | |
| 
 | |
| int
 | |
| lame_encode_buffer_interleaved_int(lame_t gfp,
 | |
|                                    const int pcm[], const int nsamples,
 | |
|                                    unsigned char *mp3buf, const int mp3buf_size)
 | |
| {
 | |
|     /* input is assumed to be normalized to +/- MAX(int) for full scale */
 | |
|     FLOAT const norm = (1.0 / (1L << (8 * sizeof(int)-16)));
 | |
|     return lame_encode_buffer_template(gfp, pcm, pcm + 1, nsamples, mp3buf, mp3buf_size, pcm_int_type, 2, norm);
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| /*****************************************************************
 | |
|  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)
 | |
| {
 | |
|     int     rc = -3;
 | |
|     if (is_lame_global_flags_valid(gfp)) {
 | |
|         lame_internal_flags *const gfc = gfp->internal_flags;
 | |
|         if (is_lame_internal_flags_valid(gfc)) {
 | |
|             flush_bitstream(gfc);
 | |
|             /* if user specifed buffer size = 0, dont check size */
 | |
|             if (mp3buffer_size == 0)
 | |
|                 mp3buffer_size = INT_MAX;
 | |
|             rc = copy_buffer(gfc, mp3buffer, mp3buffer_size, 1);
 | |
|             save_gain_values(gfc);
 | |
|         }
 | |
|     }
 | |
|     return rc;
 | |
| }
 | |
| 
 | |
| 
 | |
| /* 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)
 | |
| {
 | |
|     if (is_lame_global_flags_valid(gfp)) {
 | |
|         lame_internal_flags *const gfc = gfp->internal_flags;
 | |
|         if (gfc != 0) {
 | |
|             gfc->ov_enc.frame_number = 0;
 | |
| 
 | |
|             if (gfp->write_id3tag_automatic) {
 | |
|                 (void) id3tag_write_v2(gfp);
 | |
|             }
 | |
|             /* initialize histogram data optionally used by frontend */
 | |
|             memset(gfc->ov_enc.bitrate_channelmode_hist, 0,
 | |
|                    sizeof(gfc->ov_enc.bitrate_channelmode_hist));
 | |
|             memset(gfc->ov_enc.bitrate_blocktype_hist, 0,
 | |
|                    sizeof(gfc->ov_enc.bitrate_blocktype_hist));
 | |
| 
 | |
|             gfc->ov_rpg.PeakSample = 0.0;
 | |
| 
 | |
|             /* Write initial VBR Header to bitstream and init VBR data */
 | |
|             if (gfc->cfg.write_lame_tag)
 | |
|                 (void) InitVbrTag(gfp);
 | |
| 
 | |
| 
 | |
|             return 0;
 | |
|         }
 | |
|     }
 | |
|     return -3;
 | |
| }
 | |
| 
 | |
| 
 | |
| /*****************************************************************/
 | |
| /* 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;
 | |
|     SessionConfig_t const *cfg;
 | |
|     EncStateVar_t *esv;
 | |
|     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;
 | |
|     int     frames_left;
 | |
|     int     samples_to_encode;
 | |
|     int     pcm_samples_per_frame;
 | |
|     int     mf_needed;
 | |
|     int     is_resampling_necessary;
 | |
|     double  resample_ratio = 1;
 | |
| 
 | |
|     if (!is_lame_global_flags_valid(gfp)) {
 | |
|         return -3;
 | |
|     }
 | |
|     gfc = gfp->internal_flags;
 | |
|     if (!is_lame_internal_flags_valid(gfc)) {
 | |
|         return -3;
 | |
|     }
 | |
|     cfg = &gfc->cfg;
 | |
|     esv = &gfc->sv_enc;
 | |
|     
 | |
|     /* Was flush already called? */
 | |
|     if (esv->mf_samples_to_encode < 1) {
 | |
|         return 0;
 | |
|     }
 | |
|     pcm_samples_per_frame = 576 * cfg->mode_gr;
 | |
|     mf_needed = calcNeeded(cfg);
 | |
| 
 | |
|     samples_to_encode = esv->mf_samples_to_encode - POSTDELAY;
 | |
| 
 | |
|     memset(buffer, 0, sizeof(buffer));
 | |
|     mp3count = 0;
 | |
| 
 | |
|     is_resampling_necessary = isResamplingNecessary(cfg);
 | |
|     if (is_resampling_necessary) {
 | |
|         resample_ratio = (double)cfg->samplerate_in / (double)cfg->samplerate_out;
 | |
|         /* delay due to resampling; needs to be fixed, if resampling code gets changed */
 | |
|         samples_to_encode += 16. / resample_ratio;
 | |
|     }
 | |
|     end_padding = pcm_samples_per_frame - (samples_to_encode % pcm_samples_per_frame);
 | |
|     if (end_padding < 576)
 | |
|         end_padding += pcm_samples_per_frame;
 | |
|     gfc->ov_enc.encoder_padding = end_padding;
 | |
|     
 | |
|     frames_left = (samples_to_encode + end_padding) / pcm_samples_per_frame;
 | |
|     while (frames_left > 0 && imp3 >= 0) {
 | |
|         int const frame_num = gfc->ov_enc.frame_number;
 | |
|         int     bunch = mf_needed - esv->mf_size;
 | |
| 
 | |
|         bunch *= resample_ratio;
 | |
|         if (bunch > 1152) bunch = 1152;
 | |
|         if (bunch < 1) bunch = 1;
 | |
| 
 | |
|         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], bunch,
 | |
|                                   mp3buffer, mp3buffer_size_remaining);
 | |
| 
 | |
|         mp3buffer += imp3;
 | |
|         mp3count += imp3;
 | |
|         {   /* even a single pcm sample can produce several frames!
 | |
|              * for example: 1 Hz input file resampled to 8 kHz mpeg2.5
 | |
|              */
 | |
|             int const new_frames = gfc->ov_enc.frame_number - frame_num;
 | |
|             if (new_frames > 0)
 | |
|                 frames_left -=  new_frames;
 | |
|         }
 | |
|     }
 | |
|     /* Set esv->mf_samples_to_encode to 0, so we may detect
 | |
|      * and break loops calling it more than once in a row.
 | |
|      */
 | |
|     esv->mf_samples_to_encode = 0;
 | |
| 
 | |
|     if (imp3 < 0) {
 | |
|         /* some type of fatal error */
 | |
|         return imp3;
 | |
|     }
 | |
| 
 | |
|     mp3buffer_size_remaining = mp3buffer_size - mp3count;
 | |
|     /* if user specifed buffer size = 0, dont check size */
 | |
|     if (mp3buffer_size == 0)
 | |
|         mp3buffer_size_remaining = INT_MAX;
 | |
| 
 | |
|     /* mp3 related stuff.  bit buffer might still contain some mp3 data */
 | |
|     flush_bitstream(gfc);
 | |
|     imp3 = copy_buffer(gfc, mp3buffer, mp3buffer_size_remaining, 1);
 | |
|     save_gain_values(gfc);
 | |
|     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 = INT_MAX;
 | |
| 
 | |
|     if (gfp->write_id3tag_automatic) {
 | |
|         /* write a id3 tag to the bitstream */
 | |
|         (void) id3tag_write_v1(gfp);
 | |
| 
 | |
|         imp3 = copy_buffer(gfc, mp3buffer, mp3buffer_size_remaining, 0);
 | |
| 
 | |
|         if (imp3 < 0) {
 | |
|             return imp3;
 | |
|         }
 | |
|         mp3count += imp3;
 | |
|     }
 | |
| #if 0
 | |
|     {
 | |
|         int const ed = gfc->ov_enc.encoder_delay;
 | |
|         int const ep = gfc->ov_enc.encoder_padding;
 | |
|         int const ns = (gfc->ov_enc.frame_number * pcm_samples_per_frame) - (ed + ep);
 | |
|         double  duration = ns;
 | |
|         duration /= cfg->samplerate_out;
 | |
|         MSGF(gfc, "frames=%d\n", gfc->ov_enc.frame_number);
 | |
|         MSGF(gfc, "pcm_samples_per_frame=%d\n", pcm_samples_per_frame);
 | |
|         MSGF(gfc, "encoder delay=%d\n", ed);
 | |
|         MSGF(gfc, "encoder padding=%d\n", ep);
 | |
|         MSGF(gfc, "sample count=%d (%g)\n", ns, cfg->samplerate_in * duration);
 | |
|         MSGF(gfc, "duration=%g sec\n", duration);
 | |
|     }
 | |
| #endif
 | |
|     return mp3count;
 | |
| }
 | |
| 
 | |
| /***********************************************************************
 | |
|  *
 | |
|  *      lame_close ()
 | |
|  *
 | |
|  *  frees internal buffers
 | |
|  *
 | |
|  ***********************************************************************/
 | |
| 
 | |
| int
 | |
| lame_close(lame_global_flags * gfp)
 | |
| {
 | |
|     int     ret = 0;
 | |
|     if (gfp && gfp->class_id == LAME_ID) {
 | |
|         lame_internal_flags *const gfc = gfp->internal_flags;
 | |
|         gfp->class_id = 0;
 | |
|         if (NULL == gfc || gfc->class_id != LAME_ID) {
 | |
|             ret = -3;
 | |
|         }
 | |
|         if (NULL != gfc) {
 | |
|             gfc->lame_init_params_successful = 0;
 | |
|             gfc->class_id = 0;
 | |
|             /* this routine will free all malloc'd data in gfc, and then free gfc: */
 | |
|             freegfc(gfc);
 | |
|             gfp->internal_flags = NULL;
 | |
|         }
 | |
|         if (gfp->lame_allocated_gfp) {
 | |
|             gfp->lame_allocated_gfp = 0;
 | |
|             free(gfp);
 | |
|         }
 | |
|     }
 | |
|     return ret;
 | |
| }
 | |
| 
 | |
| /*****************************************************************/
 | |
| /* flush internal mp3 buffers, and free internal buffers         */
 | |
| /*****************************************************************/
 | |
| #if DEPRECATED_OR_OBSOLETE_CODE_REMOVED
 | |
| int CDECL
 | |
| lame_encode_finish(lame_global_flags * gfp, unsigned char *mp3buffer, int mp3buffer_size);
 | |
| #else
 | |
| #endif
 | |
| 
 | |
| int
 | |
| lame_encode_finish(lame_global_flags * gfp, unsigned char *mp3buffer, int mp3buffer_size)
 | |
| {
 | |
|     int const ret = lame_encode_flush(gfp, mp3buffer, mp3buffer_size);
 | |
| 
 | |
|     (void) lame_close(gfp);
 | |
| 
 | |
|     return ret;
 | |
| }
 | |
| 
 | |
| /*****************************************************************/
 | |
| /* write VBR Xing header, and ID3 version 1 tag, if asked for    */
 | |
| /*****************************************************************/
 | |
| void    lame_mp3_tags_fid(lame_global_flags * gfp, FILE * fpStream);
 | |
| 
 | |
| void
 | |
| lame_mp3_tags_fid(lame_global_flags * gfp, FILE * fpStream)
 | |
| {
 | |
|     lame_internal_flags *gfc;
 | |
|     SessionConfig_t const *cfg;
 | |
|     if (!is_lame_global_flags_valid(gfp)) {
 | |
|         return;
 | |
|     }
 | |
|     gfc = gfp->internal_flags;
 | |
|     if (!is_lame_internal_flags_valid(gfc)) {
 | |
|         return;
 | |
|     }
 | |
|     cfg = &gfc->cfg;
 | |
|     if (!cfg->write_lame_tag) {
 | |
|         return;
 | |
|     }
 | |
|     /* Write Xing header again */
 | |
|     if (fpStream && !fseek(fpStream, 0, SEEK_SET)) {
 | |
|         int     rc = PutVbrTag(gfp, fpStream);
 | |
|         switch (rc) {
 | |
|         default:
 | |
|             /* OK */
 | |
|             break;
 | |
| 
 | |
|         case -1:
 | |
|             ERRORF(gfc, "Error: could not update LAME tag.\n");
 | |
|             break;
 | |
| 
 | |
|         case -2:
 | |
|             ERRORF(gfc, "Error: could not update LAME tag, file not seekable.\n");
 | |
|             break;
 | |
| 
 | |
|         case -3:
 | |
|             ERRORF(gfc, "Error: could not update LAME tag, file not readable.\n");
 | |
|             break;
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| static int
 | |
| lame_init_internal_flags(lame_internal_flags* gfc)
 | |
| {
 | |
|     if (NULL == gfc)
 | |
|         return -1;
 | |
| 
 | |
|     gfc->cfg.vbr_min_bitrate_index = 1; /* not  0 ????? */
 | |
|     gfc->cfg.vbr_max_bitrate_index = 13; /* not 14 ????? */
 | |
|     gfc->cfg.decode_on_the_fly = 0;
 | |
|     gfc->cfg.findReplayGain = 0;
 | |
|     gfc->cfg.findPeakSample = 0;
 | |
| 
 | |
|     gfc->sv_qnt.OldValue[0] = 180;
 | |
|     gfc->sv_qnt.OldValue[1] = 180;
 | |
|     gfc->sv_qnt.CurrentStep[0] = 4;
 | |
|     gfc->sv_qnt.CurrentStep[1] = 4;
 | |
|     gfc->sv_qnt.masking_lower = 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->sv_enc.mf_samples_to_encode = ENCDELAY + POSTDELAY;
 | |
|     gfc->sv_enc.mf_size = ENCDELAY - MDCTDELAY; /* we pad input with this many 0's */
 | |
|     gfc->ov_enc.encoder_padding = 0;
 | |
|     gfc->ov_enc.encoder_delay = ENCDELAY;
 | |
| 
 | |
|     gfc->ov_rpg.RadioGain = 0;
 | |
|     gfc->ov_rpg.noclipGainChange = 0;
 | |
|     gfc->ov_rpg.noclipScale = -1.0;
 | |
| 
 | |
|     gfc->ATH = lame_calloc(ATH_t, 1);
 | |
|     if (NULL == gfc->ATH)
 | |
|         return -2;      /* maybe error codes should be enumerated in lame.h ?? */
 | |
| 
 | |
|     gfc->sv_rpg.rgdata = lame_calloc(replaygain_t, 1);
 | |
|     if (NULL == gfc->sv_rpg.rgdata) {
 | |
|         return -2;
 | |
|     }
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| /* initialize mp3 encoder */
 | |
| #if DEPRECATED_OR_OBSOLETE_CODE_REMOVED
 | |
| static
 | |
| #else
 | |
| #endif
 | |
| int
 | |
| lame_init_old(lame_global_flags * gfp)
 | |
| {
 | |
|     disable_FPE();      /* disable floating point exceptions */
 | |
| 
 | |
|     memset(gfp, 0, sizeof(lame_global_flags));
 | |
| 
 | |
|     gfp->class_id = LAME_ID;
 | |
| 
 | |
|     /* 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->strict_ISO = MDB_MAXIMUM;
 | |
| 
 | |
|     gfp->mode = NOT_SET;
 | |
|     gfp->original = 1;
 | |
|     gfp->samplerate_in = 44100;
 | |
|     gfp->num_channels = 2;
 | |
|     gfp->num_samples = MAX_U_32_NUM;
 | |
| 
 | |
|     gfp->write_lame_tag = 1;
 | |
|     gfp->quality = -1;
 | |
|     gfp->short_blocks = short_block_not_set;
 | |
|     gfp->subblock_gain = -1;
 | |
| 
 | |
|     gfp->lowpassfreq = 0;
 | |
|     gfp->highpassfreq = 0;
 | |
|     gfp->lowpasswidth = -1;
 | |
|     gfp->highpasswidth = -1;
 | |
| 
 | |
|     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;
 | |
| 
 | |
|     gfp->quant_comp = -1;
 | |
|     gfp->quant_comp_short = -1;
 | |
| 
 | |
|     gfp->msfix = -1;
 | |
| 
 | |
|     gfp->attackthre = -1;
 | |
|     gfp->attackthre_s = -1;
 | |
| 
 | |
|     gfp->scale = 1;
 | |
|     gfp->scale_left = 1;
 | |
|     gfp->scale_right = 1;
 | |
| 
 | |
|     gfp->ATHcurve = -1;
 | |
|     gfp->ATHtype = -1;  /* default = -1 = set in lame_init_params */
 | |
|     /* 2 = equal loudness curve */
 | |
|     gfp->athaa_sensitivity = 0.0; /* no offset */
 | |
|     gfp->athaa_type = -1;
 | |
|     gfp->useTemporal = -1;
 | |
|     gfp->interChRatio = -1;
 | |
| 
 | |
|     gfp->findReplayGain = 0;
 | |
|     gfp->decode_on_the_fly = 0;
 | |
| 
 | |
|     gfp->asm_optimizations.mmx = 1;
 | |
|     gfp->asm_optimizations.amd3dnow = 1;
 | |
|     gfp->asm_optimizations.sse = 1;
 | |
| 
 | |
|     gfp->preset = 0;
 | |
| 
 | |
|     gfp->write_id3tag_automatic = 1;
 | |
| 
 | |
|     gfp->report.debugf = &lame_report_def;
 | |
|     gfp->report.errorf = &lame_report_def;
 | |
|     gfp->report.msgf = &lame_report_def;
 | |
| 
 | |
|     gfp->internal_flags = lame_calloc(lame_internal_flags, 1);
 | |
| 
 | |
|     if (lame_init_internal_flags(gfp->internal_flags) < 0) {
 | |
|         freegfc(gfp->internal_flags);
 | |
|         gfp->internal_flags = 0;
 | |
|         return -1;
 | |
|     }
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| 
 | |
| lame_global_flags *
 | |
| lame_init(void)
 | |
| {
 | |
|     lame_global_flags *gfp;
 | |
|     int     ret;
 | |
| 
 | |
|     init_log_table();
 | |
| 
 | |
|     gfp = lame_calloc(lame_global_flags, 1);
 | |
|     if (gfp == NULL)
 | |
|         return NULL;
 | |
| 
 | |
|     ret = lame_init_old(gfp);
 | |
|     if (ret != 0) {
 | |
|         free(gfp);
 | |
|         return NULL;
 | |
|     }
 | |
| 
 | |
|     gfp->lame_allocated_gfp = 1;
 | |
|     return gfp;
 | |
| }
 | |
| 
 | |
| 
 | |
| /***********************************************************************
 | |
|  *
 | |
|  *  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_kbps(const lame_global_flags * gfp, int bitrate_kbps[14])
 | |
| {
 | |
|     if (is_lame_global_flags_valid(gfp)) {
 | |
|         lame_internal_flags const *const gfc = gfp->internal_flags;
 | |
|         if (is_lame_internal_flags_valid(gfc)) {
 | |
|             SessionConfig_t const *const cfg = &gfc->cfg;
 | |
|             int     i;
 | |
|             if (cfg->free_format) {
 | |
|                 for (i = 0; i < 14; i++)
 | |
|                     bitrate_kbps[i] = -1;
 | |
|                 bitrate_kbps[0] = cfg->avg_bitrate;
 | |
|             }
 | |
|             else {
 | |
|                 for (i = 0; i < 14; i++)
 | |
|                     bitrate_kbps[i] = bitrate_table[cfg->version][i + 1];
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| void
 | |
| lame_bitrate_hist(const lame_global_flags * gfp, int bitrate_count[14])
 | |
| {
 | |
|     if (is_lame_global_flags_valid(gfp)) {
 | |
|         lame_internal_flags const *const gfc = gfp->internal_flags;
 | |
|         if (is_lame_internal_flags_valid(gfc)) {
 | |
|             SessionConfig_t const *const cfg = &gfc->cfg;
 | |
|             EncResult_t const *const eov = &gfc->ov_enc;
 | |
|             int     i;
 | |
| 
 | |
|             if (cfg->free_format) {
 | |
|                 for (i = 0; i < 14; i++) {
 | |
|                     bitrate_count[i] = 0;
 | |
|                 }
 | |
|                 bitrate_count[0] = eov->bitrate_channelmode_hist[0][4];
 | |
|             }
 | |
|             else {
 | |
|                 for (i = 0; i < 14; i++) {
 | |
|                     bitrate_count[i] = eov->bitrate_channelmode_hist[i + 1][4];
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| void
 | |
| lame_stereo_mode_hist(const lame_global_flags * gfp, int stmode_count[4])
 | |
| {
 | |
|     if (is_lame_global_flags_valid(gfp)) {
 | |
|         lame_internal_flags const *const gfc = gfp->internal_flags;
 | |
|         if (is_lame_internal_flags_valid(gfc)) {
 | |
|             EncResult_t const *const eov = &gfc->ov_enc;
 | |
|             int     i;
 | |
| 
 | |
|             for (i = 0; i < 4; i++) {
 | |
|                 stmode_count[i] = eov->bitrate_channelmode_hist[15][i];
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| void
 | |
| lame_bitrate_stereo_mode_hist(const lame_global_flags * gfp, int bitrate_stmode_count[14][4])
 | |
| {
 | |
|     if (is_lame_global_flags_valid(gfp)) {
 | |
|         lame_internal_flags const *const gfc = gfp->internal_flags;
 | |
|         if (is_lame_internal_flags_valid(gfc)) {
 | |
|             SessionConfig_t const *const cfg = &gfc->cfg;
 | |
|             EncResult_t const *const eov = &gfc->ov_enc;
 | |
|             int     i;
 | |
|             int     j;
 | |
| 
 | |
|             if (cfg->free_format) {
 | |
|                 for (j = 0; j < 14; j++)
 | |
|                     for (i = 0; i < 4; i++) {
 | |
|                         bitrate_stmode_count[j][i] = 0;
 | |
|                     }
 | |
|                 for (i = 0; i < 4; i++) {
 | |
|                     bitrate_stmode_count[0][i] = eov->bitrate_channelmode_hist[0][i];
 | |
|                 }
 | |
|             }
 | |
|             else {
 | |
|                 for (j = 0; j < 14; j++) {
 | |
|                     for (i = 0; i < 4; i++) {
 | |
|                         bitrate_stmode_count[j][i] = eov->bitrate_channelmode_hist[j + 1][i];
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| void
 | |
| lame_block_type_hist(const lame_global_flags * gfp, int btype_count[6])
 | |
| {
 | |
|     if (is_lame_global_flags_valid(gfp)) {
 | |
|         lame_internal_flags const *const gfc = gfp->internal_flags;
 | |
|         if (is_lame_internal_flags_valid(gfc)) {
 | |
|             EncResult_t const *const eov = &gfc->ov_enc;
 | |
|             int     i;
 | |
| 
 | |
|             for (i = 0; i < 6; ++i) {
 | |
|                 btype_count[i] = eov->bitrate_blocktype_hist[15][i];
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| void
 | |
| lame_bitrate_block_type_hist(const lame_global_flags * gfp, int bitrate_btype_count[14][6])
 | |
| {
 | |
|     if (is_lame_global_flags_valid(gfp)) {
 | |
|         lame_internal_flags const *const gfc = gfp->internal_flags;
 | |
|         if (is_lame_internal_flags_valid(gfc)) {
 | |
|             SessionConfig_t const *const cfg = &gfc->cfg;
 | |
|             EncResult_t const *const eov = &gfc->ov_enc;
 | |
|             int     i, j;
 | |
| 
 | |
|             if (cfg->free_format) {
 | |
|                 for (j = 0; j < 14; ++j) {
 | |
|                     for (i = 0; i < 6; ++i) {
 | |
|                         bitrate_btype_count[j][i] = 0;
 | |
|                     }
 | |
|                 }
 | |
|                 for (i = 0; i < 6; ++i) {
 | |
|                     bitrate_btype_count[0][i] = eov->bitrate_blocktype_hist[0][i];
 | |
|                 }
 | |
|             }
 | |
|             else {
 | |
|                 for (j = 0; j < 14; ++j) {
 | |
|                     for (i = 0; i < 6; ++i) {
 | |
|                         bitrate_btype_count[j][i] = eov->bitrate_blocktype_hist[j + 1][i];
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| /* end of lame.c */
 |