//-----------------------------------------------------------------------------
//
//  $Logfile:: /Source/snd_loc.h                                              $
// $Revision:: 2                                                              $
//   $Author:: Burgermac                                                      $
//     $Date:: 12/27/00 7:31 PM                                               $
//
// Copyright (C) 1998 by Ritual Entertainment, Inc.
// All rights reserved.
//
// This source is may not be distributed and/or modified without
// expressly written permission by Ritual Entertainment, Inc.
//
// DESCRIPTION:
// private sound functions
//

#ifndef __SND_LOC_H__
#define __SND_LOC_H__

#include "wave.h"

#define SND_BUFFER_SIZE		16384 /* FS: DMA BUFFER SIZE. NOTE: Q1 uses 4096. */
#define	PAINTBUFFER_SIZE	2048 /* FS: NOTE: Q1 uses 512 */

// !!! if this is changed, the asm code must change !!!
typedef struct
{
	int			left;
	int			right;
} portable_samplepair_t;

typedef struct
{
	int 		length;
	int 		loopstart;
	int 		speed;			// not needed, because converted on load?
	int 		width;
	int 		stereo;
	int			type;
	int			blockalign;
	int			real_length;
	byte		data[1];		// variable sized
} sfxcache_t;

typedef struct sfx_s
{
	char 		name[MAX_QPATH];
	int			registration_sequence;
	sfxcache_t	*cache;
} sfx_t;

typedef struct
{
	int			real_pos;
	int			nibble;
	int			ima_pos;
	int			index;    // Index into step size table
	int			previousValue; // Most recent sample value
	int			r_index;    // Index into step size table
	int			r_previousValue; // Most recent sample value
} ImaState;

// a playsound_t will be generated by each call to S_StartSound,
// when the mixer reaches playsound->begin, the playsound will
// be assigned to a channel
typedef struct playsound_s
{
	struct playsound_s	*prev, *next;
	sfx_t		*sfx;
	float		volume;
	float		attenuation;
	int			entnum;
	int			entchannel;
	qboolean	fixed_origin;	// use origin field instead of entnum's origin
	vec3_t		origin;
	unsigned	begin;			// begin on this sample
	float		pitch;      // pitch shift, 1.0 is normal, 0.5 is half speed and so forth
	float		fadetime;
	int			pos;        // start time of sample
	ImaState	state;
	int			flags;      // sound properties
} playsound_t;

typedef struct
{
	int			channels;
	int			samples;				// mono samples in buffer
	int			submission_chunk;		// don't mix less than this #
	int			samplepos;				// in mono samples
	int			samplebits;
	int			speed;
	byte		*buffer;
} dma_t;


// !!! if this is changed, the asm code must change !!!
typedef struct
{
	sfx_t		*sfx;			// sfx number
	int			leftvol;		// 0-255 volume
	int			rightvol;		// 0-255 volume
	int			end;			// end time in global paintsamples
	int			pos;			// sample position in sfx
   // above here is assembly dependent
	int			srcstep;    // step for pitch independence
	int			srcfrac;    // frac for pitch independence
	int			looping;		// where to loop, -1 = no looping OBSOLETE?
	int			entnum;			// to allow overriding a specific sound
	int			entchannel;		//
	vec3_t		origin;			// only use if fixed_origin is set
	vec_t		dist_mult;		// distance multiplier (attenuation/clipK)
	int			master_vol;		// 0-255 master volume
	qboolean	fixed_origin;	// use origin instead of fetching entnum's origin
	qboolean	autosound;		// from an entity->sound, cleared each frame
	float		pitch;      // pitch shift, 1.0 is normal, 0.5 is half speed and so forth
	ImaState	state;
	int			fadefrac;   // fade fraction
	int			fadestep;   // fade step, if this non-zero then a fade is active
	int			fadepos;    // fadepos, relative to the mixbuffer time, this is also used for pausing
	int			flags;      // sound properties (SOUND_SYNCH, SOUND_SYNCH_FADE)
//////////////////////////////////////////////////////////////////////////////////
#ifdef _ADD_EAX_
	int			rleftvol;		// 0-255 volume
	int			rrightvol;		// 0-255 volume
#endif
//////////////////////////////////////////////////////////////////////////////////
} channel_t;

//
// wave stuff has been moved to wave.c/wave.h
//

//
// SIN TYPEDEFS
//
#define MAX_SONGALIAS_LENGTH 32
#define MAX_SONGNAME_LENGTH 64

#define SONG_LOOP       0x1
#define SONG_RESTART    0x2
#define SONG_INTERRUPT  0x4

#define SOUND_PAUSED       0x100
#define SOUND_FADING       0x200
#define SOUND_PAUSING      0x400

typedef struct
{
	char		alias[ MAX_SONGALIAS_LENGTH ];
	char		path[ MAX_SONGNAME_LENGTH ];
	int			flags;
	float		volume;
	float		fadetime;
	int			current_pos;
	ImaState	current_state;
	sfx_t		*song;
} song_t;
//
// SIN DEFINES
//
#define SND_FRAC_BITS 9
//
// CHANNEL TYPES
//
#define NORMAL_CHANNEL
//
// SIN USEFUL MACROS
//
//#define SAMPLE_TO_SIN_MULTIPLIER( SC ) ( (float)( (float)dma.speed/(float)(SC)->speed )*( (float)dma.samplebits/(float)((SC)->width << 3) ) )
#define SAMPLE_TO_SIN_MULTIPLIER ( (float)( (float)dma.speed/((float)sc->speed * ch->pitch)) )
#define SIN_TO_SAMPLE_MULTIPLIER ( (float)( ((float)sc->speed * ch->pitch))/(float)dma.speed )
#define SAMPLE_TO_SIN_VALUE( VALUE ) ( (float)(VALUE)*SAMPLE_TO_SIN_MULTIPLIER )
#define SIN_TO_SAMPLE_VALUE( VALUE ) ( (float)(VALUE)*SIN_TO_SAMPLE_MULTIPLIER )
/*
====================================================================

  SYSTEM SPECIFIC FUNCTIONS

====================================================================
*/

// initializes cycling through a DMA buffer and returns information on it
qboolean SNDDMA_Init(void);

// gets the current DMA position
int		SNDDMA_GetDMAPos(void);

// shutdown the DMA xfer.
void	SNDDMA_Shutdown(void);

void	SNDDMA_BeginPainting (void);

void	SNDDMA_Submit(void);
#ifdef __DJGPP__
void GUS_ClearDMA (void); /* FS: This stops the constant clicking sound during map loads and pause screens */
#endif

//====================================================================

#define	MAX_CHANNELS			32
extern	channel_t   channels[MAX_CHANNELS];

extern	int		paintedtime;
extern	int		s_rawend;
extern	vec3_t	listener_origin;
extern	vec3_t	listener_forward;
extern	vec3_t	listener_right;
extern	vec3_t	listener_up;
extern	dma_t	dma;
extern	playsound_t	s_pendingplays;

#define	MAX_RAW_SAMPLES	8192
extern	portable_samplepair_t	s_rawsamples[MAX_RAW_SAMPLES];

extern cvar_t	*s_volume;
extern cvar_t	*s_sounddir;
extern cvar_t	*s_nosound;
extern cvar_t	*s_loadas8bit;
extern cvar_t	*s_khz;
extern cvar_t	*s_show;
extern cvar_t	*s_mixahead;
extern cvar_t	*s_testsound;
extern cvar_t	*s_primary;

extern cvar_t	*s_musicdir;
extern cvar_t	*s_musicvolume;
extern cvar_t	*s_dialogvolume;

#ifdef __USEA3D
extern qboolean snd_isa3d;

extern cvar_t *gpclbuffsize;
extern cvar_t *gpclRolloff;
extern cvar_t *gpclDoppler;
extern cvar_t *gpclDistance;
extern cvar_t *gpclMin;
extern cvar_t *gpclMax;
extern cvar_t *gpclWaterEq;
extern cvar_t *gpcl2DVolume;

// 2.0 Vars

extern cvar_t *gpclGeometry;
extern cvar_t *gpclNumLeaf;
extern cvar_t *gpclRefGain;
extern cvar_t *gpclRefDelay;
extern cvar_t *gpclPolyKeep;
extern cvar_t *gpclPolySize;
extern cvar_t *gpclPolyReflectSize;
extern cvar_t *gpclShowTossed;
extern cvar_t *gpclNumPolys;

extern cvar_t *gpclUsePVS;
extern cvar_t *gpclBloat;

extern cvar_t *gpclOcclude;
extern cvar_t *gpclReflect;
extern cvar_t *gpclOccFact;
extern cvar_t *gpclOccEpsilon;

#endif  // __USEA3D

void S_InitScaletable (void);

sfxcache_t *S_LoadSound (sfx_t *s);
sfxcache_t *S_LoadSong (sfx_t *s);
void S_FreeSound (sfx_t *s);

void S_IssuePlaysound (playsound_t *ps);

void S_PaintChannels(int endtime);

// picks a channel based on priorities, empty slots, number of channels

#ifdef __USEA3D
channel_t *S_PickChannel(int entnum, int entchannel, qboolean bUseAutoSettings, sfxcache_t *sc, sfx_t *sfx);
#else
channel_t *S_PickChannel(int entnum, int entchannel);
#endif

// spatializes a channel
void S_Spatialize(channel_t *ch);

void S_FadeSound( channel_t * ch, float fadetime, qboolean fadeout );
sfxcache_t *S_LoadRaw( int khz, int bits, int channels, int length, byte * data );

//
// MUSIC Stuff
//
qboolean MUSIC_SongEnded ( channel_t *ch );
void MUSIC_SongFaded ( channel_t *ch );
void MUSIC_Shutdown( void );

#endif
