
/*
SFXR = CreateSfxr(
16, //Bitrate
44100,  //SampleRate
0.4, // SoundVolume
2, // WaveType
0.71243950240000004 , // BaseFrequency
0.8169000000000001, // MinFrequency
0.061040000000000004 ,// FrequencySlide
0, // FrequencySlideDelta
0.15325,// SquareDuty
0,// SquareDutySweep
0.08567999999999999,// VibratoDepth
0.07175999999999999,// VibratoSpeed
0,// VibratoDelay
0,// Attack=0
0.20008,// Sustain=
0.7758799999999999,// Decay
0.37835,// Release
false,// Filter
1,// LowPassFilterCutoff
0,// LowPassFilterCutoffSweep
0, // Filter Resonance
0.13871999999999998, // HighPassFilterCutoff
0,// HighPassFilterCutoffSweep
0.46077000000000007,// PhaserOffset
0.13242,// PhaserOffsetSweep
0,// RepeatSpeed
0,// Arpeggio=
0  // ArpeggioSpeed

);
//Abort(SFXR.getWaveType());

SFX = SFXR.getSoundEffect(0);

SFX.play();

Abort('testme')

*/
/*
A = {
	n: 1,
	valueOf: function(){ return this.n;}
}

function BO(){
	if(this instanceof BO== false) {
		return new BO();
	}
	this.n = 6;
	this.valueOf = function(){return this.n}
}

B = new BO();


Abort (A + B + 2);

Q = GetGlobalConfiguration(A);
Abort(Q);

obj.valueOf()

if(IsKeyPressed({A:"29"})) Abort('www')
*/


RequireScript('buttons.js');
RequireScript('sliders.js');
RequireScript('digitharia.js');
RequireScript('digitharia_mouse.js');
RequireScript('objects.js');
LL = OpenLog("LL")

SFXR = CreateSfxr(16,44100);
//Abort(SFXR.getWaveType());

SFX = SFXR.getSoundEffect(0);


// Array to hold buttons to display
var DISPLAYBUTTONS = new Array();
var DISPLAYSLIDERS = new Array();
function registerBasicButton(button){
	for (var i = 0, len = arguments.length; i < len; i++){
		button = arguments[i];
		DISPLAYBUTTONS.push(button);

		IE.addClick(MOUSE_LEFT,
			button.x,
			button.y,
			button.x2,
			button.y2,
			function(){ this.that.setPressed(true); this.that.action();},
			function(){ this.that.setPressed(false);},
			function(){ this.that.setPressed(true); this.that.action();},
			undefined,
			function(){ this.that.setPressed(true); this.that.action();},
			undefined,
			function(){ this.that.setOver(true);},
			function(){ this.that.setOver(false);},
			button
		);
	}
}

function registerSlider(slider){
	for (var i = 0, len = arguments.length; i < len; i++){
		slider = arguments[i];
		DISPLAYSLIDERS.push(slider);
		IE.addClick(MOUSE_LEFT,
			slider.x,
			slider.y,
			slider.x2,
			slider.y2,
			function(){ LL.write('PRESSDOWN'); this.that.setPressed(true); this.that.action();},
			function(){ LL.write('LIFTUP'); this.that.setPressed(false);},
			function(){ this.that.setPressed(true); this.that.action();},
			undefined,
			function(){ this.that.setPressed(true); this.that.action();},
			undefined,
			function(){ this.that.setOver(true);},
			function(){ this.that.setOver(false);},
			slider,
			slider.name
		);
	}
}
function displayBasicButtons() { for (var i = DISPLAYBUTTONS.length-1; i >=0; --i){ DISPLAYBUTTONS[i].display(); } }
function displaySliders() { for (var i = DISPLAYSLIDERS.length-1; i >=0; --i){ DISPLAYSLIDERS[i].display(); } }

var W = 0;
var font = GetSystemFont();
var m9 = LoadFont('mistress9.rfn');
slider = LoadSurface('slider48.png');
aqua = LoadWindowStyle('aqua.rws');
sliderball = LoadSurface('ball.png'); sliderball.rescale(8,8); sliderball = sliderball.createImage();


MOUSE_LEFT = 0
MOUSE_RIGHT = 1
MOUSE_MIDDLE = 2

var MasterVolume = SFXR.getMasterVolume();
var SoundVolume = SFXR.getSoundVolume();
var Bitrate = SFXR.getBitrate(); // 16 or 8 bits
var SampleRate = SFXR.getSampleRate(); // 44100 
var WaveType = SFXR.getWaveType(); // SQUAREWAVE, SAWTOOTH, SINEWAVE, NOISE
var BaseFrequency = SFXR.getBaseFrequency();
var MinFrequency = SFXR.getMinFrequency();
var FrequencySlide = SFXR.getFrequencySlide();
var FrequencySlideDelta = SFXR.getFrequencySlideDelta();
var SquareDuty = SFXR.getSquareDuty();
var SquareDutySweep = SFXR.getSquareDutySweep();
var VibratoDepth = SFXR.getVibratoDepth();
var VibratoSpeed = SFXR.getVibratoSpeed();
var VibratoDelay = SFXR.getVibratoDelay();
var Attack = SFXR.getAttack();
var Sustain = SFXR.getSustain();
var Release = SFXR.getRelease();
var Decay = SFXR.getDecay();
var Filter = SFXR.getFilter();
var LowPassFilterCutoff = SFXR.getLowPassFilterCutoff();
var LowPassFilterCutoffSweep = SFXR.getLowPassFilterCutoffSweep();
var FilterResonance = SFXR.getFilterResonance();
var HighPassFilterCutoff = SFXR.getHighPassFilterCutoff();
var HighPassFilterCutoffSweep = SFXR.getHighPassFilterCutoffSweep();
var PhaserOffset = SFXR.getPhaserOffset();
var PhaserOffsetSweep = SFXR.getPhaserOffsetSweep();
var RepeatSpeed = SFXR.getRepeatSpeed();
var Arpeggio = SFXR.getArpeggio();
var ArpeggioSpeed = SFXR.getArpeggioSpeed();

// unselect all wavetypes
function deselectWaves(){
	WaveType0.setSelected(false);
	WaveType1.setSelected(false);
	WaveType2.setSelected(false);
	WaveType3.setSelected(false);
}

function AdjustSliderButton(slider, value){
	if(slider.value == Attack)
		return;
	slider.setValue(value);
	IE.MOUSEACTION[MOUSE_LEFT][slider.name].x1 = slider.x;
	IE.MOUSEACTION[MOUSE_LEFT][slider.name].y1 = slider.y;
	IE.MOUSEACTION[MOUSE_LEFT][slider.name].x2 = slider.x2;
	IE.MOUSEACTION[MOUSE_LEFT][slider.name].y2 = slider.y2;
	
}

function updateSliders(){
	var s;
	for (var i = DISPLAYSLIDERS.length-1; i >=0; --i){ 
		s = DISPLAYSLIDERS[i];
		switch(s.name){
			case "Attack Time": AdjustSliderButton(s, Attack); break;
			case "Sustain Time": AdjustSliderButton(s, Sustain); break;
			case "Sustain Punch": AdjustSliderButton(s, Release); break;
			case "Decay Time": AdjustSliderButton(s, Decay); break;
			case "Start Frequency": AdjustSliderButton(s, BaseFrequency); break;
			case "Min Frequency": AdjustSliderButton(s, MinFrequency); break;
			case "Slide": AdjustSliderButton(s, FrequencySlide); break;
			case "Delta Slide": AdjustSliderButton(s, FrequencySlideDelta); break;
			case "Vibrato Depth": AdjustSliderButton(s, VibratoDepth); break;
			case "Vibrato Speed": AdjustSliderButton(s, VibratoSpeed); break;
			case "Vibrato Delay": AdjustSliderButton(s, VibratoDelay); break;

			case "Square Duty": AdjustSliderButton(s, SquareDuty); break;
			case "Duty Sweep": AdjustSliderButton(s, SquareDutySweep); break;
			case "Repeat Speed": AdjustSliderButton(s, RepeatSpeed); break;
			case "Phaser Offset": AdjustSliderButton(s, PhaserOffset); break;
			case "Phaser Sweep": AdjustSliderButton(s, PhaserOffsetSweep); break;
			case "LP Cutoff": AdjustSliderButton(s, LowPassFilterCutoff); break;
			case "LP Cutoff Sweep": AdjustSliderButton(s, LowPassFilterCutoffSweep); break;
			case "LP Resonance": AdjustSliderButton(s, FilterResonance); break;
			case "HP Cutoff": AdjustSliderButton(s, HighPassFilterCutoff); break;
			case "HP Cutoff Sweep": AdjustSliderButton(s, HighPassFilterCutoffSweep); break;

		}
	}

}

function updateSFXR(){
	SFXR.setMasterVolume(MasterVolume);
	
	SFXR.setSoundVolume(SoundVolume);
	SFXR.setBitrate(Bitrate);
	SFXR.setSampleRate(SampleRate); // 44100 
	SFXR.setWaveType(WaveType); // SQUAREWAVE, SAWTOOTH, SINEWAVE, NOISE
	SFXR.setBaseFrequency(BaseFrequency);
	SFXR.setMinFrequency(MinFrequency);
	SFXR.setFrequencySlide(FrequencySlide);
	SFXR.setFrequencySlideDelta(FrequencySlideDelta);
	SFXR.setSquareDuty(SquareDuty);
	SFXR.setSquareDutySweep(SquareDutySweep);
	SFXR.setVibratoDepth(VibratoDepth);
	SFXR.setVibratoSpeed(VibratoSpeed);
	SFXR.setVibratoDelay(VibratoDelay);
	SFXR.setAttack(Attack);
	SFXR.setSustain(Sustain);
	SFXR.setRelease(Release);
	SFXR.setDecay(Decay);
	SFXR.setFilter(Filter);
	SFXR.setLowPassFilterCutoff(LowPassFilterCutoff);
	SFXR.setLowPassFilterCutoffSweep(LowPassFilterCutoffSweep);
	SFXR.setFilterResonance(FilterResonance);
	SFXR.setHighPassFilterCutoff(HighPassFilterCutoff);
	SFXR.setHighPassFilterCutoffSweep(HighPassFilterCutoffSweep);
	SFXR.setPhaserOffset(PhaserOffset);
	SFXR.setPhaserOffsetSweep(PhaserOffsetSweep);
	SFXR.setRepeatSpeed(RepeatSpeed);
	SFXR.setArpeggio(Arpeggio);
	SFXR.setArpeggioSpeed(ArpeggioSpeed);
	
	LL.write("*** SAMPLESIZE="+SFXR.getSampleSize());
	
	LL.write(MasterVolume+"=MasterVolume="+SFXR.getMasterVolume());
	LL.write(SoundVolume+"=SoundVolume="+SFXR.getSoundVolume());
	LL.write(Bitrate+"=Bitrate="+SFXR.getBitrate());
LL.write(SampleRate+"=SampleRate="+SFXR.getSampleRate());
LL.write(WaveType+"=WaveType="+SFXR.getWaveType());
LL.write(BaseFrequency+"=BaseFrequency="+SFXR.getBaseFrequency());
LL.write(MinFrequency+"=MinFrequency="+SFXR.getMinFrequency());
LL.write(FrequencySlide+"=FrequencySlide="+SFXR.getFrequencySlide());
LL.write(FrequencySlideDelta+"=FrequencySlideDelta="+SFXR.getFrequencySlideDelta());
LL.write(SquareDuty+"=SquareDuty="+SFXR.getSquareDuty());
LL.write(SquareDutySweep+"=SquareDutySweep="+SFXR.getSquareDutySweep());
LL.write(VibratoDepth+"=VibratoDepth="+SFXR.getVibratoDepth());
LL.write(VibratoSpeed+"=VibratoSpeed="+SFXR.getVibratoSpeed());
LL.write(VibratoDelay+"=VibratoDelay="+SFXR.getVibratoDelay());
LL.write(Attack+"=Attack="+SFXR.getAttack());
LL.write(Sustain+"=Sustain="+SFXR.getSustain());
LL.write(Release+"=Release="+SFXR.getRelease());
LL.write(Decay+"=Decay="+SFXR.getDecay());
LL.write(Filter+"=Filter="+SFXR.getFilter());
LL.write(LowPassFilterCutoff+"=LowPassFilterCutoff="+SFXR.getLowPassFilterCutoff());
LL.write(LowPassFilterCutoffSweep+"=LowPassFilterCutoffSweep="+SFXR.getLowPassFilterCutoffSweep());
LL.write(FilterResonance+"=FilterResonance="+SFXR.getFilterResonance());
LL.write(HighPassFilterCutoff+"=HighPassFilterCutoff="+SFXR.getHighPassFilterCutoff());
LL.write(HighPassFilterCutoffSweep+"=HighPassFilterCutoffSweep="+SFXR.getHighPassFilterCutoffSweep());
LL.write(PhaserOffset+"=PhaserOffset="+SFXR.getPhaserOffset());
LL.write(PhaserOffsetSweep+"=PhaserOffsetSweep="+SFXR.getPhaserOffsetSweep());
LL.write(RepeatSpeed+"=RepeatSpeed="+SFXR.getRepeatSpeed());
LL.write(Arpeggio+"=Arpeggio="+SFXR.getArpeggio());
LL.write(ArpeggioSpeed+"=ArpeggioSpeed="+SFXR.getArpeggioSpeed());

}

function ResetParams(){
	SFXR.reset();
	MasterVolume = SFXR.getMasterVolume();
	SoundVolume = SFXR.getSoundVolume();
	Bitrate = SFXR.getBitrate(); // 16 or 8 bits
	SampleRate = SFXR.getSampleRate(); // 44100 
	WaveType = SFXR.getWaveType(); // SQUAREWAVE, SAWTOOTH, SINEWAVE, NOISE
	BaseFrequency = SFXR.getBaseFrequency();
	MinFrequency = SFXR.getMinFrequency();
	FrequencySlide = SFXR.getFrequencySlide();
	FrequencySlideDelta = SFXR.getFrequencySlideDelta();
	SquareDuty = SFXR.getSquareDuty();
	SquareDutySweep = SFXR.getSquareDutySweep();
	VibratoDepth = SFXR.getVibratoDepth();
	VibratoSpeed = SFXR.getVibratoSpeed();
	VibratoDelay = SFXR.getVibratoDelay();
	Attack = SFXR.getAttack();
	Sustain = SFXR.getSustain();
	Release = SFXR.getRelease();
	Decay = SFXR.getDecay();
	Filter = SFXR.getFilter();
	LowPassFilterCutoff = SFXR.getLowPassFilterCutoff();
	LowPassFilterCutoffSweep = SFXR.getLowPassFilterCutoffSweep();
	FilterResonance = SFXR.getFilterResonance();
	HighPassFilterCutoff = SFXR.getHighPassFilterCutoff();
	HighPassFilterCutoffSweep = SFXR.getHighPassFilterCutoffSweep();
	PhaserOffset = SFXR.getPhaserOffset();
	PhaserOffsetSweep = SFXR.getPhaserOffsetSweep();
	RepeatSpeed = SFXR.getRepeatSpeed();
	Arpeggio = SFXR.getArpeggio();
	ArpeggioSpeed = SFXR.getArpeggioSpeed();
	
	BR.setlabel(Bitrate+" bits");
	SR.setlabel(SampleRate+" hz");

}

// Math definitions
function clamp(v,l,h) {return v<l?l:v>h?h:v;} // Force value v between lower l and upper h boundaries
const RAND_MAX = 32767;  // C++ rand = function(){return Math.floor(Math.random()*RAND_MAX)}
function rnd(n) {return Math.floor(Math.random()*RAND_MAX)%(n+1);}
function frnd(range) {return rnd(10000)/10000*range;}
function pow(a,b) {return Math.pow(a,b);}


function AutoPlay(){
	updateSFXR();
	if(SFXR.getSampleSize()>1){
		SFX = SFXR.getSoundEffect(0);
		SFX.play();
	}
	GarbageCollect();
}

// Functions for random sound generation
Generator = {
	pickup: function(){
		ResetParams();
		BaseFrequency = 0.4 + frnd(0.5);
		Attack = 0.0;
		Sustain = frnd(0.1);
		Release = 0.1 + frnd(0.4);
		Decay = 0.3 + frnd(0.3);
		if(rnd(1)){
			Arpeggio = 0.5 + frnd(0.2);
			ArpeggioSpeed = 0.2 + frnd(0.4);
		}
		AutoPlay();
	},
	laser: function(){
		ResetParams();
		wave_type = rnd(2);
		if(wave_type == 2 && rnd(1))
			wave_type = rnd(1);
		BaseFrequency = 0.5 + frnd(0.5);
		MinFrequency = BaseFrequency - 0.2 - frnd(0.6);
		if(MinFrequency < 0.2) MinFrequency = 0.2;
		FrequencySlide = -0.15 - frnd(0.2);
		if(rnd(2) == 0) {
			BaseFrequency = 0.3 + frnd(0.6);
			MinFrequency = frnd(0.1);
			FrequencySlide = -0.35 - frnd(0.3);
		}
		if(rnd(1)) {
			SquareDuty = frnd(0.5);
			SquareDuty_ramp = frnd(0.2);
		} else {
			SquareDuty = 0.4 + frnd(0.5);
			SquareDuty_ramp = -frnd(0.7);
		}
		Attack = 0.0;
		Sustain = 0.1 + frnd(0.2);
		Release = frnd(0.4);
		if(rnd(1))
			Decay = frnd(0.3);
		if(rnd(2) == 0) {
			PhaserOffset = frnd(0.2);
			PhaserOffsetSweep = -frnd(0.2);
		}
		if(rnd(1))
			HighPassFilterCutoff = frnd(0.3);
		AutoPlay()
	},
	explosion: function(){
		ResetParams();
                                wave_type=3;
                                if(rnd(1))
                                {
                                        BaseFrequency=0.1+frnd(0.4);
                                        FrequencySlide=-0.1+frnd(0.4);
                                }
                                else
                                {
                                        BaseFrequency=0.2+frnd(0.7);
                                        FrequencySlide=-0.2-frnd(0.2);
                                }
                                BaseFrequency*=BaseFrequency;
                                if(rnd(4)==0)
                                        FrequencySlide=0.0;
                                if(rnd(2)==0)
                                        RepeatSpeed=0.3+frnd(0.5);
                                Attack=0.0;
                                Sustain=0.1+frnd(0.3);
                                Release=frnd(0.5);
                                if(rnd(1)==0)
                                {
                                        PhaserOffset=-0.3+frnd(0.9);
                                        PhaserOffsetSweep=-frnd(0.3);
                                }
                                Decay=0.2+frnd(0.6);
                                if(rnd(1))
                                {
                                        VibratoDepth=frnd(0.7);
                                        VibratoSpeed=frnd(0.6);
                                }
                                if(rnd(2)==0)
                                {
                                        Arpeggio=0.6+frnd(0.3);
                                        ArpeggioSpeed=0.8-frnd(1.6);
                                }
		AutoPlay();
	},

	powerup: function(){
		ResetParams();
                                if(rnd(1))
                                        wave_type=1;
                                else
                                        SquareDuty=frnd(0.6);
                                if(rnd(1))
                                {
                                        BaseFrequency=0.2+frnd(0.3);
                                        FrequencySlide=0.1+frnd(0.4);
                                        RepeatSpeed=0.4+frnd(0.4);
                                }
                                else
                                {
                                        BaseFrequency=0.2+frnd(0.3);
                                        FrequencySlide=0.05+frnd(0.2);
                                        if(rnd(1))
                                        {
                                                VibratoDepth=frnd(0.7);
                                                VibratoSpeed=frnd(0.6);
                                        }
                                }
                                Attack=0.0;
                                Sustain=frnd(0.4);
                                Release=0.1+frnd(0.4);
		AutoPlay()
	},
	hit: function(){
		ResetParams();
                                wave_type=rnd(2);
                                if(wave_type==2)
                                        wave_type=3;
                                if(wave_type==0)
                                        SquareDuty=frnd(0.6);
                                BaseFrequency=0.2+frnd(0.6);
                                FrequencySlide=-0.3-frnd(0.4);
                                Attack=0.0;
                                Sustain=frnd(0.1);
                                Release=0.1+frnd(0.2);
                                if(rnd(1))
                                        HighPassFilterCutoff=frnd(0.3);
		AutoPlay()
	},
	jump: function(){
		ResetParams();
                                wave_type=0;
                                SquareDuty=frnd(0.6);
                                BaseFrequency=0.3+frnd(0.3);
                                FrequencySlide=0.1+frnd(0.2);
                                Attack=0.0;
                                Sustain=0.1+frnd(0.3);
                                Release=0.1+frnd(0.2);
                                if(rnd(1))
                                        HighPassFilterCutoff=frnd(0.3);
                                if(rnd(1))
                                        LowPassFilterCutoffSweep=1.0-frnd(0.6);
		AutoPlay()
	},
	blip: function(){
		ResetParams();
                                wave_type=rnd(1);
                                if(wave_type==0)
                                        SquareDuty=frnd(0.6);
                                BaseFrequency=0.2+frnd(0.4);
                                Attack=0.0;
                                Sustain=0.1+frnd(0.1);
                                Release=frnd(0.2);
                                HighPassFilterCutoff=0.1;
		AutoPlay()
	},
	mutate: function(){
                if(rnd(1)) BaseFrequency+=frnd(0.1)-0.05;
//              if(rnd(1)) MinFrequency+=frnd(0.1)-0.05;
                if(rnd(1)) FrequencySlide+=frnd(0.1)-0.05;
                if(rnd(1)) FrequencySlideDelta+=frnd(0.1)-0.05;
                if(rnd(1)) SquareDuty+=frnd(0.1)-0.05;
                if(rnd(1)) SquareDuty_ramp+=frnd(0.1)-0.05;
                if(rnd(1)) VibratoDepth+=frnd(0.1)-0.05;
                if(rnd(1)) VibratoSpeed+=frnd(0.1)-0.05;
                if(rnd(1)) VibratoDelay+=frnd(0.1)-0.05;
                if(rnd(1)) Attack+=frnd(0.1)-0.05;
                if(rnd(1)) Sustain+=frnd(0.1)-0.05;
                if(rnd(1)) Release+=frnd(0.1)-0.05;
                if(rnd(1)) Decay+=frnd(0.1)-0.05;
                if(rnd(1)) FilterResonance+=frnd(0.1)-0.05;
                if(rnd(1)) LowPassFilterCutoffSweep+=frnd(0.1)-0.05;
                if(rnd(1)) LowPassFilterCutoff+=frnd(0.1)-0.05;
                if(rnd(1)) HighPassFilterCutoff+=frnd(0.1)-0.05;
                if(rnd(1)) HighPassFilterCutoffSweep+=frnd(0.1)-0.05;
                if(rnd(1)) PhaserOffset+=frnd(0.1)-0.05;
                if(rnd(1)) PhaserOffsetSweep+=frnd(0.1)-0.05;
                if(rnd(1)) RepeatSpeed+=frnd(0.1)-0.05;
                if(rnd(1)) Arpeggio+=frnd(0.1)-0.05;
                if(rnd(1)) ArpeggioSpeed+=frnd(0.1)-0.05;
		AutoPlay();
	},
	randomize: function(){
               BaseFrequency=pow(frnd(2.0)-1.0, 2.0);
                if(rnd(1))
                        BaseFrequency=pow(frnd(2.0)-1.0, 3.0)+0.5;
                MinFrequency=0.0;
                FrequencySlide=pow(frnd(2.0)-1.0, 5.0);
                if(BaseFrequency>0.7 && FrequencySlide>0.2)
                        FrequencySlide=-FrequencySlide;
                if(BaseFrequency<0.2 && FrequencySlide<-0.05)
                        FrequencySlide=-FrequencySlide;
                FrequencySlideDelta=pow(frnd(2.0)-1.0, 3.0);
                SquareDuty=frnd(2.0)-1.0;
                SquareDuty_ramp=pow(frnd(2.0)-1.0, 3.0);
                VibratoDepth=pow(frnd(2.0)-1.0, 3.0);
                VibratoSpeed=frnd(2.0)-1.0;
                VibratoDecay=frnd(2.0)-1.0;
                Attack=pow(frnd(2.0)-1.0, 3.0);
                Sustain=pow(frnd(2.0)-1.0, 2.0);
                Release=frnd(2.0)-1.0;
                Decay=pow(frnd(0.8), 2.0);
                if(Attack+Sustain+Release<0.2)
                {
                        Sustain+=0.2+frnd(0.3);
                        Release+=0.2+frnd(0.3);
                }
                FilterResonance=frnd(2.0)-1.0;
                LowPassFilterCutoffSweep=1.0-pow(frnd(1.0), 3.0);
                LowPassFilterCutoff=pow(frnd(2.0)-1.0, 3.0);
                if(LowPassFilterCutoffSweep<0.1 && LowPassFilterCutoff<-0.05)
                        LowPassFilterCutoff=-LowPassFilterCutoff;
                HighPassFilterCutoff=pow(frnd(1.0), 5.0);
                HighPassFilterCutoffSweep=pow(frnd(2.0)-1.0, 5.0);
                PhaserOffset=pow(frnd(2.0)-1.0, 3.0);
                PhaserOffsetSweep=pow(frnd(2.0)-1.0, 3.0);
                RepeatSpeed=frnd(2.0)-1.0;
                Arpeggio=frnd(2.0)-1.0;
                ArpeggioSpeed=frnd(2.0)-1.0;
		AutoPlay()
	},
}


function Digits(n,wide){
	var retval = "";
	var d=10;
	while(--wide>0){
		if(n<d) retval += "0";
		d*=10;
	}
	return retval + n;
}

function chr(asciicode) { return String.fromCharCode(asciicode); }
function ord(charstring) { return charstring.charCodeAt(0); }

function game(){

	IE = new InputEngine();
	IE.InitMouse();
	IE.addKey(KEY_SPACE, 
		function(){ P.setPressed(true); AutoPlay();},
		function(){ P.setPressed(false); }
	);
	IE.addKey(KEY_ESCAPE,  function(){Exit();});
	IE.addKey(KEY_G,  function(){GarbageCollect ();});
	//SetFrameRate(60);
	// Define buttons
	E = new BasicButton({ x:GetScreenWidth()-35, y:0,  name: "X", label: "Quit", action:function(){Exit();}  }); 
	WaveType0 = new BasicButton({ x:70,              y:14, label:"SquareWave", font:m9, action:function(){WaveType=0;deselectWaves();this.setSelected(1);} });
	WaveType1 = new BasicButton({ x:WaveType0.x2+10, y:14, label:"SawTooth",   font:m9, action:function(){WaveType=1;deselectWaves();this.setSelected(1);} });
	WaveType2 = new BasicButton({ x:WaveType1.x2+10, y:14, label:"SineWave",   font:m9, action:function(){WaveType=2;deselectWaves();this.setSelected(1);} });
	WaveType3 = new BasicButton({ x:WaveType2.x2+10, y:14, label:"Noise",      font:m9, action:function(){WaveType=3;deselectWaves();this.setSelected(1);} });
	if(WaveType == 0)
		WaveType0.setSelected(1);
	else if(WaveType == 1)
		WaveType1.setSelected(1);
	else if(WaveType == 2)
		WaveType2.setSelected(1);
	else if(WaveType == 3)
		WaveType3.setSelected(1);

	G1 = new BasicButton({ x:1, y:20, label:"Pickup/Coin", font:m9, action:Generator.pickup });
	G2 = new BasicButton({ x:1, y:35, label:"Laser/Shoot", font:m9, action:Generator.laser });
	G3 = new BasicButton({ x:1, y:50, label:"Explosion",   font:m9, action:Generator.explosion });
	G4 = new BasicButton({ x:1, y:65, label:"Powerup",     font:m9, action:Generator.powerup });
	G5 = new BasicButton({ x:1, y:80, label:"Hit/Hurt",    font:m9, action:Generator.hit });
	G6 = new BasicButton({ x:1, y:95, label:"Jump",        font:m9, action:Generator.jump });
	G7 = new BasicButton({ x:1, y:110,label:"Blip/Select", font:m9, action:Generator.blip });
	GM = new BasicButton({ x:1, y:200,label:"Mutate",      font:m9, action:Generator.mutate});
	GR = new BasicButton({ x:1, y:215,label:"Randomize",   font:m9, action:Generator.randomize});

	RESET = new BasicButton({ x:1, y:135,label:"Reset",   font:m9, action:function(){SFXR.reset(); ResetParams(); } });

	BR = new BasicButton({ x:4, y:150,label:"16 bits",   font:m9, action:function(){Bitrate= Bitrate>10? 8:16;this.label=Bitrate+" bits";} });
	SR = new BasicButton({ x:4, y:165,label:"44100 hz",   font:m9, action:function(){
		SampleRate= SampleRate==8000?11000: SampleRate==11000? 22500: SampleRate==22500? 44100: 8000;this.label=SampleRate+" hz";
	} });


	Vm = new BasicButton({ x:64,    y:GetScreenHeight()-15, borderX:2, borderY:0, label: "-", action: function(){MasterVolume = clamp(Math.floor(255*MasterVolume-1),0,255)/255} });
	Vp = new BasicButton({ x:64+28, y:GetScreenHeight()-15, borderY:0, label: "+", action: function(){MasterVolume = clamp(Math.floor(255*MasterVolume+1),0,255)/255} });
	P = new BasicButton({ x:110, y:GetScreenHeight()-15, borderX:1, borderY:1, label: "Play (space)", action: AutoPlay });
	S = new BasicButton({ x:200, y:GetScreenHeight()-15, borderX:1, borderY:1, label: "Save (javascript)", font:m9, action: saveJSon });
	IE.addKey(KEY_F2, 
		function(){ S.setPressed(true); saveJSon(); },
		function(){ S.setPressed(false); }
	);

	// Register the buttons
	registerBasicButton(E, Vm, Vp, P, S);
	registerBasicButton(WaveType0, WaveType1, WaveType2, WaveType3);
	registerBasicButton(G1, G2, G3, G4, G5, G6, G7, RESET, GM, GR,  BR,SR);

	// Create Background
	var bg = CreateSurface(GetScreenWidth(), GetScreenHeight(), CreateColor(50,50,250,255));
	bg.applyColorFX4(0,0,GetScreenWidth(), GetScreenHeight(),
		CreateColorMatrix(30, 255,0,0, 30, 0,255,0, 30, 0,0,255),
		CreateColorMatrix(0, 255,0,0, 0, 0,255,0, 0, 0,0,255),
		CreateColorMatrix(0, 255,0,0, 0, 0,255,0, 0, 0,0,255),
		CreateColorMatrix(0, 100,0,0, 0, 0,100,0, 0, 0,0,100));

	bg.drawText(m9,   5, 2, "Generator");
	bg.drawText(m9, 100, 2, "Manual Settings");
	bg.line( 60, 0,   60,GetScreenHeight(), CreateColor(20,20,20,255));
	bg.line(187, 35, 187,GetScreenHeight(), CreateColor(20,20,20,255));
	bg.line( 60, 35, GetScreenWidth(), 35, CreateColor(20,20,20,255));

	var txt = [ "Attack Time", "Sustain Time", "Sustain Punch", "Decay Time",
		"Start Frequency", "Min Frequency", "Slide", "Delta Slide", "Vibrato Depth", "Vibrato Speed", "Vibrato Delay",
		"Change Amount", "Change Speed"];
	for(var i=0 ; i<txt.length ; ++i){
		bg.blitSurface(slider,62,40+13*i);
		bg.drawText(m9, 112, 38+i*13, txt[i]);
		if(txt[i] == "Slide" || txt[i] == "Delta Slide")
			var s = new Slider({ x:64, y:38+13*i, ball:sliderball, min:-1, max:1, x_min:62, x_max:62+48-8,  name:txt[i], action:function(){} });
		else
			var s = new Slider({ x:64, y:38+13*i, ball:sliderball, min:0, max:1, x_min:62, x_max:62+48-8,  name:txt[i], action:function(){} });
		registerSlider(s);

	}
	bg.line(60 , 87 , 187, 87, CreateColor(20,20,20,255));
	bg.line(60 , 165 , 187, 165, CreateColor(20,20,20,255));

	var txt = [ "Square Duty", "Duty Sweep", "Repeat Speed", "Phaser Offset", "Phaser Sweep" ];
	for(var i=0 ; i<txt.length ; ++i){
		bg.blitSurface(slider,190,40+13*i);
		bg.drawText(m9, 190+50, 38+i*13, txt[i]);
		if(txt[i] == "Square Duty" || txt[i] == "Repeat Speed")
			var s = new Slider({ x:192, y:38+13*i, ball:sliderball, min:0, max:1, x_min:190, x_max:190+48-8,  name:txt[i], action:function(){} });
		else
			var s = new Slider({ x:192, y:38+13*i, ball:sliderball, min:-1, max:1, x_min:190, x_max:190+48-8,  name:txt[i], action:function(){} });
		registerSlider(s);
	}
	bg.line(187 , 100 , GetScreenWidth(), 100, CreateColor(20,20,20,255));
	bg.drawText(m9, 218,102, "Low Pass Filter");

	var txt = [ "LP Cutoff", "LP Cutoff Sweep", "LP Resonance" ];
	for(var i=0 ; i<txt.length ; ++i){
		bg.blitSurface(slider,190,117+13*i);
		bg.drawText(m9, 190+50, 115+i*13, txt[i]);
		if(txt[i] == "LP Cutoff Sweep")
			var s = new Slider({ x:192, y:115+13*i, ball:sliderball, min:-1, max:1, x_min:190, x_max:190+48-8,  name:txt[i], action:function(){} });
		else
			var s = new Slider({ x:192, y:115+13*i, ball:sliderball, min:0, max:1, x_min:190, x_max:190+48-8,  name:txt[i], action:function(){} });
		registerSlider(s);
	}
	bg.drawText(m9, 218,154, "High Pass Filter");
	var txt = [ "HP Cutoff", "HP Cutoff Sweep" ];
	for(var i=0 ; i<txt.length ; ++i){
		bg.blitSurface(slider,190,169+13*i);
		bg.drawText(m9, 190+50, 167+i*13, txt[i]);
		if(txt[i] == "HP Cutoff Sweep")
			var s = new Slider({ x:192, y:167+13*i, ball:sliderball, min:-1, max:1, x_min:190, x_max:190+48-8,  name:txt[i], action:function(){} });
		else
			var s = new Slider({ x:192, y:167+13*i, ball:sliderball, min:0, max:1, x_min:190, x_max:190+48-8,  name:txt[i], action:function(){} });
		registerSlider(s);
	}


	bg.drawText(m9, 60,GetScreenHeight()-25, chr(30) + "- Volume " + chr(31));
	bg.drawText(font, 0,GetScreenHeight()-10, "SFXR 0.3");
	bg = bg.createImage();

	var endgame = false;
	while(!endgame){
		bg.blit(0,0);
		IE.handleMouseInput();
		IE.handleKeyboardInput();
		//aqua.drawWindow(16,32,60,170);
		//sliderball.zoomBlit(30,10-5, 0.5);
		//font.drawText(0,GetScreenHeight()-10, W + "("+IE.mouseX+","+IE.mouseY+")");
		m9.drawText(64+11, GetScreenHeight()-13, Digits(Math.floor(MasterVolume*255),3));

		displayBasicButtons();
		updateSliders();
		displaySliders();

		IE.DisplayMouse();
		FlipScreen();
	}
}


function saveJSon(){
	RequireSystemScript('input.js')
	var h = GetScreenWidth()>>1;
	var v = GetScreenHeight()>>1;
	aqua.drawWindow(h-40,v-30,80,16);
	var f = font.clone();
	f.setColorMask(CreateColor(10,10,10));

	m9.setColorMask(CreateColor(10,10,10,100));
	m9.drawText(h-48+2,v-30-18, "Save SFXR File - JSon");
	m9.setColorMask(CreateColor(255,255,255));
	m9.drawText(h-48,v-30-20, "Save SFXR File - JSon");
	while (AreKeysLeft()) {var key = GetKey();} // Empty keybuffer (may have been overflown with spaces)
	var key = GetString(h-48, v-32+4, f, 14, true);
	if(key){
		FH = OpenFile("sfxr.txt");
		FH.write(key,"CreateSfxr(" +
			Bitrate + "," +
			SampleRate + "," +
			SoundVolume + "," +
			WaveType + "," +
			BaseFrequency + "," +
			MinFrequency + "," +
			FrequencySlide + "," +
			FrequencySlideDelta + "," +
			SquareDuty + "," +
			SquareDutySweep + "," +
			VibratoDepth + "," +
			VibratoSpeed + "," +
			VibratoDelay + "," +
			Attack + "," +
			Sustain + "," +
			Decay + "," +
			Release + "," +
			Filter + "," +
			LowPassFilterCutoff + "," +
			LowPassFilterCutoffSweep + "," +
			FilterResonance + "," +
			HighPassFilterCutoff + "," +
			HighPassFilterCutoffSweep + "," +
			PhaserOffset + "," +
			PhaserOffsetSweep + "," +
			RepeatSpeed + "," +
			Arpeggio + "," +
			ArpeggioSpeed + ");"
		);
		FH.close();
	}
}

