#ifndef S3_TYPES_H
 
#define S3_TYPES_H
 
 
 
#include "s3/s3.h"
 
 
 
#include <miniaudio/miniaudio.h>
 
#include <stdint.h>
 
 
 
// extern int PDGetTotalTime();
 
// extern void dr_dprintf(char* fmt_string, ...);
 
 
 
#define MIN(a, b) ((a) < (b) ? a : b)
 
#define MAX(a, b) ((a) > (b) ? a : b)
 
 
 
// Internal typedefs
 
 
 
typedef float tF32;
 
typedef tS3_sound_source* tS3_sound_source_ptr;
 
typedef int tS3_sound_tag;
 
typedef int tS3_sound_id;
 
typedef int tS3_type;
 
typedef int tS3_repeats;
 
typedef int tS3_volume;
 
typedef int tS3_effect_tag;
 
typedef long tS3_priority;
 
typedef long tS3_pitch;
 
typedef long tS3_speed;
 
typedef struct tS3_outlet tS3_outlet;
 
typedef struct tS3_descriptor tS3_descriptor;
 
typedef struct tS3_channel tS3_channel;
 
typedef struct tS3_sound_source tS3_sound_source;
 
typedef tS3_outlet* tS3_outlet_ptr;
 
 
 
typedef enum tS3_error_codes {
 
    eS3_error_none = 0,
 
    eS3_error_digi_init = 1,
 
    eS3_error_midi_init = 2,
 
    eS3_error_memory = 3,
 
    eS3_error_readfile = 4,
 
    eS3_error_soundbank = 5,
 
    eS3_error_bad_id = 6,
 
    eS3_error_bad_stag = 7,
 
    eS3_error_load_sound = 8,
 
    eS3_error_start_sound = 9,
 
    eS3_error_channel_alloc = 10,
 
    eS3_error_not_spatial = 11,
 
    eS3_error_function_failed = 12,
 
    eS3_error_load_song = 13,
 
    eS3_error_song_not_loaded = 14,
 
    eS3_error_start_song = 15,
 
    eS3_error_start_cda = 16,
 
    eS3_error_cda_not_init = 17,
 
    eS3_error_already_started_cda = 18,
 
    eS3_error_nonexistant_source = 19
 
} tS3_error_codes;
 
 
 
typedef enum tS3_termination_reason {
 
    eS3_tr_natural = 0,
 
    eS3_tr_stopped = 1,
 
    eS3_tr_overridden = 2
 
} tS3_termination_reason;
 
 
 
typedef enum tS3_filter_type {
 
    eS3_filter_none = 0,
 
    eS3_filter_reversed = 1,
 
    eS3_filter_echo = 2
 
} tS3_filter_type;
 
 
 
typedef enum tS3_sound_type {
 
    eS3_ST_sample = 0,
 
    eS3_ST_midi = 1,
 
    eS3_ST_cda = 2
 
} tS3_sound_type;
 
 
 
typedef void tS3_outlet_callback(tS3_outlet*, tS3_sound_tag, tS3_termination_reason);
 
typedef void tS3_sample_filter(tS3_effect_tag, tS3_sound_tag);
 
 
 
typedef struct tS3_channel {
 
    int active;
 
    int termination_reason;
 
    int needs_service;
 
    int repetitions;
 
    int rate;
 
    int spatial_sound;
 
    unsigned int song_handle;
 
    tS3_sound_tag tag;
 
    tS3_type type;
 
    tS3_volume left_volume;
 
    tS3_volume right_volume;
 
    float volume_multiplier;
 
    tS3_vector3 position;
 
    tS3_vector3 velocity;
 
    tS3_vector3 lastpos;
 
    tS3_volume initial_volume;
 
    tS3_pitch initial_pitch;
 
    float pMax_distance_squared;
 
    tS3_outlet* owner_outlet;
 
    tS3_descriptor* descriptor;
 
    tS3_channel* next;
 
    char* type_struct_sample;
 
    char* type_struct_midi;
 
    char* type_struct_cda;
 
    tS3_sound_source* sound_source_ptr;
 
} tS3_channel;
 
 
 
typedef struct tS3_outlet {
 
    int id;
 
    int max_channels;
 
    int independent_pitch;
 
    tS3_channel* channel_list;
 
    tS3_outlet* prev;
 
    tS3_outlet* next;
 
    tS3_outlet_callback* callback;
 
} tS3_outlet;
 
 
 
typedef struct tS3_descriptor {
 
    tS3_sound_id id;
 
    tS3_type type;
 
    tS3_priority priority;
 
    tS3_repeats repeats;
 
    tS3_volume min_volume;
 
    tS3_volume max_volume;
 
    tS3_pitch min_pitch;
 
    tS3_pitch max_pitch;
 
    tS3_speed min_speed;
 
    tS3_speed max_speed;
 
    tS3_descriptor* prev;
 
    tS3_descriptor* next;
 
    int flags;
 
    int midi_song_handle;
 
    int special_fx;
 
    int memory_proxy;
 
    char* sound_data;
 
    char* filename;
 
    // win95 only
 
    // LPDIRECTSOUNDBUFFER sound_buffer;
 
} tS3_descriptor;
 
 
 
typedef struct tS3_sound_source {
 
    tS3_channel* channel;
 
    int brender_vector;
 
    void* position_ptr;
 
    void* velocity_ptr;
 
    tS3_outlet* bound_outlet;
 
    tS3_sound_source* prev;
 
    tS3_sound_source* next;
 
    int ambient;
 
    tS3_repeats ambient_repeats;
 
    int time_since_last_played;
 
    tS3_sound_id sound_id;
 
    float max_distance_sq;
 
    int period;
 
    tS3_volume volume;
 
    tS3_pitch pitch;
 
    tS3_speed speed;
 
    tS3_sound_tag tag;
 
} tS3_sound_source;
 
 
 
typedef struct tS3_sample {
 
    int size;
 
    int rate;
 
    int resolution;
 
    int channels;
 
    char* dataptr;
 
    void* freeptr;
 
} tS3_sample;
 
 
 
typedef struct tS3_hardware_info {
 
    int device_installed;
 
    int timer_installed;
 
    int num_channels;
 
    int max_resolution;
 
    int stereo_flag;
 
    int max_sample_rate;
 
    int min_sample_rate;
 
    int independent_pitch;
 
} tS3_hardware_info;
 
 
 
// Everything below added by dethrace
 
typedef struct tS3_soundbank_read_ctx {
 
    int data_len;
 
    int unk1;
 
    int nlines;
 
    char* data;
 
} tS3_soundbank_read_ctx;
 
 
 
#pragma pack(push, 1)
 
typedef struct tWAVEFORMATEX_ {
 
    int16_t wFormatTag;
 
    int16_t nChannels;
 
    int32_t nSamplesPerSec;
 
    int32_t nAvgBytesPerSec;
 
    int16_t nBlockAlign;
 
    int16_t wBitsPerSample;
 
    int16_t cbSize;
 
} tWAVEFORMATEX_;
 
#pragma pack(pop)
 
 
 
#pragma pack(push, 1)
 
typedef struct wav_header {
 
    // RIFF Header
 
    char riff_header[4]; // Contains "RIFF"
 
    int32_t wav_size;    // Size of the wav portion of the file, which follows the first 8 bytes. File size - 8
 
    char wave_header[4]; // Contains "WAVE"
 
 
 
    // Format Header
 
    char fmt_header[4];     // Contains "fmt " (includes trailing space)
 
    int32_t fmt_chunk_size; // Should be 16 for PCM
 
    int16_t audio_format;   // Should be 1 for PCM. 3 for IEEE Float
 
    int16_t num_channels;
 
    int32_t sample_rate;
 
    int32_t byte_rate;        // Number of bytes per second. sample_rate * num_channels * Bytes Per Sample
 
    int16_t sample_alignment; // num_channels * Bytes Per Sample
 
    int16_t bit_depth;        // Number of bits per sample
 
 
 
    // Data
 
    char data_header[4]; // Contains "data"
 
    int32_t data_bytes;  // Number of bytes in data. Number of samples * num_channels * sample byte size
 
} wav_header;
 
#pragma pack(pop)
 
 
 
#endif