/*(LGPL)
---------------------------------------------------------------------------
	a_types.h - Commonly used types in the engine
---------------------------------------------------------------------------
 * Copyright (C) 2001, 2002, David Olofson
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 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
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#ifndef _A_TYPES_H_
#define _A_TYPES_H_

#include "sdl_compat.h"

/* Builtin patch drivers */
typedef enum
{
	PD_NONE = -1,	/* No driver! */
	PD_MONO = 0,	/* Basic monophonic */
	PD_POLY,	/* Basic polyphonic */
	PD_MIDI,	/* Basic MIDI player */
	PD_EEL		/* User EEL code driver */
} patch_drivers_t;


/* Voice tag special codes */
typedef enum
{
	AVT_FUTURE = -2,
	AVT_ALL = -1
} audio_voice_tags_t;


/*
 * DAHDSR envelope generator parameters:
 *
 *   Level
 *     ^
 *     |         __L1__
 *     |        /|    |\
 *     |       / |    | \
 *     |__L0__/  |    |  \__L2__
 *     |     |   |    |   |    |\
 *     |  D  | A | H  | D | S  |R\
 *     |_____|___|____|___|____|__\____\
 *     |     |   |    |   |    |   |   / Time
 *      DELAY T1  HOLD T2   T3  T4
 *
 * State by state description:
 *
 *	D: Set to L0, and hold for DELAY seconds.
 *	A: Ramp to L1 over T1 seconds.
 *	H: Hold at L1 for HOLD seconds.
 *	D: Ramp to L2 over T2 seconds.
 *	S: if T3 < 0
 *		Hold at L2 until CE_STOP is received.
 *	   else
 *		Hold at L2 for T3 seconds.
 *	R: Ramp to 0 over T3 seconds.
 *
 * If T3 is set to a negative value, sustain lasts until
 * a CE_STOP event is received. If T3 is 0 of higher,
 * sustain lasts for T3 seconds.
 *
 * The EG will *always* load L0, but from then on, if a
 * phase has a zero duration, that phase is skipped.
 * Note that skipping any of the A, D and R phases will
 * produce clicks, unless the adjacent levels are
 * identical.
 *
 * In some cases, it's desirable that the EG immediately
 * skips to the release phase when a CE_STOP event is
 * received, whereas in other cases, this would result
 * in problems with very short notes. Therefore, there is
 * a boolean control 'ENV_SKIP' that make it possible to
 * specify which behavior is desired.
 * '1' will make the EG skip to release upon receiving
 * CE_STOP. '0' will result in the EG taking no action
 * on CE_STOP until the sustain phase is reached the
 * normal way.
 * 'ENV_SKIP' has no effect if "timed sustain" is used;
 * T3 must be < 0, or CE_STOP is entirely ignored.
 *
TODO:
	* Turn this into a generic EG, with "unlimited"
	  number of phases. The current way of marking
	  the sustain hold point would still work,
	  although one would have to replace the ramp/
	  wait mechanism with a test for change in sc.

	* Implement "quadratic taper" or similar non-
	  linear transform of the output. The EG will
	  have to generate a reasonably dense stream
	  of voice control events, since voice ramps
	  are still linear.
 */

/* Audio Patch Parameters */
typedef enum
{
	APP_FIRST = 0,
	/* Patch Driver Plugin */
	APP_DRIVER = 0,	/* (int) Patch driver index */

	/* Oscillator */
	APP_WAVE,	/* (int) Waveform index */

	/* "Special" features */
	APP_RANDPITCH,	/* (fixp) Random pitch depth */
	APP_RANDVOL,	/* (fixp) Random volume depth */

	/* Envelope Generator */
	APP_ENV_SKIP,	/* (bool) skip to sustain on CE_STOP */
	APP_ENV_L0,	/* (fixp) envelope level 0 (initial) */
	APP_ENV_DELAY,	/* (fixp) envelope delay-to-attack */
	APP_ENV_T1,	/* (fixp) envelope attack time */
	APP_ENV_L1,	/* (fixp) envelope hold level */
	APP_ENV_HOLD,	/* (fixp) envelope hold time */
	APP_ENV_T2,	/* (fixp) envelope decay time */
	APP_ENV_L2,	/* (fixp) envelope sustain level */
	APP_ENV_T3,	/* (fixp) envelope sustain time */
	APP_ENV_T4,	/* (fixp) envelope release time */

	/* LFO Generator */
	APP_LFO_DELAY,	/* (fixp) LFO delay-to-start */
	APP_LFO_ATTACK,	/* (fixp) LFO attack time-to-full */
	APP_LFO_DECAY,	/* (fixp) LFO decay time-to-zero */
	APP_LFO_RATE,	/* (fixp) LFO frequency */
	APP_LFO_SHAPE,	/* (int) LFO modulation waveform */

	/* Modulation Matrix */
	APP_ENV2PITCH,	/* (fixp) */
	APP_ENV2VOL,	/* (fixp) */
	APP_LFO2PITCH,	/* (fixp) */
	APP_LFO2VOL,	/* (fixp) */
#if 0
	APP_ENV2CUT,	/* (fixp) */
	APP_LFO2CUT,	/* (fixp) */
TODO:
	/*
	 * Controls for the resonant filter
	 * (Setting CUT to 0 disables the filter.)
	 */
	APP_FILT_CUT,	/* (fixp) Filter cutoff */
	APP_FILT_RES,	/* (fixp) Filter resonance */

	/*
	 * Distortion control
	 */
	APP_DIST_GAIN,	/* (fixp) Pre-limiter gain */
	APP_DIST_CLIP,	/* (fixp) Limiter clip threshold */
	APP_DIST_DRIVE,	/* (fixp) Feedback from the clipped peaks */
#endif
	APP_COUNT,
	APP_LAST = APP_COUNT - 1
} audio_pparams_t;
typedef int appbank_t[APP_COUNT];


/*
 * The voice structure:
 *      OSC -> VOL/PAN/SEND
 *                |   |
 *                | : '-> o-> FX BUS 0
 *                '-----> o-> FX BUS 1
 *                  :  :  ...    ...
 *                  :  :  o-> FX BUS N-1
 *
 *	That's it! No filters, and just one oscillator. The
 *	interesting part is the output section.
 *
 *	Every voice has two output bus selectors, each on
 *	referencing a stereo bus, on which further
 *	processing may be applied. By setting either bus
 *	selector to -1, or by pointing both at the same bus,
 *	only the Primary Output will be used, and some some
 *	CPU power is saved during mixing. :-)
 *
 *	As opposed to most MIDI synths, this engine allows
 *	you to select one or two output busses for each
 *	voice, using one as the Primary Output (level set
 *	by CC7: Volume) and the other as the Secondary
 *	Output (level set by CC91: Reverb Depth, multiplied
 *	by CC7.)
 *
 *	The MIDI implementation uses CC92 and CC94 to select
 *	Primary and Secondary Output busses, respectively.
 */

/*
 * Audio Channel & Group Controls
FIXME:	Channels use all, groups use a subset - which sucks!
FIXME:	I've considered using the OpenGL approach with a single,
FIXME:	global enum - but that can only provide runtime "enum
FIXME:	type checking". Seems like only languages other than the
FIXME:	native language of this engine can do it right...
FIXME:	(Another reason to use EEL wherever possible.)
 *
 * The Priority System:
 *	Set ACC_PRIORITY to 0 to have a channel grab a
 *	voice, and have it excluded from the dynamic
 *	voice allocation system.
 *
 *	Other values specify channel priority for voice
 *	stealing - higher values mean lower priority.
 *	Higher priority channels win when fighting for
 *	voices. Priority 0 voices cannot be stolen.
 */

typedef enum
{
	ACC_FIRST = 0,
/*--- Controls that are NOT transformed ---*/
	ACC_GROUP = 0,	/* mixer group */
	ACC_PRIORITY,	/* Voice Allocation Priority */
	ACC_PATCH,	/* (int) Patch index */

	ACC_PRIM_BUS,	/* (int) target bus for ACC_VOLUME */
	ACC_SEND_BUS,	/* (int) target bus for ACC_SEND */

/*--- Controls that are transformed by adding ---*/
	ACC_PAN,	/* (fixp[-1, 1]) pre-send pan */
	ACC_PITCH,	/* (fixp) linear frequency; int <==> MIDI */

/*--- Controls that are transformed by multiplying ---*/
	ACC_VOLUME,	/* (fixp) primary "send" level */
	ACC_SEND,	/* (fixp) secondary send level */

/*--- Patch Controls (Not transformed) ---*/
	ACC_MOD1,	/* (fixp) Modulation 1 depth */
	ACC_MOD2,	/* (fixp) Modulation 2 depth */
	ACC_MOD3,	/* (fixp) Modulation 3 depth */

	ACC_X,		/* (fixp) X position */
	ACC_Y,		/* (fixp) Y position */
	ACC_Z,		/* (fixp) Z position */

	ACC_COUNT,
	ACC_LAST = ACC_COUNT - 1
} audio_ctls_t;
typedef int accbank_t[ACC_COUNT];


/*
 * Bus Control:
 *	The first 8 MIDI channels can be used for controlling
 *	the signal processing done between the busses, and
 *	between the busses and the output buffer.
 *
 *	A set of non-standard MIDI CCs are used for this:
 *		CC 39: Select Insert Slot for subsequent CCs.
 *
 *	Slot 0 is used to access the dry/pre insert send level
 *	controls. Thus, CCs 40..45 are ignored for slot 0.
 *
 *	The FX parameter CC range is mapped to according to
 *	[0, 128] ==> [0.0, 2.0]. (That is, you can't reach the
 *	exact value of 2.0, as the highest CC value is 127.)
 *		CC 40: Insert Effect Type
 *		CC 41: Insert Effect Parameter 1 (Time 1)
 *		CC 42: Insert Effect Parameter 2 (Time 2)
 *		CC 43: Insert Effect Parameter 3 (Depth 1)
 *		CC 44: Insert Effect Parameter 4 (Depth 2)
 *		CC 45: Insert Effect Parameter 5 (Rate)
 *
 *	This one is not transformed at all - MIDI CCs 0..127
 *	are used directly. Obviously, it's preferred that
 *	plugins map integer parameters that fit in that range
 *	to Parameter 6.
 *		CC 46: Insert Effect Parameter 6 (Mode/Special)
 *
 *	The following CC doubles as "dry send to master", when
 *	used on slot 0.
 *		CC 47: Post insert send to master ("Wet")
 *
 *	The next set of CC are IMHO, a bit dodgy in the current
 *	implementation. Indeed, they work, but you have to
 *	accept that the engine processes the busses in a fixed
 *	order, meaning that you can only send from lower number
 *	busses to higher number busses - not the other way
 *	around. (In fact, the engine won't even consider the
 *	controls for the "broken" connections when mixing.)
 *
 *	Note that when used on slot 0, these act as *dry* send
 *	levels, as there cannot be an insert in slot 0.
 *		CC 48: Post insert send to bus 1
 *		CC 49: Post insert send to bus 2
 *		CC 50: Post insert send to bus 3
 *		CC 51: Post insert send to bus 4
 *		CC 52: Post insert send to bus 5
 *		CC 53: Post insert send to bus 6
 *		CC 54: Post insert send to bus 7
 *		CC 55: Post insert send to bus 8
 *
 *	Note that the post insert sends won't be considered
 *	if no effect is enabled. (They would just double the
 *	functionality of the pre insert sends, for extra cost
 *	and no use.)
 */

/* Audio Bus Controls */
typedef enum
{
	ABC_FIRST = 0,

	/* NOTE: The ABC_FX_* controls of slot 0 are ignored! */
	ABC_FX_TYPE = 0,	/* (int) */
	ABC_FX_PARAM_1,		/* (fixp) Time/f/Amount 1 */
	ABC_FX_PARAM_2,		/* (fixp) Time/f/Amount 2 */
	ABC_FX_PARAM_3,		/* (fixp) Depth/Level 1 */
	ABC_FX_PARAM_4,		/* (fixp) Depth/Level 2 */
	ABC_FX_PARAM_5,		/* (fixp) Rate/Level */
	ABC_FX_PARAM_6,		/* (int)  Mode/Special */

	ABC_SEND_MASTER,	/* (fixp) Post FX send to master */

	ABC_SEND_BUS_0,		/* (fixp) Post FX send to bus 0 */
	ABC_SEND_BUS_1,		/* (fixp) Post FX send to bus 1 */
	ABC_SEND_BUS_2,		/* (fixp) Post FX send to bus 2 */
	ABC_SEND_BUS_3,		/* (fixp) Post FX send to bus 3 */
	ABC_SEND_BUS_4,		/* (fixp) Post FX send to bus 4 */
	ABC_SEND_BUS_5,		/* (fixp) Post FX send to bus 5 */
	ABC_SEND_BUS_6,		/* (fixp) Post FX send to bus 6 */
	ABC_SEND_BUS_7,		/* (fixp) Post FX send to bus 7 */

	ABC_COUNT,
	ABC_LAST = ABC_COUNT -1
} audio_busctls_t;
typedef int abcbank_t[ABC_COUNT];

/*
 * Generic Effect API - for busses and inserts.
 */
typedef enum
{
	AFX_NONE = 0,
	AFX_DELAY,	/* 1: Tap 1	2: Tap 2
			 * 3: Gain 1	4: Gain 2
			 * 5: Feedback Level
			 */
	AFX_ECHO,	/* 1: Ldelay	2: Rdelay
			 * 3: Lgain	4: Rgain
			 * 5: Feedback Delay
			 */
	AFX_REVERB,	/* 1: Early reflections duration
			 * 2: Tail duration
			 * 3: Early reflections level
			 * 4: Tail Feedback Level
			 * 5: Feedback LP Cutoff
			 */
	AFX_CHORUS,	/* 1: Left Vibrato Speed
			 * 2: Right Vibrato Speed
			 * 3: Left Vibrato Depth
			 * 4: Right Vibrato Depth
			 * 5: Feedback Level
			 */
	AFX_FLANGER,	/* Same as chorus; only different scale. */
	AFX_FILTER,	/* 1: Left Cut	2: Right Cut
			 * 3: Left Reso	4: Right Resonance
			 * 5: <unused>
			 */
	AFX_DIST,	/* 1: Bass	2: Treble
			 * 3: Pre Gain	4: Post Gain
			 * 4: Drive
			 */
	AFX_WAH,	/* 1: Low Limit		2: High Limit
			 * 3: Sensitivity	4: Gain
			 * 5: Resonance
			 */
	AFX_EQ,		/* 1: Bass f	2: Treble f
			 * 3: Bass Gain	4: Treble Gain
			 * 4: Mid Gain
			 */
	AFX_ENHANCER,	/* 1: Mid f	2: High f
			 * 3: Mid Sens.	4: High Sensitivity
			 * 5: Artificial Treble Strength
			 */
	AFX_COMPRESSOR,	/* 1: Attack	2: Release
			 * 3: Gain	4: Threshold
			 * 5: Knee Softness
			 */
	AFX_MAXIMIZER	/* 1: Low Split	2: High Split
			 * 3: Low Boost	4: High Boost
			 * 5: Mid Boost
			 */
} audio_fxtypes_t;


typedef enum
{
	AR_WORST = -3,
	AR_MEDIUM = -2,
	AR_BEST = -1,

	AR_NEAREST = 0,	/* Nearest sample ("useless") */
	AR_NEAREST_4X,	/* Nearest with 4x oversampling */
	AR_LINEAR,	/* Linear Interpolation */
	AR_LINEAR_2X_R,	/* LI w/ 2x oversampling + ramp smoothing */
	AR_LINEAR_4X_R,	/* LI w/ 4x oversampling + ramp smoothing */
	AR_LINEAR_8X_R,	/* LI w/ 8x oversampling + ramp smoothing */
	AR_LINEAR_16X_R,/* LI w/ 16x oversampling + ramp smoothing */
	AR_CUBIC_R	/* Cubic interpolation + ramp smoothing */
} audio_resample_t;


typedef enum
{
	AF_MONO8 = 0,	/* Mono Sint8 */
	AF_STEREO8,	/* Stereo Sint8 */
	AF_MONO16,	/* Mono Sint16 */
	AF_STEREO16,	/* Stereo Sint16 */
	AF_MONO32,	/* Mono float32 */
	AF_STEREO32,	/* Stereo float32 */
	AF_MIDI		/* Midi sequence */
} audio_formats_t;


typedef enum
{
	AQ_VERY_LOW,	/* Nearest, no oversampling */
	AQ_LOW,		/* Nearest, 4x oversampling */
	AQ_NORMAL,	/* Linear interpolation */
	AQ_HIGH,	/* LI with adaptive oversampling 2x..8x */
	AQ_VERY_HIGH	/* LI with fixed 16x oversampling */
} audio_quality_t;

#undef	A_USE_INT64
#ifdef SDL_HAS_64BIT_TYPE
#	define	A_USE_INT64
#endif

#endif /*_A_TYPES_H_*/
