Blame frontend/get_audio.c

Packit 47f805
/*
Packit 47f805
 *      Get Audio routines source file
Packit 47f805
 *
Packit 47f805
 *      Copyright (c) 1999 Albert L Faber
Packit 47f805
 *                    2008-2017 Robert Hegemann
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: get_audio.c,v 1.167 2017/09/06 15:07:29 robert Exp $ */
Packit 47f805
Packit 47f805
Packit 47f805
#ifdef HAVE_CONFIG_H
Packit 47f805
# include <config.h>
Packit 47f805
#endif
Packit 47f805
Packit 47f805
#include <assert.h>
Packit 47f805
Packit 47f805
#ifdef HAVE_LIMITS_H
Packit 47f805
# include <limits.h>
Packit 47f805
#endif
Packit 47f805
Packit 47f805
#include <stdio.h>
Packit 47f805
Packit 47f805
#ifdef STDC_HEADERS
Packit 47f805
# include <stdlib.h>
Packit 47f805
# include <string.h>
Packit 47f805
#else
Packit 47f805
# ifndef HAVE_STRCHR
Packit 47f805
#  define strchr index
Packit 47f805
#  define strrchr rindex
Packit 47f805
# endif
Packit 47f805
char   *strchr(), *strrchr();
Packit 47f805
# ifndef HAVE_MEMCPY
Packit 47f805
#  define memcpy(d, s, n) bcopy ((s), (d), (n))
Packit 47f805
#  define memmove(d, s, n) bcopy ((s), (d), (n))
Packit 47f805
# endif
Packit 47f805
#endif
Packit 47f805
Packit 47f805
#ifdef HAVE_INTTYPES_H
Packit 47f805
# include <inttypes.h>
Packit 47f805
#else
Packit 47f805
# ifdef HAVE_STDINT_H
Packit 47f805
#  include <stdint.h>
Packit 47f805
# endif
Packit 47f805
#endif
Packit 47f805
Packit 47f805
#define         MAX_U_32_NUM            0xFFFFFFFF
Packit 47f805
Packit 47f805
Packit 47f805
#include <math.h>
Packit 47f805
Packit 47f805
#if defined(__riscos__)
Packit 47f805
# include <kernel.h>
Packit 47f805
# include <sys/swis.h>
Packit 47f805
#elif defined(_WIN32)
Packit 47f805
# include <sys/types.h>
Packit 47f805
# include <sys/stat.h>
Packit 47f805
#else
Packit 47f805
# include <sys/stat.h>
Packit 47f805
#endif
Packit 47f805
Packit 47f805
#ifdef __sun__
Packit 47f805
/* woraround for SunOS 4.x, it has SEEK_* defined here */
Packit 47f805
#include <unistd.h>
Packit 47f805
#endif
Packit 47f805
Packit 47f805
#include "lame.h"
Packit 47f805
#include "main.h"
Packit 47f805
#include "get_audio.h"
Packit 47f805
#include "lametime.h"
Packit 47f805
#include "console.h"
Packit 47f805
Packit 47f805
#ifdef WITH_DMALLOC
Packit 47f805
#include <dmalloc.h>
Packit 47f805
#endif
Packit 47f805
Packit 47f805
#ifndef STR
Packit 47f805
# define __STR(x)  #x
Packit 47f805
# define STR(x)    __STR(x)
Packit 47f805
#define __LOC__ __FILE__ "("STR(__LINE__)") : "
Packit 47f805
#endif
Packit 47f805
Packit 47f805
Packit 47f805
#define FLOAT_TO_UNSIGNED(f) ((unsigned long)(((long)((f) - 2147483648.0)) + 2147483647L + 1))
Packit 47f805
#define UNSIGNED_TO_FLOAT(u) (((double)((long)((u) - 2147483647L - 1))) + 2147483648.0)
Packit 47f805
Packit 47f805
static unsigned int uint32_high_low(unsigned char *bytes)
Packit 47f805
{
Packit 47f805
    uint32_t const hh = bytes[0];
Packit 47f805
    uint32_t const hl = bytes[1];
Packit 47f805
    uint32_t const lh = bytes[2];
Packit 47f805
    uint32_t const ll = bytes[3];
Packit 47f805
    return (hh << 24) | (hl << 16) | (lh << 8) | ll;
Packit 47f805
}
Packit 47f805
Packit 47f805
static double
Packit 47f805
read_ieee_extended_high_low(FILE * fp)
Packit 47f805
{
Packit 47f805
    unsigned char bytes[10];
Packit 47f805
    memset(bytes, 0, 10);
Packit 47f805
    fread(bytes, 1, 10, fp);
Packit 47f805
    {
Packit 47f805
        int32_t const s = (bytes[0] & 0x80);
Packit 47f805
        int32_t const e_h = (bytes[0] & 0x7F);
Packit 47f805
        int32_t const e_l = bytes[1];
Packit 47f805
        int32_t e = (e_h << 8) | e_l;
Packit 47f805
        uint32_t const hm = uint32_high_low(bytes + 2);
Packit 47f805
        uint32_t const lm = uint32_high_low(bytes + 6);
Packit 47f805
        double  result = 0;
Packit 47f805
        if (e != 0 || hm != 0 || lm != 0) {
Packit 47f805
            if (e == 0x7fff) {
Packit 47f805
                result = HUGE_VAL;
Packit 47f805
            }
Packit 47f805
            else {
Packit 47f805
                double  mantissa_h = UNSIGNED_TO_FLOAT(hm);
Packit 47f805
                double  mantissa_l = UNSIGNED_TO_FLOAT(lm);
Packit 47f805
                e -= 0x3fff;
Packit 47f805
                e -= 31;
Packit 47f805
                result = ldexp(mantissa_h, e);
Packit 47f805
                e -= 32;
Packit 47f805
                result += ldexp(mantissa_l, e);
Packit 47f805
            }
Packit 47f805
        }
Packit 47f805
        return s ? -result : result;
Packit 47f805
    }
Packit 47f805
}
Packit 47f805
Packit 47f805
Packit 47f805
static int
Packit 47f805
read_16_bits_low_high(FILE * fp)
Packit 47f805
{
Packit 47f805
    unsigned char bytes[2] = { 0, 0 };
Packit 47f805
    fread(bytes, 1, 2, fp);
Packit 47f805
    {
Packit 47f805
        int32_t const low = bytes[0];
Packit 47f805
        int32_t const high = (signed char) (bytes[1]);
Packit 47f805
        return (high << 8) | low;
Packit 47f805
    }
Packit 47f805
}
Packit 47f805
Packit 47f805
Packit 47f805
static int
Packit 47f805
read_32_bits_low_high(FILE * fp)
Packit 47f805
{
Packit 47f805
    unsigned char bytes[4] = { 0, 0, 0, 0 };
Packit 47f805
    fread(bytes, 1, 4, fp);
Packit 47f805
    {
Packit 47f805
        int32_t const low = bytes[0];
Packit 47f805
        int32_t const medl = bytes[1];
Packit 47f805
        int32_t const medh = bytes[2];
Packit 47f805
        int32_t const high = (signed char) (bytes[3]);
Packit 47f805
        return (high << 24) | (medh << 16) | (medl << 8) | low;
Packit 47f805
    }
Packit 47f805
}
Packit 47f805
Packit 47f805
static int
Packit 47f805
read_16_bits_high_low(FILE * fp)
Packit 47f805
{
Packit 47f805
    unsigned char bytes[2] = { 0, 0 };
Packit 47f805
    fread(bytes, 1, 2, fp);
Packit 47f805
    {
Packit 47f805
        int32_t const low = bytes[1];
Packit 47f805
        int32_t const high = (signed char) (bytes[0]);
Packit 47f805
        return (high << 8) | low;
Packit 47f805
    }
Packit 47f805
}
Packit 47f805
Packit 47f805
static int
Packit 47f805
read_32_bits_high_low(FILE * fp)
Packit 47f805
{
Packit 47f805
    unsigned char bytes[4] = { 0, 0, 0, 0 };
Packit 47f805
    fread(bytes, 1, 4, fp);
Packit 47f805
    {
Packit 47f805
        int32_t const low = bytes[3];
Packit 47f805
        int32_t const medl = bytes[2];
Packit 47f805
        int32_t const medh = bytes[1];
Packit 47f805
        int32_t const high = (signed char) (bytes[0]);
Packit 47f805
        return (high << 24) | (medh << 16) | (medl << 8) | low;
Packit 47f805
    }
Packit 47f805
}
Packit 47f805
Packit 47f805
static void
Packit 47f805
write_16_bits_low_high(FILE * fp, int val)
Packit 47f805
{
Packit 47f805
    unsigned char bytes[2];
Packit 47f805
    bytes[0] = (val & 0xff);
Packit 47f805
    bytes[1] = ((val >> 8) & 0xff);
Packit 47f805
    fwrite(bytes, 1, 2, fp);
Packit 47f805
}
Packit 47f805
Packit 47f805
static void
Packit 47f805
write_32_bits_low_high(FILE * fp, int val)
Packit 47f805
{
Packit 47f805
    unsigned char bytes[4];
Packit 47f805
    bytes[0] = (val & 0xff);
Packit 47f805
    bytes[1] = ((val >> 8) & 0xff);
Packit 47f805
    bytes[2] = ((val >> 16) & 0xff);
Packit 47f805
    bytes[3] = ((val >> 24) & 0xff);
Packit 47f805
    fwrite(bytes, 1, 4, fp);
Packit 47f805
}
Packit 47f805
Packit 47f805
#ifdef LIBSNDFILE
Packit 47f805
Packit 47f805
#include <sndfile.h>
Packit 47f805
Packit 47f805
Packit 47f805
#else
Packit 47f805
Packit 47f805
typedef void SNDFILE;
Packit 47f805
Packit 47f805
#endif /* ifdef LIBSNDFILE */
Packit 47f805
Packit 47f805
Packit 47f805
Packit 47f805
typedef struct blockAlign_struct {
Packit 47f805
    unsigned long offset;
Packit 47f805
    unsigned long blockSize;
Packit 47f805
} blockAlign;
Packit 47f805
Packit 47f805
typedef struct IFF_AIFF_struct {
Packit 47f805
    short   numChannels;
Packit 47f805
    unsigned long numSampleFrames;
Packit 47f805
    short   sampleSize;
Packit 47f805
    double  sampleRate;
Packit 47f805
    unsigned long sampleType;
Packit 47f805
    blockAlign blkAlgn;
Packit 47f805
} IFF_AIFF;
Packit 47f805
Packit 47f805
Packit 47f805
Packit 47f805
struct PcmBuffer {
Packit 47f805
    void   *ch[2];           /* buffer for each channel */
Packit 47f805
    int     w;               /* sample width */
Packit 47f805
    int     n;               /* number samples allocated */
Packit 47f805
    int     u;               /* number samples used */
Packit 47f805
    int     skip_start;      /* number samples to ignore at the beginning */
Packit 47f805
    int     skip_end;        /* number samples to ignore at the end */
Packit 47f805
};
Packit 47f805
Packit 47f805
typedef struct PcmBuffer PcmBuffer;
Packit 47f805
Packit 47f805
static void
Packit 47f805
initPcmBuffer(PcmBuffer * b, int w)
Packit 47f805
{
Packit 47f805
    b->ch[0] = 0;
Packit 47f805
    b->ch[1] = 0;
Packit 47f805
    b->w = w;
Packit 47f805
    b->n = 0;
Packit 47f805
    b->u = 0;
Packit 47f805
    b->skip_start = 0;
Packit 47f805
    b->skip_end = 0;
Packit 47f805
}
Packit 47f805
Packit 47f805
static void
Packit 47f805
freePcmBuffer(PcmBuffer * b)
Packit 47f805
{
Packit 47f805
    if (b != 0) {
Packit 47f805
        free(b->ch[0]);
Packit 47f805
        free(b->ch[1]);
Packit 47f805
        b->ch[0] = 0;
Packit 47f805
        b->ch[1] = 0;
Packit 47f805
        b->n = 0;
Packit 47f805
        b->u = 0;
Packit 47f805
    }
Packit 47f805
}
Packit 47f805
Packit 47f805
static int
Packit 47f805
addPcmBuffer(PcmBuffer * b, void *a0, void *a1, int read)
Packit 47f805
{
Packit 47f805
    int     a_n;
Packit 47f805
Packit 47f805
    if (b == 0) {
Packit 47f805
        return 0;
Packit 47f805
    }
Packit 47f805
    if (read < 0) {
Packit 47f805
        return b->u - b->skip_end;
Packit 47f805
    }
Packit 47f805
    if (b->skip_start >= read) {
Packit 47f805
        b->skip_start -= read;
Packit 47f805
        return b->u - b->skip_end;
Packit 47f805
    }
Packit 47f805
    a_n = read - b->skip_start;
Packit 47f805
Packit 47f805
    if (b != 0 && a_n > 0) {
Packit 47f805
        int const a_skip = b->w * b->skip_start;
Packit 47f805
        int const a_want = b->w * a_n;
Packit 47f805
        int const b_used = b->w * b->u;
Packit 47f805
        int const b_have = b->w * b->n;
Packit 47f805
        int const b_need = b->w * (b->u + a_n);
Packit 47f805
        if (b_have < b_need) {
Packit 47f805
            b->n = b->u + a_n;
Packit 47f805
            b->ch[0] = realloc(b->ch[0], b_need);
Packit 47f805
            b->ch[1] = realloc(b->ch[1], b_need);
Packit 47f805
        }
Packit 47f805
        b->u += a_n;
Packit 47f805
        if (b->ch[0] != 0 && a0 != 0) {
Packit 47f805
            char   *src = a0;
Packit 47f805
            char   *dst = b->ch[0];
Packit 47f805
            memcpy(dst + b_used, src + a_skip, a_want);
Packit 47f805
        }
Packit 47f805
        if (b->ch[1] != 0 && a1 != 0) {
Packit 47f805
            char   *src = a1;
Packit 47f805
            char   *dst = b->ch[1];
Packit 47f805
            memcpy(dst + b_used, src + a_skip, a_want);
Packit 47f805
        }
Packit 47f805
    }
Packit 47f805
    b->skip_start = 0;
Packit 47f805
    return b->u - b->skip_end;
Packit 47f805
}
Packit 47f805
Packit 47f805
static int
Packit 47f805
takePcmBuffer(PcmBuffer * b, void *a0, void *a1, int a_n, int mm)
Packit 47f805
{
Packit 47f805
    if (a_n > mm) {
Packit 47f805
        a_n = mm;
Packit 47f805
    }
Packit 47f805
    if (b != 0 && a_n > 0) {
Packit 47f805
        int const a_take = b->w * a_n;
Packit 47f805
        if (a0 != 0 && b->ch[0] != 0) {
Packit 47f805
            memcpy(a0, b->ch[0], a_take);
Packit 47f805
        }
Packit 47f805
        if (a1 != 0 && b->ch[1] != 0) {
Packit 47f805
            memcpy(a1, b->ch[1], a_take);
Packit 47f805
        }
Packit 47f805
        b->u -= a_n;
Packit 47f805
        if (b->u < 0) {
Packit 47f805
            b->u = 0;
Packit 47f805
            return a_n;
Packit 47f805
        }
Packit 47f805
        if (b->ch[0] != 0) {
Packit 47f805
            memmove(b->ch[0], (char *) b->ch[0] + a_take, b->w * b->u);
Packit 47f805
        }
Packit 47f805
        if (b->ch[1] != 0) {
Packit 47f805
            memmove(b->ch[1], (char *) b->ch[1] + a_take, b->w * b->u);
Packit 47f805
        }
Packit 47f805
    }
Packit 47f805
    return a_n;
Packit 47f805
}
Packit 47f805
Packit 47f805
/* global data for get_audio.c. */
Packit 47f805
typedef struct get_audio_global_data_struct {
Packit 47f805
    int     count_samples_carefully;
Packit 47f805
    int     pcmbitwidth;
Packit 47f805
    int     pcmswapbytes;
Packit 47f805
    int     pcm_is_unsigned_8bit;
Packit 47f805
    int     pcm_is_ieee_float;
Packit 47f805
    unsigned int num_samples_read;
Packit 47f805
    FILE   *music_in;
Packit 47f805
    SNDFILE *snd_file;
Packit 47f805
    hip_t   hip;
Packit 47f805
    PcmBuffer pcm32;
Packit 47f805
    PcmBuffer pcm16;
Packit 47f805
    size_t  in_id3v2_size;
Packit 47f805
    unsigned char* in_id3v2_tag;
Packit 47f805
} get_audio_global_data;
Packit 47f805
Packit 47f805
static get_audio_global_data global;
Packit 47f805
Packit 47f805
Packit 47f805
Packit 47f805
#ifdef AMIGA_MPEGA
Packit 47f805
int     lame_decode_initfile(const char *fullname, mp3data_struct * const mp3data);
Packit 47f805
#else
Packit 47f805
int     lame_decode_initfile(FILE * fd, mp3data_struct * mp3data, int *enc_delay, int *enc_padding);
Packit 47f805
#endif
Packit 47f805
Packit 47f805
/* read mp3 file until mpglib returns one frame of PCM data */
Packit 47f805
static int lame_decode_fromfile(FILE * fd, short int pcm_l[], short int pcm_r[],
Packit 47f805
                                mp3data_struct * mp3data);
Packit 47f805
Packit 47f805
Packit 47f805
static int read_samples_pcm(FILE * musicin, int sample_buffer[2304], int samples_to_read);
Packit 47f805
static int read_samples_mp3(lame_t gfp, FILE * musicin, short int mpg123pcm[2][1152]);
Packit 47f805
#ifdef LIBSNDFILE
Packit 47f805
static SNDFILE *open_snd_file(lame_t gfp, char const *inPath);
Packit 47f805
#endif
Packit 47f805
static FILE *open_mpeg_file(lame_t gfp, char const *inPath, int *enc_delay, int *enc_padding);
Packit 47f805
static FILE *open_wave_file(lame_t gfp, char const *inPath, int *enc_delay, int *enc_padding);
Packit 47f805
static int close_input_file(FILE * musicin);
Packit 47f805
Packit 47f805
Packit 47f805
static  size_t
Packit 47f805
min_size_t(size_t a, size_t b)
Packit 47f805
{
Packit 47f805
    if (a < b) {
Packit 47f805
        return a;
Packit 47f805
    }
Packit 47f805
    return b;
Packit 47f805
}
Packit 47f805
Packit 47f805
enum ByteOrder machine_byte_order(void);
Packit 47f805
Packit 47f805
enum ByteOrder
Packit 47f805
machine_byte_order(void)
Packit 47f805
{
Packit 47f805
    long    one = 1;
Packit 47f805
    return !(*((char *) (&one))) ? ByteOrderBigEndian : ByteOrderLittleEndian;
Packit 47f805
}
Packit 47f805
Packit 47f805
Packit 47f805
Packit 47f805
/* Replacement for forward fseek(,,SEEK_CUR), because fseek() fails on pipes */
Packit 47f805
Packit 47f805
Packit 47f805
static int
Packit 47f805
fskip(FILE * fp, long offset, int whence)
Packit 47f805
{
Packit 47f805
#ifndef PIPE_BUF
Packit 47f805
    char    buffer[4096];
Packit 47f805
#else
Packit 47f805
    char    buffer[PIPE_BUF];
Packit 47f805
#endif
Packit 47f805
Packit 47f805
/* S_ISFIFO macro is defined on newer Linuxes */
Packit 47f805
#ifndef S_ISFIFO
Packit 47f805
# ifdef _S_IFIFO
Packit 47f805
    /* _S_IFIFO is defined on Win32 and Cygwin */
Packit 47f805
#  define S_ISFIFO(m) (((m)&_S_IFIFO) == _S_IFIFO)
Packit 47f805
# endif
Packit 47f805
#endif
Packit 47f805
Packit 47f805
#ifdef S_ISFIFO
Packit 47f805
    /* fseek is known to fail on pipes with several C-Library implementations
Packit 47f805
       workaround: 1) test for pipe
Packit 47f805
       2) for pipes, only relatvie seeking is possible
Packit 47f805
       3)            and only in forward direction!
Packit 47f805
       else fallback to old code
Packit 47f805
     */
Packit 47f805
    {
Packit 47f805
        int const fd = fileno(fp);
Packit 47f805
        struct stat file_stat;
Packit 47f805
Packit 47f805
        if (fstat(fd, &file_stat) == 0) {
Packit 47f805
            if (S_ISFIFO(file_stat.st_mode)) {
Packit 47f805
                if (whence != SEEK_CUR || offset < 0) {
Packit 47f805
                    return -1;
Packit 47f805
                }
Packit 47f805
                while (offset > 0) {
Packit 47f805
                    size_t const bytes_to_skip = min_size_t(sizeof(buffer), offset);
Packit 47f805
                    size_t const read = fread(buffer, 1, bytes_to_skip, fp);
Packit 47f805
                    if (read < 1) {
Packit 47f805
                        return -1;
Packit 47f805
                    }
Packit 47f805
                    assert( read <= LONG_MAX );
Packit 47f805
                    offset -= (long) read;
Packit 47f805
                }
Packit 47f805
                return 0;
Packit 47f805
            }
Packit 47f805
        }
Packit 47f805
    }
Packit 47f805
#endif
Packit 47f805
    if (0 == fseek(fp, offset, whence)) {
Packit 47f805
        return 0;
Packit 47f805
    }
Packit 47f805
Packit 47f805
    if (whence != SEEK_CUR || offset < 0) {
Packit 47f805
        if (global_ui_config.silent < 10) {
Packit 47f805
            error_printf
Packit 47f805
                ("fskip problem: Mostly the return status of functions is not evaluate so it is more secure to polute <stderr>.\n");
Packit 47f805
        }
Packit 47f805
        return -1;
Packit 47f805
    }
Packit 47f805
Packit 47f805
    while (offset > 0) {
Packit 47f805
        size_t const bytes_to_skip = min_size_t(sizeof(buffer), offset);
Packit 47f805
        size_t const read = fread(buffer, 1, bytes_to_skip, fp);
Packit 47f805
        if (read < 1) {
Packit 47f805
            return -1;
Packit 47f805
        }
Packit 47f805
        assert( read <= LONG_MAX );
Packit 47f805
        offset -= (long) read;
Packit 47f805
    }
Packit 47f805
Packit 47f805
    return 0;
Packit 47f805
}
Packit 47f805
Packit 47f805
Packit 47f805
static  off_t
Packit 47f805
lame_get_file_size(FILE * fp)
Packit 47f805
{
Packit 47f805
    struct stat sb;
Packit 47f805
    int     fd = fileno(fp);
Packit 47f805
Packit 47f805
    if (0 == fstat(fd, &sb))
Packit 47f805
        return sb.st_size;
Packit 47f805
    return (off_t) - 1;
Packit 47f805
}
Packit 47f805
Packit 47f805
Packit 47f805
FILE   *
Packit 47f805
init_outfile(char const *outPath, int decode)
Packit 47f805
{
Packit 47f805
    FILE   *outf;
Packit 47f805
Packit 47f805
    /* open the output file */
Packit 47f805
    if (0 == strcmp(outPath, "-")) {
Packit 47f805
        outf = stdout;
Packit 47f805
        lame_set_stream_binary_mode(outf);
Packit 47f805
    }
Packit 47f805
    else {
Packit 47f805
        outf = lame_fopen(outPath, "w+b");
Packit 47f805
#ifdef __riscos__
Packit 47f805
        /* Assign correct file type */
Packit 47f805
        if (outf != NULL) {
Packit 47f805
            char   *p, *out_path = strdup(outPath);
Packit 47f805
            for (p = out_path; *p; p++) { /* ugly, ugly to modify a string */
Packit 47f805
                switch (*p) {
Packit 47f805
                case '.':
Packit 47f805
                    *p = '/';
Packit 47f805
                    break;
Packit 47f805
                case '/':
Packit 47f805
                    *p = '.';
Packit 47f805
                    break;
Packit 47f805
                }
Packit 47f805
            }
Packit 47f805
            SetFiletype(out_path, decode ? 0xFB1 /*WAV*/ : 0x1AD /*AMPEG*/);
Packit 47f805
            free(out_path);
Packit 47f805
        }
Packit 47f805
#else
Packit 47f805
        (void) decode;
Packit 47f805
#endif
Packit 47f805
    }
Packit 47f805
    return outf;
Packit 47f805
}
Packit 47f805
Packit 47f805
Packit 47f805
static void
Packit 47f805
setSkipStartAndEnd(lame_t gfp, int enc_delay, int enc_padding)
Packit 47f805
{
Packit 47f805
    int     skip_start = 0, skip_end = 0;
Packit 47f805
Packit 47f805
    if (global_decoder.mp3_delay_set)
Packit 47f805
        skip_start = global_decoder.mp3_delay;
Packit 47f805
Packit 47f805
    switch (global_reader.input_format) {
Packit 47f805
    case sf_mp123:
Packit 47f805
        break;
Packit 47f805
Packit 47f805
    case sf_mp3:
Packit 47f805
        if (skip_start == 0) {
Packit 47f805
            if (enc_delay > -1 || enc_padding > -1) {
Packit 47f805
                if (enc_delay > -1)
Packit 47f805
                    skip_start = enc_delay + 528 + 1;
Packit 47f805
                if (enc_padding > -1)
Packit 47f805
                    skip_end = enc_padding - (528 + 1);
Packit 47f805
            }
Packit 47f805
            else
Packit 47f805
                skip_start = lame_get_encoder_delay(gfp) + 528 + 1;
Packit 47f805
        }
Packit 47f805
        else {
Packit 47f805
            /* user specified a value of skip. just add for decoder */
Packit 47f805
            skip_start += 528 + 1; /* mp3 decoder has a 528 sample delay, plus user supplied "skip" */
Packit 47f805
        }
Packit 47f805
        break;
Packit 47f805
    case sf_mp2:
Packit 47f805
        skip_start += 240 + 1;
Packit 47f805
        break;
Packit 47f805
    case sf_mp1:
Packit 47f805
        skip_start += 240 + 1;
Packit 47f805
        break;
Packit 47f805
    case sf_raw:
Packit 47f805
        skip_start += 0; /* other formats have no delay *//* is += 0 not better ??? */
Packit 47f805
        break;
Packit 47f805
    case sf_wave:
Packit 47f805
        skip_start += 0; /* other formats have no delay *//* is += 0 not better ??? */
Packit 47f805
        break;
Packit 47f805
    case sf_aiff:
Packit 47f805
        skip_start += 0; /* other formats have no delay *//* is += 0 not better ??? */
Packit 47f805
        break;
Packit 47f805
    default:
Packit 47f805
        skip_start += 0; /* other formats have no delay *//* is += 0 not better ??? */
Packit 47f805
        break;
Packit 47f805
    }
Packit 47f805
    skip_start = skip_start < 0 ? 0 : skip_start;
Packit 47f805
    skip_end = skip_end < 0 ? 0 : skip_end;
Packit 47f805
    global. pcm16.skip_start = global.pcm32.skip_start = skip_start;
Packit 47f805
    global. pcm16.skip_end = global.pcm32.skip_end = skip_end;
Packit 47f805
}
Packit 47f805
Packit 47f805
Packit 47f805
Packit 47f805
int
Packit 47f805
init_infile(lame_t gfp, char const *inPath)
Packit 47f805
{
Packit 47f805
    int     enc_delay = 0, enc_padding = 0;
Packit 47f805
    /* open the input file */
Packit 47f805
    global. count_samples_carefully = 0;
Packit 47f805
    global. num_samples_read = 0;
Packit 47f805
    global. pcmbitwidth = global_raw_pcm.in_bitwidth;
Packit 47f805
    global. pcmswapbytes = global_reader.swapbytes;
Packit 47f805
    global. pcm_is_unsigned_8bit = global_raw_pcm.in_signed == 1 ? 0 : 1;
Packit 47f805
    global. pcm_is_ieee_float = 0;
Packit 47f805
    global. hip = 0;
Packit 47f805
    global. music_in = 0;
Packit 47f805
    global. snd_file = 0;
Packit 47f805
    global. in_id3v2_size = 0;
Packit 47f805
    global. in_id3v2_tag = 0;
Packit 47f805
    if (is_mpeg_file_format(global_reader.input_format)) {
Packit 47f805
        global. music_in = open_mpeg_file(gfp, inPath, &enc_delay, &enc_padding);
Packit 47f805
    }
Packit 47f805
    else {
Packit 47f805
#ifdef LIBSNDFILE
Packit 47f805
        if (strcmp(inPath, "-") != 0) { /* not for stdin */
Packit 47f805
            global. snd_file = open_snd_file(gfp, inPath);
Packit 47f805
        }
Packit 47f805
#endif
Packit 47f805
        if (global.snd_file == 0) {
Packit 47f805
            global. music_in = open_wave_file(gfp, inPath, &enc_delay, &enc_padding);
Packit 47f805
        }
Packit 47f805
    }
Packit 47f805
    initPcmBuffer(&global.pcm32, sizeof(int));
Packit 47f805
    initPcmBuffer(&global.pcm16, sizeof(short));
Packit 47f805
    setSkipStartAndEnd(gfp, enc_delay, enc_padding);
Packit 47f805
    {
Packit 47f805
        unsigned long n = lame_get_num_samples(gfp);
Packit 47f805
        if (n != MAX_U_32_NUM) {
Packit 47f805
            unsigned long const discard = global.pcm32.skip_start + global.pcm32.skip_end;
Packit 47f805
            lame_set_num_samples(gfp, n > discard ? n - discard : 0);
Packit 47f805
        }
Packit 47f805
    }
Packit 47f805
    return (global.snd_file != NULL || global.music_in != NULL) ? 1 : -1;
Packit 47f805
}
Packit 47f805
Packit 47f805
int
Packit 47f805
samples_to_skip_at_start(void)
Packit 47f805
{
Packit 47f805
    return global.pcm32.skip_start;
Packit 47f805
}
Packit 47f805
Packit 47f805
int
Packit 47f805
samples_to_skip_at_end(void)
Packit 47f805
{
Packit 47f805
    return global.pcm32.skip_end;
Packit 47f805
}
Packit 47f805
Packit 47f805
void
Packit 47f805
close_infile(void)
Packit 47f805
{
Packit 47f805
#if defined(HAVE_MPGLIB)
Packit 47f805
    if (global.hip != 0) {
Packit 47f805
        hip_decode_exit(global.hip); /* release mp3decoder memory */
Packit 47f805
        global. hip = 0;
Packit 47f805
    }
Packit 47f805
#endif
Packit 47f805
    close_input_file(global.music_in);
Packit 47f805
#ifdef LIBSNDFILE
Packit 47f805
    if (global.snd_file) {
Packit 47f805
        if (sf_close(global.snd_file) != 0) {
Packit 47f805
            if (global_ui_config.silent < 10) {
Packit 47f805
                error_printf("Could not close sound file \n");
Packit 47f805
            }
Packit 47f805
        }
Packit 47f805
        global. snd_file = 0;
Packit 47f805
    }
Packit 47f805
#endif
Packit 47f805
    freePcmBuffer(&global.pcm32);
Packit 47f805
    freePcmBuffer(&global.pcm16);
Packit 47f805
    global. music_in = 0;
Packit 47f805
    free(global.in_id3v2_tag);
Packit 47f805
    global.in_id3v2_tag = 0;
Packit 47f805
    global.in_id3v2_size = 0;
Packit 47f805
}
Packit 47f805
Packit 47f805
Packit 47f805
static int
Packit 47f805
        get_audio_common(lame_t gfp, int buffer[2][1152], short buffer16[2][1152]);
Packit 47f805
Packit 47f805
/************************************************************************
Packit 47f805
*
Packit 47f805
* get_audio()
Packit 47f805
*
Packit 47f805
* PURPOSE:  reads a frame of audio data from a file to the buffer,
Packit 47f805
*   aligns the data for future processing, and separates the
Packit 47f805
*   left and right channels
Packit 47f805
*
Packit 47f805
************************************************************************/
Packit 47f805
int
Packit 47f805
get_audio(lame_t gfp, int buffer[2][1152])
Packit 47f805
{
Packit 47f805
    int     used = 0, read = 0;
Packit 47f805
    do {
Packit 47f805
        read = get_audio_common(gfp, buffer, NULL);
Packit 47f805
        used = addPcmBuffer(&global.pcm32, buffer[0], buffer[1], read);
Packit 47f805
    } while (used <= 0 && read > 0);
Packit 47f805
    if (read < 0) {
Packit 47f805
        return read;
Packit 47f805
    }
Packit 47f805
    if (global_reader.swap_channel == 0)
Packit 47f805
        return takePcmBuffer(&global.pcm32, buffer[0], buffer[1], used, 1152);
Packit 47f805
    else
Packit 47f805
        return takePcmBuffer(&global.pcm32, buffer[1], buffer[0], used, 1152);
Packit 47f805
}
Packit 47f805
Packit 47f805
/*
Packit 47f805
  get_audio16 - behave as the original get_audio function, with a limited
Packit 47f805
                16 bit per sample output
Packit 47f805
*/
Packit 47f805
int
Packit 47f805
get_audio16(lame_t gfp, short buffer[2][1152])
Packit 47f805
{
Packit 47f805
    int     used = 0, read = 0;
Packit 47f805
    do {
Packit 47f805
        read = get_audio_common(gfp, NULL, buffer);
Packit 47f805
        used = addPcmBuffer(&global.pcm16, buffer[0], buffer[1], read);
Packit 47f805
    } while (used <= 0 && read > 0);
Packit 47f805
    if (read < 0) {
Packit 47f805
        return read;
Packit 47f805
    }
Packit 47f805
    if (global_reader.swap_channel == 0)
Packit 47f805
        return takePcmBuffer(&global.pcm16, buffer[0], buffer[1], used, 1152);
Packit 47f805
    else
Packit 47f805
        return takePcmBuffer(&global.pcm16, buffer[1], buffer[0], used, 1152);
Packit 47f805
}
Packit 47f805
Packit 47f805
/************************************************************************
Packit 47f805
  get_audio_common - central functionality of get_audio*
Packit 47f805
    in: gfp
Packit 47f805
        buffer    output to the int buffer or 16-bit buffer
Packit 47f805
   out: buffer    int output    (if buffer != NULL)
Packit 47f805
        buffer16  16-bit output (if buffer == NULL) 
Packit 47f805
returns: samples read
Packit 47f805
note: either buffer or buffer16 must be allocated upon call
Packit 47f805
*/
Packit 47f805
static int
Packit 47f805
get_audio_common(lame_t gfp, int buffer[2][1152], short buffer16[2][1152])
Packit 47f805
{
Packit 47f805
    const int num_channels = lame_get_num_channels(gfp);
Packit 47f805
    const int framesize = lame_get_framesize(gfp);
Packit 47f805
    int     insamp[2 * 1152];
Packit 47f805
    short   buf_tmp16[2][1152];
Packit 47f805
    int     samples_read;
Packit 47f805
    int     samples_to_read;
Packit 47f805
    unsigned int remaining;
Packit 47f805
    int     i;
Packit 47f805
    int    *p;
Packit 47f805
Packit 47f805
    /* sanity checks, that's what we expect to be true */
Packit 47f805
    if ((num_channels < 1 || 2 < num_channels)
Packit 47f805
      ||(framesize < 1 || 1152 < framesize)) {
Packit 47f805
        if (global_ui_config.silent < 10) {
Packit 47f805
            error_printf("Error: internal problem!\n");
Packit 47f805
        }
Packit 47f805
        return -1;
Packit 47f805
    }
Packit 47f805
Packit 47f805
    /* 
Packit 47f805
     * NOTE: LAME can now handle arbritray size input data packets,
Packit 47f805
     * so there is no reason to read the input data in chuncks of
Packit 47f805
     * size "framesize".  EXCEPT:  the LAME graphical frame analyzer 
Packit 47f805
     * will get out of sync if we read more than framesize worth of data.
Packit 47f805
     */
Packit 47f805
Packit 47f805
    samples_to_read = framesize;
Packit 47f805
Packit 47f805
    /* if this flag has been set, then we are carefull to read
Packit 47f805
     * exactly num_samples and no more.  This is useful for .wav and .aiff
Packit 47f805
     * files which have id3 or other tags at the end.  Note that if you
Packit 47f805
     * are using LIBSNDFILE, this is not necessary 
Packit 47f805
     */
Packit 47f805
    if (global.count_samples_carefully) {
Packit 47f805
        unsigned int tmp_num_samples;
Packit 47f805
        /* get num_samples */
Packit 47f805
        if (is_mpeg_file_format(global_reader.input_format)) {
Packit 47f805
            tmp_num_samples = global_decoder.mp3input_data.nsamp;
Packit 47f805
        }
Packit 47f805
        else {
Packit 47f805
            tmp_num_samples = lame_get_num_samples(gfp);
Packit 47f805
        }
Packit 47f805
        if (global.num_samples_read < tmp_num_samples) {
Packit 47f805
            remaining = tmp_num_samples - global.num_samples_read;
Packit 47f805
        }
Packit 47f805
        else {
Packit 47f805
            remaining = 0;
Packit 47f805
        }
Packit 47f805
        if (remaining < (unsigned int) framesize && 0 != tmp_num_samples)
Packit 47f805
            /* in case the input is a FIFO (at least it's reproducible with
Packit 47f805
               a FIFO) tmp_num_samples may be 0 and therefore remaining
Packit 47f805
               would be 0, but we need to read some samples, so don't
Packit 47f805
               change samples_to_read to the wrong value in this case */
Packit 47f805
            samples_to_read = remaining;
Packit 47f805
    }
Packit 47f805
Packit 47f805
    if (is_mpeg_file_format(global_reader.input_format)) {
Packit 47f805
        if (buffer != NULL)
Packit 47f805
            samples_read = read_samples_mp3(gfp, global.music_in, buf_tmp16);
Packit 47f805
        else
Packit 47f805
            samples_read = read_samples_mp3(gfp, global.music_in, buffer16);
Packit 47f805
        if (samples_read < 0) {
Packit 47f805
            return samples_read;
Packit 47f805
        }
Packit 47f805
    }
Packit 47f805
    else {
Packit 47f805
        if (global.snd_file) {
Packit 47f805
#ifdef LIBSNDFILE
Packit 47f805
            samples_read = sf_read_int(global.snd_file, insamp, num_channels * samples_to_read);
Packit 47f805
#else
Packit 47f805
            samples_read = 0;
Packit 47f805
#endif
Packit 47f805
        }
Packit 47f805
        else {
Packit 47f805
            samples_read =
Packit 47f805
                read_samples_pcm(global.music_in, insamp, num_channels * samples_to_read);
Packit 47f805
        }
Packit 47f805
        if (samples_read < 0) {
Packit 47f805
            return samples_read;
Packit 47f805
        }
Packit 47f805
        p = insamp + samples_read;
Packit 47f805
        samples_read /= num_channels;
Packit 47f805
        if (buffer != NULL) { /* output to int buffer */
Packit 47f805
            if (num_channels == 2) {
Packit 47f805
                for (i = samples_read; --i >= 0;) {
Packit 47f805
                    buffer[1][i] = *--p;
Packit 47f805
                    buffer[0][i] = *--p;
Packit 47f805
                }
Packit 47f805
            }
Packit 47f805
            else if (num_channels == 1) {
Packit 47f805
                memset(buffer[1], 0, samples_read * sizeof(int));
Packit 47f805
                for (i = samples_read; --i >= 0;) {
Packit 47f805
                    buffer[0][i] = *--p;
Packit 47f805
                }
Packit 47f805
            }
Packit 47f805
            else
Packit 47f805
                assert(0);
Packit 47f805
        }
Packit 47f805
        else {          /* convert from int; output to 16-bit buffer */
Packit 47f805
            if (num_channels == 2) {
Packit 47f805
                for (i = samples_read; --i >= 0;) {
Packit 47f805
                    buffer16[1][i] = *--p >> (8 * sizeof(int) - 16);
Packit 47f805
                    buffer16[0][i] = *--p >> (8 * sizeof(int) - 16);
Packit 47f805
                }
Packit 47f805
            }
Packit 47f805
            else if (num_channels == 1) {
Packit 47f805
                memset(buffer16[1], 0, samples_read * sizeof(short));
Packit 47f805
                for (i = samples_read; --i >= 0;) {
Packit 47f805
                    buffer16[0][i] = *--p >> (8 * sizeof(int) - 16);
Packit 47f805
                }
Packit 47f805
            }
Packit 47f805
            else
Packit 47f805
                assert(0);
Packit 47f805
        }
Packit 47f805
    }
Packit 47f805
Packit 47f805
    /* LAME mp3 output 16bit -  convert to int, if necessary */
Packit 47f805
    if (is_mpeg_file_format(global_reader.input_format)) {
Packit 47f805
        if (buffer != NULL) {
Packit 47f805
            for (i = samples_read; --i >= 0;)
Packit 47f805
                buffer[0][i] = buf_tmp16[0][i] << (8 * sizeof(int) - 16);
Packit 47f805
            if (num_channels == 2) {
Packit 47f805
                for (i = samples_read; --i >= 0;)
Packit 47f805
                    buffer[1][i] = buf_tmp16[1][i] << (8 * sizeof(int) - 16);
Packit 47f805
            }
Packit 47f805
            else if (num_channels == 1) {
Packit 47f805
                memset(buffer[1], 0, samples_read * sizeof(int));
Packit 47f805
            }
Packit 47f805
            else
Packit 47f805
                assert(0);
Packit 47f805
        }
Packit 47f805
    }
Packit 47f805
Packit 47f805
Packit 47f805
    /* if ... then it is considered infinitely long.
Packit 47f805
       Don't count the samples */
Packit 47f805
    if (global.count_samples_carefully)
Packit 47f805
        global. num_samples_read += samples_read;
Packit 47f805
Packit 47f805
    return samples_read;
Packit 47f805
}
Packit 47f805
Packit 47f805
Packit 47f805
Packit 47f805
static int
Packit 47f805
read_samples_mp3(lame_t gfp, FILE * musicin, short int mpg123pcm[2][1152])
Packit 47f805
{
Packit 47f805
    int     out;
Packit 47f805
#if defined(AMIGA_MPEGA)  ||  defined(HAVE_MPGLIB)
Packit 47f805
    int     samplerate;
Packit 47f805
    static const char type_name[] = "MP3 file";
Packit 47f805
Packit 47f805
    out = lame_decode_fromfile(musicin, mpg123pcm[0], mpg123pcm[1], &global_decoder.mp3input_data);
Packit 47f805
    /*
Packit 47f805
     * out < 0:  error, probably EOF
Packit 47f805
     * out = 0:  not possible with lame_decode_fromfile() ???
Packit 47f805
     * out > 0:  number of output samples
Packit 47f805
     */
Packit 47f805
    if (out < 0) {
Packit 47f805
        memset(mpg123pcm, 0, sizeof(**mpg123pcm) * 2 * 1152);
Packit 47f805
        return 0;
Packit 47f805
    }
Packit 47f805
Packit 47f805
    if (lame_get_num_channels(gfp) != global_decoder.mp3input_data.stereo) {
Packit 47f805
        if (global_ui_config.silent < 10) {
Packit 47f805
            error_printf("Error: number of channels has changed in %s - not supported\n",
Packit 47f805
                         type_name);
Packit 47f805
        }
Packit 47f805
        out = -1;
Packit 47f805
    }
Packit 47f805
    samplerate = global_reader.input_samplerate;
Packit 47f805
    if (samplerate == 0) {
Packit 47f805
        samplerate = global_decoder.mp3input_data.samplerate;
Packit 47f805
    }
Packit 47f805
    if (lame_get_in_samplerate(gfp) != samplerate) {
Packit 47f805
        if (global_ui_config.silent < 10) {
Packit 47f805
            error_printf("Error: sample frequency has changed in %s - not supported\n", type_name);
Packit 47f805
        }
Packit 47f805
        out = -1;
Packit 47f805
    }
Packit 47f805
#else
Packit 47f805
    out = -1;
Packit 47f805
#endif
Packit 47f805
    return out;
Packit 47f805
}
Packit 47f805
Packit 47f805
static
Packit 47f805
int set_input_num_channels(lame_t gfp, int num_channels)
Packit 47f805
{
Packit 47f805
    if (gfp) {
Packit 47f805
        if (-1 == lame_set_num_channels(gfp, num_channels)) {
Packit 47f805
            if (global_ui_config.silent < 10) {
Packit 47f805
                error_printf("Unsupported number of channels: %d\n", num_channels);
Packit 47f805
            }
Packit 47f805
            return 0;
Packit 47f805
        }
Packit 47f805
    }
Packit 47f805
    return 1;
Packit 47f805
}
Packit 47f805
Packit 47f805
static
Packit 47f805
int set_input_samplerate(lame_t gfp, int input_samplerate)
Packit 47f805
{
Packit 47f805
    if (gfp) {
Packit 47f805
        int sr = global_reader.input_samplerate;
Packit 47f805
        if (sr == 0) sr = input_samplerate;
Packit 47f805
        if (-1 == lame_set_in_samplerate(gfp, sr)) {
Packit 47f805
            if (global_ui_config.silent < 10) {
Packit 47f805
                error_printf("Unsupported sample rate: %d\n", sr);
Packit 47f805
            }
Packit 47f805
            return 0;
Packit 47f805
        }
Packit 47f805
    }
Packit 47f805
    return 1;
Packit 47f805
}
Packit 47f805
Packit 47f805
int
Packit 47f805
WriteWaveHeader(FILE * const fp, int pcmbytes, int freq, int channels, int bits)
Packit 47f805
{
Packit 47f805
    int     bytes = (bits + 7) / 8;
Packit 47f805
Packit 47f805
    /* quick and dirty, but documented */
Packit 47f805
    fwrite("RIFF", 1, 4, fp); /* label */
Packit 47f805
    write_32_bits_low_high(fp, pcmbytes + 44 - 8); /* length in bytes without header */
Packit 47f805
    fwrite("WAVEfmt ", 2, 4, fp); /* 2 labels */
Packit 47f805
    write_32_bits_low_high(fp, 2 + 2 + 4 + 4 + 2 + 2); /* length of PCM format declaration area */
Packit 47f805
    write_16_bits_low_high(fp, 1); /* is PCM? */
Packit 47f805
    write_16_bits_low_high(fp, channels); /* number of channels */
Packit 47f805
    write_32_bits_low_high(fp, freq); /* sample frequency in [Hz] */
Packit 47f805
    write_32_bits_low_high(fp, freq * channels * bytes); /* bytes per second */
Packit 47f805
    write_16_bits_low_high(fp, channels * bytes); /* bytes per sample time */
Packit 47f805
    write_16_bits_low_high(fp, bits); /* bits per sample */
Packit 47f805
    fwrite("data", 1, 4, fp); /* label */
Packit 47f805
    write_32_bits_low_high(fp, pcmbytes); /* length in bytes of raw PCM data */
Packit 47f805
Packit 47f805
    return ferror(fp) ? -1 : 0;
Packit 47f805
}
Packit 47f805
Packit 47f805
Packit 47f805
Packit 47f805
Packit 47f805
#if defined(LIBSNDFILE)
Packit 47f805
Packit 47f805
extern SNDFILE *sf_wchar_open(wchar_t const *wpath, int mode, SF_INFO * sfinfo);
Packit 47f805
Packit 47f805
static SNDFILE *
Packit 47f805
open_snd_file(lame_t gfp, char const *inPath)
Packit 47f805
{
Packit 47f805
    char const *lpszFileName = inPath;
Packit 47f805
    SNDFILE *gs_pSndFileIn = NULL;
Packit 47f805
    SF_INFO gs_wfInfo;
Packit 47f805
Packit 47f805
    {
Packit 47f805
#if defined( _WIN32 ) && !defined(__MINGW32__)
Packit 47f805
        wchar_t *file_name = utf8ToUnicode(lpszFileName);
Packit 47f805
#endif
Packit 47f805
        /* Try to open the sound file */
Packit 47f805
        memset(&gs_wfInfo, 0, sizeof(gs_wfInfo));
Packit 47f805
#if defined( _WIN32 ) && !defined(__MINGW32__)
Packit 47f805
        gs_pSndFileIn = sf_wchar_open(file_name, SFM_READ, &gs_wfInfo);
Packit 47f805
#else
Packit 47f805
        gs_pSndFileIn = sf_open(lpszFileName, SFM_READ, &gs_wfInfo);
Packit 47f805
#endif
Packit 47f805
Packit 47f805
        if (gs_pSndFileIn == NULL) {
Packit 47f805
            if (global_raw_pcm.in_signed == 0 && global_raw_pcm.in_bitwidth != 8) {
Packit 47f805
                error_printf("Unsigned input only supported with bitwidth 8\n");
Packit 47f805
#if defined( _WIN32 ) && !defined(__MINGW32__)
Packit 47f805
                free(file_name);
Packit 47f805
#endif
Packit 47f805
                return 0;
Packit 47f805
            }
Packit 47f805
            /* set some defaults incase input is raw PCM */
Packit 47f805
            gs_wfInfo.seekable = (global_reader.input_format != sf_raw); /* if user specified -r, set to not seekable */
Packit 47f805
            gs_wfInfo.samplerate = lame_get_in_samplerate(gfp);
Packit 47f805
            gs_wfInfo.channels = lame_get_num_channels(gfp);
Packit 47f805
            gs_wfInfo.format = SF_FORMAT_RAW;
Packit 47f805
            if ((global_raw_pcm.in_endian == ByteOrderLittleEndian) ^ (global_reader.swapbytes !=
Packit 47f805
                                                                       0)) {
Packit 47f805
                gs_wfInfo.format |= SF_ENDIAN_LITTLE;
Packit 47f805
            }
Packit 47f805
            else {
Packit 47f805
                gs_wfInfo.format |= SF_ENDIAN_BIG;
Packit 47f805
            }
Packit 47f805
            switch (global_raw_pcm.in_bitwidth) {
Packit 47f805
            case 8:
Packit 47f805
                gs_wfInfo.format |=
Packit 47f805
                    global_raw_pcm.in_signed == 0 ? SF_FORMAT_PCM_U8 : SF_FORMAT_PCM_S8;
Packit 47f805
                break;
Packit 47f805
            case 16:
Packit 47f805
                gs_wfInfo.format |= SF_FORMAT_PCM_16;
Packit 47f805
                break;
Packit 47f805
            case 24:
Packit 47f805
                gs_wfInfo.format |= SF_FORMAT_PCM_24;
Packit 47f805
                break;
Packit 47f805
            case 32:
Packit 47f805
                gs_wfInfo.format |= SF_FORMAT_PCM_32;
Packit 47f805
                break;
Packit 47f805
            default:
Packit 47f805
                break;
Packit 47f805
            }
Packit 47f805
#if defined( _WIN32 ) && !defined(__MINGW32__)
Packit 47f805
            gs_pSndFileIn = sf_wchar_open(file_name, SFM_READ, &gs_wfInfo);
Packit 47f805
#else
Packit 47f805
            gs_pSndFileIn = sf_open(lpszFileName, SFM_READ, &gs_wfInfo);
Packit 47f805
#endif
Packit 47f805
        }
Packit 47f805
#if defined( _WIN32 ) && !defined(__MINGW32__)
Packit 47f805
        free(file_name);
Packit 47f805
#endif
Packit 47f805
Packit 47f805
        /* Check result */
Packit 47f805
        if (gs_pSndFileIn == NULL) {
Packit 47f805
            sf_perror(gs_pSndFileIn);
Packit 47f805
            if (global_ui_config.silent < 10) {
Packit 47f805
                error_printf("Could not open sound file \"%s\".\n", lpszFileName);
Packit 47f805
            }
Packit 47f805
            return 0;
Packit 47f805
        }
Packit 47f805
        sf_command(gs_pSndFileIn, SFC_SET_SCALE_FLOAT_INT_READ, NULL, SF_TRUE);
Packit 47f805
Packit 47f805
        if ((gs_wfInfo.format & SF_FORMAT_RAW) == SF_FORMAT_RAW) {
Packit 47f805
            global_reader.input_format = sf_raw;
Packit 47f805
        }
Packit 47f805
Packit 47f805
#ifdef _DEBUG_SND_FILE
Packit 47f805
        printf("\n\nSF_INFO structure\n");
Packit 47f805
        printf("samplerate        :%d\n", gs_wfInfo.samplerate);
Packit 47f805
        printf("samples           :%d\n", gs_wfInfo.frames);
Packit 47f805
        printf("channels          :%d\n", gs_wfInfo.channels);
Packit 47f805
        printf("format            :");
Packit 47f805
Packit 47f805
        /* new formats from sbellon@sbellon.de  1/2000 */
Packit 47f805
Packit 47f805
        switch (gs_wfInfo.format & SF_FORMAT_TYPEMASK) {
Packit 47f805
        case SF_FORMAT_WAV:
Packit 47f805
            printf("Microsoft WAV format (big endian). ");
Packit 47f805
            break;
Packit 47f805
        case SF_FORMAT_AIFF:
Packit 47f805
            printf("Apple/SGI AIFF format (little endian). ");
Packit 47f805
            break;
Packit 47f805
        case SF_FORMAT_AU:
Packit 47f805
            printf("Sun/NeXT AU format (big endian). ");
Packit 47f805
            break;
Packit 47f805
            /*
Packit 47f805
               case SF_FORMAT_AULE:
Packit 47f805
               DEBUGF("DEC AU format (little endian). ");
Packit 47f805
               break;
Packit 47f805
             */
Packit 47f805
        case SF_FORMAT_RAW:
Packit 47f805
            printf("RAW PCM data. ");
Packit 47f805
            break;
Packit 47f805
        case SF_FORMAT_PAF:
Packit 47f805
            printf("Ensoniq PARIS file format. ");
Packit 47f805
            break;
Packit 47f805
        case SF_FORMAT_SVX:
Packit 47f805
            printf("Amiga IFF / SVX8 / SV16 format. ");
Packit 47f805
            break;
Packit 47f805
        case SF_FORMAT_NIST:
Packit 47f805
            printf("Sphere NIST format. ");
Packit 47f805
            break;
Packit 47f805
        default:
Packit 47f805
            assert(0);
Packit 47f805
            break;
Packit 47f805
        }
Packit 47f805
Packit 47f805
        switch (gs_wfInfo.format & SF_FORMAT_SUBMASK) {
Packit 47f805
            /*
Packit 47f805
               case SF_FORMAT_PCM:
Packit 47f805
               DEBUGF("PCM data in 8, 16, 24 or 32 bits.");
Packit 47f805
               break;
Packit 47f805
             */
Packit 47f805
        case SF_FORMAT_FLOAT:
Packit 47f805
            printf("32 bit Intel x86 floats.");
Packit 47f805
            break;
Packit 47f805
        case SF_FORMAT_ULAW:
Packit 47f805
            printf("U-Law encoded.");
Packit 47f805
            break;
Packit 47f805
        case SF_FORMAT_ALAW:
Packit 47f805
            printf("A-Law encoded.");
Packit 47f805
            break;
Packit 47f805
        case SF_FORMAT_IMA_ADPCM:
Packit 47f805
            printf("IMA ADPCM.");
Packit 47f805
            break;
Packit 47f805
        case SF_FORMAT_MS_ADPCM:
Packit 47f805
            printf("Microsoft ADPCM.");
Packit 47f805
            break;
Packit 47f805
            /*
Packit 47f805
               case SF_FORMAT_PCM_BE:
Packit 47f805
               DEBUGF("Big endian PCM data.");
Packit 47f805
               break;
Packit 47f805
               case SF_FORMAT_PCM_LE:
Packit 47f805
               DEBUGF("Little endian PCM data.");
Packit 47f805
               break;
Packit 47f805
             */
Packit 47f805
        case SF_FORMAT_PCM_S8:
Packit 47f805
            printf("Signed 8 bit PCM.");
Packit 47f805
            break;
Packit 47f805
        case SF_FORMAT_PCM_U8:
Packit 47f805
            printf("Unsigned 8 bit PCM.");
Packit 47f805
            break;
Packit 47f805
        case SF_FORMAT_PCM_16:
Packit 47f805
            printf("Signed 16 bit PCM.");
Packit 47f805
            break;
Packit 47f805
        case SF_FORMAT_PCM_24:
Packit 47f805
            printf("Signed 24 bit PCM.");
Packit 47f805
            break;
Packit 47f805
        case SF_FORMAT_PCM_32:
Packit 47f805
            printf("Signed 32 bit PCM.");
Packit 47f805
            break;
Packit 47f805
            /*
Packit 47f805
               case SF_FORMAT_SVX_FIB:
Packit 47f805
               DEBUGF("SVX Fibonacci Delta encoding.");
Packit 47f805
               break;
Packit 47f805
               case SF_FORMAT_SVX_EXP:
Packit 47f805
               DEBUGF("SVX Exponential Delta encoding.");
Packit 47f805
               break;
Packit 47f805
             */
Packit 47f805
        default:
Packit 47f805
            assert(0);
Packit 47f805
            break;
Packit 47f805
        }
Packit 47f805
Packit 47f805
        printf("\n");
Packit 47f805
        printf("sections          :%d\n", gs_wfInfo.sections);
Packit 47f805
        printf("seekable          :%d\n", gs_wfInfo.seekable);
Packit 47f805
#endif
Packit 47f805
        /* Check result */
Packit 47f805
        if (gs_pSndFileIn == NULL) {
Packit 47f805
            sf_perror(gs_pSndFileIn);
Packit 47f805
            if (global_ui_config.silent < 10) {
Packit 47f805
                error_printf("Could not open sound file \"%s\".\n", lpszFileName);
Packit 47f805
            }
Packit 47f805
            return 0;
Packit 47f805
        }
Packit 47f805
Packit 47f805
Packit 47f805
        if(gs_wfInfo.frames >= 0 && gs_wfInfo.frames < (sf_count_t)(unsigned)MAX_U_32_NUM)
Packit 47f805
            (void) lame_set_num_samples(gfp, gs_wfInfo.frames);
Packit 47f805
        else
Packit 47f805
            (void) lame_set_num_samples(gfp, MAX_U_32_NUM);
Packit 47f805
        if (!set_input_num_channels(gfp, gs_wfInfo.channels)) {
Packit 47f805
            sf_close(gs_pSndFileIn);
Packit 47f805
            return 0;
Packit 47f805
        }
Packit 47f805
        if (!set_input_samplerate(gfp, gs_wfInfo.samplerate)) {
Packit 47f805
            sf_close(gs_pSndFileIn);
Packit 47f805
            return 0;
Packit 47f805
        }
Packit 47f805
        global. pcmbitwidth = 32;
Packit 47f805
    }
Packit 47f805
#if 0
Packit 47f805
    if (lame_get_num_samples(gfp) == MAX_U_32_NUM) {
Packit 47f805
        /* try to figure out num_samples */
Packit 47f805
        double const flen = lame_get_file_size(lpszFileName);
Packit 47f805
        if (flen >= 0) {
Packit 47f805
            /* try file size, assume 2 bytes per sample */
Packit 47f805
            lame_set_num_samples(gfp, flen / (2 * lame_get_num_channels(gfp)));
Packit 47f805
        }
Packit 47f805
    }
Packit 47f805
#endif
Packit 47f805
    return gs_pSndFileIn;
Packit 47f805
}
Packit 47f805
Packit 47f805
#endif /* defined(LIBSNDFILE) */
Packit 47f805
Packit 47f805
Packit 47f805
Packit 47f805
/************************************************************************
Packit 47f805
unpack_read_samples - read and unpack signed low-to-high byte or unsigned
Packit 47f805
                      single byte input. (used for read_samples function)
Packit 47f805
                      Output integers are stored in the native byte order
Packit 47f805
                      (little or big endian).  -jd
Packit 47f805
  in: samples_to_read
Packit 47f805
      bytes_per_sample
Packit 47f805
      swap_order    - set for high-to-low byte order input stream
Packit 47f805
 i/o: pcm_in
Packit 47f805
 out: sample_buffer  (must be allocated up to samples_to_read upon call)
Packit 47f805
returns: number of samples read
Packit 47f805
*/
Packit 47f805
static int
Packit 47f805
unpack_read_samples(const int samples_to_read, const int bytes_per_sample,
Packit 47f805
                    const int swap_order, int *sample_buffer, FILE * pcm_in)
Packit 47f805
{
Packit 47f805
    int     samples_read;
Packit 47f805
    int     i;
Packit 47f805
    int    *op;              /* output pointer */
Packit 47f805
    unsigned char *ip = (unsigned char *) sample_buffer; /* input pointer */
Packit 47f805
    const int b = sizeof(int) * 8;
Packit 47f805
Packit 47f805
    {
Packit 47f805
        size_t  samples_read_ = fread(sample_buffer, bytes_per_sample, samples_to_read, pcm_in);
Packit 47f805
        assert( samples_read_ <= INT_MAX );
Packit 47f805
        samples_read = (int) samples_read_;
Packit 47f805
    }
Packit 47f805
    op = sample_buffer + samples_read;
Packit 47f805
Packit 47f805
#define GA_URS_IFLOOP( ga_urs_bps ) \
Packit 47f805
    if( bytes_per_sample == ga_urs_bps ) \
Packit 47f805
      for( i = samples_read * bytes_per_sample; (i -= bytes_per_sample) >=0;)
Packit 47f805
Packit 47f805
    if (swap_order == 0) {
Packit 47f805
        GA_URS_IFLOOP(1)
Packit 47f805
            * --op = ip[i] << (b - 8);
Packit 47f805
        GA_URS_IFLOOP(2)
Packit 47f805
            * --op = ip[i] << (b - 16) | ip[i + 1] << (b - 8);
Packit 47f805
        GA_URS_IFLOOP(3)
Packit 47f805
            * --op = ip[i] << (b - 24) | ip[i + 1] << (b - 16) | ip[i + 2] << (b - 8);
Packit 47f805
        GA_URS_IFLOOP(4)
Packit 47f805
            * --op =
Packit 47f805
            ip[i] << (b - 32) | ip[i + 1] << (b - 24) | ip[i + 2] << (b - 16) | ip[i + 3] << (b -
Packit 47f805
                                                                                              8);
Packit 47f805
    }
Packit 47f805
    else {
Packit 47f805
        GA_URS_IFLOOP(1)
Packit 47f805
            * --op = (ip[i] ^ 0x80) << (b - 8) | 0x7f << (b - 16); /* convert from unsigned */
Packit 47f805
        GA_URS_IFLOOP(2)
Packit 47f805
            * --op = ip[i] << (b - 8) | ip[i + 1] << (b - 16);
Packit 47f805
        GA_URS_IFLOOP(3)
Packit 47f805
            * --op = ip[i] << (b - 8) | ip[i + 1] << (b - 16) | ip[i + 2] << (b - 24);
Packit 47f805
        GA_URS_IFLOOP(4)
Packit 47f805
            * --op =
Packit 47f805
            ip[i] << (b - 8) | ip[i + 1] << (b - 16) | ip[i + 2] << (b - 24) | ip[i + 3] << (b -
Packit 47f805
                                                                                             32);
Packit 47f805
    }
Packit 47f805
#undef GA_URS_IFLOOP
Packit 47f805
    if (global.pcm_is_ieee_float) {
Packit 47f805
        ieee754_float32_t const m_max = INT_MAX;
Packit 47f805
        ieee754_float32_t const m_min = -(ieee754_float32_t) INT_MIN;
Packit 47f805
        ieee754_float32_t *x = (ieee754_float32_t *) sample_buffer;
Packit 47f805
        assert(sizeof(ieee754_float32_t) == sizeof(int));
Packit 47f805
        for (i = 0; i < samples_to_read; ++i) {
Packit 47f805
            ieee754_float32_t const u = x[i];
Packit 47f805
            int     v;
Packit 47f805
            if (u >= 1) {
Packit 47f805
                v = INT_MAX;
Packit 47f805
            }
Packit 47f805
            else if (u <= -1) {
Packit 47f805
                v = INT_MIN;
Packit 47f805
            }
Packit 47f805
            else if (u >= 0) {
Packit 47f805
                v = (int) (u * m_max + 0.5f);
Packit 47f805
            }
Packit 47f805
            else {
Packit 47f805
                v = (int) (u * m_min - 0.5f);
Packit 47f805
            }
Packit 47f805
            sample_buffer[i] = v;
Packit 47f805
        }
Packit 47f805
    }
Packit 47f805
    return (samples_read);
Packit 47f805
}
Packit 47f805
Packit 47f805
Packit 47f805
Packit 47f805
/************************************************************************
Packit 47f805
*
Packit 47f805
* read_samples()
Packit 47f805
*
Packit 47f805
* PURPOSE:  reads the PCM samples from a file to the buffer
Packit 47f805
*
Packit 47f805
*  SEMANTICS:
Packit 47f805
* Reads #samples_read# number of shorts from #musicin# filepointer
Packit 47f805
* into #sample_buffer[]#.  Returns the number of samples read.
Packit 47f805
*
Packit 47f805
************************************************************************/
Packit 47f805
Packit 47f805
static int
Packit 47f805
read_samples_pcm(FILE * musicin, int sample_buffer[2304], int samples_to_read)
Packit 47f805
{
Packit 47f805
    int     samples_read;
Packit 47f805
    int     bytes_per_sample = global.pcmbitwidth / 8;
Packit 47f805
    int     swap_byte_order; /* byte order of input stream */
Packit 47f805
Packit 47f805
    switch (global.pcmbitwidth) {
Packit 47f805
    case 32:
Packit 47f805
    case 24:
Packit 47f805
    case 16:
Packit 47f805
        if (global_raw_pcm.in_signed == 0) {
Packit 47f805
            if (global_ui_config.silent < 10) {
Packit 47f805
                error_printf("Unsigned input only supported with bitwidth 8\n");
Packit 47f805
            }
Packit 47f805
            return -1;
Packit 47f805
        }
Packit 47f805
        swap_byte_order = (global_raw_pcm.in_endian != ByteOrderLittleEndian) ? 1 : 0;
Packit 47f805
        if (global.pcmswapbytes) {
Packit 47f805
            swap_byte_order = !swap_byte_order;
Packit 47f805
        }
Packit 47f805
        break;
Packit 47f805
Packit 47f805
    case 8:
Packit 47f805
        swap_byte_order = global.pcm_is_unsigned_8bit;
Packit 47f805
        break;
Packit 47f805
Packit 47f805
    default:
Packit 47f805
        if (global_ui_config.silent < 10) {
Packit 47f805
            error_printf("Only 8, 16, 24 and 32 bit input files supported \n");
Packit 47f805
        }
Packit 47f805
        return -1;
Packit 47f805
    }
Packit 47f805
    if (samples_to_read < 0 || samples_to_read > 2304) {
Packit 47f805
        if (global_ui_config.silent < 10) {
Packit 47f805
            error_printf("Error: unexpected number of samples to read: %d\n", samples_to_read);
Packit 47f805
        }
Packit 47f805
        return -1;
Packit 47f805
    }
Packit 47f805
    samples_read = unpack_read_samples(samples_to_read, bytes_per_sample, swap_byte_order,
Packit 47f805
                                       sample_buffer, musicin);
Packit 47f805
    if (ferror(musicin)) {
Packit 47f805
        if (global_ui_config.silent < 10) {
Packit 47f805
            error_printf("Error reading input file\n");
Packit 47f805
        }
Packit 47f805
        return -1;
Packit 47f805
    }
Packit 47f805
Packit 47f805
    return samples_read;
Packit 47f805
}
Packit 47f805
Packit 47f805
Packit 47f805
Packit 47f805
/* AIFF Definitions */
Packit 47f805
Packit 47f805
static int const IFF_ID_FORM = 0x464f524d; /* "FORM" */
Packit 47f805
static int const IFF_ID_AIFF = 0x41494646; /* "AIFF" */
Packit 47f805
static int const IFF_ID_AIFC = 0x41494643; /* "AIFC" */
Packit 47f805
static int const IFF_ID_COMM = 0x434f4d4d; /* "COMM" */
Packit 47f805
static int const IFF_ID_SSND = 0x53534e44; /* "SSND" */
Packit 47f805
static int const IFF_ID_MPEG = 0x4d504547; /* "MPEG" */
Packit 47f805
Packit 47f805
static int const IFF_ID_NONE = 0x4e4f4e45; /* "NONE" *//* AIFF-C data format */
Packit 47f805
static int const IFF_ID_2CBE = 0x74776f73; /* "twos" *//* AIFF-C data format */
Packit 47f805
static int const IFF_ID_2CLE = 0x736f7774; /* "sowt" *//* AIFF-C data format */
Packit 47f805
Packit 47f805
static int const WAV_ID_RIFF = 0x52494646; /* "RIFF" */
Packit 47f805
static int const WAV_ID_WAVE = 0x57415645; /* "WAVE" */
Packit 47f805
static int const WAV_ID_FMT = 0x666d7420; /* "fmt " */
Packit 47f805
static int const WAV_ID_DATA = 0x64617461; /* "data" */
Packit 47f805
Packit 47f805
#ifndef WAVE_FORMAT_PCM
Packit 47f805
static short const WAVE_FORMAT_PCM = 0x0001;
Packit 47f805
#endif
Packit 47f805
#ifndef WAVE_FORMAT_IEEE_FLOAT
Packit 47f805
static short const WAVE_FORMAT_IEEE_FLOAT = 0x0003;
Packit 47f805
#endif
Packit 47f805
#ifndef WAVE_FORMAT_EXTENSIBLE
Packit 47f805
static short const WAVE_FORMAT_EXTENSIBLE = 0xFFFE;
Packit 47f805
#endif
Packit 47f805
Packit 47f805
Packit 47f805
static long
Packit 47f805
make_even_number_of_bytes_in_length(long x)
Packit 47f805
{
Packit 47f805
    if ((x & 0x01) != 0) {
Packit 47f805
        return x + 1;
Packit 47f805
    }
Packit 47f805
    return x;
Packit 47f805
}
Packit 47f805
Packit 47f805
Packit 47f805
/*****************************************************************************
Packit 47f805
 *
Packit 47f805
 *	Read Microsoft Wave headers
Packit 47f805
 *
Packit 47f805
 *	By the time we get here the first 32-bits of the file have already been
Packit 47f805
 *	read, and we're pretty sure that we're looking at a WAV file.
Packit 47f805
 *
Packit 47f805
 *****************************************************************************/
Packit 47f805
Packit 47f805
static int
Packit 47f805
parse_wave_header(lame_global_flags * gfp, FILE * sf)
Packit 47f805
{
Packit 47f805
    int     format_tag = 0;
Packit 47f805
    int     channels = 0;
Packit 47f805
    int     bits_per_sample = 0;
Packit 47f805
    int     samples_per_sec = 0;
Packit 47f805
Packit 47f805
Packit 47f805
    int     is_wav = 0;
Packit 47f805
    unsigned long    data_length = 0, subSize = 0;
Packit 47f805
    int     loop_sanity = 0;
Packit 47f805
Packit 47f805
    (void) read_32_bits_high_low(sf); /* file_length */
Packit 47f805
    if (read_32_bits_high_low(sf) != WAV_ID_WAVE)
Packit 47f805
        return -1;
Packit 47f805
Packit 47f805
    for (loop_sanity = 0; loop_sanity < 20; ++loop_sanity) {
Packit 47f805
        int     type = read_32_bits_high_low(sf);
Packit 47f805
Packit 47f805
        if (type == WAV_ID_FMT) {
Packit 47f805
            subSize = read_32_bits_low_high(sf);
Packit 47f805
            subSize = make_even_number_of_bytes_in_length(subSize);
Packit 47f805
            if (subSize < 16) {
Packit 47f805
                /*DEBUGF(
Packit 47f805
                   "'fmt' chunk too short (only %ld bytes)!", subSize);  */
Packit 47f805
                return -1;
Packit 47f805
            }
Packit 47f805
Packit 47f805
            format_tag = read_16_bits_low_high(sf);
Packit 47f805
            subSize -= 2;
Packit 47f805
            channels = read_16_bits_low_high(sf);
Packit 47f805
            subSize -= 2;
Packit 47f805
            samples_per_sec = read_32_bits_low_high(sf);
Packit 47f805
            subSize -= 4;
Packit 47f805
            (void) read_32_bits_low_high(sf); /* avg_bytes_per_sec */
Packit 47f805
            subSize -= 4;
Packit 47f805
            (void) read_16_bits_low_high(sf); /* block_align */
Packit 47f805
            subSize -= 2;
Packit 47f805
            bits_per_sample = read_16_bits_low_high(sf);
Packit 47f805
            subSize -= 2;
Packit 47f805
Packit 47f805
            /* WAVE_FORMAT_EXTENSIBLE support */
Packit 47f805
            if ((subSize > 9) && (format_tag == WAVE_FORMAT_EXTENSIBLE)) {
Packit 47f805
                read_16_bits_low_high(sf); /* cbSize */
Packit 47f805
                read_16_bits_low_high(sf); /* ValidBitsPerSample */
Packit 47f805
                read_32_bits_low_high(sf); /* ChannelMask */
Packit 47f805
                /* SubType coincident with format_tag for PCM int or float */
Packit 47f805
                format_tag = read_16_bits_low_high(sf);
Packit 47f805
                subSize -= 10;
Packit 47f805
            }
Packit 47f805
Packit 47f805
            /* DEBUGF("   skipping %d bytes\n", subSize); */
Packit 47f805
Packit 47f805
            if (subSize > 0) {
Packit 47f805
                if (fskip(sf, (long) subSize, SEEK_CUR) != 0)
Packit 47f805
                    return -1;
Packit 47f805
            };
Packit 47f805
Packit 47f805
        }
Packit 47f805
        else if (type == WAV_ID_DATA) {
Packit 47f805
            subSize = read_32_bits_low_high(sf);
Packit 47f805
            data_length = subSize;
Packit 47f805
            is_wav = 1;
Packit 47f805
            /* We've found the audio data. Read no further! */
Packit 47f805
            break;
Packit 47f805
Packit 47f805
        }
Packit 47f805
        else {
Packit 47f805
            subSize = read_32_bits_low_high(sf);
Packit 47f805
            subSize = make_even_number_of_bytes_in_length(subSize);
Packit 47f805
            if (fskip(sf, (long) subSize, SEEK_CUR) != 0) {
Packit 47f805
                return -1;
Packit 47f805
            }
Packit 47f805
        }
Packit 47f805
    }
Packit 47f805
    if (is_wav) {
Packit 47f805
        if (format_tag == 0x0050 || format_tag == 0x0055) {
Packit 47f805
            return sf_mp123;
Packit 47f805
        }
Packit 47f805
        if (format_tag != WAVE_FORMAT_PCM && format_tag != WAVE_FORMAT_IEEE_FLOAT) {
Packit 47f805
            if (global_ui_config.silent < 10) {
Packit 47f805
                error_printf("Unsupported data format: 0x%04X\n", format_tag);
Packit 47f805
            }
Packit 47f805
            return 0;   /* oh no! non-supported format  */
Packit 47f805
        }
Packit 47f805
Packit 47f805
Packit 47f805
        /* make sure the header is sane */
Packit 47f805
        if (!set_input_num_channels(gfp, channels))
Packit 47f805
            return 0;
Packit 47f805
        if (!set_input_samplerate(gfp, samples_per_sec))
Packit 47f805
            return 0;
Packit 47f805
        /* avoid division by zero */
Packit 47f805
        if (bits_per_sample < 1) {
Packit 47f805
            if (global_ui_config.silent < 10)
Packit 47f805
                error_printf("Unsupported bits per sample: %d\n", bits_per_sample);
Packit 47f805
            return -1;
Packit 47f805
        }
Packit 47f805
        global. pcmbitwidth = bits_per_sample;
Packit 47f805
        global. pcm_is_unsigned_8bit = 1;
Packit 47f805
        global. pcm_is_ieee_float = (format_tag == WAVE_FORMAT_IEEE_FLOAT ? 1 : 0);
Packit 47f805
        if (data_length == MAX_U_32_NUM)
Packit 47f805
            (void) lame_set_num_samples(gfp, MAX_U_32_NUM);
Packit 47f805
        else
Packit 47f805
            (void) lame_set_num_samples(gfp, data_length / (channels * ((bits_per_sample + 7) / 8)));
Packit 47f805
        return 1;
Packit 47f805
    }
Packit 47f805
    return -1;
Packit 47f805
}
Packit 47f805
Packit 47f805
Packit 47f805
Packit 47f805
/************************************************************************
Packit 47f805
* aiff_check2
Packit 47f805
*
Packit 47f805
* PURPOSE:	Checks AIFF header information to make sure it is valid.
Packit 47f805
*	        returns 0 on success, 1 on errors
Packit 47f805
************************************************************************/
Packit 47f805
Packit 47f805
static int
Packit 47f805
aiff_check2(IFF_AIFF * const pcm_aiff_data)
Packit 47f805
{
Packit 47f805
    if (pcm_aiff_data->sampleType != (unsigned long) IFF_ID_SSND) {
Packit 47f805
        if (global_ui_config.silent < 10) {
Packit 47f805
            error_printf("ERROR: input sound data is not PCM\n");
Packit 47f805
        }
Packit 47f805
        return 1;
Packit 47f805
    }
Packit 47f805
    switch (pcm_aiff_data->sampleSize) {
Packit 47f805
    case 32:
Packit 47f805
    case 24:
Packit 47f805
    case 16:
Packit 47f805
    case 8:
Packit 47f805
        break;
Packit 47f805
    default:
Packit 47f805
        if (global_ui_config.silent < 10) {
Packit 47f805
            error_printf("ERROR: input sound data is not 8, 16, 24 or 32 bits\n");
Packit 47f805
        }
Packit 47f805
        return 1;
Packit 47f805
    }
Packit 47f805
    if (pcm_aiff_data->numChannels != 1 && pcm_aiff_data->numChannels != 2) {
Packit 47f805
        if (global_ui_config.silent < 10) {
Packit 47f805
            error_printf("ERROR: input sound data is not mono or stereo\n");
Packit 47f805
        }
Packit 47f805
        return 1;
Packit 47f805
    }
Packit 47f805
    if (pcm_aiff_data->blkAlgn.blockSize != 0) {
Packit 47f805
        if (global_ui_config.silent < 10) {
Packit 47f805
            error_printf("ERROR: block size of input sound data is not 0 bytes\n");
Packit 47f805
        }
Packit 47f805
        return 1;
Packit 47f805
    }
Packit 47f805
    /* A bug, since we correctly skip the offset earlier in the code.
Packit 47f805
       if (pcm_aiff_data->blkAlgn.offset != 0) {
Packit 47f805
       error_printf("Block offset is not 0 bytes in '%s'\n", file_name);
Packit 47f805
       return 1;
Packit 47f805
       } */
Packit 47f805
Packit 47f805
    return 0;
Packit 47f805
}
Packit 47f805
Packit 47f805
Packit 47f805
/*****************************************************************************
Packit 47f805
 *
Packit 47f805
 *	Read Audio Interchange File Format (AIFF) headers.
Packit 47f805
 *
Packit 47f805
 *	By the time we get here the first 32 bits of the file have already been
Packit 47f805
 *	read, and we're pretty sure that we're looking at an AIFF file.
Packit 47f805
 *
Packit 47f805
 *****************************************************************************/
Packit 47f805
Packit 47f805
static int
Packit 47f805
parse_aiff_header(lame_global_flags * gfp, FILE * sf)
Packit 47f805
{
Packit 47f805
    long    chunkSize = 0, subSize = 0, typeID = 0, dataType = IFF_ID_NONE;
Packit 47f805
    IFF_AIFF aiff_info;
Packit 47f805
    int     seen_comm_chunk = 0, seen_ssnd_chunk = 0;
Packit 47f805
    long    pcm_data_pos = -1;
Packit 47f805
Packit 47f805
    memset(&aiff_info, 0, sizeof(aiff_info));
Packit 47f805
    chunkSize = read_32_bits_high_low(sf);
Packit 47f805
Packit 47f805
    typeID = read_32_bits_high_low(sf);
Packit 47f805
    if ((typeID != IFF_ID_AIFF) && (typeID != IFF_ID_AIFC))
Packit 47f805
        return -1;
Packit 47f805
Packit 47f805
    while (chunkSize > 0) {
Packit 47f805
        long    ckSize;
Packit 47f805
        int     type = read_32_bits_high_low(sf);
Packit 47f805
        chunkSize -= 4;
Packit 47f805
Packit 47f805
        /* DEBUGF(
Packit 47f805
           "found chunk type %08x '%4.4s'\n", type, (char*)&type); */
Packit 47f805
Packit 47f805
        /* don't use a switch here to make it easier to use 'break' for SSND */
Packit 47f805
        if (type == IFF_ID_COMM) {
Packit 47f805
            seen_comm_chunk = seen_ssnd_chunk + 1;
Packit 47f805
            subSize = read_32_bits_high_low(sf);
Packit 47f805
            ckSize = make_even_number_of_bytes_in_length(subSize);
Packit 47f805
            chunkSize -= ckSize;
Packit 47f805
Packit 47f805
            aiff_info.numChannels = (short) read_16_bits_high_low(sf);
Packit 47f805
            ckSize -= 2;
Packit 47f805
            aiff_info.numSampleFrames = read_32_bits_high_low(sf);
Packit 47f805
            ckSize -= 4;
Packit 47f805
            aiff_info.sampleSize = (short) read_16_bits_high_low(sf);
Packit 47f805
            ckSize -= 2;
Packit 47f805
            aiff_info.sampleRate = read_ieee_extended_high_low(sf);
Packit 47f805
            ckSize -= 10;
Packit 47f805
            if (typeID == IFF_ID_AIFC) {
Packit 47f805
                dataType = read_32_bits_high_low(sf);
Packit 47f805
                ckSize -= 4;
Packit 47f805
            }
Packit 47f805
            if (fskip(sf, ckSize, SEEK_CUR) != 0)
Packit 47f805
                return -1;
Packit 47f805
        }
Packit 47f805
        else if (type == IFF_ID_SSND) {
Packit 47f805
            seen_ssnd_chunk = 1;
Packit 47f805
            subSize = read_32_bits_high_low(sf);
Packit 47f805
            ckSize = make_even_number_of_bytes_in_length(subSize);
Packit 47f805
            chunkSize -= ckSize;
Packit 47f805
Packit 47f805
            aiff_info.blkAlgn.offset = read_32_bits_high_low(sf);
Packit 47f805
            ckSize -= 4;
Packit 47f805
            aiff_info.blkAlgn.blockSize = read_32_bits_high_low(sf);
Packit 47f805
            ckSize -= 4;
Packit 47f805
Packit 47f805
            aiff_info.sampleType = IFF_ID_SSND;
Packit 47f805
Packit 47f805
            if (seen_comm_chunk > 0) {
Packit 47f805
                if (fskip(sf, (long) aiff_info.blkAlgn.offset, SEEK_CUR) != 0)
Packit 47f805
                    return -1;
Packit 47f805
                /* We've found the audio data. Read no further! */
Packit 47f805
                break;
Packit 47f805
            }
Packit 47f805
            pcm_data_pos = ftell(sf);
Packit 47f805
            if (pcm_data_pos >= 0) {
Packit 47f805
                pcm_data_pos += aiff_info.blkAlgn.offset;
Packit 47f805
            }
Packit 47f805
            if (fskip(sf, ckSize, SEEK_CUR) != 0)
Packit 47f805
                return -1;
Packit 47f805
        }
Packit 47f805
        else {
Packit 47f805
            subSize = read_32_bits_high_low(sf);
Packit 47f805
            ckSize = make_even_number_of_bytes_in_length(subSize);
Packit 47f805
            chunkSize -= ckSize;
Packit 47f805
Packit 47f805
            if (fskip(sf, ckSize, SEEK_CUR) != 0)
Packit 47f805
                return -1;
Packit 47f805
        }
Packit 47f805
    }
Packit 47f805
    if (dataType == IFF_ID_2CLE) {
Packit 47f805
        global. pcmswapbytes = global_reader.swapbytes;
Packit 47f805
    }
Packit 47f805
    else if (dataType == IFF_ID_2CBE) {
Packit 47f805
        global. pcmswapbytes = !global_reader.swapbytes;
Packit 47f805
    }
Packit 47f805
    else if (dataType == IFF_ID_NONE) {
Packit 47f805
        global. pcmswapbytes = !global_reader.swapbytes;
Packit 47f805
    }
Packit 47f805
    else {
Packit 47f805
        return -1;
Packit 47f805
    }
Packit 47f805
Packit 47f805
    /* DEBUGF("Parsed AIFF %d\n", is_aiff); */
Packit 47f805
    if (seen_comm_chunk && (seen_ssnd_chunk > 0 || aiff_info.numSampleFrames == 0)) {
Packit 47f805
        /* make sure the header is sane */
Packit 47f805
        if (0 != aiff_check2(&aiff_info))
Packit 47f805
            return 0;
Packit 47f805
        if (!set_input_num_channels(gfp, aiff_info.numChannels))
Packit 47f805
            return 0;
Packit 47f805
        if (!set_input_samplerate(gfp, (int) aiff_info.sampleRate))
Packit 47f805
            return 0;
Packit 47f805
        (void) lame_set_num_samples(gfp, aiff_info.numSampleFrames);
Packit 47f805
        global. pcmbitwidth = aiff_info.sampleSize;
Packit 47f805
        global. pcm_is_unsigned_8bit = 0;
Packit 47f805
        global. pcm_is_ieee_float = 0; /* FIXME: possible ??? */
Packit 47f805
        if (pcm_data_pos >= 0) {
Packit 47f805
            if (fseek(sf, pcm_data_pos, SEEK_SET) != 0) {
Packit 47f805
                if (global_ui_config.silent < 10) {
Packit 47f805
                    error_printf("Can't rewind stream to audio data position\n");
Packit 47f805
                }
Packit 47f805
                return 0;
Packit 47f805
            }
Packit 47f805
        }
Packit 47f805
Packit 47f805
        return 1;
Packit 47f805
    }
Packit 47f805
    return -1;
Packit 47f805
}
Packit 47f805
Packit 47f805
Packit 47f805
Packit 47f805
/************************************************************************
Packit 47f805
*
Packit 47f805
* parse_file_header
Packit 47f805
*
Packit 47f805
* PURPOSE: Read the header from a bytestream.  Try to determine whether
Packit 47f805
*		   it's a WAV file or AIFF without rewinding, since rewind
Packit 47f805
*		   doesn't work on pipes and there's a good chance we're reading
Packit 47f805
*		   from stdin (otherwise we'd probably be using libsndfile).
Packit 47f805
*
Packit 47f805
* When this function returns, the file offset will be positioned at the
Packit 47f805
* beginning of the sound data.
Packit 47f805
*
Packit 47f805
************************************************************************/
Packit 47f805
Packit 47f805
static int
Packit 47f805
parse_file_header(lame_global_flags * gfp, FILE * sf)
Packit 47f805
{
Packit 47f805
Packit 47f805
    int     type = read_32_bits_high_low(sf);
Packit 47f805
    /*
Packit 47f805
       DEBUGF(
Packit 47f805
       "First word of input stream: %08x '%4.4s'\n", type, (char*) &type); 
Packit 47f805
     */
Packit 47f805
    global. count_samples_carefully = 0;
Packit 47f805
    global. pcm_is_unsigned_8bit = global_raw_pcm.in_signed == 1 ? 0 : 1;
Packit 47f805
    /*global_reader.input_format = sf_raw; commented out, because it is better to fail
Packit 47f805
       here as to encode some hundreds of input files not supported by LAME
Packit 47f805
       If you know you have RAW PCM data, use the -r switch
Packit 47f805
     */
Packit 47f805
Packit 47f805
    if (type == WAV_ID_RIFF) {
Packit 47f805
        /* It's probably a WAV file */
Packit 47f805
        int const ret = parse_wave_header(gfp, sf);
Packit 47f805
        if (ret == sf_mp123) {
Packit 47f805
        	global. count_samples_carefully = 1;
Packit 47f805
            return sf_mp123;
Packit 47f805
        }
Packit 47f805
        if (ret > 0) {
Packit 47f805
            if (lame_get_num_samples(gfp) == MAX_U_32_NUM || global_reader.ignorewavlength == 1)
Packit 47f805
            {
Packit 47f805
                global. count_samples_carefully = 0;
Packit 47f805
                lame_set_num_samples(gfp, MAX_U_32_NUM);
Packit 47f805
            }
Packit 47f805
            else
Packit 47f805
                global. count_samples_carefully = 1;
Packit 47f805
            return sf_wave;
Packit 47f805
        }
Packit 47f805
        if (ret < 0) {
Packit 47f805
            if (global_ui_config.silent < 10) {
Packit 47f805
                error_printf("Warning: corrupt or unsupported WAVE format\n");
Packit 47f805
            }
Packit 47f805
        }
Packit 47f805
    }
Packit 47f805
    else if (type == IFF_ID_FORM) {
Packit 47f805
        /* It's probably an AIFF file */
Packit 47f805
        int const ret = parse_aiff_header(gfp, sf);
Packit 47f805
        if (ret > 0) {
Packit 47f805
            global. count_samples_carefully = 1;
Packit 47f805
            return sf_aiff;
Packit 47f805
        }
Packit 47f805
        if (ret < 0) {
Packit 47f805
            if (global_ui_config.silent < 10) {
Packit 47f805
                error_printf("Warning: corrupt or unsupported AIFF format\n");
Packit 47f805
            }
Packit 47f805
        }
Packit 47f805
    }
Packit 47f805
    else {
Packit 47f805
        if (global_ui_config.silent < 10) {
Packit 47f805
            error_printf("Warning: unsupported audio format\n");
Packit 47f805
        }
Packit 47f805
    }
Packit 47f805
    return sf_unknown;
Packit 47f805
}
Packit 47f805
Packit 47f805
Packit 47f805
static int
Packit 47f805
open_mpeg_file_part2(lame_t gfp, FILE* musicin, char const *inPath, int *enc_delay, int *enc_padding)
Packit 47f805
{
Packit 47f805
#ifdef HAVE_MPGLIB
Packit 47f805
    if (-1 == lame_decode_initfile(musicin, &global_decoder.mp3input_data, enc_delay, enc_padding)) {
Packit 47f805
        if (global_ui_config.silent < 10) {
Packit 47f805
            error_printf("Error reading headers in mp3 input file %s.\n", inPath);
Packit 47f805
        }
Packit 47f805
        return 0;
Packit 47f805
    }
Packit 47f805
#endif
Packit 47f805
    if (!set_input_num_channels(gfp, global_decoder.mp3input_data.stereo)) {
Packit 47f805
        return 0;
Packit 47f805
    }
Packit 47f805
    if (!set_input_samplerate(gfp, global_decoder.mp3input_data.samplerate)) {
Packit 47f805
        return 0;
Packit 47f805
    }
Packit 47f805
    (void) lame_set_num_samples(gfp, global_decoder.mp3input_data.nsamp);
Packit 47f805
    return 1;
Packit 47f805
}
Packit 47f805
Packit 47f805
Packit 47f805
static FILE *
Packit 47f805
open_wave_file(lame_t gfp, char const *inPath, int *enc_delay, int *enc_padding)
Packit 47f805
{
Packit 47f805
    FILE   *musicin;
Packit 47f805
Packit 47f805
    /* set the defaults from info incase we cannot determine them from file */
Packit 47f805
    lame_set_num_samples(gfp, MAX_U_32_NUM);
Packit 47f805
Packit 47f805
    if (!strcmp(inPath, "-")) {
Packit 47f805
        lame_set_stream_binary_mode(musicin = stdin); /* Read from standard input. */
Packit 47f805
    }
Packit 47f805
    else {
Packit 47f805
        if ((musicin = lame_fopen(inPath, "rb")) == NULL) {
Packit 47f805
            if (global_ui_config.silent < 10) {
Packit 47f805
                error_printf("Could not find \"%s\".\n", inPath);
Packit 47f805
            }
Packit 47f805
            return 0;
Packit 47f805
        }
Packit 47f805
    }
Packit 47f805
Packit 47f805
    if (global_reader.input_format == sf_ogg) {
Packit 47f805
        if (global_ui_config.silent < 10) {
Packit 47f805
            error_printf("sorry, vorbis support in LAME is deprecated.\n");
Packit 47f805
        }
Packit 47f805
        close_input_file(musicin);
Packit 47f805
        return 0;
Packit 47f805
    }
Packit 47f805
    else if (global_reader.input_format == sf_raw) {
Packit 47f805
        /* assume raw PCM */
Packit 47f805
        if (global_ui_config.silent < 9) {
Packit 47f805
            console_printf("Assuming raw pcm input file");
Packit 47f805
            if (global_reader.swapbytes)
Packit 47f805
                console_printf(" : Forcing byte-swapping\n");
Packit 47f805
            else
Packit 47f805
                console_printf("\n");
Packit 47f805
        }
Packit 47f805
        global. pcmswapbytes = global_reader.swapbytes;
Packit 47f805
    }
Packit 47f805
    else {
Packit 47f805
        global_reader.input_format = parse_file_header(gfp, musicin);
Packit 47f805
    }
Packit 47f805
    if (global_reader.input_format == sf_mp123) {
Packit 47f805
        if (open_mpeg_file_part2(gfp, musicin, inPath, enc_delay, enc_padding))
Packit 47f805
            return musicin;
Packit 47f805
        close_input_file(musicin);
Packit 47f805
        return 0;
Packit 47f805
    }
Packit 47f805
    if (global_reader.input_format == sf_unknown) {
Packit 47f805
        close_input_file(musicin);
Packit 47f805
        return 0;
Packit 47f805
    }
Packit 47f805
Packit 47f805
    if (lame_get_num_samples(gfp) == MAX_U_32_NUM && musicin != stdin) {
Packit 47f805
        int const tmp_num_channels = lame_get_num_channels(gfp);
Packit 47f805
        double const flen = lame_get_file_size(musicin); /* try to figure out num_samples */
Packit 47f805
        if (flen >= 0 && tmp_num_channels > 0 ) {
Packit 47f805
            /* try file size, assume 2 bytes per sample */
Packit 47f805
            unsigned long fsize = (unsigned long) (flen / (2 * tmp_num_channels));
Packit 47f805
            (void) lame_set_num_samples(gfp, fsize);
Packit 47f805
            global. count_samples_carefully = 0;
Packit 47f805
        }
Packit 47f805
    }
Packit 47f805
    return musicin;
Packit 47f805
}
Packit 47f805
Packit 47f805
Packit 47f805
Packit 47f805
static FILE *
Packit 47f805
open_mpeg_file(lame_t gfp, char const *inPath, int *enc_delay, int *enc_padding)
Packit 47f805
{
Packit 47f805
    FILE   *musicin;
Packit 47f805
Packit 47f805
    /* set the defaults from info incase we cannot determine them from file */
Packit 47f805
    lame_set_num_samples(gfp, MAX_U_32_NUM);
Packit 47f805
Packit 47f805
    if (strcmp(inPath, "-") == 0) {
Packit 47f805
        musicin = stdin;
Packit 47f805
        lame_set_stream_binary_mode(musicin); /* Read from standard input. */
Packit 47f805
    }
Packit 47f805
    else {
Packit 47f805
        musicin = lame_fopen(inPath, "rb");
Packit 47f805
        if (musicin == NULL) {
Packit 47f805
            if (global_ui_config.silent < 10) {
Packit 47f805
                error_printf("Could not find \"%s\".\n", inPath);
Packit 47f805
            }
Packit 47f805
            return 0;
Packit 47f805
        }
Packit 47f805
    }
Packit 47f805
#ifdef AMIGA_MPEGA
Packit 47f805
    if (-1 == lame_decode_initfile(inPath, &global_decoder.mp3input_data)) {
Packit 47f805
        if (global_ui_config.silent < 10) {
Packit 47f805
            error_printf("Error reading headers in mp3 input file %s.\n", inPath);
Packit 47f805
        }
Packit 47f805
        close_input_file(musicin);
Packit 47f805
        return 0;
Packit 47f805
    }
Packit 47f805
#endif
Packit 47f805
    if ( 0 == open_mpeg_file_part2(gfp, musicin, inPath, enc_delay, enc_padding) ) {
Packit 47f805
        close_input_file(musicin);
Packit 47f805
        return 0;
Packit 47f805
    }
Packit 47f805
    if (lame_get_num_samples(gfp) == MAX_U_32_NUM && musicin != stdin) {
Packit 47f805
        double  flen = lame_get_file_size(musicin); /* try to figure out num_samples */
Packit 47f805
        if (flen >= 0) {
Packit 47f805
            /* try file size, assume 2 bytes per sample */
Packit 47f805
            if (global_decoder.mp3input_data.bitrate > 0) {
Packit 47f805
                double  totalseconds =
Packit 47f805
                    (flen * 8.0 / (1000.0 * global_decoder.mp3input_data.bitrate));
Packit 47f805
                unsigned long tmp_num_samples =
Packit 47f805
                    (unsigned long) (totalseconds * lame_get_in_samplerate(gfp));
Packit 47f805
Packit 47f805
                (void) lame_set_num_samples(gfp, tmp_num_samples);
Packit 47f805
                global_decoder.mp3input_data.nsamp = tmp_num_samples;
Packit 47f805
                global. count_samples_carefully = 0;
Packit 47f805
            }
Packit 47f805
        }
Packit 47f805
    }
Packit 47f805
    return musicin;
Packit 47f805
}
Packit 47f805
Packit 47f805
Packit 47f805
static int
Packit 47f805
close_input_file(FILE * musicin)
Packit 47f805
{
Packit 47f805
    int     ret = 0;
Packit 47f805
Packit 47f805
    if (musicin != stdin && musicin != 0) {
Packit 47f805
        ret = fclose(musicin);
Packit 47f805
    }
Packit 47f805
    if (ret != 0) {
Packit 47f805
        if (global_ui_config.silent < 10) {
Packit 47f805
            error_printf("Could not close audio input file\n");
Packit 47f805
        }
Packit 47f805
    }
Packit 47f805
    return ret;
Packit 47f805
}
Packit 47f805
Packit 47f805
Packit 47f805
Packit 47f805
#if defined(HAVE_MPGLIB)
Packit 47f805
static int
Packit 47f805
check_aid(const unsigned char *header)
Packit 47f805
{
Packit 47f805
    return 0 == memcmp(header, "AiD\1", 4);
Packit 47f805
}
Packit 47f805
Packit 47f805
/*
Packit 47f805
 * Please check this and don't kill me if there's a bug
Packit 47f805
 * This is a (nearly?) complete header analysis for a MPEG-1/2/2.5 Layer I, II or III
Packit 47f805
 * data stream
Packit 47f805
 */
Packit 47f805
Packit 47f805
static int
Packit 47f805
is_syncword_mp123(const void *const headerptr)
Packit 47f805
{
Packit 47f805
    const unsigned char *const p = headerptr;
Packit 47f805
    static const char abl2[16] = { 0, 7, 7, 7, 0, 7, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8 };
Packit 47f805
Packit 47f805
    if ((p[0] & 0xFF) != 0xFF)
Packit 47f805
        return 0;       /* first 8 bits must be '1' */
Packit 47f805
    if ((p[1] & 0xE0) != 0xE0)
Packit 47f805
        return 0;       /* next 3 bits are also */
Packit 47f805
    if ((p[1] & 0x18) == 0x08)
Packit 47f805
        return 0;       /* no MPEG-1, -2 or -2.5 */
Packit 47f805
    switch (p[1] & 0x06) {
Packit 47f805
    default:
Packit 47f805
    case 0x00:         /* illegal Layer */
Packit 47f805
        return 0;
Packit 47f805
Packit 47f805
    case 0x02:         /* Layer3 */
Packit 47f805
        if (global_reader.input_format != sf_mp3 && global_reader.input_format != sf_mp123) {
Packit 47f805
            return 0;
Packit 47f805
        }
Packit 47f805
        global_reader.input_format = sf_mp3;
Packit 47f805
        break;
Packit 47f805
Packit 47f805
    case 0x04:         /* Layer2 */
Packit 47f805
        if (global_reader.input_format != sf_mp2 && global_reader.input_format != sf_mp123) {
Packit 47f805
            return 0;
Packit 47f805
        }
Packit 47f805
        global_reader.input_format = sf_mp2;
Packit 47f805
        break;
Packit 47f805
Packit 47f805
    case 0x06:         /* Layer1 */
Packit 47f805
        if (global_reader.input_format != sf_mp1 && global_reader.input_format != sf_mp123) {
Packit 47f805
            return 0;
Packit 47f805
        }
Packit 47f805
        global_reader.input_format = sf_mp1;
Packit 47f805
        break;
Packit 47f805
    }
Packit 47f805
    if ((p[1] & 0x06) == 0x00)
Packit 47f805
        return 0;       /* no Layer I, II and III */
Packit 47f805
    if ((p[2] & 0xF0) == 0xF0)
Packit 47f805
        return 0;       /* bad bitrate */
Packit 47f805
    if ((p[2] & 0x0C) == 0x0C)
Packit 47f805
        return 0;       /* no sample frequency with (32,44.1,48)/(1,2,4)     */
Packit 47f805
    if ((p[1] & 0x18) == 0x18 && (p[1] & 0x06) == 0x04 && abl2[p[2] >> 4] & (1 << (p[3] >> 6)))
Packit 47f805
        return 0;
Packit 47f805
    if ((p[3] & 3) == 2)
Packit 47f805
        return 0;       /* reserved enphasis mode */
Packit 47f805
    return 1;
Packit 47f805
}
Packit 47f805
Packit 47f805
static size_t
Packit 47f805
lenOfId3v2Tag(unsigned char const* buf)
Packit 47f805
{
Packit 47f805
    unsigned int b0 = buf[0] & 127;
Packit 47f805
    unsigned int b1 = buf[1] & 127;
Packit 47f805
    unsigned int b2 = buf[2] & 127;
Packit 47f805
    unsigned int b3 = buf[3] & 127;
Packit 47f805
    return (((((b0 << 7) + b1) << 7) + b2) << 7) + b3;
Packit 47f805
}
Packit 47f805
Packit 47f805
int
Packit 47f805
lame_decode_initfile(FILE * fd, mp3data_struct * mp3data, int *enc_delay, int *enc_padding)
Packit 47f805
{
Packit 47f805
    /*  VBRTAGDATA pTagData; */
Packit 47f805
    /* int xing_header,len2,num_frames; */
Packit 47f805
    unsigned char buf[100];
Packit 47f805
    int     ret;
Packit 47f805
    size_t  len;
Packit 47f805
    int     aid_header;
Packit 47f805
    short int pcm_l[1152], pcm_r[1152];
Packit 47f805
    int     freeformat = 0;
Packit 47f805
Packit 47f805
    memset(mp3data, 0, sizeof(mp3data_struct));
Packit 47f805
    if (global.hip) {
Packit 47f805
        hip_decode_exit(global.hip);
Packit 47f805
    }
Packit 47f805
    global. hip = hip_decode_init();
Packit 47f805
    hip_set_msgf(global.hip, global_ui_config.silent < 10 ? &frontend_msgf : 0);
Packit 47f805
    hip_set_errorf(global.hip, global_ui_config.silent < 10 ? &frontend_errorf : 0);
Packit 47f805
    hip_set_debugf(global.hip, &frontend_debugf);
Packit 47f805
Packit 47f805
    len = 4;
Packit 47f805
    if (fread(buf, 1, len, fd) != len)
Packit 47f805
        return -1;      /* failed */
Packit 47f805
    while (buf[0] == 'I' && buf[1] == 'D' && buf[2] == '3') {
Packit 47f805
        len = 6;
Packit 47f805
        if (fread(&buf[4], 1, len, fd) != len)
Packit 47f805
            return -1;  /* failed */
Packit 47f805
        len = lenOfId3v2Tag(&buf[6]);
Packit 47f805
        if (global.in_id3v2_size < 1) {
Packit 47f805
            global.in_id3v2_size = 10 + len;
Packit 47f805
            global.in_id3v2_tag = malloc(global.in_id3v2_size);
Packit 47f805
            if (global.in_id3v2_tag) {
Packit 47f805
                memcpy(global.in_id3v2_tag, buf, 10);
Packit 47f805
                if (fread(&global.in_id3v2_tag[10], 1, len, fd) != len)
Packit 47f805
                    return -1;  /* failed */
Packit 47f805
                len = 0; /* copied, nothing to skip */
Packit 47f805
            }
Packit 47f805
            else {
Packit 47f805
                global.in_id3v2_size = 0;
Packit 47f805
            }
Packit 47f805
        }
Packit 47f805
        assert( len <= LONG_MAX );
Packit 47f805
        fskip(fd, (long) len, SEEK_CUR);
Packit 47f805
        len = 4;
Packit 47f805
        if (fread(&buf, 1, len, fd) != len)
Packit 47f805
            return -1;  /* failed */
Packit 47f805
    }
Packit 47f805
    aid_header = check_aid(buf);
Packit 47f805
    if (aid_header) {
Packit 47f805
        if (fread(&buf, 1, 2, fd) != 2)
Packit 47f805
            return -1;  /* failed */
Packit 47f805
        aid_header = (unsigned char) buf[0] + 256 * (unsigned char) buf[1];
Packit 47f805
        if (global_ui_config.silent < 9) {
Packit 47f805
            console_printf("Album ID found.  length=%i \n", aid_header);
Packit 47f805
        }
Packit 47f805
        /* skip rest of AID, except for 6 bytes we have already read */
Packit 47f805
        fskip(fd, aid_header - 6, SEEK_CUR);
Packit 47f805
Packit 47f805
        /* read 4 more bytes to set up buffer for MP3 header check */
Packit 47f805
        if (fread(&buf, 1, len, fd) != len)
Packit 47f805
            return -1;  /* failed */
Packit 47f805
    }
Packit 47f805
    len = 4;
Packit 47f805
    while (!is_syncword_mp123(buf)) {
Packit 47f805
        unsigned int i;
Packit 47f805
        for (i = 0; i < len - 1; i++)
Packit 47f805
            buf[i] = buf[i + 1];
Packit 47f805
        if (fread(buf + len - 1, 1, 1, fd) != 1)
Packit 47f805
            return -1;  /* failed */
Packit 47f805
    }
Packit 47f805
Packit 47f805
    if ((buf[2] & 0xf0) == 0) {
Packit 47f805
        if (global_ui_config.silent < 9) {
Packit 47f805
            console_printf("Input file is freeformat.\n");
Packit 47f805
        }
Packit 47f805
        freeformat = 1;
Packit 47f805
    }
Packit 47f805
    /* now parse the current buffer looking for MP3 headers.    */
Packit 47f805
    /* (as of 11/00: mpglib modified so that for the first frame where  */
Packit 47f805
    /* headers are parsed, no data will be decoded.   */
Packit 47f805
    /* However, for freeformat, we need to decode an entire frame, */
Packit 47f805
    /* so mp3data->bitrate will be 0 until we have decoded the first */
Packit 47f805
    /* frame.  Cannot decode first frame here because we are not */
Packit 47f805
    /* yet prepared to handle the output. */
Packit 47f805
    ret = hip_decode1_headersB(global.hip, buf, len, pcm_l, pcm_r, mp3data, enc_delay, enc_padding);
Packit 47f805
    if (-1 == ret)
Packit 47f805
        return -1;
Packit 47f805
Packit 47f805
    /* repeat until we decode a valid mp3 header.  */
Packit 47f805
    while (!mp3data->header_parsed) {
Packit 47f805
        len = fread(buf, 1, sizeof(buf), fd);
Packit 47f805
        if (len != sizeof(buf))
Packit 47f805
            return -1;
Packit 47f805
        ret =
Packit 47f805
            hip_decode1_headersB(global.hip, buf, len, pcm_l, pcm_r, mp3data, enc_delay,
Packit 47f805
                                 enc_padding);
Packit 47f805
        if (-1 == ret)
Packit 47f805
            return -1;
Packit 47f805
    }
Packit 47f805
Packit 47f805
    if (mp3data->bitrate == 0 && !freeformat) {
Packit 47f805
        if (global_ui_config.silent < 10) {
Packit 47f805
            error_printf("fail to sync...\n");
Packit 47f805
        }
Packit 47f805
        return lame_decode_initfile(fd, mp3data, enc_delay, enc_padding);
Packit 47f805
    }
Packit 47f805
Packit 47f805
    if (mp3data->totalframes > 0) {
Packit 47f805
        /* mpglib found a Xing VBR header and computed nsamp & totalframes */
Packit 47f805
    }
Packit 47f805
    else {
Packit 47f805
        /* set as unknown.  Later, we will take a guess based on file size
Packit 47f805
         * ant bitrate */
Packit 47f805
        mp3data->nsamp = MAX_U_32_NUM;
Packit 47f805
    }
Packit 47f805
Packit 47f805
Packit 47f805
    /*
Packit 47f805
       report_printf("ret = %i NEED_MORE=%i \n",ret,MP3_NEED_MORE);
Packit 47f805
       report_printf("stereo = %i \n",mp.fr.stereo);
Packit 47f805
       report_printf("samp = %i  \n",freqs[mp.fr.sampling_frequency]);
Packit 47f805
       report_printf("framesize = %i  \n",framesize);
Packit 47f805
       report_printf("bitrate = %i  \n",mp3data->bitrate);
Packit 47f805
       report_printf("num frames = %ui  \n",num_frames);
Packit 47f805
       report_printf("num samp = %ui  \n",mp3data->nsamp);
Packit 47f805
       report_printf("mode     = %i  \n",mp.fr.mode);
Packit 47f805
     */
Packit 47f805
Packit 47f805
    return 0;
Packit 47f805
}
Packit 47f805
Packit 47f805
/*
Packit 47f805
For lame_decode_fromfile:  return code
Packit 47f805
  -1     error
Packit 47f805
   n     number of samples output.  either 576 or 1152 depending on MP3 file.
Packit 47f805
Packit 47f805
Packit 47f805
For lame_decode1_headers():  return code
Packit 47f805
  -1     error
Packit 47f805
   0     ok, but need more data before outputing any samples
Packit 47f805
   n     number of samples output.  either 576 or 1152 depending on MP3 file.
Packit 47f805
*/
Packit 47f805
static int
Packit 47f805
lame_decode_fromfile(FILE * fd, short pcm_l[], short pcm_r[], mp3data_struct * mp3data)
Packit 47f805
{
Packit 47f805
    int     ret = 0;
Packit 47f805
    size_t  len = 0;
Packit 47f805
    unsigned char buf[1024];
Packit 47f805
Packit 47f805
    /* first see if we still have data buffered in the decoder: */
Packit 47f805
    ret = hip_decode1_headers(global.hip, buf, len, pcm_l, pcm_r, mp3data);
Packit 47f805
    if (ret != 0)
Packit 47f805
        return ret;
Packit 47f805
Packit 47f805
Packit 47f805
    /* read until we get a valid output frame */
Packit 47f805
    for (;;) {
Packit 47f805
        len = fread(buf, 1, 1024, fd);
Packit 47f805
        if (len == 0) {
Packit 47f805
            /* we are done reading the file, but check for buffered data */
Packit 47f805
            ret = hip_decode1_headers(global.hip, buf, len, pcm_l, pcm_r, mp3data);
Packit 47f805
            if (ret <= 0) {
Packit 47f805
                return -1; /* done with file */
Packit 47f805
            }
Packit 47f805
            break;
Packit 47f805
        }
Packit 47f805
Packit 47f805
        ret = hip_decode1_headers(global.hip, buf, len, pcm_l, pcm_r, mp3data);
Packit 47f805
        if (ret == -1) {
Packit 47f805
            return -1;
Packit 47f805
        }
Packit 47f805
        if (ret > 0)
Packit 47f805
            break;
Packit 47f805
    }
Packit 47f805
    return ret;
Packit 47f805
}
Packit 47f805
#endif /* defined(HAVE_MPGLIB) */
Packit 47f805
Packit 47f805
Packit 47f805
int
Packit 47f805
is_mpeg_file_format(int input_file_format)
Packit 47f805
{
Packit 47f805
    switch (input_file_format) {
Packit 47f805
    case sf_mp1:
Packit 47f805
        return 1;
Packit 47f805
    case sf_mp2:
Packit 47f805
        return 2;
Packit 47f805
    case sf_mp3:
Packit 47f805
        return 3;
Packit 47f805
    case sf_mp123:
Packit 47f805
        return -1;
Packit 47f805
    default:
Packit 47f805
        break;
Packit 47f805
    }
Packit 47f805
    return 0;
Packit 47f805
}
Packit 47f805
Packit 47f805
Packit 47f805
#define LOW__BYTE(x) (x & 0x00ff)
Packit 47f805
#define HIGH_BYTE(x) ((x >> 8) & 0x00ff)
Packit 47f805
Packit 47f805
void
Packit 47f805
put_audio16(FILE * outf, short Buffer[2][1152], int iread, int nch)
Packit 47f805
{
Packit 47f805
    char    data[2 * 1152 * 2];
Packit 47f805
    int     i, m = 0;
Packit 47f805
Packit 47f805
    if (global_decoder.disable_wav_header && global_reader.swapbytes) {
Packit 47f805
        if (nch == 1) {
Packit 47f805
            for (i = 0; i < iread; i++) {
Packit 47f805
                short   x = Buffer[0][i];
Packit 47f805
                /* write 16 Bits High Low */
Packit 47f805
                data[m++] = HIGH_BYTE(x);
Packit 47f805
                data[m++] = LOW__BYTE(x);
Packit 47f805
            }
Packit 47f805
        }
Packit 47f805
        else {
Packit 47f805
            for (i = 0; i < iread; i++) {
Packit 47f805
                short   x = Buffer[0][i], y = Buffer[1][i];
Packit 47f805
                /* write 16 Bits High Low */
Packit 47f805
                data[m++] = HIGH_BYTE(x);
Packit 47f805
                data[m++] = LOW__BYTE(x);
Packit 47f805
                /* write 16 Bits High Low */
Packit 47f805
                data[m++] = HIGH_BYTE(y);
Packit 47f805
                data[m++] = LOW__BYTE(y);
Packit 47f805
            }
Packit 47f805
        }
Packit 47f805
    }
Packit 47f805
    else {
Packit 47f805
        if (nch == 1) {
Packit 47f805
            for (i = 0; i < iread; i++) {
Packit 47f805
                short   x = Buffer[0][i];
Packit 47f805
                /* write 16 Bits Low High */
Packit 47f805
                data[m++] = LOW__BYTE(x);
Packit 47f805
                data[m++] = HIGH_BYTE(x);
Packit 47f805
            }
Packit 47f805
        }
Packit 47f805
        else {
Packit 47f805
            for (i = 0; i < iread; i++) {
Packit 47f805
                short   x = Buffer[0][i], y = Buffer[1][i];
Packit 47f805
                /* write 16 Bits Low High */
Packit 47f805
                data[m++] = LOW__BYTE(x);
Packit 47f805
                data[m++] = HIGH_BYTE(x);
Packit 47f805
                /* write 16 Bits Low High */
Packit 47f805
                data[m++] = LOW__BYTE(y);
Packit 47f805
                data[m++] = HIGH_BYTE(y);
Packit 47f805
            }
Packit 47f805
        }
Packit 47f805
    }
Packit 47f805
    if (m > 0) {
Packit 47f805
        fwrite(data, 1, m, outf);
Packit 47f805
    }
Packit 47f805
    if (global_writer.flush_write == 1) {
Packit 47f805
        fflush(outf);
Packit 47f805
    }
Packit 47f805
}
Packit 47f805
Packit 47f805
hip_t
Packit 47f805
get_hip(void)
Packit 47f805
{
Packit 47f805
    return global.hip;
Packit 47f805
}
Packit 47f805
Packit 47f805
size_t
Packit 47f805
sizeOfOldTag(lame_t gf)
Packit 47f805
{
Packit 47f805
    (void) gf;
Packit 47f805
    return global.in_id3v2_size;
Packit 47f805
}
Packit 47f805
Packit 47f805
unsigned char*
Packit 47f805
getOldTag(lame_t gf)
Packit 47f805
{
Packit 47f805
    (void) gf;
Packit 47f805
    return global.in_id3v2_tag;
Packit 47f805
}
Packit 47f805
Packit 47f805
/* end of get_audio.c */