/* ========================================================================================== */
/* CRYSOUND Dynamic DLL loading header. Copyright (c), Firelight Technologies Pty, Ltd 1999-2003. */
/* ========================================================================================== */

#ifndef _CRYSOUNDDYN_H_
#define _CRYSOUNDDYN_H_

#ifdef WIN32
  #include <windows.h>
#else
  #include <dlfcn.h>
  #include <string.h>
#endif

#include "crysound.h"

typedef struct
{
    void           *module;

    signed char     (F_API *CS_SetOutput)(int outputtype);
    signed char     (F_API *CS_SetDriver)(int driver);
    signed char     (F_API *CS_SetMixer)(int mixer);
    signed char     (F_API *CS_SetBufferSize)(int len_ms);
    signed char     (F_API *CS_SetHWND)(void *hwnd);
    signed char     (F_API *CS_SetMinHardwareChannels)(int min);
    signed char     (F_API *CS_SetMaxHardwareChannels)(int max);
    signed char     (F_API *CS_SetMemorySystem)(void *pool, int poollen, CS_ALLOCCALLBACK useralloc, CS_REALLOCCALLBACK userrealloc, CS_FREECALLBACK userfree);
    signed char     (F_API *CS_Init)(int mixrate, int maxsoftwarechannels, unsigned int flags);
    void            (F_API *CS_Close)();
    void            (F_API *CS_SetSpeakerMode)(unsigned int speakermode);
    void            (F_API *CS_SetSFXMasterVolume)(int volume);
    void            (F_API *CS_SetPanSeperation)(float pansep);
    void            (F_API *CS_File_SetCallbacks)(CS_OPENCALLBACK  useropen, CS_CLOSECALLBACK userclose, CS_READCALLBACK userread, CS_SEEKCALLBACK  userseek, CS_TELLCALLBACK  usertell);
    int             (F_API *CS_GetError)();
    float           (F_API *CS_GetVersion)();
    int             (F_API *CS_GetOutput)();
    void *          (F_API *CS_GetOutputHandle)();
    int             (F_API *CS_GetDriver)();
    int             (F_API *CS_GetMixer)();
    int             (F_API *CS_GetNumDrivers)();
    signed char *   (F_API *CS_GetDriverName)(int id);
    signed char     (F_API *CS_GetDriverCaps)(int id, unsigned int *caps);
    int             (F_API *CS_GetOutputRate)();
    int             (F_API *CS_GetMaxChannels)();
    int             (F_API *CS_GetMaxSamples)();
    int             (F_API *CS_GetSFXMasterVolume)();
    int             (F_API *CS_GetNumHardwareChannels)();
    int             (F_API *CS_GetChannelsPlaying)();
    float           (F_API *CS_GetCPUUsage)();
    void            (F_API *CS_GetMemoryStats)(unsigned int *currentalloced, unsigned int *maxalloced);
    CS_SAMPLE * (F_API *CS_Sample_Load)(int index, const char *name_or_data, unsigned int mode, int memlength);
    CS_SAMPLE * (F_API *CS_Sample_Alloc)(int index, int length, unsigned int mode, int deffreq, int defvol, int defpan, int defpri);
    void            (F_API *CS_Sample_Free)(CS_SAMPLE *sptr);
    signed char     (F_API *CS_Sample_Upload)(CS_SAMPLE *sptr, void *srcdata, unsigned int mode);
    signed char     (F_API *CS_Sample_Lock)(CS_SAMPLE *sptr, int offset, int length, void **ptr1, void **ptr2, unsigned int *len1, unsigned int *len2);
    signed char     (F_API *CS_Sample_Unlock)(CS_SAMPLE *sptr, void *ptr1, void *ptr2, unsigned int len1, unsigned int len2);
    signed char     (F_API *CS_Sample_SetMode)(CS_SAMPLE *sptr, unsigned int mode);
    signed char     (F_API *CS_Sample_SetLoopPoints)(CS_SAMPLE *sptr, int loopstart, int loopend);
    signed char     (F_API *CS_Sample_SetDefaults)(CS_SAMPLE *sptr, int deffreq, int defvol, int defpan, int defpri);
    signed char     (F_API *CS_Sample_SetMinMaxDistance)(CS_SAMPLE *sptr, float min, float max);
    signed char     (F_API *CS_Sample_SetMaxPlaybacks)(CS_SAMPLE *sptr, int max);
    CS_SAMPLE * (F_API *CS_Sample_Get)(int sampno);
    char *          (F_API *CS_Sample_GetName)(CS_SAMPLE *sptr);
    unsigned int    (F_API *CS_Sample_GetLength)(CS_SAMPLE *sptr);
    signed char     (F_API *CS_Sample_GetLoopPoints)(CS_SAMPLE *sptr, int *loopstart, int *loopend);
    signed char     (F_API *CS_Sample_GetDefaults)(CS_SAMPLE *sptr, int *deffreq, int *defvol, int *defpan, int *defpri);
    unsigned int    (F_API *CS_Sample_GetMode)(CS_SAMPLE *sptr);
    int             (F_API *CS_PlaySound)(int channel, CS_SAMPLE *sptr);
    int             (F_API *CS_PlaySoundEx)(int channel, CS_SAMPLE *sptr, CS_DSPUNIT *dsp, signed char startpaused);
    signed char     (F_API *CS_StopSound)(int channel);
    signed char     (F_API *CS_SetFrequency)(int channel, int freq);
    signed char     (F_API *CS_SetVolume)(int channel, int vol);
    signed char     (F_API *CS_SetVolumeAbsolute)(int channel, int vol);
    signed char     (F_API *CS_SetPan)(int channel, int pan);
    signed char     (F_API *CS_SetSurround)(int channel, signed char surround);
    signed char     (F_API *CS_SetMute)(int channel, signed char mute);
    signed char     (F_API *CS_SetPriority)(int channel, int priority);
    signed char     (F_API *CS_SetReserved)(int channel, signed char reserved);
    signed char     (F_API *CS_SetPaused)(int channel, signed char paused);
    signed char     (F_API *CS_SetLoopMode)(int channel, unsigned int loopmode);
    signed char     (F_API *CS_SetCurrentPosition)(int channel, unsigned int offset);
    signed char     (F_API *CS_IsPlaying)(int channel);
    int             (F_API *CS_GetFrequency)(int channel);
    int             (F_API *CS_GetVolume)(int channel);
    int             (F_API *CS_GetPan)(int channel);
    signed char     (F_API *CS_GetSurround)(int channel);
    signed char     (F_API *CS_GetMute)(int channel);
    int             (F_API *CS_GetPriority)(int channel);
    signed char     (F_API *CS_GetReserved)(int channel);
    signed char     (F_API *CS_GetPaused)(int channel);
    unsigned int    (F_API *CS_GetLoopMode)(int channel);
    unsigned int    (F_API *CS_GetCurrentPosition)(int channel);
    CS_SAMPLE * (F_API *CS_GetCurrentSample)(int channel);
    signed char     (F_API *CS_GetCurrentLevels)(int channel, float *l, float *r);
    int             (F_API *CS_FX_Enable)(int channel, unsigned int fx);    /* See CS_FX_MODES */
    signed char     (F_API *CS_FX_Disable)(int channel);    
    signed char     (F_API *CS_FX_SetChorus)(int fxid, float WetDryMix, float Depth, float Feedback, float Frequency, int Waveform, float Delay, int Phase);
    signed char     (F_API *CS_FX_SetCompressor)(int fxid, float Gain, float Attack, float Release, float Threshold, float Ratio, float Predelay);
    signed char     (F_API *CS_FX_SetDistortion)(int fxid, float Gain, float Edge, float PostEQCenterFrequency, float PostEQBandwidth, float PreLowpassCutoff);
    signed char     (F_API *CS_FX_SetEcho)(int fxid, float WetDryMix, float Feedback, float LeftDelay, float RightDelay, int PanDelay);
    signed char     (F_API *CS_FX_SetFlanger)(int fxid, float WetDryMix, float Depth, float Feedback, float Frequency, int Waveform, float Delay, int Phase);
    signed char     (F_API *CS_FX_SetGargle)(int fxid, int RateHz, int WaveShape);
    signed char     (F_API *CS_FX_SetI3DL2Reverb)(int fxid, int Room, int RoomHF, float RoomRolloffFactor, float DecayTime, float DecayHFRatio, int Reflections, float ReflectionsDelay, int Reverb, float ReverbDelay, float Diffusion, float Density, float HFReference);
    signed char     (F_API *CS_FX_SetParamEQ)(int fxid, float Center, float Bandwidth, float Gain);
    signed char     (F_API *CS_FX_SetWavesReverb)(int fxid, float InGain, float ReverbMix, float ReverbTime, float HighFreqRTRatio);  
    void            (F_API *CS_Update)();   /* you must call this once a frame */
    void            (F_API *CS_3D_SetDopplerFactor)(float scale);
    void            (F_API *CS_3D_SetDistanceFactor)(float scale);
    void            (F_API *CS_3D_SetRolloffFactor)(float scale);
    signed char     (F_API *CS_3D_SetAttributes)(int channel, float *pos, float *vel);
    signed char     (F_API *CS_3D_GetAttributes)(int channel, float *pos, float *vel);
    void            (F_API *CS_3D_Listener_SetCurrent)(int current, int numlisteners);  /* use this if you use multiple listeners / splitscreen */
    void            (F_API *CS_3D_Listener_SetAttributes)(float *pos, float *vel, float fx, float fy, float fz, float tx, float ty, float tz);
    void            (F_API *CS_3D_Listener_GetAttributes)(float *pos, float *vel, float *fx, float *fy, float *fz, float *tx, float *ty, float *tz);
    signed char     (F_API *CS_Stream_SetBufferSize)(int ms);      /* call this before opening streams, not after */
    CS_STREAM * (F_API *CS_Stream_OpenFile)(const char *filename, unsigned int mode, int memlength);
    CS_STREAM * (F_API *CS_Stream_Create)(CS_STREAMCALLBACK callback, int length, unsigned int mode, int samplerate, int userdata);
    int             (F_API *CS_Stream_Play)(int channel, CS_STREAM *stream);
    int             (F_API *CS_Stream_PlayEx)(int channel, CS_STREAM *stream, CS_DSPUNIT *dsp, signed char startpaused);
    signed char     (F_API *CS_Stream_Stop)(CS_STREAM *stream);
    signed char     (F_API *CS_Stream_Close)(CS_STREAM *stream);
    signed char     (F_API *CS_Stream_SetEndCallback)(CS_STREAM *stream, CS_STREAMCALLBACK callback, int userdata);
    signed char     (F_API *CS_Stream_SetSynchCallback)(CS_STREAM *stream, CS_STREAMCALLBACK callback, int userdata);
    CS_SAMPLE * (F_API *CS_Stream_GetSample)(CS_STREAM *stream);   /* every stream contains a sample to playback on */
    CS_DSPUNIT *(F_API *CS_Stream_CreateDSP)(CS_STREAM *stream, CS_DSPCALLBACK callback, int priority, int param);
    signed char     (F_API *CS_Stream_SetPosition)(CS_STREAM *stream, unsigned int position);
    unsigned int    (F_API *CS_Stream_GetPosition)(CS_STREAM *stream);
    signed char     (F_API *CS_Stream_SetTime)(CS_STREAM *stream, int ms);
    int             (F_API *CS_Stream_GetTime)(CS_STREAM *stream);
    int             (F_API *CS_Stream_GetLength)(CS_STREAM *stream);
    int             (F_API *CS_Stream_GetLengthMs)(CS_STREAM *stream);
    signed char     (F_API *CS_Stream_SetSubStream)(CS_STREAM *stream, int index);
    int             (F_API *CS_Stream_GetNumSubStreams)(CS_STREAM *stream);
    signed char     (F_API *CS_Stream_SetSubStreamSentence)(CS_STREAM *stream, int *sentencelist, int numitems);
    signed char     (F_API *CS_Stream_SetMode)(CS_STREAM *stream, unsigned int mode);
    unsigned int    (F_API *CS_Stream_GetMode)(CS_STREAM *stream);
    signed char     (F_API *CS_Stream_SetLoopPoints)(CS_STREAM *stream, unsigned int loopstartpcm, unsigned int loopendpcm);
    signed char     (F_API *CS_Stream_SetLoopCount)(CS_STREAM *stream, int count);
    int             (F_API *CS_Stream_AddSynchPoint)(CS_STREAM *stream, unsigned int pcmoffset, int userdata);
    signed char     (F_API *CS_Stream_DeleteSynchPoint)(CS_STREAM *stream, int index);
    int             (F_API *CS_Stream_GetNumSynchPoints)(CS_STREAM *stream);
    int             (F_API *CS_Stream_GetOpenState)(CS_STREAM *stream);
    signed char     (F_API *CS_CD_Play)(char drive, int track);
    void            (F_API *CS_CD_SetPlayMode)(char drive, signed char mode);
    signed char     (F_API *CS_CD_Stop)(char drive);
    signed char     (F_API *CS_CD_SetPaused)(char drive, signed char paused);
    signed char     (F_API *CS_CD_SetVolume)(char drive, int volume);
    signed char     (F_API *CS_CD_SetTrackTime)(char drive, unsigned int ms);
    signed char     (F_API *CS_CD_Eject)(char drive);
    signed char     (F_API *CS_CD_GetPaused)(char drive);
    int             (F_API *CS_CD_GetTrack)(char drive);
    int             (F_API *CS_CD_GetNumTracks)(char drive);
    int             (F_API *CS_CD_GetVolume)(char drive);
    int             (F_API *CS_CD_GetTrackLength)(char drive, int track); 
    int             (F_API *CS_CD_GetTrackTime)(char drive);
    CS_DSPUNIT *(F_API *CS_DSP_Create)(CS_DSPCALLBACK callback, int priority, int param);
    void            (F_API *CS_DSP_Free)(CS_DSPUNIT *unit);
    void            (F_API *CS_DSP_SetPriority)(CS_DSPUNIT *unit, int priority);
    int             (F_API *CS_DSP_GetPriority)(CS_DSPUNIT *unit);
    void            (F_API *CS_DSP_SetActive)(CS_DSPUNIT *unit, signed char active);
    signed char     (F_API *CS_DSP_GetActive)(CS_DSPUNIT *unit);
    CS_DSPUNIT *(F_API *CS_DSP_GetClearUnit)();
    CS_DSPUNIT *(F_API *CS_DSP_GetSFXUnit)();
    CS_DSPUNIT *(F_API *CS_DSP_GetMusicUnit)();
    CS_DSPUNIT *(F_API *CS_DSP_GetFFTUnit)();
    CS_DSPUNIT *(F_API *CS_DSP_GetClipAndCopyUnit)();
    signed char     (F_API *CS_DSP_MixBuffers)(void *destbuffer, void *srcbuffer, int len, int freq, int vol, int pan, unsigned int mode);
    void            (F_API *CS_DSP_ClearMixBuffer)();
    int             (F_API *CS_DSP_GetBufferLength)();      /* Length of each DSP update */
    int             (F_API *CS_DSP_GetBufferLengthTotal)(); /* Total buffer length due to CS_SetBufferSize */
    float *         (F_API *CS_DSP_GetSpectrum)();          /* Array of 512 floats - call CS_DSP_SetActive(CS_DSP_GetFFTUnit(), TRUE)) for this to work. */
    signed char     (F_API *CS_Reverb_SetProperties)(CS_REVERB_PROPERTIES *prop);
    signed char     (F_API *CS_Reverb_GetProperties)(CS_REVERB_PROPERTIES *prop);
    signed char     (F_API *CS_Reverb_SetChannelProperties)(int channel, CS_REVERB_CHANNELPROPERTIES *prop);
    signed char     (F_API *CS_Reverb_GetChannelProperties)(int channel, CS_REVERB_CHANNELPROPERTIES *prop);
    signed char     (F_API *CS_Record_SetDriver)(int outputtype);
    int             (F_API *CS_Record_GetNumDrivers)();
    signed char *   (F_API *CS_Record_GetDriverName)(int id);
    int             (F_API *CS_Record_GetDriver)();
    signed char     (F_API *CS_Record_StartSample)(CS_SAMPLE *sptr, signed char loop);
    signed char     (F_API *CS_Record_Stop)();
    int             (F_API *CS_Record_GetPosition)();  
    CM_MODULE * (F_API *CM_LoadSong)(const char *name);
    CM_MODULE * (F_API *CM_LoadSongEx)(void *data, int length);
    int             (F_API *CM_GetOpenState)(CM_MODULE *mod);
    signed char     (F_API *CM_FreeSong)(CM_MODULE *mod);
    signed char     (F_API *CM_PlaySong)(CM_MODULE *mod);
    signed char     (F_API *CM_StopSong)(CM_MODULE *mod);
    void            (F_API *CM_StopAllSongs)();
    signed char     (F_API *CM_SetZxxCallback)(CM_MODULE *mod, CM_CALLBACK callback);
    signed char     (F_API *CM_SetRowCallback)(CM_MODULE *mod, CM_CALLBACK callback, int rowstep);
    signed char     (F_API *CM_SetOrderCallback)(CM_MODULE *mod, CM_CALLBACK callback, int orderstep);
    signed char     (F_API *CM_SetInstCallback)(CM_MODULE *mod, CM_CALLBACK callback, int instrument);
    signed char     (F_API *CM_SetSample)(CM_MODULE *mod, int sampno, CS_SAMPLE *sptr);
    signed char     (F_API *CM_SetUserData)(CM_MODULE *mod, unsigned int userdata);
    signed char     (F_API *CM_OptimizeChannels)(CM_MODULE *mod, int maxchannels, int minvolume);
    signed char     (F_API *CM_SetReverb)(signed char reverb);             /* MIDI only */
    signed char     (F_API *CM_SetLooping)(CM_MODULE *mod, signed char looping);
    signed char     (F_API *CM_SetOrder)(CM_MODULE *mod, int order);
    signed char     (F_API *CM_SetPaused)(CM_MODULE *mod, signed char pause);
    signed char     (F_API *CM_SetMasterVolume)(CM_MODULE *mod, int volume);
    signed char     (F_API *CM_SetMasterSpeed)(CM_MODULE *mode, float speed);
    signed char     (F_API *CM_SetPanSeperation)(CM_MODULE *mod, float pansep);
    char *          (F_API *CM_GetName)(CM_MODULE *mod);
    int             (F_API *CM_GetType)(CM_MODULE *mod);
    int             (F_API *CM_GetNumOrders)(CM_MODULE *mod);
    int             (F_API *CM_GetNumPatterns)(CM_MODULE *mod);
    int             (F_API *CM_GetNumInstruments)(CM_MODULE *mod);
    int             (F_API *CM_GetNumSamples)(CM_MODULE *mod);
    int             (F_API *CM_GetNumChannels)(CM_MODULE *mod);
    CS_SAMPLE * (F_API *CM_GetSample)(CM_MODULE *mod, int sampno);
    int             (F_API *CM_GetPatternLength)(CM_MODULE *mod, int orderno);
    signed char     (F_API *CM_IsFinished)(CM_MODULE *mod);
    signed char     (F_API *CM_IsPlaying)(CM_MODULE *mod);
    int             (F_API *CM_GetMasterVolume)(CM_MODULE *mod);
    int             (F_API *CM_GetGlobalVolume)(CM_MODULE *mod);
    int             (F_API *CM_GetOrder)(CM_MODULE *mod);
    int             (F_API *CM_GetPattern)(CM_MODULE *mod);
    int             (F_API *CM_GetSpeed)(CM_MODULE *mod);
    int             (F_API *CM_GetBPM)(CM_MODULE *mod);
    int             (F_API *CM_GetRow)(CM_MODULE *mod);
    signed char     (F_API *CM_GetPaused)(CM_MODULE *mod);
    int             (F_API *CM_GetTime)(CM_MODULE *mod);
    int             (F_API *CM_GetRealChannel)(CM_MODULE *mod, int modchannel);
    unsigned int    (F_API *CM_GetUserData)(CM_MODULE *mod);
} CS_INSTANCE;


static CS_INSTANCE *CS_CreateInstance(char *dllName)
{
    CS_INSTANCE *instance;

    instance = (CS_INSTANCE *)calloc(sizeof(CS_INSTANCE), 1);
    if (!instance)
    {
        return NULL;
    }

#ifdef WIN32
    instance->module = LoadLibrary(dllName);
#else
    instance->module = dlopen(dllName, RTLD_GLOBAL | RTLD_LAZY);
#endif
    if (!instance->module)
    {
        free(instance);
        return NULL;
    }

#ifdef WIN32
    #define F_GETPROC(_x, _y)                                                                       \
    {                                                                                             \
        *((unsigned int *)&instance->_x) = (unsigned int)GetProcAddress((HMODULE)instance->module, _y);    \
        if (!instance->_x)                                                                        \
        {                                                                                         \
            FreeLibrary((HMODULE)instance->module);                                                        \
            free(instance);                                                                       \
            return NULL;                                                                          \
        }                                                                                         \
    }
#else
    #define F_GETPROC(_x, _y)                                                                       \
    {                                                                                             \
        char tmp[] = _y;                                                                          \
        *(strchr(tmp, '@')) = 0;                                                                  \
        *((unsigned int *)&instance->_x) = (unsigned int)dlsym(instance->module, &tmp[1]);        \
        if (!instance->_x)                                                                        \
        {                                                                                         \
            dlclose(instance->module);                                                            \
            free(instance);                                                                       \
            return NULL;                                                                          \
        }                                                                                         \
    }
#endif

    F_GETPROC(CS_SetOutput, "_CS_SetOutput@4");
    F_GETPROC(CS_SetDriver, "_CS_SetDriver@4");
    F_GETPROC(CS_SetMixer, "_CS_SetMixer@4");
    F_GETPROC(CS_SetBufferSize, "_CS_SetBufferSize@4");
    F_GETPROC(CS_SetHWND, "_CS_SetHWND@4");
    F_GETPROC(CS_SetMinHardwareChannels, "_CS_SetMinHardwareChannels@4");
    F_GETPROC(CS_SetMaxHardwareChannels, "_CS_SetMaxHardwareChannels@4");
    F_GETPROC(CS_SetMemorySystem, "_CS_SetMemorySystem@20");
    F_GETPROC(CS_Init, "_CS_Init@12");
    F_GETPROC(CS_Close, "_CS_Close@0");
    F_GETPROC(CS_SetSFXMasterVolume, "_CS_SetSFXMasterVolume@4");
    F_GETPROC(CS_SetPanSeperation, "_CS_SetPanSeperation@4");
    F_GETPROC(CS_SetSpeakerMode, "_CS_SetSpeakerMode@4");
    F_GETPROC(CS_GetError, "_CS_GetError@0");
    F_GETPROC(CS_GetVersion, "_CS_GetVersion@0");
    F_GETPROC(CS_GetOutput, "_CS_GetOutput@0");
    F_GETPROC(CS_GetOutputHandle, "_CS_GetOutputHandle@0");
    F_GETPROC(CS_GetDriver, "_CS_GetDriver@0");
    F_GETPROC(CS_GetMixer, "_CS_GetMixer@0");
    F_GETPROC(CS_GetNumDrivers, "_CS_GetNumDrivers@0");
    F_GETPROC(CS_GetDriverName, "_CS_GetDriverName@4");
    F_GETPROC(CS_GetDriverCaps, "_CS_GetDriverCaps@8");
    F_GETPROC(CS_GetOutputRate, "_CS_GetOutputRate@0");
    F_GETPROC(CS_GetMaxChannels, "_CS_GetMaxChannels@0");
    F_GETPROC(CS_GetMaxSamples, "_CS_GetMaxSamples@0");
    F_GETPROC(CS_GetSFXMasterVolume, "_CS_GetSFXMasterVolume@0");
    F_GETPROC(CS_GetNumHardwareChannels, "_CS_GetNumHardwareChannels@0");
    F_GETPROC(CS_GetChannelsPlaying, "_CS_GetChannelsPlaying@0");
    F_GETPROC(CS_GetCPUUsage, "_CS_GetCPUUsage@0");
    F_GETPROC(CS_GetMemoryStats, "_CS_GetMemoryStats@8");
    F_GETPROC(CS_Sample_Load, "_CS_Sample_Load@16");
    F_GETPROC(CS_Sample_Alloc, "_CS_Sample_Alloc@28");
    F_GETPROC(CS_Sample_Free, "_CS_Sample_Free@4");
    F_GETPROC(CS_Sample_Upload, "_CS_Sample_Upload@12");
    F_GETPROC(CS_Sample_Lock, "_CS_Sample_Lock@28");
    F_GETPROC(CS_Sample_Unlock, "_CS_Sample_Unlock@20");
    F_GETPROC(CS_Sample_SetMode, "_CS_Sample_SetMode@8");
    F_GETPROC(CS_Sample_SetLoopPoints, "_CS_Sample_SetLoopPoints@12");
    F_GETPROC(CS_Sample_SetDefaults, "_CS_Sample_SetDefaults@20");
    F_GETPROC(CS_Sample_SetMinMaxDistance, "_CS_Sample_SetMinMaxDistance@12");
    F_GETPROC(CS_Sample_SetMaxPlaybacks, "_CS_Sample_SetMaxPlaybacks@8");
    F_GETPROC(CS_Sample_Get, "_CS_Sample_Get@4");
    F_GETPROC(CS_Sample_GetName, "_CS_Sample_GetName@4");
    F_GETPROC(CS_Sample_GetLength, "_CS_Sample_GetLength@4");
    F_GETPROC(CS_Sample_GetLoopPoints, "_CS_Sample_GetLoopPoints@12");
    F_GETPROC(CS_Sample_GetDefaults, "_CS_Sample_GetDefaults@20");
    F_GETPROC(CS_Sample_GetMode, "_CS_Sample_GetMode@4");
    F_GETPROC(CS_PlaySound, "_CS_PlaySound@8");
    F_GETPROC(CS_PlaySoundEx, "_CS_PlaySoundEx@16");
    F_GETPROC(CS_StopSound, "_CS_StopSound@4");
    F_GETPROC(CS_SetFrequency, "_CS_SetFrequency@8");
    F_GETPROC(CS_SetVolume, "_CS_SetVolume@8");
    F_GETPROC(CS_SetVolumeAbsolute, "_CS_SetVolumeAbsolute@8");
    F_GETPROC(CS_SetPan, "_CS_SetPan@8");
    F_GETPROC(CS_SetSurround, "_CS_SetSurround@8");
    F_GETPROC(CS_SetMute, "_CS_SetMute@8");
    F_GETPROC(CS_SetPriority, "_CS_SetPriority@8");
    F_GETPROC(CS_SetReserved, "_CS_SetReserved@8");
    F_GETPROC(CS_SetPaused, "_CS_SetPaused@8");
    F_GETPROC(CS_SetLoopMode, "_CS_SetLoopMode@8");
    F_GETPROC(CS_IsPlaying, "_CS_IsPlaying@4");
    F_GETPROC(CS_GetFrequency, "_CS_GetFrequency@4");
    F_GETPROC(CS_GetVolume, "_CS_GetVolume@4");
    F_GETPROC(CS_GetPan, "_CS_GetPan@4");
    F_GETPROC(CS_GetSurround, "_CS_GetSurround@4");
    F_GETPROC(CS_GetMute, "_CS_GetMute@4");
    F_GETPROC(CS_GetPriority, "_CS_GetPriority@4");
    F_GETPROC(CS_GetReserved, "_CS_GetReserved@4");
    F_GETPROC(CS_GetPaused, "_CS_GetPaused@4");
    F_GETPROC(CS_GetLoopMode, "_CS_GetLoopMode@4");
    F_GETPROC(CS_GetCurrentPosition, "_CS_GetCurrentPosition@4");
    F_GETPROC(CS_SetCurrentPosition, "_CS_SetCurrentPosition@8");
    F_GETPROC(CS_GetCurrentSample, "_CS_GetCurrentSample@4");
    F_GETPROC(CS_GetCurrentLevels, "_CS_GetCurrentLevels@12");
    F_GETPROC(CS_FX_Enable, "_CS_FX_Enable@8");
    F_GETPROC(CS_FX_Disable, "_CS_FX_Disable@4");
    F_GETPROC(CS_FX_SetChorus, "_CS_FX_SetChorus@32");
    F_GETPROC(CS_FX_SetCompressor, "_CS_FX_SetCompressor@28");
    F_GETPROC(CS_FX_SetDistortion, "_CS_FX_SetDistortion@24");
    F_GETPROC(CS_FX_SetEcho, "_CS_FX_SetEcho@24");
    F_GETPROC(CS_FX_SetFlanger, "_CS_FX_SetFlanger@32");
    F_GETPROC(CS_FX_SetGargle, "_CS_FX_SetGargle@12");
    F_GETPROC(CS_FX_SetI3DL2Reverb, "_CS_FX_SetI3DL2Reverb@52");
    F_GETPROC(CS_FX_SetParamEQ, "_CS_FX_SetParamEQ@16");
    F_GETPROC(CS_FX_SetWavesReverb, "_CS_FX_SetWavesReverb@20");
    F_GETPROC(CS_Update, "_CS_Update@0");
    F_GETPROC(CS_3D_SetAttributes, "_CS_3D_SetAttributes@12");
    F_GETPROC(CS_3D_GetAttributes, "_CS_3D_GetAttributes@12");
    F_GETPROC(CS_3D_Listener_SetCurrent, "_CS_3D_Listener_SetCurrent@8");
    F_GETPROC(CS_3D_Listener_SetAttributes, "_CS_3D_Listener_SetAttributes@32");
    F_GETPROC(CS_3D_Listener_GetAttributes, "_CS_3D_Listener_GetAttributes@32");
    F_GETPROC(CS_3D_SetDopplerFactor, "_CS_3D_SetDopplerFactor@4");
    F_GETPROC(CS_3D_SetDistanceFactor, "_CS_3D_SetDistanceFactor@4");
    F_GETPROC(CS_3D_SetRolloffFactor, "_CS_3D_SetRolloffFactor@4");
    F_GETPROC(CS_Stream_OpenFile, "_CS_Stream_OpenFile@12");
    F_GETPROC(CS_Stream_Create, "_CS_Stream_Create@20");
    F_GETPROC(CS_Stream_Play, "_CS_Stream_Play@8");
    F_GETPROC(CS_Stream_PlayEx, "_CS_Stream_PlayEx@16");
    F_GETPROC(CS_Stream_Stop, "_CS_Stream_Stop@4");
    F_GETPROC(CS_Stream_Close, "_CS_Stream_Close@4");
    F_GETPROC(CS_Stream_SetEndCallback, "_CS_Stream_SetEndCallback@12");
    F_GETPROC(CS_Stream_SetSynchCallback, "_CS_Stream_SetSynchCallback@12");
    F_GETPROC(CS_Stream_GetSample, "_CS_Stream_GetSample@4");
    F_GETPROC(CS_Stream_CreateDSP, "_CS_Stream_CreateDSP@16");
    F_GETPROC(CS_Stream_SetBufferSize, "_CS_Stream_SetBufferSize@4");
    F_GETPROC(CS_Stream_SetPosition, "_CS_Stream_SetPosition@8");
    F_GETPROC(CS_Stream_GetPosition, "_CS_Stream_GetPosition@4");
    F_GETPROC(CS_Stream_SetTime, "_CS_Stream_SetTime@8");
    F_GETPROC(CS_Stream_GetTime, "_CS_Stream_GetTime@4");
    F_GETPROC(CS_Stream_GetLength, "_CS_Stream_GetLength@4");
    F_GETPROC(CS_Stream_GetLengthMs, "_CS_Stream_GetLengthMs@4");
    F_GETPROC(CS_Stream_SetMode, "_CS_Stream_SetMode@8");
    F_GETPROC(CS_Stream_GetMode, "_CS_Stream_GetMode@4");
    F_GETPROC(CS_Stream_SetSubStream, "_CS_Stream_SetSubStream@8");
    F_GETPROC(CS_Stream_GetNumSubStreams, "_CS_Stream_GetNumSubStreams@4");
    F_GETPROC(CS_Stream_SetSubStreamSentence, "_CS_Stream_SetSubStreamSentence@12");
    F_GETPROC(CS_Stream_SetLoopPoints, "_CS_Stream_SetLoopPoints@12");
    F_GETPROC(CS_Stream_SetLoopCount, "_CS_Stream_SetLoopCount@8");
    F_GETPROC(CS_Stream_AddSynchPoint, "_CS_Stream_AddSynchPoint@12");
    F_GETPROC(CS_Stream_DeleteSynchPoint, "_CS_Stream_DeleteSynchPoint@8");
    F_GETPROC(CS_Stream_GetNumSynchPoints, "_CS_Stream_GetNumSynchPoints@4");
    F_GETPROC(CS_Stream_GetOpenState, "_CS_Stream_GetOpenState@4");
    F_GETPROC(CS_CD_Play, "_CS_CD_Play@8");
    F_GETPROC(CS_CD_SetPlayMode, "_CS_CD_SetPlayMode@8");
    F_GETPROC(CS_CD_Stop, "_CS_CD_Stop@4");
    F_GETPROC(CS_CD_SetPaused, "_CS_CD_SetPaused@8");
    F_GETPROC(CS_CD_SetVolume, "_CS_CD_SetVolume@8");
    F_GETPROC(CS_CD_SetTrackTime, "_CS_CD_SetTrackTime@8");
    F_GETPROC(CS_CD_Eject, "_CS_CD_Eject@4");
    F_GETPROC(CS_CD_GetPaused, "_CS_CD_GetPaused@4");
    F_GETPROC(CS_CD_GetTrack, "_CS_CD_GetTrack@4");
    F_GETPROC(CS_CD_GetNumTracks, "_CS_CD_GetNumTracks@4");
    F_GETPROC(CS_CD_GetVolume, "_CS_CD_GetVolume@4");
    F_GETPROC(CS_CD_GetTrackLength, "_CS_CD_GetTrackLength@8");
    F_GETPROC(CS_CD_GetTrackTime, "_CS_CD_GetTrackTime@4");
    F_GETPROC(CS_DSP_Create, "_CS_DSP_Create@12");
    F_GETPROC(CS_DSP_Free, "_CS_DSP_Free@4");
    F_GETPROC(CS_DSP_SetPriority, "_CS_DSP_SetPriority@8");
    F_GETPROC(CS_DSP_GetPriority, "_CS_DSP_GetPriority@4");
    F_GETPROC(CS_DSP_SetActive, "_CS_DSP_SetActive@8");
    F_GETPROC(CS_DSP_GetActive, "_CS_DSP_GetActive@4");
    F_GETPROC(CS_DSP_GetClearUnit, "_CS_DSP_GetClearUnit@0");
    F_GETPROC(CS_DSP_GetSFXUnit, "_CS_DSP_GetSFXUnit@0");
    F_GETPROC(CS_DSP_GetMusicUnit, "_CS_DSP_GetMusicUnit@0");
    F_GETPROC(CS_DSP_GetClipAndCopyUnit, "_CS_DSP_GetClipAndCopyUnit@0");
    F_GETPROC(CS_DSP_GetFFTUnit, "_CS_DSP_GetFFTUnit@0");
    F_GETPROC(CS_DSP_MixBuffers, "_CS_DSP_MixBuffers@28");
    F_GETPROC(CS_DSP_ClearMixBuffer, "_CS_DSP_ClearMixBuffer@0");
    F_GETPROC(CS_DSP_GetBufferLength, "_CS_DSP_GetBufferLength@0");
    F_GETPROC(CS_DSP_GetBufferLengthTotal, "_CS_DSP_GetBufferLengthTotal@0");
    F_GETPROC(CS_DSP_GetSpectrum, "_CS_DSP_GetSpectrum@0");
    F_GETPROC(CS_Reverb_SetProperties, "_CS_Reverb_SetProperties@4");
    F_GETPROC(CS_Reverb_GetProperties, "_CS_Reverb_GetProperties@4");
    F_GETPROC(CS_Reverb_SetChannelProperties, "_CS_Reverb_SetChannelProperties@8");
    F_GETPROC(CS_Reverb_GetChannelProperties, "_CS_Reverb_GetChannelProperties@8");
    F_GETPROC(CS_Record_SetDriver, "_CS_Record_SetDriver@4");
    F_GETPROC(CS_Record_GetNumDrivers, "_CS_Record_GetNumDrivers@0");
    F_GETPROC(CS_Record_GetDriverName, "_CS_Record_GetDriverName@4");
    F_GETPROC(CS_Record_GetDriver, "_CS_Record_GetDriver@0");
    F_GETPROC(CS_Record_StartSample, "_CS_Record_StartSample@8");
    F_GETPROC(CS_Record_Stop, "_CS_Record_Stop@0");
    F_GETPROC(CS_Record_GetPosition, "_CS_Record_GetPosition@0");
    F_GETPROC(CS_File_SetCallbacks, "_CS_File_SetCallbacks@20");
    F_GETPROC(CM_LoadSong, "_CM_LoadSong@4");
    F_GETPROC(CM_LoadSongEx, "_CM_LoadSongEx@20");
    F_GETPROC(CM_GetOpenState, "_CM_GetOpenState@4");
    F_GETPROC(CM_FreeSong, "_CM_FreeSong@4");
    F_GETPROC(CM_PlaySong, "_CM_PlaySong@4");
    F_GETPROC(CM_StopSong, "_CM_StopSong@4");
    F_GETPROC(CM_StopAllSongs, "_CM_StopAllSongs@0");
    F_GETPROC(CM_SetZxxCallback, "_CM_SetZxxCallback@8");
    F_GETPROC(CM_SetRowCallback, "_CM_SetRowCallback@12");
    F_GETPROC(CM_SetOrderCallback, "_CM_SetOrderCallback@12");
    F_GETPROC(CM_SetInstCallback, "_CM_SetInstCallback@12");
    F_GETPROC(CM_SetSample, "_CM_SetSample@12");
    F_GETPROC(CM_SetUserData, "_CM_SetUserData@8");
    F_GETPROC(CM_OptimizeChannels, "_CM_OptimizeChannels@12");
    F_GETPROC(CM_SetReverb, "_CM_SetReverb@4");
    F_GETPROC(CM_SetLooping, "_CM_SetLooping@8");
    F_GETPROC(CM_SetOrder, "_CM_SetOrder@8");
    F_GETPROC(CM_SetPaused, "_CM_SetPaused@8");
    F_GETPROC(CM_SetMasterVolume, "_CM_SetMasterVolume@8");
    F_GETPROC(CM_SetMasterSpeed, "_CM_SetMasterSpeed@8");
    F_GETPROC(CM_SetPanSeperation, "_CM_SetPanSeperation@8");
    F_GETPROC(CM_GetName, "_CM_GetName@4");
    F_GETPROC(CM_GetType, "_CM_GetType@4");
    F_GETPROC(CM_GetNumOrders, "_CM_GetNumOrders@4");
    F_GETPROC(CM_GetNumPatterns, "_CM_GetNumPatterns@4");
    F_GETPROC(CM_GetNumInstruments, "_CM_GetNumInstruments@4");
    F_GETPROC(CM_GetNumSamples, "_CM_GetNumSamples@4");
    F_GETPROC(CM_GetNumChannels, "_CM_GetNumChannels@4");
    F_GETPROC(CM_GetSample, "_CM_GetSample@8");
    F_GETPROC(CM_GetPatternLength, "_CM_GetPatternLength@8");
    F_GETPROC(CM_IsFinished, "_CM_IsFinished@4");
    F_GETPROC(CM_IsPlaying, "_CM_IsPlaying@4");
    F_GETPROC(CM_GetMasterVolume, "_CM_GetMasterVolume@4");
    F_GETPROC(CM_GetGlobalVolume, "_CM_GetGlobalVolume@4");
    F_GETPROC(CM_GetOrder, "_CM_GetOrder@4");
    F_GETPROC(CM_GetPattern, "_CM_GetPattern@4");
    F_GETPROC(CM_GetSpeed, "_CM_GetSpeed@4");
    F_GETPROC(CM_GetBPM, "_CM_GetBPM@4");
    F_GETPROC(CM_GetRow, "_CM_GetRow@4");
    F_GETPROC(CM_GetPaused, "_CM_GetPaused@4");
    F_GETPROC(CM_GetTime, "_CM_GetTime@4");
    F_GETPROC(CM_GetRealChannel, "_CM_GetRealChannel@8");
    F_GETPROC(CM_GetUserData, "_CM_GetUserData@4");

    return instance;
}

static void CS_FreeInstance(CS_INSTANCE *instance)
{
    if (instance)
    {
        if (instance->module)
        {
#ifdef WIN32
            FreeLibrary((HMODULE)instance->module);
#else
            dlclose(instance->module);
#endif
        }
        free(instance);
    }
}

#endif

