text: //this code is sloppily ripped from an unfinished sound system written for internal use by m.gambrell
  //it is released into the public domain and its stability is not warranted
  
  
  #define _USE_MATH_DEFINES
  #include <math.h>
  #include <stdlib.h>
  #include <map>
  #include <stack>
  #include <ctype.h>
  #include <queue>
  
  
  const int OAKRA_U8 = 0;
  const int OAKRA_S16 = 1;
  const int OAKRA_S32 = 2;
  
  const int OAKRA_STATUS_STOPPED = 0;
  const int OAKRA_STATUS_PLAYING = 1;
  
  struct OAKRA_Format {
  	int channels, format, rate, size;
  };
  
  //implements an easy to use, bland callback
  template <typename T> struct OAKRA_Callback {
  	OAKRA_Callback() { func = 0; param = 0; }
  	T operator()() { if(func) return func(param); }
  	T (*func)(void *param);
  	void *param;
  };
  template <typename T, typename TARG> struct OAKRA_ArgumentCallback {
  	OAKRA_ArgumentCallback() { func = 0; param = 0; }
  	T operator()(TARG arg) { if(func) return func(param,arg); }
  	T (*func)(void *param, TARG arg);
  	void *param;
  };
  
  class OAKRA_Module {
  public:
  	virtual int generate(int samples, void *buf) { return 0; }
  
  	int adapt_to_2S16(int samples, void *buf, OAKRA_Format &sourceFormat) {
  		short *sbuf = (short *)buf;
  		unsigned char *bbuf = (unsigned char *)buf;
  		if(sourceFormat.format == OAKRA_S16) {
  			if(sourceFormat.channels == 2) return samples;
  			for(int i=samples-1,j=samples*2-2;i>=0;i--,j-=2)
  				sbuf[j] = sbuf[j+1] = sbuf[i];
  		} else {
  			if(sourceFormat.channels == 1)
  				for(int i=samples-1,j=samples*2-2;i>=0;i--,j-=2)
  					sbuf[j] = sbuf[j+1] = ((int)bbuf[i]-128)<<8;
  			else
  				for(int j=samples*2-2;j>=0;j--)
  					sbuf[j] = sbuf[j+1] = ((int)bbuf[j]-128)<<8;
  		}
  		return samples;
  	}
  
  	//trashes some samples using the buffer provided
  	void trash(int samples, void *buf, int bufsamples) {
  		while(samples) {
  			int todo = std::min(samples,bufsamples);
  			generate(todo,buf);
  			samples -= todo;
  		}
  	}
  
  	static int calcSize(OAKRA_Format &format) {
  		int size = format.channels;
  		if(format.format == OAKRA_S16) size *= 2;
  		return size;
  	}
  
  	static int getFormatShift(OAKRA_Format &format) {
  		if(format.size==1) return 0;
  		else if(format.size==2) return 1;
  		else if(format.size==4) return 2;
  		return -1; //try and crash!
  	}
  
  	static void *malloc(int len) { 
  		void *ptr = ::malloc(len);
  		return ptr;
  	}
  	void *malloc(int sampsize, int len) { return malloc(sampsize*len); }
  	void *malloc(int sampsize, int channels, int len) { return malloc(sampsize*len*channels); }
  	void *realloc(void *ptr, int len) {
  		ptr = ::realloc(ptr,len);
  		return ptr;
  	}
  	void free(void *ptr) {
  		::free(ptr);
  	}
  	
  
  	static int generateNoise(int samples, void *buf, int sampleSize) {
  		for(int i=0;i<samples;i++)
  			for(int j=0;j<sampleSize;j++)
  				((char *)buf)[i*sampleSize+j] = rand();
  		return samples;
  	}
  
  	static int generateSilence(int samples, void *buf, int sampleSize) {
  		int n = sampleSize*samples;
  		memset(buf,0,n);
  		return samples;
  	}
  
  	static int generateSilence(int samples, void *buf, OAKRA_Format &format) {
  		int n = format.size*samples;
  		memset(buf,0,n);
  		return samples;
  	}
  
  
  	template<typename T>
  	T *malloc() {
  		return (T *)malloc(sizeof(T));
  	}
  	template<typename T>
  	T *malloc(int amt) {
  		return (T *)malloc(sizeof(T)*amt);
  	}
  	template<typename T>
  	T **nmalloc(int number) {
  		return (T **)malloc(sizeof(T)*number);
  	}
  };
  
  class OAKRA_IQueryFormat {
  public:
  	virtual OAKRA_Format &queryFormat() = 0;
  };
  
  //this is basically a filter class
  //one source, one sink
  class OAKRA_BasicModule : public OAKRA_Module {
  public:
  	OAKRA_Module *source, *sink;
  	OAKRA_BasicModule() { source = sink = 0; }
  };
  
  class OAKRA_Voice : public OAKRA_BasicModule {
  public:
  	OAKRA_Voice() { dead = false; }
  	virtual ~OAKRA_Voice() { }
  	virtual void setPan(int pan) = 0;
  	virtual int getPan() =0;
  	virtual void setVol(int vol) = 0;
  	virtual int getVol()=0;
  	virtual void setSource(OAKRA_Module *source) = 0;
  	
  	virtual void volFade(int start, int end, int ms)=0;
  
  	//call this when youre in the middle of rendering the voice, but have decided to quit
  	//the driver will then trash the voice as soon as it gets the chance.
  	//you dont have to have the driver locked to call it. that would be illogical,
  	//as the driver is currently locked while it is rendering!
  	virtual void die() {
  		dead = true;
  	}
  
  	//indicates whether a voice is dead
  	bool dead;
  
  	//callback fired when a voice dies
  	OAKRA_Callback<void> callbackDied;
  };
  
  
  class OAKRA_OutputDriver : public OAKRA_BasicModule {
  public:
  	virtual ~OAKRA_OutputDriver() {} ;
      virtual OAKRA_Voice *getVoice(OAKRA_Format &format) = 0;
  	virtual OAKRA_Voice *getVoice(OAKRA_Format &format, OAKRA_Module *source) = 0;
  
  	//this should be safe to call from within a driver callback. in general, nothing else will be.
  	//even if you dont delete the voice (if youre recycling it) you should clear out the source asap
  	virtual void freeVoice(OAKRA_Voice *voice) = 0;
  
  	virtual void lock() = 0;
  	virtual void unlock() = 0;
  };
  
  
  class OAKRA_Module_OutputDS : public OAKRA_OutputDriver {
  	
  	void *threadData;
  	void *data;
  
  public:
  
  	OAKRA_Module_OutputDS();
  	~OAKRA_Module_OutputDS();
  	OAKRA_Voice *getVoice(OAKRA_Format &format);
  	OAKRA_Voice *getVoice(OAKRA_Format &format, OAKRA_Module *source);
  	void freeVoice(OAKRA_Voice *voice);
  	void freeVoiceInternal(OAKRA_Voice *voice, bool internal);
  	void start(void *hwnd);
  	void update();
  	void beginThread();
  	void endThread();
  	void lock();
  	void unlock();
  };
  