
#define PLAY_AHEAD              100
#define PLAY_AHEAD_NOTES        50
#define MAXTRACKS               64


#define NOTEOFF                 0x80
#define NOTEON                  0x90
#define KEYPRESSURE             0xa0
#define CONTROLCHANGE           0xb0
#define PROGRAMCHANGE           0xc0
#define CHANNELPRESSURE         0xd0
#define PITCHWHEEL              0xe0
#define SYSTEM                  0xf0

#define SYSTEM_EXCL1            0x0
#define SYSTEM_EXCL2            0x7
#define SYSTEM_META             0xf
#define SYSTEM_END              0xf7

#define META_SETTEMPO           0x51

#define CTRL_VOLUME             7
#define CTRL_PAN                10


typedef struct soundevent {
  int time;             // beats
  char duration;        // 1/20th sec
  char pan;             // 0 - 127
  char volume;          // 0 - 127
  char note;
  char internalvoice;
  char midiinstrument;
} soundevent;

typedef struct midievent {
  int time;             // beats
  int duration;         // ticks
  char voice;           // internal voices
  char pan;             // 0 - 127
  char volume;          // 0 - 127
  char note;
  char channel;
  char transpose;
  char midiinstrument;
} midievent;


extern struct tracks {
  byte *start;
  byte *end;
  int nextevent;
  int events;
  struct midievent *unpacked;
} tracks[MAXTRACKS];

extern struct channelinfo {
  char internalvoice;
  char pan;              // currently unused
  char volume;           // 0..&7f
  char transpose;
  char midiinstrument;
} channelinfo[16];

extern struct soundchannels {
  int start;
  int free;
  int internalvoice;
} soundchannels[9];


extern char voicemap[128], drummap[128], internalmap[33];
extern int transposemap[128], drumtranspose[128];
extern os_dynamic_area_no eventarea;

extern int TRACKS, TICKSPERQUARTER, CURRENTBEAT, TEMPO, PLAYING;
extern int CHANNELS, RATE, POSITION, NEXTEVENT, EVENTS, STARTTIME;
extern soundevent *START;


void internalmapping(int voice, char *name);
byte *readticks(byte *file, int *ticks);
byte *readword(byte *file, int *ticks);
byte *readtriple(byte *file, int *ticks);
byte *readshort(byte *file, int *ticks);
void init_soundsystem(void);
void reset_soundsystem(void);
int midi_countevents(byte *midi, byte *end);
void midi_unpacktrack(byte *midi, byte *end, struct midievent *output, int events);
void play_note(int time, int duration, int note, int pan, int volume, int voice);
