
/* Generated by Interface Builder */

#import "LorenzController.h"
#import <appkit/appkit.h>
#import <musickit/musickit.h>
#import "ChaosPlot.h"

#define SXM	25.0
#define SXm	(-25.0)
#define BXM	60.0
#define BXm	(-60.0)
#define SYM	30.0
#define SYm	(-30.0)
#define BYM	80.0
#define BYm	(-80.0)
#define SZM	60.0
#define SZm	0.0
#define BZM	300.0
#define BZm	0.0

#define sSXM	"25"
#define sSXm	"-25"
#define sBXM	"60"
#define sBXm	"-60"
#define sSYM	"30"
#define sSYm	"-30"
#define sBYM	"80"
#define sBYm	"-80"
#define sSZM	"60"
#define sSZm	"0"
#define sBZM	"300"
#define sBZm	"0"


@implementation LorenzController

- initWithPlot:plotter withConductor:conductor
{
	[super init];
	[NXApp loadNibSection:"LorenzControl.nib" owner:self withNames:NO];
	[thePanel makeKeyAndOrderFront:self];
	cPlot = plotter;
	cConductor = conductor;
	[self changePlotMode:sPlotButton];
	return self;
}

- closeUp
{
	[thePanel close];
	return self;
}

- changePlotMode:sender
{
	char *xM, *xl, *xm, *yM, *yl, *ym;

	[Conductor lockPerformance];
	[cConductor emptyQueue];
	[Conductor unlockPerformance];

	switch ([sender selectedTag]) {
		case 0: 
		case 1:
		case 2: plotMode = [sender selectedTag]; break;
		case 3: zoomMode = SMALL; break;
		case 4: zoomMode = LARGE; break;
	}

	switch (plotMode) {
		case XY:
			if (zoomMode == SMALL) { xM=sSXM; xm=sSXm; yM=sSYM; ym=sSYm; }
			else { xM=sBXM; xm=sBXm; yM=sBYM; ym=sBYm; }
			xl="X"; yl="Y";
			break;
		case YZ:
			if (zoomMode == SMALL) { xM=sSYM; xm=sSYm; yM=sSZM; ym=sSZm; }
			else { xM=sBYM; xm=sBYm; yM=sBZM; ym=sBZm; }
			xl="Y"; yl="Z";
			break;
		case XZ:
			if (zoomMode == SMALL) { xM=sSXM; xm=sSXm; yM=sSZM; ym=sSZm; }
			else { xM=sBXM; xm=sBXm; yM=sBZM; ym=sBZm; }
			xl="X"; yl="Z";
			break;
	}
	[cPlot display];
	[cPlot labelPlot:"Lorenz System" Titlefont:[Font newFont:"Helvetica-Oblique" size:18]
		Xmax:xM  Xlabel:xl  Xmin:xm
		Ymax:yM  Ylabel:yl  Ymin:ym
		axisFont:[Font newFont:"Helvetica" size:18]];

	return self;
}

- setUp
{
	X = [sInitValueFields doubleValueAt:0];
	Y = [sInitValueFields doubleValueAt:1];
	Z = [sInitValueFields doubleValueAt:2];
	speed = [sSpeedField floatValue];
	duration = [sDurationField floatValue];
	S = [sSField doubleValue];
	R = [sRField doubleValue];
	B = [sBField doubleValue];
	[self setSoundMode:DSP];
	axisMode = [sAxisButtons selectedTag];
	plotMode = XY;
	delta_T = .01 * (25.0 / R);
	return self;
}

- setSoundMode:(int)mode
{
	switch (soundMode = mode) {
		case DSP:
			[[sFreqBox setTitle:"Frequency (Hz)"] display];
			[sFreqRangeSlider setMinValue:0.0];
			[sFreqRangeSlider setMaxValue:4000.0];
			[sFreqRangeSlider setFloatValue:500.0];
			[sFreqRangeField setFloatValue:500.0];
			[sFreqCenterSlider setMinValue:0.0];
			[sFreqCenterSlider setMaxValue:4000.0];
			[sFreqCenterSlider setFloatValue:500.0];
			[sFreqCenterField setFloatValue:500.0];
			freqRange = [sFreqRangeField floatValue];
			freqCenter = [sFreqCenterField floatValue];
			[[sAmpBox setTitle:"Amplitude (dB)"] display];
			[sAmpRangeSlider setMinValue:0.0];
			[sAmpRangeSlider setMaxValue:60.0];
			[sAmpRangeSlider setFloatValue:30.0];
			[sAmpRangeField setFloatValue:30.0];
			[sAmpCenterSlider setMinValue:-60.0];
			[sAmpCenterSlider setMaxValue:0.0];
			[sAmpCenterSlider setFloatValue:-20.0];
			[sAmpCenterField setFloatValue:-20.0];
			ampRange = [sAmpRangeField floatValue];
			ampCenter = [sAmpCenterField floatValue];
			break;
		case MIDI:
			[[sFreqBox setTitle:"Key"] display];
			[sFreqRangeSlider setMinValue:0.0];
			[sFreqRangeSlider setMaxValue:127.0];
			[sFreqRangeSlider setFloatValue:64.0];
			[sFreqRangeField setFloatValue:64.0];
			[sFreqCenterSlider setMinValue:0.0];
			[sFreqCenterSlider setMaxValue:127.0];
			[sFreqCenterSlider setFloatValue:64.0];
			[sFreqCenterField setFloatValue:64.0];
			freqRange = [sFreqRangeField floatValue];
			freqCenter = [sFreqCenterField floatValue];
			[[sAmpBox setTitle:"Velocity"] display];
			[sAmpRangeSlider setMinValue:0.0];
			[sAmpRangeSlider setMaxValue:127.0];
			[sAmpRangeSlider setFloatValue:64.0];
			[sAmpRangeField setFloatValue:64.0];
			[sAmpCenterSlider setMinValue:0.0];
			[sAmpCenterSlider setMaxValue:127.0];
			[sAmpCenterSlider setFloatValue:64.0];
			[sAmpCenterField setFloatValue:64.0];
			ampRange = [sAmpRangeField floatValue];
			ampCenter = [sAmpCenterField floatValue];
			break;
		default:
			break;
	}
	return self;
}

- changeInitValue:sender
{
	X = [sender doubleValueAt:0];
	Y = [sender doubleValueAt:1];
	Z = [sender doubleValueAt:2];
    return self;
}

- changeDurationField:sender
{
	duration = [sender floatValue];
	[sDurationSlider setFloatValue:duration];
    return self;
}

- changeSpeedField:sender
{
	speed = [sender floatValue];
	if (speed < 0.01) {
		speed = 0.01;
		[sender setFloatValue:speed];
	}
	[sSpeedSlider setFloatValue:speed];
    return self;
}

- changeFreqCenterField:sender
{
	freqCenter = [sender floatValue];
	[sFreqCenterSlider setFloatValue:freqCenter];
    return self;
}

- changeSSlider:sender
{
	S = [sender doubleValue];
	[sSField setDoubleValue:S];
    return self;
}

- changeRSlider:sender
{
	R = [sender doubleValue];
	[sRField setDoubleValue:R];
	delta_T = .01 * (25.0 / R);
    return self;
}

- changeBSlider:sender
{
	B = [sender doubleValue];
	[sBField setDoubleValue:B];
    return self;
}

- changeFreqRangeField:sender
{
	freqRange = [sender floatValue];
	[sFreqRangeSlider setFloatValue:freqRange];
    return self;
}

- changeAmpCenterField:sender
{
	ampCenter = [sender floatValue];
	[sAmpCenterSlider setFloatValue:ampCenter];
    return self;
}

- changeRField:sender
{
	R = [sender doubleValue];
	[sRSlider setDoubleValue:R];
	delta_T = .01 * (25.0 / R);
    return self;
}

- changeSField:sender
{
	S = [sender doubleValue];
	[sSSlider setDoubleValue:S];
    return self;
}

- changeBField:sender
{
	B = [sender doubleValue];
	[sBSlider setDoubleValue:B];
    return self;
}

- changeAmpRangeField:sender
{
	ampRange = [sender floatValue];
	[sAmpRangeSlider setFloatValue:ampRange];
    return self;
}

- changeAmpRangeSlider:sender
{
	ampRange = [sender floatValue];
	[sAmpRangeField setFloatValue:ampRange];
    return self;
}

- changeFreqRangeSlider:sender
{
	freqRange = [sender floatValue];
	[sFreqRangeField setFloatValue:freqRange];
    return self;
}

- changeAmpCenterSlider:sender
{
	ampCenter = [sender floatValue];
	[sAmpCenterField setIntValue:ampCenter];
    return self;
}

- changeSpeedSlider:sender
{
	speed = [sender floatValue];
	[sSpeedField setFloatValue:speed];
    return self;
}

- changeDurationSlider:sender
{
	duration = [sender floatValue];
	[sDurationField setFloatValue:duration];
    return self;
}

- changeFreqCenterSlider:sender
{
	freqCenter = [sender floatValue];
	[sFreqCenterField setFloatValue:freqCenter];
    return self;
}

- changeAxis:sender
{
	axisMode = [sender selectedTag];
    return self;
}


- iterateFreq:(float *)freq Amp:(float *)amp Dur:(float *)dur Next:(float *)next 
	X:(float *)xpos Y:(float *)ypos
{
	double xdot, ydot, zdot;

	switch (plotMode) {
		case XY: 
			if (zoomMode == SMALL) { *xpos = (X-SXm)/(SXM-SXm); *ypos = (Y-SYm)/(SYM-SYm); }
			else { *xpos = (X-BXm)/(BXM-BXm); *ypos = (Y-BYm)/(BYM-BYm); }
			break;
		case YZ:
			if (zoomMode == SMALL) { *xpos = (Y-SYm)/(SYM-SYm); *ypos = (Z-SZm)/(SZM-SZm); }
			else { *xpos = (Y-BYm)/(BYM-BYm); *ypos = (Z-BZm)/(BZM-BZm); }
			break;
		case XZ:
			if (zoomMode == SMALL) { *xpos = (X-SXm)/(SXM-SXm); *ypos = (Z-SZm)/(SZM-SZm); }
			else { *xpos = (X-BXm)/(BXM-BXm); *ypos = (Z-BZm)/(BZM-BZm); }
			break;
	}

	switch (axisMode) {
		case XYZ:
			if (zoomMode == SMALL) *freq = (X-SXm)/(SXM-SXm); else *freq = (X-BXm)/(BXM-BXm);
			if (zoomMode == SMALL) *amp = (Y-SYm)/(SYM-SYm); else *amp = (Y-BYm)/(BYM-BYm); 
			if (zoomMode == SMALL) *next = (Z-SZm)/(SZM-SZm); else *next = (Z-BZm)/(BZM-BZm);
			break;
		case YXZ:
			if (zoomMode == SMALL) *freq = (Y-SYm)/(SYM-SYm); else *freq = (Y-BYm)/(BYM-BYm); 
			if (zoomMode == SMALL) *amp = (X-SXm)/(SXM-SXm); else *amp = (X-BXm)/(BXM-BXm);
			if (zoomMode == SMALL) *next = (Z-SZm)/(SZM-SZm); else *next = (Z-BZm)/(BZM-BZm);
			break;
		case ZYX:
			if (zoomMode == SMALL) *freq = (Z-SZm)/(SZM-SZm); else *freq = (Z-BZm)/(BZM-BZm);
			if (zoomMode == SMALL) *amp = (Y-SYm)/(SYM-SYm); else *amp = (Y-BYm)/(BYM-BYm); 
			if (zoomMode == SMALL) *next = (X-SXm)/(SXM-SXm); else *next = (X-BXm)/(BXM-BXm);
			break;
		case YZX:
			if (zoomMode == SMALL) *freq = (Y-SYm)/(SYM-SYm); else *freq = (Y-BYm)/(BYM-BYm); 
			if (zoomMode == SMALL) *amp = (Z-SZm)/(SZM-SZm); else *amp = (Z-BZm)/(BZM-BZm);
			if (zoomMode == SMALL) *next = (X-SXm)/(SXM-SXm); else *next = (X-BXm)/(BXM-BXm);
			break;
		case ZXY:
			if (zoomMode == SMALL) *freq = (Z-SZm)/(SZM-SZm); else *freq = (Z-BZm)/(BZM-BZm);
			if (zoomMode == SMALL) *amp = (X-SXm)/(SXM-SXm); else *amp = (X-BXm)/(BXM-BXm);
			if (zoomMode == SMALL) *next = (Y-SYm)/(SYM-SYm); else *next = (Y-BYm)/(BYM-BYm); 
			break;
		case XZY:
			if (zoomMode == SMALL) *freq = (X-SXm)/(SXM-SXm); else *freq = (X-BXm)/(BXM-BXm);
			if (zoomMode == SMALL) *amp = (Z-SZm)/(SZM-SZm); else *amp = (Z-BZm)/(BZM-BZm);
			if (zoomMode == SMALL) *next = (Y-SYm)/(SYM-SYm); else *next = (Y-BYm)/(BYM-BYm); 
			break;
	}
	*freq *= freqRange; *freq += freqCenter;
	*amp *= ampRange; *amp += ampCenter;
	*next *= speed;
	*dur = duration;

	xdot = S * (Y - X);
	ydot = (R * X) - Y - (X * Z);
	zdot = (X * Y) - (B * Z);
	X += xdot * delta_T;
	Y += ydot * delta_T;
	Z += zdot * delta_T;

	return self;
}

@end

