#ifndef _Intrument_h
#define _Intrument_h

// instrument header info
#include "TimTypes.h"

struct Envelope
{
	uint32_t*   pTable;
	uint8_t     Flags;
	uint8_t     Points;
	uint8_t     LoopStart;
	uint8_t     LoopEnd;
	uint8_t     SustainStart;
	uint8_t     SustainEnd;
	uint8_t     dummy[2];
};

typedef enum
{ Envelope_Flag_On      = 1
, Envelope_Flag_Sustain = 2
, Envelope_Flag_Loop    = 4
, Envelope_Flag_Carry   = 8
} Envelope_Flags;

struct NoteMap
{
	uint8_t	    Volume;  // [1-256] - 1
	uint8_t	    SampleNr;
	uint16_t    Pitch; // in 1/256 semitone
};

typedef struct
{
	uint8_t Speed;
	uint8_t Depth;
	uint8_t Type;
	uint8_t Rate;
} AutoVibrato;

struct Instrument
{
	uint8_t*    pName;
	uint8_t*    pFilename;
	NoteMap*    pNotesMap;
	Envelope    VolumeEnvelope;
	Envelope    PanningEnvelope;
	Envelope    PitchEnvelope;
	Envelope    FilterEnvelope;
	uint32_t    FadeoutVolume;
	uint8_t     Flags;
	uint8_t     NewNoteAction;
	uint8_t     DuplicateCheckType;
	uint8_t     DuplicateNoteAction;
	uint32_t    Panning;
	uint8_t     VolumeSwing; // %
	uint8_t     PanningSwing; // [0-256]
	uint8_t     PitchPanSep;
	uint8_t     PitchPanCenter;
	uint8_t     FilterCutoff;
	uint8_t     FilterResonance;
	uint8_t     dummy[2];
	AutoVibrato Vibrato;
};

typedef enum
{ Inst_Flag_Set_Panning   = 1
} Inst_Flags;

typedef enum
{ note_action_cut         = 0
, note_action_off         = 1
, note_action_offxm       = 2
, note_action_fade        = 3
, note_action_sustain_off = 4
, note_action_continue    = 5
} Note_Actions;

typedef enum
{ Inst_DCT_off          = 0
, Inst_DCT_note         = 1
, Inst_DCT_sample       = 2
, Inst_DCT_instrument   = 3
, Inst_DCT_all          = 4 // used internally by past note action
} Inst_DCTs;

struct Sample
{
	// Do not alter the order
	uint32_t    Size;          // Samples count (<> Byte count)
	void*       Ptr;           // Pointer to the samples
	uint32_t    LoopStart;     // [0, Size]
	uint32_t    LoopEnd;       // [LoopStart, Size]
	uint32_t    Type;          // See below
	uint32_t    DefaultVolume; // [0, 256]
	int32_t     FineTune;      // in 1/2^31 semitone
	uint32_t    Frequency;     // in Hz
	uint8_t*    pName;
	uint8_t*    pFilename;
	uint32_t    ScaleVolume;   // [0, 256]
	uint32_t    SustainStart;  // [0, Size]
	uint32_t    SustainEnd;    // [SustainStart, Size]
	uint32_t    Panning;       // [0, 256], 384 for surround
	int32_t     RelTone;       // [-128*256, 127*256] in 1/256 semitone
	AutoVibrato Vibrato;
};

typedef enum
{ Smp_Type_Unsigned       = 0x00000001
, Smp_Type_Stereo         = 0x00000002
, Smp_Type_16bit          = 0x00000004
, Smp_Type_Loop           = 0x00000008
, Smp_Type_Loop_Bidi      = 0x00000010
, Smp_Type_Sustain        = 0x00000020
, Smp_Type_Sustain_Bidi   = 0x00000040
, Smp_Type_Set_Panning    = 0x00000080
, Smp_Type_Undefined      = 0x00000100 // Sample does not exist
, Smp_Type_Delta          = 0x04000000
, Smp_Type_BigEndian      = 0x08000000
, Smp_Type_ExternalName   = 0x10000000 // no need to free memory
, Smp_Type_ExternalFile   = 0x20000000 // no need to free memory
, Smp_Type_ExternalPtr    = 0x40000000 // no need to free memory
, Smp_Type_VisibleBits    = 0x000001fe
} Smp_Types;

#endif
