#include "stdafx.h"
#include "common.h"

//extern MIDASmodulePlayHandle playHandle;

//MIDASpostProcessor mpp;

#define BPM 0x7a

int COMB=256;
int DELAY=16384*2;

/*
#define CFEEDBACK 0.8
#define DATAMIX 1		// raw volume level
#define COMBMIX 0.0		// combed level
#define DELAYMIX 0.4	// delayed level
*/

float CFEEDBACK=0.6;
float DATAMIX=1.1;
float COMBMIX=0.60;
float DELAYMIX=0.19;


int *icomb;
int *idelay;
int combpos=0;
int delaypos=0;
float *fcomb=(float*)icomb;
float *fdelay=(float*)idelay;


void CALLBACK SyncCallback(unsigned syncNum, unsigned position, unsigned row)
{
	/* Prevent warnings: */
	position = position;
	row = row;

	int i=syncNum / 16;
	int j=syncNum & 15;
	if (i==0)
	{
		// sync
		if (j>=14) palrev=!palrev;
	}
	else if (i==1)
	{
		// reso
		CFEEDBACK=0.063333*j;
	}
	else if (i==2)
	{
		// comb mix vol
		COMBMIX=0.075*j;
	}
	else if (i==3)
	{
		// delay mix
		if (j>8) j=j*3/2;

		DELAYMIX=0.02375*j;
	}


	/*
	unsigned char str[256];
	sprintf(str,"combfbk=%4.2f data=%4.2f comb=%4.2f delay=%4.2f ",CFEEDBACK,DATAMIX,COMBMIX,DELAYMIX);
	monow(20*160,str);
	//setpalcol(63,0,0,50);
	sprintf(str,"W %x %x",i,j);
	monow(21*160,str);
	*/
}


int fxkeys()
{
	unsigned char c;
	if (kbhit()) c=getch(); else return 0;
	if (c!=0) return c;
	c=getch();
	switch (c)
	{
	case 59:CFEEDBACK-=0.05;break;
	case 60:CFEEDBACK+=0.05;break;
	case 61:DATAMIX-=0.05;break;
	case 62:DATAMIX+=0.05;break;
	case 63:COMBMIX-=0.05;break;
	case 64:COMBMIX+=0.05;break;
	case 65:DELAYMIX-=0.05;break;
	case 66:DELAYMIX+=0.05;break;
	case 'H':
	case 'P':
		fxon=!fxon;
		break;
	case 'K':
		//MIDASsetPosition(playHandle,curord-1);
		break;
	case 'M':
		//MIDASsetPosition(playHandle,curord+1);
		break;

	}

	unsigned char str[256];
	sprintf((char*)str,"combfbk=%4.2f data=%4.2f comb=%4.2f delay=%4.2f ",CFEEDBACK,DATAMIX,COMBMIX,DELAYMIX);
	monow(20*160,str);

	return 0;
}


void CALLBACK intcalc(void *vdata, unsigned numSamples, void *user)
{
	if (!fxon) return;
	if (!numSamples) return;
	int *data=(int*)vdata;
	int ol,or,co,cp;
	while (numSamples--)
	{
		co=icomb[combpos];
		cp=icomb[combpos+1];

		icomb[combpos]=(CFEEDBACK*cp)+data[0];
		ol=data[1]*DATAMIX+co*COMBMIX+idelay[delaypos]*DELAYMIX;


		icomb[combpos+1]=(CFEEDBACK*co)+data[1];
		or=data[0]*DATAMIX+co*COMBMIX+idelay[delaypos+1]*DELAYMIX;

		*data++=idelay[delaypos]=ol;
		*data++=idelay[delaypos+1]=or;

		combpos=(combpos+2);while (combpos>=COMB) combpos-=COMB;
		delaypos=(delaypos+2);while (delaypos>=DELAY) delaypos-=DELAY;
	}
}


void CALLBACK floatcalc(void *vdata, unsigned numSamples, void *user)
{
	if (!fxon) return;
	if (!numSamples) return;
	float *data=(float*)vdata;
	float ol,or,co,cp;
	while (numSamples--)
	{
		co=fcomb[combpos];
		cp=fcomb[combpos+1];
		fcomb[combpos]=(CFEEDBACK*cp)+data[0];
		ol=data[1]*DATAMIX+co*COMBMIX+fdelay[delaypos]*DELAYMIX;


		fcomb[combpos+1]=(CFEEDBACK*co)+data[1];
		or=data[0]*DATAMIX+co*COMBMIX+fdelay[delaypos+1]*DELAYMIX;

		*data++=fdelay[delaypos]=ol;
		*data++=fdelay[delaypos+1]=or;

		combpos=(combpos+2);while (combpos>=COMB) combpos-=COMB;
		delaypos=(delaypos+2);while (delaypos>=DELAY) delaypos-=DELAY;
	}
}


void initfx()
{
#ifndef NOMUS
	if (!fxon || nosnd) return;

//W32TODO 	memset(&mpp,0,sizeof(mpp));
//W32TODO 	mpp.floatStereo=floatcalc;
//W32TODO 	mpp.intStereo=intcalc;

	int mr=44100;//MIDASgetOption(MIDAS_OPTION_MIXRATE);
	if (mr<=0) mr=22049;
	COMB=mr/172;
	DELAY=(mr*60*3/4)/BPM;
	icomb=new int[COMB];memset(icomb,0,4*COMB);
	idelay=new int[DELAY];memset(idelay,0,4*DELAY);
	printf("mixrate = %dHz  comb = %0.1fms  delay = %0.1fms\n",mr,COMB/(mr*0.002f),DELAY/(mr*0.002f));
	//W32TODO fxon=MIDASaddPostProcessor(&mpp,MIDAS_POST_PROC_FIRST,NULL);


#endif
}

void closefx()
{
#ifndef NOMUS
	if (!fxon || nosnd) return;
	//MIDASremovePostProcessor(&mpp);
	//MIDASsetMusicSyncCallback(playHandle, NULL);
	delete [] icomb;
	delete [] idelay;
#endif
}