/*

  in_cube Gamecube Stream Player for Winamp
  by hcs

  includes work by Destop and bero

*/

// CUBEFILE structure, prototypes for everything

#ifndef _CUBE_H

#define _CUBE_H

#ifdef __cplusplus
extern "C" {
#endif

#define f32 float
#define u8  unsigned char
#define s16 signed short
#define u16 unsigned short
#define s32 signed int
#define u32 unsigned int


//    Some optimisations
#define HEX_8000_DIV_EIGHT_MUL_FOURTEEN 896//(57344*4)   //0x8000 / 8 * 14
#define HEX_1000_MUL_ONE_POINT_SEVEN 6963.2     //0x1000 * 1.7
#define HEX_1000_MUL_ZERO_POINT_SEVEN_THREE 2990.08      //0x1000 * 0.73
#define HEX_TEN_THOUSAND_MUL_HEX_TEN_THOUSAND 0x10000*0x10000//4294967296
#define UPDATE_576 567000.0                      //576.0 * 1000.0
#define UPDATE_128 128000.0                      //128.0 * 1000.0
#define UPDATE_64 64000.0                        //64.0 * 1000.0
#define SEVEN_DIV_EIGHT 0.875                    //7/8
#define ADD_FOUR_ADD_EIGHTEEN +22                //+4+18
#define EIGHTEEN_DIV_THIRTY_TWO 0.5625           //18/32
#define SIXTEEN_MUL_EIGHTEEN 288                 //16*18
#define SIXTEEN_DIV_FOURTEEN 1.1428571428571428571428571428571  //16/14
#define EIGHT_MUL_EIGHT      64                  //8*8
#define FOURTEEN_DIV_EIGHT 1.75//14/8

#define BPS 16

int get16bit(unsigned char* p);
int get32bit(unsigned char* p);
int get16bitL(unsigned char* p);
int get32bitL(unsigned char* p);

// both header and file type
typedef enum {
	type_std,   // devkit standard DSP
	type_sfass, // Star Fox Assault Cstr (DSP)
	type_mp2,   // Metroid Prime 2 RS03 (DSP)
	type_pm2,   // Paper Mario 2 STM (DSP)
	type_halp,  // HALPST (DSP)
	type_mp2d,  // Metroid Prime 2 Demo (DSP)
	type_idsp,  // IDSP (DSP)
	type_spt,   // SPT+SPD (DSP)
	type_mss,   // MSS (DSP)
	type_gcm,   // GCM (DSP)
	type_mpdsp, // Monopoly Party hack (DSP)
	type_ish,   // ISH+ISD (DSP)
	type_ymf,   // YMF (DSP)
	type_rsddsp,// RSD (DSP)
	type_idsp2, // IDSP (Harvest Moon - Another Wonderful Life) (DSP)
	type_gcub,  // GCub (DSP)
	type_wam,   // WAM (RIFF) (DSP)
	type_wvs,   // WVS (DSP)
	type_adx03, // ADX type 03
	type_adx04, // ADX type 04
	type_adp,   // ADP
	type_rsdpcm,// RSD (PCM)
	type_astpcm,// AST (PCM)
	type_whdpcm,// (from WHD, Hitman 2) (PCM)
	type_afc,   // AFC
	type_astafc,// AFC in an AST wrapper
	type_vag,   // VAG
	type_ads,   // ASD (VAG)
	type_rsf,   // RSF
} filetype;

// structure for a single channel
typedef struct {
	HANDLE infile; // processing on a single channel needs this,also this allows for seperate L/R files to be played at once
	
	// header data
	u32 num_samples;
	u32 num_adpcm_nibbles;
	u32 sample_rate;
	u16 loop_flag;
	u16 format;
	u32 sa,ea,ca;
	s16 coef[16];
	u16 gain; // never used anyway
	u16 ps,yn1,yn2;
	u16 lps,lyn1,lyn2;
	
	short chanbuf[HEX_8000_DIV_EIGHT_MUL_FOURTEEN];
	int readloc,writeloc; // offsets into the chanbuf
	filetype type;
	short bps; // bits per "size", 4 if offsets specified in nibbles, 8 if bytes
	u32 chanstart; // offset in file of start of this channel
	s32 offs; // current location
	s32 loopoffs;
	union { // sample history (either long or short, ADP uses long, others use short)
		long lhist1;
		short hist1;
	};
	union {
		long lhist2;
		short hist2;
	};
	long interleave; // _bytes_ of interleave, 0 if none
} CUBESTREAM;

// structure represents a DSP file
typedef struct {
	CUBESTREAM ch[2];
	int NCH;
	int ADXCH; // number of channels in an ADX (may be different from number being rendered)
	long nrsamples;
	long file_length;
	long nexthalp; // next HALPST header
	long halpsize;
	long samplesdone,loopsamplesdone,loopnexthalp,loophalpsize;
	int lastchunk;
	long startinterleave;
} CUBEFILE;

int InitDSPFILE(char * infile, CUBEFILE * dsp);
int InitADXFILE(char * infile, CUBEFILE * adx);
int InitADPFILE(char * infile, CUBEFILE * adp);
int InitPCMFILE(char * infile, CUBEFILE * pcm);
int InitAFCFILE(char * infile, CUBEFILE * afc);

int InitCUBEFILE(char * fn, CUBEFILE * cf);
void CloseCUBEFILE(CUBEFILE * dsp);

int CheckSampleRate(int sr);

long DSPdecodebuffer
(
    u8			*input, // location of encoded source samples
    s16         *out,   // location of destination buffer (16 bits / sample)
    short		coef[16],   // location of decode coefficients
	short * histp,
	short * hist2p
);


long AFCdecodebuffer
(
    u8			*input, // location of encoded source samples
    s16         *out,   // location of destination buffer (16 bits / sample)
	short * histp,
	short * hist2p
);

int ADXdecodebuffer
(
    u8			*input, // location of encoded source samples
    s16         *out,   // location of destination buffer (16 bits / sample)
	short * histp,
	short * hist2p
);

int ADPdecodebuffer(
	unsigned char *input,
	short *outl,
	short *outr,
	long *histl1,
	long *histl2,
	long *histr1,
	long *histr2
);

int VAGdecodebuffer(
	unsigned char * input,
	short * out,
	short * hist1p,
	short * hist2p
);

void RSFdecodebuffer(
	unsigned char in,
	short *out,
	short *hist1p,
	short *hist2p
);

void fillbuffers(CUBEFILE * dsp);

void fillbufferDSP(CUBESTREAM * stream);
void fillbufferDSPinterleave(CUBEFILE * stream);
void fillbufferHALP(CUBEFILE * stream);
void fillbufferADX(CUBEFILE * adx);
void fillbufferADP(CUBEFILE * adp);
void fillbufferPCM(CUBEFILE * pcm);
void fillbufferAFC(CUBEFILE * afc);
void fillbufferASTPCM(CUBEFILE * pcm);
void fillbufferPCMinterleave(CUBEFILE * pcm);
void fillbufferVAG(CUBEFILE * vag);
void fillbufferVAGinterleave(CUBEFILE * vag);
void fillbufferRSF(CUBESTREAM * stream);

// configurable ADX parameters
extern long BASE_VOL;
extern int adxonechan;

#ifdef __cplusplus
}
#endif

#endif

