/*     
 **********************************************************************
 *     sblive_voice.h -- EMU Voice Resource Manager header file
 *     Copyright 1999, 2000 Creative Labs, Inc. 
 * 
 ********************************************************************** 
 * 
 *     Date                 Author          Summary of changes 
 *     ----                 ------          ------------------ 
 *     October 20, 1999     Bertrand Lee    base code release 
 * 
 ********************************************************************** 
 * 
 *     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., 675 Mass Ave, Cambridge, MA 02139, 
 *     USA. 
 * 
 ********************************************************************** 
 */

#ifndef _VOICEMGR_H
#define _VOICEMGR_H


#define SAMPLETYPE_ROMMASK              0x8000
#define SAMPLETYPE_MONOSAMPLE           1
#define SAMPLETYPE_RIGHTSAMPLE          2
#define SAMPLETYPE_LEFTSAMPLE           4

#define SAMPLEMODE_MASK                 3
#define SAMPLEMODE_RELEASEINLOOP        1
#define SAMPLEMODE_RELEASEOUTLOOP       3

#define WAVE_RAMP_TIME_TO_TARGET        100
#define MIDI_RAMP_TIME_TO_TARGET        200

#define RAMP_REVERB_SEND_NUM            0
#define RAMP_AUX_SEND_NUM               1
#define RAMP_PAN_SEND_NUM               2
#define RAMP_CHORUS_SEND_NUM            3

/* struct emu_voice.usage flags */
#define VOICEMGR_USAGE_FREE         0x00000000
#define VOICEMGR_USAGE_MIDI         0x00000001
#define VOICEMGR_USAGE_PLAYBACK     0x00000002
#define VOICEMGR_USAGE_RECORDING    0x00000004

/* struct emu_voice.voicestate flags */
#define VOICEMGR_STATE_IDLE         0x00000000
#define VOICEMGR_STATE_ATTACK       0x00000001
#define VOICEMGR_STATE_RELEASE      0x00000002
#define VOICEMGR_STATE_IRQON        0x00000004
#define VOICEMGR_STATE_TRANSITION   0x00000008
#define VOICEMGR_STATE_SUSTAIN      0x00000010

/* struct emu_voice.flags flags */
#define VOICEMGR_FLAGS_PLAYBACK     0x00000001
#define VOICEMGR_FLAGS_MONO         0x00000002
#define VOICEMGR_FLAGS_16BIT        0x00000004
#define VOICEMGR_FLAGS_STEREOSLAVE  0x00000008
#define VOICEMGR_FLAGS_VOICEMASTER  0x80000000
#define VOICEMGR_FLAGS_FASTCALLBACK 0x40000000

#define VOICECALLBACK_EVENT_CALLBACKSIZEREACHED  0
#define VOICECALLBACK_EVENT_FREEVOICE            1
#define VOICECALLBACK_EVENT_TIMER		 2

struct voice_param 
{
	/* Sound engine */
	u32 start;
	u32 startloop;
	u32 endloop;
	u32 end;
	u16 current_pitch;
	u16 pitch_target;
	u16 current_volume;
	u16 volume_target;
	u16 current_FC;
	u16 FC_target;
	u8 pan_target;
	u8 aux_target;
	u8 coef;
	u8 sample_mode;
	u8 sample_type;

	union
	{
		struct 
		{
			/* MUST be in the following order */
			u8 reverb_send;
			u8 aux_send;
			u8 pan_send;
			u8 chorus_send;
		} tSends;
	} unSends;

	/* Envelope engine */
	u16 ampl_env_delay;
	u8 byampl_env_attack;
	u8 byampl_env_hold;
	u8 byampl_env_decay;
	u8 byampl_env_sustain;
	u8 byampl_env_release;

	u16 aux_env_delay;
	u8 byaux_env_attack;
	u8 byaux_env_hold;
	u8 byaux_env_decay;
	u8 byaux_env_sustain;
	u8 byaux_env_release;

	u16 mod_LFO_delay;	/* LFO1 */
	u16 vib_LFO_delay;	/* LFO2 */
	u8 mod_LFO_freq;	/* LFO1 */
	u8 vib_LFO_freq;	/* LFO2 */

	s8 aux_env_to_pitch;
	s8 aux_env_to_FC;
	s8 mod_LFO_to_pitch;
	s8 vib_LFO_to_pitch;
	s8 mod_LFO_to_FC;
	s8 mod_LFO_to_volume;

	u16 sample_pitch;
	u16 initial_pitch;
	u8 initial_attn;
	u8 initial_FC;

	u8 velocity;		/* BUGBUG: to be moved to aweobj */

	u32 bank;
	u8 program;
	u16 key_exclusive;
};

struct voice_allocdesc 
{
	struct sblive_hw *sb_hw;
	u32 ownertype;
	CALLBACKFN callback;
	u32 callback_data;
	u32 numvoicereqs;		/* Number of voice requests */
					/* Stereo voices count as 1 */
					/* request                  */
	u32 flags[MAXREQVOICES];	/* stereo/mono rec/playback 8/16 */
};


struct emu_voice 
{
	DLIST(struct emu_voice);	/* Doubly-linked list */

	struct sblive_hw *sb_hw;
	u32 ownertype;
	CALLBACKFN callback;
	u32 callback_data;
	u32 usage;		/* Free, MIDI, playback, recording, etc */
	u32 voicestate;		/* Release, attack, idle, etc */
	u32 voicenum;		/* Voice ID */
	u32 flags;		/* Stereo/mono, rec/playback, 8/16 bit */
	
	struct voice_param voice_params;
	struct emu_voice *master_voice;	/* Index to previous linked voiceobj */
	struct emu_voice *linked_voice;	/* Index to linked voiceobj, else set to NULL */
	
	u32 sendhandle[NUM_FXSENDS];
};


struct voice_mgr 
{
	struct sblive_hw *sb_hw;
	struct emu_voice *free_voices;
	struct emu_voice *playback_voices;
	struct emu_voice *record_voices;
	struct emu_voice *midi_voices;

	struct emu_voice voices[NUM_G];	
	
	/* Shouldn't use this directly.  Just move pointers around from */
	/* free_voices to the other lists and vice versa. */
	u32 ramp_eng_handle;
};

struct voice_cntlset 
{
	u32 paramID;
	u32 value;
};

int sblive_voiceInit(struct sblive_hw *);
int sblive_voiceExit(struct sblive_hw *);
int sblive_voiceAlloc(struct voice_allocdesc *, struct emu_voice **);
int sblive_voiceFree(struct emu_voice *);
int sblive_voiceEnableIrq(struct emu_voice *);
int sblive_voiceDisableIrq(struct emu_voice *);
int sblive_voicePlaybackSetup(struct emu_voice *);
int sblive_voiceStart(struct emu_voice *);
int sblive_voiceStop(struct emu_voice *);
int sblive_voiceSetControl(struct emu_voice *, struct voice_cntlset *, u32);
int sblive_voiceGetControl(struct emu_voice *, u32, u32 *);

#endif /* _VOICEMGR_H */
