/*
    TiMidity++ -- MIDI to WAVE converter and player
    Copyright (C) 1999-2002 Masanao Izumo <mo@goice.co.jp>
    Copyright (C) 1995 Tuukka Toivonen <tt@cgs.fi>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#ifndef SYSDEP_H_INCLUDED
#define SYSDEP_H_INCLUDED 1

#include <limits.h>
#include "config.h"

/* The size of the internal buffer is 2^AUDIO_BUFFER_BITS samples.
   This determines maximum number of samples ever computed in a row.

   For Linux and FreeBSD users:

   This also specifies the size of the buffer fragment.  A smaller
   fragment gives a faster response in interactive mode -- 10 or 11 is
   probably a good number. Unfortunately some sound cards emit a click
   when switching DMA buffers. If this happens to you, try increasing
   this number to reduce the frequency of the clicks.

   For other systems:

   You should probably use a larger number for improved performance.

*/
#ifndef DEFAULT_AUDIO_BUFFER_BITS
#  define DEFAULT_AUDIO_BUFFER_BITS 11
#endif

#define SAMPLE_LENGTH_BITS 32

#define VOLATILE_TOUCH(val) /* do nothing */
#define VOLATILE volatile

/* Byte order */
#ifdef ENDIAN_IS_BIG
# ifndef BIG_ENDIAN
#  define BIG_ENDIAN 4321
# endif
# undef LITTLE_ENDIAN
#else
# undef BIG_ENDIAN
# ifndef LITTLE_ENDIAN
#  define LITTLE_ENDIAN 1234
# endif
#endif

#define CONFIG_FILE "./tmidi.cfg"  /* unused */

/* integer type definitions: ISO C now knows a better way */
#ifdef HPUX
typedef          char   int8;
typedef unsigned char  uint8;
typedef          short  int16;
typedef unsigned short uint16;
#else
typedef   signed char   int8;
typedef unsigned char  uint8;
typedef   signed short  int16;
typedef unsigned short uint16;
#endif
typedef          int   int32;
typedef unsigned int  uint32;
#ifdef LONG8_BIT /* 64bit architectures */
typedef          long  int64;
typedef unsigned long uint64;
#else /* 32bit architectures */
typedef          long long  int64;
typedef unsigned long long uint64;
#endif
#define TIMIDITY_HAVE_INT64 1


/* Instrument files are little-endian, MIDI files big-endian, so we
   need to do some conversions. */
#define XCHG_SHORT(x) ((((x)&0xFF)<<8) | (((x)>>8)&0xFF))
# define XCHG_LONG(x) ((((x)&0xFF)<<24) | \
		      (((x)&0xFF00)<<8) | \
		      (((x)&0xFF0000)>>8) | \
		      (((x)>>24)&0xFF))

#ifdef LITTLE_ENDIAN
# define LE_SHORT(x) (x)
# define LE_LONG(x) (x)
# define BE_SHORT(x) XCHG_SHORT(x)
# define BE_LONG(x) XCHG_LONG(x)
#else /* BIG_ENDIAN */
# define BE_SHORT(x) (x)
# define BE_LONG(x) (x)
# define LE_SHORT(x) XCHG_SHORT(x)
# define LE_LONG(x) XCHG_LONG(x)
#endif /* LITTLE_ENDIAN */

/* max_channels is defined in "timidity.h" */
#if MAX_CHANNELS <= 32
typedef struct _ChannelBitMask
{
    uint32 b; /* 32-bit bitvector */
} ChannelBitMask;
#define CLEAR_CHANNELMASK(bits)		((bits).b = 0)
#define FILL_CHANNELMASK(bits)		((bits).b = ~0)
#define IS_SET_CHANNELMASK(bits, c) ((bits).b &   (1u << (c)))
#define SET_CHANNELMASK(bits, c)    ((bits).b |=  (1u << (c)))
#define UNSET_CHANNELMASK(bits, c)  ((bits).b &= ~(1u << (c)))
#define TOGGLE_CHANNELMASK(bits, c) ((bits).b ^=  (1u << (c)))
#define COPY_CHANNELMASK(dest, src)	((dest).b = (src).b)
#define REVERSE_CHANNELMASK(bits)	((bits).b = ~(bits).b)
#define COMPARE_CHANNELMASK(bitsA, bitsB)	((bitsA).b == (bitsB).b)
#else
typedef struct _ChannelBitMask
{
    uint32 b[8];		/* 256-bit bitvector */
} ChannelBitMask;
#define CLEAR_CHANNELMASK(bits) \
	memset((bits).b, 0, sizeof(ChannelBitMask))
#define FILL_CHANNELMASK(bits) \
	memset((bits).b, 0xFF, sizeof(ChannelBitMask))
#define IS_SET_CHANNELMASK(bits, c) \
	((bits).b[((c) >> 5) & 0x7] &   (1u << ((c) & 0x1F)))
#define SET_CHANNELMASK(bits, c) \
	((bits).b[((c) >> 5) & 0x7] |=  (1u << ((c) & 0x1F)))
#define UNSET_CHANNELMASK(bits, c) \
	((bits).b[((c) >> 5) & 0x7] &= ~(1u << ((c) & 0x1F)))
#define TOGGLE_CHANNELMASK(bits, c) \
	((bits).b[((c) >> 5) & 0x7] ^=  (1u << ((c) & 0x1F)))
#define COPY_CHANNELMASK(dest, src) \
	memcpy(&(dest), &(src), sizeof(ChannelBitMask))
#define REVERSE_CHANNELMASK(bits) \
	((bits).b[((c) >> 5) & 0x7] = ~(bits).b[((c) >> 5) & 0x7])
#define COMPARE_CHANNELMASK(bitsA, bitsB) \
	(memcmp((bitsA).b, (bitsB).b, sizeof ((bitsA).b)) == 0)
#endif

#ifdef LOOKUP_HACK
   typedef int8 sample_t;
   typedef uint8 final_volume_t;
#  define FINAL_VOLUME(v) ((final_volume_t)~_l2u[v])
#  define MIXUP_SHIFT 5
#  define MAX_AMP_VALUE 4095
#else
   typedef int16 sample_t;
   typedef int32 final_volume_t;
#  define FINAL_VOLUME(v) (v)
#  define MAX_AMP_VALUE ((1<<(AMP_BITS+1))-1)
#endif
#define MIN_AMP_VALUE (MAX_AMP_VALUE >> 9)

#if SAMPLE_LENGTH_BITS > 32 
#if TIMIDITY_HAVE_INT64
typedef int64 splen_t;
#define SPLEN_T_MAX (splen_t)((((uint64)1)<<63)-1)
#else	/* TIMIDITY_HAVE_INT64 */
typedef uint32 splen_t;
#define SPLEN_T_MAX (splen_t)((uint32)0xFFFFFFFF)
#endif	/* TIMIDITY_HAVE_INT64 */
#elif SAMPLE_LENGTH_BITS == 32
typedef uint32 splen_t;
#define SPLEN_T_MAX (splen_t)((uint32)0xFFFFFFFF)
#else	/* SAMPLE_LENGTH_BITS */
typedef int32 splen_t;
#define SPLEN_T_MAX (splen_t)((((uint32)1)<<31)-1)
#endif	/* SAMPLE_LENGTH_BITS */

#ifdef USE_LDEXP
#  define TIM_FSCALE(a,b) ldexp((double)(a),(b))
#  define TIM_FSCALENEG(a,b) ldexp((double)(a),-(b))
#  include <math.h>
#else
#  define TIM_FSCALE(a,b) ((a) * (double)(1<<(b)))
#  define TIM_FSCALENEG(a,b) ((a) * (1.0 / (double)(1<<(b))))
#endif

#ifdef HPUX
#undef mono
#endif

#ifdef sun
#ifndef SOLARIS
/* SunOS 4.x */
#include <sys/stdtypes.h>
#include <memory.h>
#define memcpy(x, y, n) bcopy(y, x, n)
#endif /* SOLARIS */
#endif /* sun */


/* The path separator (D.M.) */
/* Unix: "/" */
#define PATH_SEP '/'
#define PATH_STRING "/"

#ifdef PATH_SEP2
#define IS_PATH_SEP(c) ((c) == PATH_SEP || (c) == PATH_SEP2)
#else
#define IS_PATH_SEP(c) ((c) == PATH_SEP)
#endif

/* new line code */
#ifndef NLS
# define NLS "\n"
#endif /* NLS */

#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif /* M_PI */

#define SAFE_CONVERT_LENGTH(len) (6 * (len) + 1)

#endif /* SYSDEP_H_INCUDED */
