mirror of
				https://github.com/cookiengineer/audacity
				synced 2025-10-31 14:13:50 +01:00 
			
		
		
		
	Using LAME 3.10 Windows project files substantially changed from original, and included into audacity solution.
		
			
				
	
	
		
			1019 lines
		
	
	
		
			25 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1019 lines
		
	
	
		
			25 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  *	lame utility library source file
 | |
|  *
 | |
|  *	Copyright (c) 1999 Albert L Faber
 | |
|  *	Copyright (c) 2000-2005 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: util.c,v 1.159 2017/09/06 15:07:30 robert Exp $ */
 | |
| 
 | |
| #ifdef HAVE_CONFIG_H
 | |
| # include <config.h>
 | |
| #endif
 | |
| 
 | |
| #include <float.h>
 | |
| #include "lame.h"
 | |
| #include "machine.h"
 | |
| #include "encoder.h"
 | |
| #include "util.h"
 | |
| #include "tables.h"
 | |
| 
 | |
| #define PRECOMPUTE
 | |
| #if defined(__FreeBSD__) && !defined(__alpha__)
 | |
| # include <machine/floatingpoint.h>
 | |
| #endif
 | |
| 
 | |
| 
 | |
| /***********************************************************************
 | |
| *
 | |
| *  Global Function Definitions
 | |
| *
 | |
| ***********************************************************************/
 | |
| /*empty and close mallocs in gfc */
 | |
| 
 | |
| void
 | |
| free_id3tag(lame_internal_flags * const gfc)
 | |
| {
 | |
|     gfc->tag_spec.language[0] = 0;
 | |
|     if (gfc->tag_spec.title != 0) {
 | |
|         free(gfc->tag_spec.title);
 | |
|         gfc->tag_spec.title = 0;
 | |
|     }
 | |
|     if (gfc->tag_spec.artist != 0) {
 | |
|         free(gfc->tag_spec.artist);
 | |
|         gfc->tag_spec.artist = 0;
 | |
|     }
 | |
|     if (gfc->tag_spec.album != 0) {
 | |
|         free(gfc->tag_spec.album);
 | |
|         gfc->tag_spec.album = 0;
 | |
|     }
 | |
|     if (gfc->tag_spec.comment != 0) {
 | |
|         free(gfc->tag_spec.comment);
 | |
|         gfc->tag_spec.comment = 0;
 | |
|     }
 | |
| 
 | |
|     if (gfc->tag_spec.albumart != 0) {
 | |
|         free(gfc->tag_spec.albumart);
 | |
|         gfc->tag_spec.albumart = 0;
 | |
|         gfc->tag_spec.albumart_size = 0;
 | |
|         gfc->tag_spec.albumart_mimetype = MIMETYPE_NONE;
 | |
|     }
 | |
|     if (gfc->tag_spec.v2_head != 0) {
 | |
|         FrameDataNode *node = gfc->tag_spec.v2_head;
 | |
|         do {
 | |
|             void   *p = node->dsc.ptr.b;
 | |
|             void   *q = node->txt.ptr.b;
 | |
|             void   *r = node;
 | |
|             node = node->nxt;
 | |
|             free(p);
 | |
|             free(q);
 | |
|             free(r);
 | |
|         } while (node != 0);
 | |
|         gfc->tag_spec.v2_head = 0;
 | |
|         gfc->tag_spec.v2_tail = 0;
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| static void
 | |
| free_global_data(lame_internal_flags * gfc)
 | |
| {
 | |
|     if (gfc && gfc->cd_psy) {
 | |
|         if (gfc->cd_psy->l.s3) {
 | |
|             /* XXX allocated in psymodel_init() */
 | |
|             free(gfc->cd_psy->l.s3);
 | |
|         }
 | |
|         if (gfc->cd_psy->s.s3) {
 | |
|             /* XXX allocated in psymodel_init() */
 | |
|             free(gfc->cd_psy->s.s3);
 | |
|         }
 | |
|         free(gfc->cd_psy);
 | |
|         gfc->cd_psy = 0;
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| void
 | |
| freegfc(lame_internal_flags * const gfc)
 | |
| {                       /* bit stream structure */
 | |
|     int     i;
 | |
| 
 | |
|     if (gfc == 0) return;
 | |
| 
 | |
|     for (i = 0; i <= 2 * BPC; i++)
 | |
|         if (gfc->sv_enc.blackfilt[i] != NULL) {
 | |
|             free(gfc->sv_enc.blackfilt[i]);
 | |
|             gfc->sv_enc.blackfilt[i] = NULL;
 | |
|         }
 | |
|     if (gfc->sv_enc.inbuf_old[0]) {
 | |
|         free(gfc->sv_enc.inbuf_old[0]);
 | |
|         gfc->sv_enc.inbuf_old[0] = NULL;
 | |
|     }
 | |
|     if (gfc->sv_enc.inbuf_old[1]) {
 | |
|         free(gfc->sv_enc.inbuf_old[1]);
 | |
|         gfc->sv_enc.inbuf_old[1] = NULL;
 | |
|     }
 | |
| 
 | |
|     if (gfc->bs.buf != NULL) {
 | |
|         free(gfc->bs.buf);
 | |
|         gfc->bs.buf = NULL;
 | |
|     }
 | |
| 
 | |
|     if (gfc->VBR_seek_table.bag) {
 | |
|         free(gfc->VBR_seek_table.bag);
 | |
|         gfc->VBR_seek_table.bag = NULL;
 | |
|         gfc->VBR_seek_table.size = 0;
 | |
|     }
 | |
|     if (gfc->ATH) {
 | |
|         free(gfc->ATH);
 | |
|     }
 | |
|     if (gfc->sv_rpg.rgdata) {
 | |
|         free(gfc->sv_rpg.rgdata);
 | |
|     }
 | |
|     if (gfc->sv_enc.in_buffer_0) {
 | |
|         free(gfc->sv_enc.in_buffer_0);
 | |
|     }
 | |
|     if (gfc->sv_enc.in_buffer_1) {
 | |
|         free(gfc->sv_enc.in_buffer_1);
 | |
|     }
 | |
|     free_id3tag(gfc);
 | |
| 
 | |
| #ifdef DECODE_ON_THE_FLY
 | |
|     if (gfc->hip) {
 | |
|         hip_decode_exit(gfc->hip);
 | |
|         gfc->hip = 0;
 | |
|     }
 | |
| #endif
 | |
| 
 | |
|     free_global_data(gfc);
 | |
| 
 | |
|     free(gfc);
 | |
| }
 | |
| 
 | |
| void
 | |
| calloc_aligned(aligned_pointer_t * ptr, unsigned int size, unsigned int bytes)
 | |
| {
 | |
|     if (ptr) {
 | |
|         if (!ptr->pointer) {
 | |
|             ptr->pointer = malloc(size + bytes);
 | |
|             if (ptr->pointer != 0) {
 | |
|                 memset(ptr->pointer, 0, size + bytes);
 | |
|                 if (bytes > 0) {
 | |
|                     ptr->aligned = (void *) ((((size_t) ptr->pointer + bytes - 1) / bytes) * bytes);
 | |
|                 }
 | |
|                 else {
 | |
|                     ptr->aligned = ptr->pointer;
 | |
|                 }
 | |
|             }
 | |
|             else {
 | |
|                 ptr->aligned = 0;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| void
 | |
| free_aligned(aligned_pointer_t * ptr)
 | |
| {
 | |
|     if (ptr) {
 | |
|         if (ptr->pointer) {
 | |
|             free(ptr->pointer);
 | |
|             ptr->pointer = 0;
 | |
|             ptr->aligned = 0;
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| /*those ATH formulas are returning
 | |
| their minimum value for input = -1*/
 | |
| 
 | |
| static  FLOAT
 | |
| ATHformula_GB(FLOAT f, FLOAT value, FLOAT f_min, FLOAT f_max)
 | |
| {
 | |
|     /* from Painter & Spanias
 | |
|        modified by Gabriel Bouvigne to better fit the reality
 | |
|        ath =    3.640 * pow(f,-0.8)
 | |
|        - 6.800 * exp(-0.6*pow(f-3.4,2.0))
 | |
|        + 6.000 * exp(-0.15*pow(f-8.7,2.0))
 | |
|        + 0.6* 0.001 * pow(f,4.0);
 | |
| 
 | |
| 
 | |
|        In the past LAME was using the Painter &Spanias formula.
 | |
|        But we had some recurrent problems with HF content.
 | |
|        We measured real ATH values, and found the older formula
 | |
|        to be inacurate in the higher part. So we made this new
 | |
|        formula and this solved most of HF problematic testcases.
 | |
|        The tradeoff is that in VBR mode it increases a lot the
 | |
|        bitrate. */
 | |
| 
 | |
| 
 | |
| /*this curve can be udjusted according to the VBR scale:
 | |
| it adjusts from something close to Painter & Spanias
 | |
| on V9 up to Bouvigne's formula for V0. This way the VBR
 | |
| bitrate is more balanced according to the -V value.*/
 | |
| 
 | |
|     FLOAT   ath;
 | |
| 
 | |
|     /* the following Hack allows to ask for the lowest value */
 | |
|     if (f < -.3)
 | |
|         f = 3410;
 | |
| 
 | |
|     f /= 1000;          /* convert to khz */
 | |
|     f = Max(f_min, f);
 | |
|     f = Min(f_max, f);
 | |
| 
 | |
|     ath = 3.640 * pow(f, -0.8)
 | |
|         - 6.800 * exp(-0.6 * pow(f - 3.4, 2.0))
 | |
|         + 6.000 * exp(-0.15 * pow(f - 8.7, 2.0))
 | |
|         + (0.6 + 0.04 * value) * 0.001 * pow(f, 4.0);
 | |
|     return ath;
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| FLOAT
 | |
| ATHformula(SessionConfig_t const *cfg, FLOAT f)
 | |
| {
 | |
|     FLOAT   ath;
 | |
|     switch (cfg->ATHtype) {
 | |
|     case 0:
 | |
|         ath = ATHformula_GB(f, 9, 0.1f, 24.0f);
 | |
|         break;
 | |
|     case 1:
 | |
|         ath = ATHformula_GB(f, -1, 0.1f, 24.0f); /*over sensitive, should probably be removed */
 | |
|         break;
 | |
|     case 2:
 | |
|         ath = ATHformula_GB(f, 0, 0.1f, 24.0f);
 | |
|         break;
 | |
|     case 3:
 | |
|         ath = ATHformula_GB(f, 1, 0.1f, 24.0f) + 6; /*modification of GB formula by Roel */
 | |
|         break;
 | |
|     case 4:
 | |
|         ath = ATHformula_GB(f, cfg->ATHcurve, 0.1f, 24.0f);
 | |
|         break;
 | |
|     case 5:
 | |
|         ath = ATHformula_GB(f, cfg->ATHcurve, 3.41f, 16.1f);
 | |
|         break;
 | |
|     default:
 | |
|         ath = ATHformula_GB(f, 0, 0.1f, 24.0f);
 | |
|         break;
 | |
|     }
 | |
|     return ath;
 | |
| }
 | |
| 
 | |
| /* see for example "Zwicker: Psychoakustik, 1982; ISBN 3-540-11401-7 */
 | |
| FLOAT
 | |
| freq2bark(FLOAT freq)
 | |
| {
 | |
|     /* input: freq in hz  output: barks */
 | |
|     if (freq < 0)
 | |
|         freq = 0;
 | |
|     freq = freq * 0.001;
 | |
|     return 13.0 * atan(.76 * freq) + 3.5 * atan(freq * freq / (7.5 * 7.5));
 | |
| }
 | |
| 
 | |
| #if 0
 | |
| extern FLOAT freq2cbw(FLOAT freq);
 | |
| 
 | |
| /* see for example "Zwicker: Psychoakustik, 1982; ISBN 3-540-11401-7 */
 | |
| FLOAT
 | |
| freq2cbw(FLOAT freq)
 | |
| {
 | |
|     /* input: freq in hz  output: critical band width */
 | |
|     freq = freq * 0.001;
 | |
|     return 25 + 75 * pow(1 + 1.4 * (freq * freq), 0.69);
 | |
| }
 | |
| 
 | |
| #endif
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| #define ABS(A) (((A)>0) ? (A) : -(A))
 | |
| 
 | |
| int
 | |
| FindNearestBitrate(int bRate, /* legal rates from 8 to 320 */
 | |
|                    int version, int samplerate)
 | |
| {                       /* MPEG-1 or MPEG-2 LSF */
 | |
|     int     bitrate;
 | |
|     int     i;
 | |
| 
 | |
|     if (samplerate < 16000)
 | |
|         version = 2;
 | |
| 
 | |
|     bitrate = bitrate_table[version][1];
 | |
| 
 | |
|     for (i = 2; i <= 14; i++) {
 | |
|         if (bitrate_table[version][i] > 0) {
 | |
|             if (ABS(bitrate_table[version][i] - bRate) < ABS(bitrate - bRate))
 | |
|                 bitrate = bitrate_table[version][i];
 | |
|         }
 | |
|     }
 | |
|     return bitrate;
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| #ifndef Min
 | |
| #define         Min(A, B)       ((A) < (B) ? (A) : (B))
 | |
| #endif
 | |
| #ifndef Max
 | |
| #define         Max(A, B)       ((A) > (B) ? (A) : (B))
 | |
| #endif
 | |
| 
 | |
| 
 | |
| /* Used to find table index when
 | |
|  * we need bitrate-based values
 | |
|  * determined using tables
 | |
|  *
 | |
|  * bitrate in kbps
 | |
|  *
 | |
|  * Gabriel Bouvigne 2002-11-03
 | |
|  */
 | |
| int
 | |
| nearestBitrateFullIndex(uint16_t bitrate)
 | |
| {
 | |
|     /* borrowed from DM abr presets */
 | |
| 
 | |
|     const int full_bitrate_table[] =
 | |
|         { 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320 };
 | |
| 
 | |
| 
 | |
|     int     lower_range = 0, lower_range_kbps = 0, upper_range = 0, upper_range_kbps = 0;
 | |
| 
 | |
| 
 | |
|     int     b;
 | |
| 
 | |
| 
 | |
|     /* We assume specified bitrate will be 320kbps */
 | |
|     upper_range_kbps = full_bitrate_table[16];
 | |
|     upper_range = 16;
 | |
|     lower_range_kbps = full_bitrate_table[16];
 | |
|     lower_range = 16;
 | |
| 
 | |
|     /* Determine which significant bitrates the value specified falls between,
 | |
|      * if loop ends without breaking then we were correct above that the value was 320
 | |
|      */
 | |
|     for (b = 0; b < 16; b++) {
 | |
|         if ((Max(bitrate, full_bitrate_table[b + 1])) != bitrate) {
 | |
|             upper_range_kbps = full_bitrate_table[b + 1];
 | |
|             upper_range = b + 1;
 | |
|             lower_range_kbps = full_bitrate_table[b];
 | |
|             lower_range = (b);
 | |
|             break;      /* We found upper range */
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /* Determine which range the value specified is closer to */
 | |
|     if ((upper_range_kbps - bitrate) > (bitrate - lower_range_kbps)) {
 | |
|         return lower_range;
 | |
|     }
 | |
|     return upper_range;
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| /* map frequency to a valid MP3 sample frequency
 | |
|  *
 | |
|  * Robert Hegemann 2000-07-01
 | |
|  */
 | |
| int
 | |
| map2MP3Frequency(int freq)
 | |
| {
 | |
|     if (freq <= 8000)
 | |
|         return 8000;
 | |
|     if (freq <= 11025)
 | |
|         return 11025;
 | |
|     if (freq <= 12000)
 | |
|         return 12000;
 | |
|     if (freq <= 16000)
 | |
|         return 16000;
 | |
|     if (freq <= 22050)
 | |
|         return 22050;
 | |
|     if (freq <= 24000)
 | |
|         return 24000;
 | |
|     if (freq <= 32000)
 | |
|         return 32000;
 | |
|     if (freq <= 44100)
 | |
|         return 44100;
 | |
| 
 | |
|     return 48000;
 | |
| }
 | |
| 
 | |
| int
 | |
| BitrateIndex(int bRate,      /* legal rates from 32 to 448 kbps */
 | |
|              int version,    /* MPEG-1 or MPEG-2/2.5 LSF */
 | |
|              int samplerate)
 | |
| {                       /* convert bitrate in kbps to index */
 | |
|     int     i;
 | |
|     if (samplerate < 16000)
 | |
|         version = 2;
 | |
|     for (i = 0; i <= 14; i++) {
 | |
|         if (bitrate_table[version][i] > 0) {
 | |
|             if (bitrate_table[version][i] == bRate) {
 | |
|                 return i;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     return -1;
 | |
| }
 | |
| 
 | |
| /* convert samp freq in Hz to index */
 | |
| 
 | |
| int
 | |
| SmpFrqIndex(int sample_freq, int *const version)
 | |
| {
 | |
|     switch (sample_freq) {
 | |
|     case 44100:
 | |
|         *version = 1;
 | |
|         return 0;
 | |
|     case 48000:
 | |
|         *version = 1;
 | |
|         return 1;
 | |
|     case 32000:
 | |
|         *version = 1;
 | |
|         return 2;
 | |
|     case 22050:
 | |
|         *version = 0;
 | |
|         return 0;
 | |
|     case 24000:
 | |
|         *version = 0;
 | |
|         return 1;
 | |
|     case 16000:
 | |
|         *version = 0;
 | |
|         return 2;
 | |
|     case 11025:
 | |
|         *version = 0;
 | |
|         return 0;
 | |
|     case 12000:
 | |
|         *version = 0;
 | |
|         return 1;
 | |
|     case 8000:
 | |
|         *version = 0;
 | |
|         return 2;
 | |
|     default:
 | |
|         *version = 0;
 | |
|         return -1;
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| /*****************************************************************************
 | |
| *
 | |
| *  End of bit_stream.c package
 | |
| *
 | |
| *****************************************************************************/
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| /* resampling via FIR filter, blackman window */
 | |
| inline static FLOAT
 | |
| blackman(FLOAT x, FLOAT fcn, int l)
 | |
| {
 | |
|     /* This algorithm from:
 | |
|        SIGNAL PROCESSING ALGORITHMS IN FORTRAN AND C
 | |
|        S.D. Stearns and R.A. David, Prentice-Hall, 1992
 | |
|      */
 | |
|     FLOAT   bkwn, x2;
 | |
|     FLOAT const wcn = (PI * fcn);
 | |
| 
 | |
|     x /= l;
 | |
|     if (x < 0)
 | |
|         x = 0;
 | |
|     if (x > 1)
 | |
|         x = 1;
 | |
|     x2 = x - .5;
 | |
| 
 | |
|     bkwn = 0.42 - 0.5 * cos(2 * x * PI) + 0.08 * cos(4 * x * PI);
 | |
|     if (fabs(x2) < 1e-9)
 | |
|         return wcn / PI;
 | |
|     else
 | |
|         return (bkwn * sin(l * wcn * x2) / (PI * l * x2));
 | |
| 
 | |
| 
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| /* gcd - greatest common divisor */
 | |
| /* Joint work of Euclid and M. Hendry */
 | |
| 
 | |
| static int
 | |
| gcd(int i, int j)
 | |
| {
 | |
|     /*    assert ( i > 0  &&  j > 0 ); */
 | |
|     return j ? gcd(j, i % j) : i;
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| static int
 | |
| fill_buffer_resample(lame_internal_flags * gfc,
 | |
|                      sample_t * outbuf,
 | |
|                      int desired_len, sample_t const *inbuf, int len, int *num_used, int ch)
 | |
| {
 | |
|     SessionConfig_t const *const cfg = &gfc->cfg;
 | |
|     EncStateVar_t *esv = &gfc->sv_enc;
 | |
|     double  resample_ratio = (double)cfg->samplerate_in / (double)cfg->samplerate_out;
 | |
|     int     BLACKSIZE;
 | |
|     FLOAT   offset, xvalue;
 | |
|     int     i, j = 0, k;
 | |
|     int     filter_l;
 | |
|     FLOAT   fcn, intratio;
 | |
|     FLOAT  *inbuf_old;
 | |
|     int     bpc;             /* number of convolution functions to pre-compute */
 | |
|     bpc = cfg->samplerate_out / gcd(cfg->samplerate_out, cfg->samplerate_in);
 | |
|     if (bpc > BPC)
 | |
|         bpc = BPC;
 | |
| 
 | |
|     intratio = (fabs(resample_ratio - floor(.5 + resample_ratio)) < FLT_EPSILON);
 | |
|     fcn = 1.00 / resample_ratio;
 | |
|     if (fcn > 1.00)
 | |
|         fcn = 1.00;
 | |
|     filter_l = 31;     /* must be odd */
 | |
|     filter_l += intratio; /* unless resample_ratio=int, it must be even */
 | |
| 
 | |
| 
 | |
|     BLACKSIZE = filter_l + 1; /* size of data needed for FIR */
 | |
| 
 | |
|     if (gfc->fill_buffer_resample_init == 0) {
 | |
|         esv->inbuf_old[0] = lame_calloc(sample_t, BLACKSIZE);
 | |
|         esv->inbuf_old[1] = lame_calloc(sample_t, BLACKSIZE);
 | |
|         for (i = 0; i <= 2 * bpc; ++i)
 | |
|             esv->blackfilt[i] = lame_calloc(sample_t, BLACKSIZE);
 | |
| 
 | |
|         esv->itime[0] = 0;
 | |
|         esv->itime[1] = 0;
 | |
| 
 | |
|         /* precompute blackman filter coefficients */
 | |
|         for (j = 0; j <= 2 * bpc; j++) {
 | |
|             FLOAT   sum = 0.;
 | |
|             offset = (j - bpc) / (2. * bpc);
 | |
|             for (i = 0; i <= filter_l; i++)
 | |
|                 sum += esv->blackfilt[j][i] = blackman(i - offset, fcn, filter_l);
 | |
|             for (i = 0; i <= filter_l; i++)
 | |
|                 esv->blackfilt[j][i] /= sum;
 | |
|         }
 | |
|         gfc->fill_buffer_resample_init = 1;
 | |
|     }
 | |
| 
 | |
|     inbuf_old = esv->inbuf_old[ch];
 | |
| 
 | |
|     /* time of j'th element in inbuf = itime + j/ifreq; */
 | |
|     /* time of k'th element in outbuf   =  j/ofreq */
 | |
|     for (k = 0; k < desired_len; k++) {
 | |
|         double  time0 = k * resample_ratio; /* time of k'th output sample */
 | |
|         int     joff;
 | |
| 
 | |
|         j = floor(time0 - esv->itime[ch]);
 | |
| 
 | |
|         /* check if we need more input data */
 | |
|         if ((filter_l + j - filter_l / 2) >= len)
 | |
|             break;
 | |
| 
 | |
|         /* blackman filter.  by default, window centered at j+.5(filter_l%2) */
 | |
|         /* but we want a window centered at time0.   */
 | |
|         offset = (time0 - esv->itime[ch] - (j + .5 * (filter_l % 2)));
 | |
|         assert(fabs(offset) <= .501);
 | |
| 
 | |
|         /* find the closest precomputed window for this offset: */
 | |
|         joff = floor((offset * 2 * bpc) + bpc + .5);
 | |
| 
 | |
|         xvalue = 0.;
 | |
|         for (i = 0; i <= filter_l; ++i) {
 | |
|             int const j2 = i + j - filter_l / 2;
 | |
|             sample_t y;
 | |
|             assert(j2 < len);
 | |
|             assert(j2 + BLACKSIZE >= 0);
 | |
|             y = (j2 < 0) ? inbuf_old[BLACKSIZE + j2] : inbuf[j2];
 | |
| #ifdef PRECOMPUTE
 | |
|             xvalue += y * esv->blackfilt[joff][i];
 | |
| #else
 | |
|             xvalue += y * blackman(i - offset, fcn, filter_l); /* very slow! */
 | |
| #endif
 | |
|         }
 | |
|         outbuf[k] = xvalue;
 | |
|     }
 | |
| 
 | |
| 
 | |
|     /* k = number of samples added to outbuf */
 | |
|     /* last k sample used data from [j-filter_l/2,j+filter_l-filter_l/2]  */
 | |
| 
 | |
|     /* how many samples of input data were used:  */
 | |
|     *num_used = Min(len, filter_l + j - filter_l / 2);
 | |
| 
 | |
|     /* adjust our input time counter.  Incriment by the number of samples used,
 | |
|      * then normalize so that next output sample is at time 0, next
 | |
|      * input buffer is at time itime[ch] */
 | |
|     esv->itime[ch] += *num_used - k * resample_ratio;
 | |
| 
 | |
|     /* save the last BLACKSIZE samples into the inbuf_old buffer */
 | |
|     if (*num_used >= BLACKSIZE) {
 | |
|         for (i = 0; i < BLACKSIZE; i++)
 | |
|             inbuf_old[i] = inbuf[*num_used + i - BLACKSIZE];
 | |
|     }
 | |
|     else {
 | |
|         /* shift in *num_used samples into inbuf_old  */
 | |
|         int const n_shift = BLACKSIZE - *num_used; /* number of samples to shift */
 | |
| 
 | |
|         /* shift n_shift samples by *num_used, to make room for the
 | |
|          * num_used new samples */
 | |
|         for (i = 0; i < n_shift; ++i)
 | |
|             inbuf_old[i] = inbuf_old[i + *num_used];
 | |
| 
 | |
|         /* shift in the *num_used samples */
 | |
|         for (j = 0; i < BLACKSIZE; ++i, ++j)
 | |
|             inbuf_old[i] = inbuf[j];
 | |
| 
 | |
|         assert(j == *num_used);
 | |
|     }
 | |
|     return k;           /* return the number samples created at the new samplerate */
 | |
| }
 | |
| 
 | |
| int
 | |
| isResamplingNecessary(SessionConfig_t const* cfg)
 | |
| {
 | |
|     int const l = cfg->samplerate_out * 0.9995f;
 | |
|     int const h = cfg->samplerate_out * 1.0005f;
 | |
|     return (cfg->samplerate_in < l) || (h < cfg->samplerate_in) ? 1 : 0;
 | |
| }
 | |
| 
 | |
| /* copy in new samples from in_buffer into mfbuf, with resampling
 | |
|    if necessary.  n_in = number of samples from the input buffer that
 | |
|    were used.  n_out = number of samples copied into mfbuf  */
 | |
| 
 | |
| void
 | |
| fill_buffer(lame_internal_flags * gfc,
 | |
|             sample_t * const mfbuf[2], sample_t const * const in_buffer[2], int nsamples, int *n_in, int *n_out)
 | |
| {
 | |
|     SessionConfig_t const *const cfg = &gfc->cfg;
 | |
|     int     mf_size = gfc->sv_enc.mf_size;
 | |
|     int     framesize = 576 * cfg->mode_gr;
 | |
|     int     nout, ch = 0;
 | |
|     int     nch = cfg->channels_out;
 | |
| 
 | |
|     /* copy in new samples into mfbuf, with resampling if necessary */
 | |
|     if (isResamplingNecessary(cfg)) {
 | |
|         do {
 | |
|             nout =
 | |
|                 fill_buffer_resample(gfc, &mfbuf[ch][mf_size],
 | |
|                                      framesize, in_buffer[ch], nsamples, n_in, ch);
 | |
|         } while (++ch < nch);
 | |
|         *n_out = nout;
 | |
|     }
 | |
|     else {
 | |
|         nout = Min(framesize, nsamples);
 | |
|         do {
 | |
|             memcpy(&mfbuf[ch][mf_size], &in_buffer[ch][0], nout * sizeof(mfbuf[0][0]));
 | |
|         } while (++ch < nch);
 | |
|         *n_out = nout;
 | |
|         *n_in = nout;
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| /***********************************************************************
 | |
| *
 | |
| *  Message Output
 | |
| *
 | |
| ***********************************************************************/
 | |
| 
 | |
| void
 | |
| lame_report_def(const char *format, va_list args)
 | |
| {
 | |
|     (void) vfprintf(stderr, format, args);
 | |
|     fflush(stderr); /* an debug function should flush immediately */
 | |
| }
 | |
| 
 | |
| void 
 | |
| lame_report_fnc(lame_report_function print_f, const char *format, ...)
 | |
| {
 | |
|     if (print_f) {
 | |
|         va_list args;
 | |
|         va_start(args, format);
 | |
|         print_f(format, args);
 | |
|         va_end(args);
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| void
 | |
| lame_debugf(const lame_internal_flags* gfc, const char *format, ...)
 | |
| {
 | |
|     if (gfc && gfc->report_dbg) {
 | |
|         va_list args;
 | |
|         va_start(args, format);
 | |
|         gfc->report_dbg(format, args);
 | |
|         va_end(args);
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| void
 | |
| lame_msgf(const lame_internal_flags* gfc, const char *format, ...)
 | |
| {
 | |
|     if (gfc && gfc->report_msg) {
 | |
|         va_list args;
 | |
|         va_start(args, format);
 | |
|         gfc->report_msg(format, args);
 | |
|         va_end(args);
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| void
 | |
| lame_errorf(const lame_internal_flags* gfc, const char *format, ...)
 | |
| {
 | |
|     if (gfc && gfc->report_err) {
 | |
|         va_list args;
 | |
|         va_start(args, format);
 | |
|         gfc->report_err(format, args);
 | |
|         va_end(args);
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| /***********************************************************************
 | |
|  *
 | |
|  *      routines to detect CPU specific features like 3DNow, MMX, SSE
 | |
|  *
 | |
|  *  donated by Frank Klemm
 | |
|  *  added Robert Hegemann 2000-10-10
 | |
|  *
 | |
|  ***********************************************************************/
 | |
| 
 | |
| #ifdef HAVE_NASM
 | |
| extern int has_MMX_nasm(void);
 | |
| extern int has_3DNow_nasm(void);
 | |
| extern int has_SSE_nasm(void);
 | |
| extern int has_SSE2_nasm(void);
 | |
| #endif
 | |
| 
 | |
| int
 | |
| has_MMX(void)
 | |
| {
 | |
| #ifdef HAVE_NASM
 | |
|     return has_MMX_nasm();
 | |
| #else
 | |
|     return 0;           /* don't know, assume not */
 | |
| #endif
 | |
| }
 | |
| 
 | |
| int
 | |
| has_3DNow(void)
 | |
| {
 | |
| #ifdef HAVE_NASM
 | |
|     return has_3DNow_nasm();
 | |
| #else
 | |
|     return 0;           /* don't know, assume not */
 | |
| #endif
 | |
| }
 | |
| 
 | |
| int
 | |
| has_SSE(void)
 | |
| {
 | |
| #ifdef HAVE_NASM
 | |
|     return has_SSE_nasm();
 | |
| #else
 | |
| #if defined( _M_X64 ) || defined( MIN_ARCH_SSE )
 | |
|     return 1;
 | |
| #else
 | |
|     return 0;           /* don't know, assume not */
 | |
| #endif
 | |
| #endif
 | |
| }
 | |
| 
 | |
| int
 | |
| has_SSE2(void)
 | |
| {
 | |
| #ifdef HAVE_NASM
 | |
|     return has_SSE2_nasm();
 | |
| #else
 | |
| #if defined( _M_X64 ) || defined( MIN_ARCH_SSE )
 | |
|     return 1;
 | |
| #else
 | |
|     return 0;           /* don't know, assume not */
 | |
| #endif
 | |
| #endif
 | |
| }
 | |
| 
 | |
| void
 | |
| disable_FPE(void)
 | |
| {
 | |
| /* extremly system dependent stuff, move to a lib to make the code readable */
 | |
| /*==========================================================================*/
 | |
| 
 | |
| 
 | |
| 
 | |
|     /*
 | |
|      *  Disable floating point exceptions
 | |
|      */
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| #if defined(__FreeBSD__) && !defined(__alpha__)
 | |
|     {
 | |
|         /* seet floating point mask to the Linux default */
 | |
|         fp_except_t mask;
 | |
|         mask = fpgetmask();
 | |
|         /* if bit is set, we get SIGFPE on that error! */
 | |
|         fpsetmask(mask & ~(FP_X_INV | FP_X_DZ));
 | |
|         /*  DEBUGF("FreeBSD mask is 0x%x\n",mask); */
 | |
|     }
 | |
| #endif
 | |
| 
 | |
| #if defined(__riscos__) && !defined(ABORTFP)
 | |
|     /* Disable FPE's under RISC OS */
 | |
|     /* if bit is set, we disable trapping that error! */
 | |
|     /*   _FPE_IVO : invalid operation */
 | |
|     /*   _FPE_DVZ : divide by zero */
 | |
|     /*   _FPE_OFL : overflow */
 | |
|     /*   _FPE_UFL : underflow */
 | |
|     /*   _FPE_INX : inexact */
 | |
|     DisableFPETraps(_FPE_IVO | _FPE_DVZ | _FPE_OFL);
 | |
| #endif
 | |
| 
 | |
|     /*
 | |
|      *  Debugging stuff
 | |
|      *  The default is to ignore FPE's, unless compiled with -DABORTFP
 | |
|      *  so add code below to ENABLE FPE's.
 | |
|      */
 | |
| 
 | |
| #if defined(ABORTFP)
 | |
| #if defined(_MSC_VER)
 | |
|     {
 | |
| #if 0
 | |
|         /* rh 061207
 | |
|            the following fix seems to be a workaround for a problem in the
 | |
|            parent process calling LAME. It would be better to fix the broken
 | |
|            application => code disabled.
 | |
|          */
 | |
| 
 | |
|         /* set affinity to a single CPU.  Fix for EAC/lame on SMP systems from
 | |
|            "Todd Richmond" <todd.richmond@openwave.com> */
 | |
|         SYSTEM_INFO si;
 | |
|         GetSystemInfo(&si);
 | |
|         SetProcessAffinityMask(GetCurrentProcess(), si.dwActiveProcessorMask);
 | |
| #endif
 | |
| #include <float.h>
 | |
|         unsigned int mask;
 | |
|         mask = _controlfp(0, 0);
 | |
|         mask &= ~(_EM_OVERFLOW | _EM_UNDERFLOW | _EM_ZERODIVIDE | _EM_INVALID);
 | |
|         mask = _controlfp(mask, _MCW_EM);
 | |
|     }
 | |
| #elif defined(__CYGWIN__)
 | |
| #  define _FPU_GETCW(cw) __asm__ ("fnstcw %0" : "=m" (*&cw))
 | |
| #  define _FPU_SETCW(cw) __asm__ ("fldcw %0" : : "m" (*&cw))
 | |
| 
 | |
| #  define _EM_INEXACT     0x00000020 /* inexact (precision) */
 | |
| #  define _EM_UNDERFLOW   0x00000010 /* underflow */
 | |
| #  define _EM_OVERFLOW    0x00000008 /* overflow */
 | |
| #  define _EM_ZERODIVIDE  0x00000004 /* zero divide */
 | |
| #  define _EM_INVALID     0x00000001 /* invalid */
 | |
|     {
 | |
|         unsigned int mask;
 | |
|         _FPU_GETCW(mask);
 | |
|         /* Set the FPU control word to abort on most FPEs */
 | |
|         mask &= ~(_EM_OVERFLOW | _EM_ZERODIVIDE | _EM_INVALID);
 | |
|         _FPU_SETCW(mask);
 | |
|     }
 | |
| # elif defined(__linux__)
 | |
|     {
 | |
| 
 | |
| #  include <fpu_control.h>
 | |
| #  ifndef _FPU_GETCW
 | |
| #  define _FPU_GETCW(cw) __asm__ ("fnstcw %0" : "=m" (*&cw))
 | |
| #  endif
 | |
| #  ifndef _FPU_SETCW
 | |
| #  define _FPU_SETCW(cw) __asm__ ("fldcw %0" : : "m" (*&cw))
 | |
| #  endif
 | |
| 
 | |
|         /* 
 | |
|          * Set the Linux mask to abort on most FPE's
 | |
|          * if bit is set, we _mask_ SIGFPE on that error!
 | |
|          *  mask &= ~( _FPU_MASK_IM | _FPU_MASK_ZM | _FPU_MASK_OM | _FPU_MASK_UM );
 | |
|          */
 | |
| 
 | |
|         unsigned int mask;
 | |
|         _FPU_GETCW(mask);
 | |
|         mask &= ~(_FPU_MASK_IM | _FPU_MASK_ZM | _FPU_MASK_OM);
 | |
|         _FPU_SETCW(mask);
 | |
|     }
 | |
| #endif
 | |
| #endif /* ABORTFP */
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| #ifdef USE_FAST_LOG
 | |
| /***********************************************************************
 | |
|  *
 | |
|  * Fast Log Approximation for log2, used to approximate every other log
 | |
|  * (log10 and log)
 | |
|  * maximum absolute error for log10 is around 10-6
 | |
|  * maximum *relative* error can be high when x is almost 1 because error/log10(x) tends toward x/e
 | |
|  *
 | |
|  * use it if typical RESULT values are > 1e-5 (for example if x>1.00001 or x<0.99999)
 | |
|  * or if the relative precision in the domain around 1 is not important (result in 1 is exact and 0)
 | |
|  *
 | |
|  ***********************************************************************/
 | |
| 
 | |
| 
 | |
| #define LOG2_SIZE       (512)
 | |
| #define LOG2_SIZE_L2    (9)
 | |
| 
 | |
| static ieee754_float32_t log_table[LOG2_SIZE + 1];
 | |
| 
 | |
| 
 | |
| 
 | |
| void
 | |
| init_log_table(void)
 | |
| {
 | |
|     int     j;
 | |
|     static int init = 0;
 | |
| 
 | |
|     /* Range for log2(x) over [1,2[ is [0,1[ */
 | |
|     assert((1 << LOG2_SIZE_L2) == LOG2_SIZE);
 | |
| 
 | |
|     if (!init) {
 | |
|         for (j = 0; j < LOG2_SIZE + 1; j++)
 | |
|             log_table[j] = log(1.0f + j / (ieee754_float32_t) LOG2_SIZE) / log(2.0f);
 | |
|     }
 | |
|     init = 1;
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| ieee754_float32_t
 | |
| fast_log2(ieee754_float32_t x)
 | |
| {
 | |
|     ieee754_float32_t log2val, partial;
 | |
|     union {
 | |
|         ieee754_float32_t f;
 | |
|         int     i;
 | |
|     } fi;
 | |
|     int     mantisse;
 | |
|     fi.f = x;
 | |
|     mantisse = fi.i & 0x7fffff;
 | |
|     log2val = ((fi.i >> 23) & 0xFF) - 0x7f;
 | |
|     partial = (mantisse & ((1 << (23 - LOG2_SIZE_L2)) - 1));
 | |
|     partial *= 1.0f / ((1 << (23 - LOG2_SIZE_L2)));
 | |
| 
 | |
| 
 | |
|     mantisse >>= (23 - LOG2_SIZE_L2);
 | |
| 
 | |
|     /* log2val += log_table[mantisse];  without interpolation the results are not good */
 | |
|     log2val += log_table[mantisse] * (1.0f - partial) + log_table[mantisse + 1] * partial;
 | |
| 
 | |
|     return log2val;
 | |
| }
 | |
| 
 | |
| #else /* Don't use FAST_LOG */
 | |
| 
 | |
| 
 | |
| void
 | |
| init_log_table(void)
 | |
| {
 | |
| }
 | |
| 
 | |
| 
 | |
| #endif
 | |
| 
 | |
| /* end of util.c */
 |