/**************************************************************************
                        VARMINT'S AUDIO TOOLS 0.61

  SOUND.H

  Written by:  Eric Jorgensen (Aug, 1995)
                    smeagol@rt66.com

                        *** NOTICE ***

  Use Varmint's Audio Tools at your own risk.  This package is not
  garanteed to work safely on any computer.

**************************************************************************/
                               // Stuff to include
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <dos.h>
#include <malloc.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
//#include "math.h"
//#include <values.h>
                               // More definitions than you can
                               // shake a stick at.
#define VAT_VERSION "0.61"

                               // Pointer type definition for samples.
                               // This definition should be far or
                               // huge.  If you use near, you will have
                               // to change the code to use malloc()
                               // instead of farmalloc()
#define SAMPLE signed char

#define MAXSOUNDS 16
#define MAXSOUNDTOKENS 50

#define WORD    unsigned short
#define DWORD   unsigned int
#define BYTE    unsigned char
#define FALSE   0
#define TRUE    1

#define TIMEOUT           32000

#define DSP_DETECT        0x02
#define DSP_GET_VERS      0xe1
#define DSP_INVOKE_INTR   0xf2
#define DSP_RESET         0x06
#define DSP_READ          0x0a
#define DSP_RSTATUS       0x0e
#define DSP_SAMPLE_RATE   0x40
#define DSP_SILENCE       0x80
#define DSP_SPKR_ON       0xd1
#define DSP_SPKR_OFF      0xd3
#define DSP_WRITE         0x0c
#define DSP_WSTATUS       0x0c

#define FM_ADLIB_ADDRESS  0x388
#define FM_BOTH_OFF       0x08
#define FM_DETECT         0x01
#define FM_LEFT_OFF       0x00
#define FM_RIGHT_OFF      0x02

#define FM_HIHAT          0x01
#define FM_TOPCYM         0x02
#define FM_TOMTOM         0x04
#define FM_SNARE          0x08
#define FM_BASS           0x10

//----------------------------------- Enumerations


typedef enum {bit8=0,bit4=1,bit26=2,bit2=3,high} playmode;
typedef enum {none,nodsp,adlib,sb20,sbpro} cardtype;
typedef enum {fmerr=0,nodsperr,irqerr,dmacherr,nomem} SBERROR;
typedef enum {v_play,v_stop,v_pause,v_resume,v_rewind,v_setrepeat,v_setpos,
              v_setrate,v_setvolume } VATCOMMAND;
typedef enum {v_fancy,v_plain,v_unused} VATPLAYTYPE;

//----------------------------------- Structures

typedef struct {
  DWORD         position;
  WORD          offset,rlength,end;
  WORD          sample_number;
  WORD          *pos;
  WORD          counter,pinc;
  WORD          period,period2,vibdepth,vibperiod;
  WORD          count;
  int           data1,data2,data3,data4;
  int           vslide;
  int           porta;
  signed char   volume,volume2;
  signed char   cut;
  BYTE          effect,x,y;
  BYTE          retrigger;
  SAMPLE        *sdata;
} CHANNEL;

typedef struct mod {
  char          title[20];
  char          sample_name[32][22];
  WORD          slength[32],offset[32],repeat[32];
  signed char   finetune[32];
  BYTE          volume[32],num_positions;
  BYTE          maxpattern,ptable[128],sig[5];
  BYTE          *pattern_data[128];
  BYTE          num_samples;
  SAMPLE        *sdata[32];
  int           repeatmusic;
  struct mod    *chain;
  void          (*chainfunc)(struct mod *);
} MOD;

typedef struct {                      // MIDI Voice data structure
  int owner_track;
  int owner_channel;
  int active;
  int note;
  int volume;
} VOICE;


typedef struct midi {                 // MIDI data structure
  int    format;                      // 0 or 1
  int    num_tracks;                  // 1 - 16
  int    divisions;                   // number ticks per quarter note
  BYTE   *track[16];                  // Track data pointers
  int    repeat;
  struct midi *chain;
  void   (*chainfunc)(struct midi *);
} MIDI;

typedef struct soundeffect {
  SAMPLE  *data;                      // pointer to sound data
  DWORD   length;                     // length of the sample iin bytes
  DWORD   position;                   // data position used internally by sbint
  WORD    *pos;                       // pointer to current byte position
  WORD    pinc;                       // rate counter
  int     repeat;                     // number of times to repeat sample
  BYTE    volume;                     // volume of the sample
  BYTE    active;                     // indicates wether sample is playing
  DWORD   id;
  VATPLAYTYPE     type;               // fancy or plain
  struct soundeffect *chain;          // sound effect to jump to when done
  struct soundeffect *next;           // Used internally for a linked list
  void (*chainfunc)(struct soundeffect *);
} SOUNDEFFECT;


//----------------------------------- FM functions

int     FMDetect(void);
void    FMWrite(WORD data);
void    FMReset(void);
BYTE    FMStatus(void);
void    FMSetVoice(BYTE voice,BYTE *ins);
void    FMSetNote(BYTE voice,BYTE note);
void    FMSetFrequency(BYTE voice,WORD freq);
void    FMKeyOn(BYTE voice);
void    FMKeyOff(BYTE voice);
void    FMSetVolume(BYTE voice,BYTE vol);
void    FMSetRythmMode(BYTE bool);
void    FMRythmOn(BYTE inst);
void    FMRythmOff(BYTE inst);

//----------------------------------- DSP functions


int     DSPReset(void);
BYTE    DSPRead(void);
void    DSPWrite(BYTE output);
WORD    DSPGetVersion(void);

//----------------------------------- Timer functions

void    TimerOn(void);
DWORD    TimerOff(void);
void    InstallTimer0(WORD period,void (*func)(void));
void    RemoveTimer0(void);
void _saveregs MilliDelay(WORD delay);
void _saveregs MicroDelay(WORD delay);
void    InitTimerFunctions(void);


//----------------------------------- MIDI/MPU functions

int     MPUEnter(void);
void    MPUExit(void);
void    MPUWrite(BYTE b);


//----------------------------------- File I/O functions

MIDI      *LoadMidi(char *filename, char *errstring);
MOD       *LoadMod(char *filename, char *errstring);
int       LoadInstruments(char *filename,BYTE inst[128][11]);


//----------------------------------- Sound Effect interface functions

int     AddChainFunction(DWORD id,void (*func)(SOUNDEFFECT *));
void    AlterSoundEffect(DWORD id,VATCOMMAND c,int parameter);
DWORD   ChainSoundEffect(SAMPLE *data,DWORD length,VATPLAYTYPE type,DWORD id);
DWORD   PlaySound(SAMPLE *data,DWORD length,VATPLAYTYPE type);

//----------------------------------- Other functions

WORD    SetSampleRate(WORD rate);
int     SBSetUp(void);
void    SBCleanUp(void);
SAMPLE  *LoadWave(char *wavefile,unsigned int *length);
void    GoVarmint(void);
void    DropDeadVarmint(void);
void    MPUWrite(BYTE b);
void    FreeMidi(MIDI *m);
void    FreeMod(MOD *freeme);
void    VarmintVSync(void);
void    TimeVSync(void);
void    ModCommand(VATCOMMAND c);
void    MidiCommand(VATCOMMAND c);
int     PercentOverhead(WORD ticks);
void    real_free(int handle);
void    *real_malloc(WORD size,int* handle);


//----------------------------------- Global Variables

                                      // MIDI parameters
extern MIDI     *midi_data;
extern WORD     midi_mpuport;
extern int      midi_usertempo;
extern int      midi_mpuout;
extern int      midi_fmout;
extern BYTE     midi_volume;
extern BYTE     *midi_patchmap;
extern BYTE     *midi_fmpatchmap;
                                      // MOD parameters
extern MOD      *mod_data;
extern int      mod_bytespertick;
extern int      mod_volume;
extern BYTE     channel_select[4];
                                      // Miscellaneous
extern char     *errname[];
extern volatile DWORD    vclock;
extern SBERROR  sberr;
extern volatile WORD     DSP_overhead;
extern volatile WORD     vsyncclock;
extern volatile BYTE     sync_on;
extern short      debug_lowdsp;
extern volatile short      debug_reverseflipflop;
