Blame libmp3lame/util.c

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