//common headers and platform specific headers
#pragma once

#include <stdio.h>

#include <vector>
#include <string>
#include <math.h>

#ifdef _WINDOWS

//Windows specific
#ifndef _WIN32_WINNT 
	#define _WIN32_WINNT 0x0500	
#endif
#include <Windows.h>
#include <MMSystem.h>
#pragma comment(lib, "winmm.lib")
#ifdef MSE_DLL
	#define MSE_API __declspec(dllexport)
#else
	#ifdef MSE_STATIC	//define this if you compile MSE source code in your app project
		#define MSE_API
	#else	
		#define MSE_API __declspec(dllimport)
	#endif
#endif

#pragma warning( disable: 4251 )
#pragma warning( disable: 4996 )
#pragma warning( disable: 4244 )
#pragma warning( disable: 4305 )
#pragma warning( disable: 4800 )
typedef HANDLE MSE_Event;
typedef HANDLE MSE_Mutex;
typedef HANDLE MSE_Thread;
#else

//Mac specific
#include <CoreFoundation/CoreFoundation.h>
#include <pthread.h>
#include <mach/mach_init.h>
#include <mach/semaphore.h>
#include <mach/task.h>
typedef unsigned int DWORD;
typedef unsigned short WORD;
typedef semaphore_t MSE_Event;
typedef pthread_mutex_t  MSE_Mutex;
typedef pthread_t MSE_Thread;
#define MSE_API

#endif

//common
#ifndef MSE_NOLIBSNDFILE	//define this if you do not want to libsndfile in static build
#define MSE_LIBSNDFILE		//libsndfile reference
#endif
typedef unsigned long long MSE_Frame;
typedef unsigned long long MSE_Size;
typedef unsigned char      MSE_Byte;
typedef std::string		   MSE_String;

typedef struct tagMSE_Rect
{
	tagMSE_Rect() { left=right=top=bottom=0; }
	tagMSE_Rect(int l, int r, int t, int b) { left=l; right=r; top=t; bottom=b; }
	bool PtInRect(int x, int y) { if(x>=left && x<=right && y>=bottom && y<=top) return true; else return false; }
	int left, right, top, bottom;
}MSE_Rect;

typedef struct tagMSE_MIDI
{
	tagMSE_MIDI() { status=data1=data2=0; frameoffset=0; }
	MSE_Byte status, data1, data2;
	unsigned int frameoffset;
}MSE_MIDI;

enum MSE_SampleType
{
	eMSE_SampleType_Unknown = 0,
	eMSE_SampleType_8bit,
	eMSE_SampleType_16bit,
	eMSE_SampleType_24bit,
	eMSE_SampleType_32bit
};

enum MSE_ResampleQuality 
{
	eMSE_ReSampleQuality_Low = 0,
	eMSE_ReSampleQuality_Mid,
	eMSE_ReSampleQuality_High
};

enum MSE_VelocityCurve
{
	eMSE_VelocityCurve_Normal = 0,
	eMSE_VelocityCurve_Strong,
	eMSE_VelocityCurve_Weak
};

enum MSE_SampleLoopType {
	eMSE_SampleLoopType_NoLoop = 0,		//normal attack and release
	eMSE_SampleLoopType_OneShot,
	eMSE_SampleLoopType_LoopUntilEnd
};

enum MSE_VoiceMode {
	eMSE_VoiceMode_Poly = 0,
	eMSE_VoiceMode_Mono,
	eMSE_VoiceMode_Legato
};

enum MSE_GroupSelection {
	eMSE_GroupSelection_AlwaysSelected = 0,
	eMSE_GroupSelection_Channel,
	eMSE_GroupSelection_Note,
	eMSE_GroupSelection_Controller,
	eMSE_GroupSelection_Program,
	eMSE_GroupSelection_Manual
};

enum MSE_OverlapTrigger {
	eMSE_OverlapTrigger_Stack = 0,
	eMSE_OverlapTrigger_RoundRobin,
	eMSE_OverlapTrigger_RandomRobin,
	eMSE_OverlapTrigger_TotalRandom
};

enum MSE_LFOWaveform {
	eMSE_LFOWaveform_Triangle, 
	eMSE_LFOWaveform_Sin, 
	eMSE_LFOWaveform_Saw,
	eMSE_LFOWaveform_Square,
	eMSE_LFOWaveform_Exponent
};

enum MSE_LFODestination {
	eMSE_LFODestination_None, 
	eMSE_LFODestination_Pitch,
	eMSE_LFODestination_Expression,
	eMSE_LFODestination_Pan
};

enum MSE_LFODepthSource {
	eMSE_LFODepthSource_None, 
	eMSE_LFODepthSource_ModWheel,
	eMSE_LFODepthSource_AfterTouch,
	eMSE_LFODepthSource_Velocity 
};

#define deleteAndNull(x)	delete (x); (x) = 0;

#define deleteAndNullArray(x)	delete [] (x); (x) = 0;
