#ifndef FMODSYSTEM_H_
#define FMODSYSTEM_H_
#include <vector>
#include "Utility/Singleton.h"
#include <fmod.h>
#include <fmod_errors.h>
#include "DFunc/debug.h"

#if defined(WIN32) || defined(__WATCOMC__) || defined(_WIN32) || defined(__WIN32__)
    #define __PACKED                         // dummy
#else
    #define __PACKED __attribute__((packed)) // gcc packed
#endif

//each value represents spectrum data in a certain frequency, using the following formula:
//entry_hz = (44100 / 2) / number
//so if number is 1024, we get:
//entry_hz = 21.53 hz

//const unsigned int spectrum_size = 1024;

class FModSystem : public Singleton<FModSystem>
{
	friend class Singleton<FModSystem>;
	friend class FModAudioProcessor;
	public:
		~FModSystem();
		
		//all the get functions
		inline FMOD_SYSTEM *getSystem() const								{ return system; }
		inline int getSpectrumSize() const									{ return spectrum_size; }
		inline int getNumRecordDrivers() const								{ return num_record_drivers; }
		inline int getRecorderDeviceID() const								{ return recorder_device_id; }
		
		//spectrum functions
		const inline float *getSpectrum() const								{ return spectrum_buffer; }
		const inline std::vector<float> &getdbSpectrum() const				{ return db_spectrum_buffer; }
		//sub-divided
		const inline std::vector<float> &getEnergySubBand() const			{ return e_subband; }
		const inline std::vector<float> &getEnergyMean() const				{ return e_mean; }
		const inline std::vector<float> &getEnergyVariance() const			{ return e_variance; }
		inline unsigned short getBandSubDivisions() const					{ return band_sub_divisions; }

		inline FMOD_CHANNELGROUP *getInputChannelGroup() const				{ return input_channel_group; }
		
		bool isFModOk(FMOD_RESULT &result) const;
	private:
		FModSystem(int s_size = 1024);
		
		unsigned int 							spectrum_size;
		std::string								input_channel_group_name;
		
		FMOD_SYSTEM 							*system;
		FMOD_RESULT 							result;							//for error handling
		FMOD_CHANNELGROUP						*input_channel_group;			//so input can be controlled for recording
		
		//system info
		int num_record_drivers;
		int recorder_device_id;
				
		//spectrum stuff
		unsigned short 							band_sub_divisions;				//how many subbands to split the 1024 samples into
		float									*spectrum_buffer;				//not a vector because it gets passed to fmod
		std::vector<float>						db_spectrum_buffer;				//holds the spectrum in decibels
		//sub-divided
		std::vector<float>						e_subband;						//instant energy @ a particular subband
		std::vector<float>						e_mean;							//mean of the histoy for each subband
		std::vector<float>						e_variance;						//statistical variance (or standard deviation depending on the 
};

#endif
