#pragma once
#include <stdint.h>
#include <stdbool.h>
#define CHN_DISOWNED 128
#define DIR_FORWARDS 0
#define DIR_BACKWARDS 1
#define PAN_SURROUND 100
#define LOOP_PINGPONG 24
#define LOOP_FORWARDS 8
enum {
ENVF_ENABLED = 1,
ENVF_LOOP = 2,
ENVF_SUSTAINLOOP = 4,
ENVF_CARRY = 8,
ENVF_TYPE_FILTER = 128 };
enum {
SMPF_ASSOCIATED_WITH_HEADER = 1,
SMPF_16BIT = 2,
SMPF_STEREO = 4,
SMPF_COMPRESSED = 8,
SMPF_USE_LOOP = 16,
SMPF_USE_SUSTAINLOOP = 32,
SMPF_LOOP_PINGPONG = 64,
SMPF_SUSTAINLOOP_PINGPONG = 128
};
enum {
HF_UPDATE_EFX_IF_CHAN_ON = 1,
HF_ALWAYS_UPDATE_EFX = 2,
HF_CHAN_ON = 4,
HF_CHAN_CUT = 8, HF_PITCH_SLIDE_ONGOING = 16,
HF_FREEPLAY_NOTE = 32, HF_ROW_UPDATED = 64,
HF_APPLY_RANDOM_VOL = 128,
HF_UPDATE_VOLEFX_IF_CHAN_ON = 256,
HF_ALWAYS_VOLEFX = 512
};
enum {
SF_CHAN_ON = 1,
SF_RECALC_PAN = 2,
SF_NOTE_OFF = 4,
SF_FADEOUT = 8,
SF_RECALC_VOL = 16,
SF_FREQ_CHANGE = 32,
SF_UPDATE_MIXERVOL = 64,
SF_CENTRAL_PAN = 128,
SF_NEW_NOTE = 256,
SF_NOTE_STOP = 512,
SF_LOOP_CHANGED = 1024,
SF_CHN_MUTED = 2048,
SF_VOLENV_ON = 4096,
SF_PANENV_ON = 8192,
SF_PITCHENV_ON = 16384,
SF_PAN_CHANGED = 32768
};
enum {
ITF_STEREO = 1,
ITF_VOL0_OPTIMIZATION = 2, ITF_INSTR_MODE = 4,
ITF_LINEAR_FRQ = 8,
ITF_OLD_EFFECTS = 16,
ITF_COMPAT_GXX = 32,
ITF_USE_MIDI_PITCH_CNTRL = 64,
ITF_REQ_MIDI_CFG = 128
};
enum {
DF_SUPPORTS_MIDI = 1,
DF_USES_VOLRAMP = 2, DF_WAVEFORM = 4, DF_HAS_RESONANCE_FILTER = 8 };
#define MAX_PATTERNS 200
#define MAX_SAMPLES 100
#define MAX_INSTRUMENTS 100
#define MAX_ORDERS 256
#define MAX_ROWS 200
#define MAX_HOST_CHANNELS 64
#define MAX_SLAVE_CHANNELS 256
#define MAX_SONGMSG_LENGTH 8000
typedef struct pattern_t
{
uint16_t Rows;
uint8_t *PackedData;
} pattern_t;
typedef struct envNode_t
{
int8_t Magnitude;
uint16_t Tick;
} envNode_t;
typedef struct env_t
{
uint8_t Flags, Num, LoopBegin, LoopEnd, SustainLoopBegin, SustainLoopEnd;
envNode_t NodePoints[25];
} env_t;
typedef struct instrument_t
{
char DOSFilename[12+1];
uint8_t NNA, DCT, DCA;
uint16_t FadeOut;
uint8_t PitchPanSep, PitchPanCenter, GlobVol, DefPan, RandVol, RandPan;
char InstrumentName[26];
uint8_t FilterCutoff, FilterResonance, MIDIChn, MIDIProg;
uint16_t MIDIBank;
uint16_t SmpNoteTable[120];
env_t VolEnv, PanEnv, PitchEnv;
} instrument_t;
typedef struct smp_t
{
char DOSFilename[12+1];
uint8_t GlobVol, Flags, Vol;
char SampleName[26];
uint8_t Cvt, DefPan;
uint32_t Length, LoopBegin, LoopEnd, C5Speed, SustainLoopBegin, SustainLoopEnd, OffsetInFile;
uint8_t AutoVibratoSpeed, AutoVibratoDepth, AutoVibratoRate, AutoVibratoWaveform;
void *Data;
void *OrigData, *DataR, *OrigDataR;
} sample_t;
typedef struct hostChn_t
{
uint16_t Flags;
uint8_t NotePackMask, RawNote, Ins, RawVolColumn, Cmd, CmdVal, OldCmd, OldCmdVal, VolCmd, VolCmdVal;
uint8_t MIDIChn, MIDIProg, TranslatedNote, Smp;
uint8_t EfxMem_DKL, EfxMem_EFG, EfxMem_O, EfxMem_I, EfxMem_J, EfxMem_N, EfxMem_P;
uint8_t EfxMem_Q, EfxMem_T, EfxMem_S, EfxMem_W, EfxMem_G_Compat, EfxMem_SFx;
uint8_t HighSmpOffs;
uint8_t HostChnNum, VolSet;
void *SlaveChnPtr;
uint8_t PattLoopStartRow, PattLoopCount;
uint8_t PanbrelloWaveform, PanbrelloPos, PanbrelloDepth, PanbrelloSpeed, LastPanbrelloData;
int8_t LastVibratoData, LastTremoloData;
uint8_t ChnPan, ChnVol;
int8_t VolSlideDelta;
uint8_t TremorCount, TremorOnOff, RetrigCount;
int32_t PortaFreq;
uint8_t VibratoWaveform, VibratoPos, VibratoDepth, VibratoSpeed;
uint8_t TremoloWaveform, TremoloPos, TremoloDepth, TremoloSpeed;
uint8_t MiscEfxData[16];
} hostChn_t;
typedef struct envState_t
{
int32_t Value, Delta;
int16_t Tick, CurNode, NextTick;
} envState_t;
typedef struct slaveChn_t
{
bool SmpIs16Bit;
uint16_t Flags;
uint32_t MixOffset; uint8_t LoopMode, LoopDirection;
int32_t LeftVolume, RightVolume;
int32_t Frequency, FrequencySet;
uint8_t AutoVibratoPos;
uint16_t AutoVibratoDepth;
int32_t OldLeftVolume, OldRightVolume;
uint8_t FinalVol128, Vol, VolSet, ChnVol, SmpVol, FinalPan;
uint16_t FadeOut;
uint8_t DCT, DCA, Pan, PanSet;
instrument_t *InsPtr;
sample_t *SmpPtr;
uint8_t Note, Ins;
uint8_t Smp;
void *HostChnPtr;
uint8_t HostChnNum, NNA, MIDIChn, MIDIProg;
uint16_t MIDIBank;
int32_t LoopBegin, LoopEnd;
uint32_t Frac32;
uint16_t FinalVol32768;
int32_t SamplingPosition;
int32_t filtera, filterb, filterc;
envState_t VolEnvState, PanEnvState, PitchEnvState;
uint32_t Delta32;
int32_t OldSamples[2];
int32_t DestVolL, DestVolR, CurrVolL, CurrVolR; float fOldSamples[4], fFiltera, fFilterb, fFilterc;
bool HasLooped;
float fOldLeftVolume, fOldRightVolume, fLeftVolume, fRightVolume;
float fDestVolL, fDestVolR, fCurrVolL, fCurrVolR;
uint64_t Frac64, Delta64;
int16_t leftTmpSamples16[3], rightTmpSamples16[4];
int8_t leftTmpSamples8[3], rightTmpSamples8[4];
int16_t leftTmpSamples16_R[3], rightTmpSamples16_R[4]; int8_t leftTmpSamples8_R[3], rightTmpSamples8_R[4];
} slaveChn_t;
typedef struct it_header_t
{
char SongName[26];
uint16_t OrdNum, InsNum, SmpNum, PatNum, Cwtv, Cmwt, Flags, Special;
uint8_t GlobalVol, MixVolume, InitialSpeed, InitialTempo, PanSep;
uint16_t MessageLength;
uint32_t MessageOffset;
uint8_t ChnlPan[MAX_HOST_CHANNELS], ChnlVol[MAX_HOST_CHANNELS];
} it_header_t;
typedef struct {
uint32_t NumChannels;
uint8_t Type, Flags, FilterParameters[128];
uint32_t MixMode, MixSpeed;
int32_t Delta32;
int64_t Delta64;
float QualityFactorTable[128], FreqParameterMultiplier, FreqMultiplier;
bool StartNoRamp;
int32_t LastLeftValue, LastRightValue;
float *fSincLUT, fLastLeftValue, fLastRightValue;
} driver_t;
typedef struct song_t
{
it_header_t Header;
uint8_t Orders[MAX_ORDERS];
instrument_t Ins[MAX_INSTRUMENTS];
sample_t Smp[MAX_SAMPLES];
pattern_t Patt[MAX_PATTERNS];
char Message[MAX_SONGMSG_LENGTH+1];
volatile bool Playing, Loaded;
uint8_t *PatternOffset, LastMIDIByte;
uint16_t CurrentOrder, CurrentPattern, CurrentRow, ProcessOrder, ProcessRow;
uint16_t BreakRow;
uint8_t RowDelay;
bool RowDelayOn, StopSong, PatternLooping;
uint16_t NumberOfRows, CurrentTick, CurrentSpeed, ProcessTick;
uint16_t Tempo, GlobalVolume;
uint16_t DecodeExpectedPattern, DecodeExpectedRow;
} song_t;
extern hostChn_t hChn[MAX_HOST_CHANNELS];
extern slaveChn_t sChn[MAX_SLAVE_CHANNELS];
extern song_t Song;
extern driver_t Driver;