
// A global object that can listen to property changes
window.wallpaperPropertyListener = {
    applyUserProperties: function(properties) {

		if (properties.amphigh)			{	ampHigh = eval(properties.amphigh.value);	}	// Amp High
		if (properties.ampmid)			{	ampMid = eval(properties.ampmid.value);		}	// Amp Mid
		if (properties.amplow)			{	ampLow = eval(properties.amplow.value);		}	// Amp Low
		if (properties.ampquiet)		{	ampQuiet = eval(properties.ampquiet.value);	}	// Amp Quiet

        // BG Rotation Value (0-72, *5=360)
        if (properties.bgrotation) {
			//Reset Orientation
			CTX.b.translate(CAN.b.width/2, CAN.b.height/2);  // Move registration point to the center of the canvas
			CTX.b.rotate(-bgRotation*Math.PI/180); //affects future renders only
			CTX.b.translate(-CAN.b.width/2, -CAN.b.height/2);  // Move registration point to default position
			//Assign new Value
            bgRotation = properties.bgrotation.value*5;
			//Rotate to new Position
			CTX.b.translate(CAN.b.width/2, CAN.b.height/2);  // Move registration point to the center of the canvas
			CTX.b.rotate(bgRotation*Math.PI/180); //affects future renders only
			CTX.b.translate(-CAN.b.width/2, -CAN.b.height/2);  // Move registration point to default position
			//Refresh
			ChangeBgColorStyle()
        }
		// BG Type
		if (properties.bgtype) {		bgType = eval(properties.bgtype.value);			updateBG();		}
		// BG Pat Num
		if (properties.bgpattern) {
			bgPatNum = eval(properties.bgpattern.value);
			if(bgPatNum==0 && bgType==1){patURL = prompt("Enter Pattern URL:", "https://cdn.pixabay.com/photo/2016/04/16/10/33/mandala-1332790_960_720.png");}
			updateBG();
			}
		// BG Img Num
		if (properties.bgimage) {
			bgImageNum = eval(properties.bgimage.value);
			if(bgImageNum==0 && bgType==2){imgURL = prompt("Enter BG URL:", "https://apod.nasa.gov/apod/image/1702/CygX1_HaOIIIRGB_eder_web.jpg");}
			updateBG();
			}
		// Play Video?
		if (properties.vidplay) {
			vidPlay = eval(properties.vidplay.value);
			if(vidPlay){vidBox.play();}		else{vidBox.pause();}
		}
		// Mute Video?
		if (properties.vidmute) {
			vidMute = eval(properties.vidmute.value);
			if(vidMute){vidBox.muted = true}		else{vidBox.muted = false}
		}		
		// Video Y Position
		if (properties.vidypos) {
			vidBox.style.top = eval(100-properties.vidypos.value).toFixed(1) + "%";
		}		
        // Video Location
		if (properties.vidlocation) {
			vidLoc = eval(properties.vidlocation.value);
			vidURL = "UserVid1.webm";
			if(vidLoc==1){vidURL = prompt("Enter Video URL:\nMust be '.webm' or '.ogv' format because Chrome.", "http://www.ioncannon.net/examples/vp8-webm/big_buck_bunny_480p.webm");}
			//if(vidLoc==2){vidURL = prompt("Enter Youtube Video ID.\nExample: bOOc3wmjj04  or  9bZkp7q19f0", "9bZkp7q19f0");} //youtube
			updateBG();		
		}		
		// BG Opacity
		if (properties.bgopacity) {
			bgDisplay.style.opacity = eval(properties.bgopacity.value)/100;//0-100
			}
		// BG X starting Pos
		if (properties.bgx) {
			var BGcoord = [eval(properties.bgx.value).toFixed(1) + "%", document.getElementById('MGdiv').style.backgroundPosition.split(' ')[1]];
			bgDisplay.style.backgroundPosition = BGcoord[0] +' '+ BGcoord[1];
			}
		// BG Y starting Pos
		if (properties.bgy) {
			var BGcoord = [document.getElementById('MGdiv').style.backgroundPosition.split(' ')[0], eval(100-properties.bgy.value).toFixed(1) + "%"];
			bgDisplay.style.backgroundPosition = BGcoord[0] +' '+ BGcoord[1];
			}

 		// BG X starting Pos
		if (properties.bgx2) 				{	bgCX = properties.bgx2.value;				ChangeBgColorStyle();	}	// BG Gradient X Pos
		if (properties.bgy2) 				{	bgCY = properties.bgy2.value *-1;			ChangeBgColorStyle();	}	// BG Gradient Y Pos
		if (properties.bgx3) 				{	bgOX = properties.bgx3.value;				ChangeBgColorStyle();	}	// BG Gradient Radial Stretch X Pos
		if (properties.bgy3) 				{	bgOY = properties.bgy3.value *-1;			ChangeBgColorStyle();	}	// BG Gradient Radial Stretch Y Pos
		if (properties.bgr1) 				{	bgR1 = properties.bgr1.value;				ChangeBgColorStyle();	}	// BG Gradient inner Radius
		if (properties.bgr2) 				{	bgR2 = properties.bgr2.value;				ChangeBgColorStyle();	}	// BG Gradient outer Radius
		if (properties.bggradstyle)			{	bgGS = properties.bggradstyle.value;		ChangeBgColorStyle();	}	// BG Gradient Style
		if (properties.bggradcoloring)		{	bgGC = properties.bggradcoloring.value;		if(bgGC > 0){bgcM = fetchCP(bgGC, bgIT);} ChangeBgColorStyle();	}	// BG Gradient Coloring
		if (properties.bggraditerations)	{	bgIT = properties.bggraditerations.value;	if(bgGC > 0){bgcM = fetchCP(bgGC, bgIT);} ChangeBgColorStyle();	}	// BG Gradient Iterations
		// BG Color Amount
		if (properties.bgcoloramount) {
			bgAmount = properties.bgcoloramount.value;
			//readjust bgGradOffset
			for(var i = 0; i < bgAmount; i++){	bgGradOffset[1][i] = i/(bgAmount);	}
			bgGradOffset[1]["First"] = 0;
			ChangeBgColorStyle();
			}

		if (properties.bggradanim)		{	bgGradAnim = properties.bggradanim.value;	if(bgGradAnim == false){ChangeBgColorStyle();}	}	// Bg Color Animate
		if (properties.bggradanimspeed) {	bgGradAnimSpeed = properties.bggradanimspeed.value; ChangeBgColorStyle();	}	// Bg Color Animation Speed

		//BG Rain
		if (properties.bgrain)				{	bgRain.on = properties.bgrain.value;				setTimeout(function(){mir()}, 150);		}	// Bg Rain
		if (properties.bgrainintensity)		{	bgRain.int = properties.bgrainintensity.value;			}	// Rain Intensity (Rate)
		if (properties.bgraingravitytype)	{	bgRain.gravT = properties.bgraingravitytype.value;		}	// Rain Gravity Type
		if (properties.bgraingravityspeed)	{	bgRain.gravS = properties.bgraingravityspeed.value;		}	// Rain Gravity Speed
		if (properties.bgrainwindtype)		{	bgRain.windT = properties.bgrainwindtype.value;			}	// Rain Wind Type
		if (properties.bgrainwinddirection)	{	bgRain.windS = properties.bgrainwinddirection.value;	}	// Rain Wind Speed
		if (properties.bgraindropsize)		{	bgRain.dSize = properties.bgraindropsize.value;			}	// Max drop size
		if (properties.bgraindropsmear)		{	bgRain.dSmear = properties.bgraindropsmear.value;		}	// Rain Smear
		if (properties.bgrainsteam)			{	bgRain.steam = properties.bgrainsteam.value;			}	// Steam glass
		if (properties.bgrainglass)			{	bgRain.glass = properties.bgrainglass.value;	bgDisplay.style.filter = 'blur('+bgRain.glass+'px)';	}	// Bg Glass Blur Effect
		if (properties.bgrainsteamcolor)	{	bgRain.steamC = fetchC(properties.bgrainsteamcolor.value); 		}	// Steam color
				
 		// BG Colors
 		if (properties.schemecolor)		{	schemeColor = fetchC(properties.schemecolor.value); ChangeBgColorStyle();	}	// Windows Scheme color 
		if (properties.bgcolor1)		{	bgColor[1] = fetchC(properties.bgcolor1.value); ChangeBgColorStyle();		}	// BG Color 1 
		if (properties.bgcolor2)		{	bgColor[2] = fetchC(properties.bgcolor2.value); ChangeBgColorStyle();		}	// BG Color 2
		if (properties.bgcolor3)		{	bgColor[3] = fetchC(properties.bgcolor3.value); ChangeBgColorStyle();		}	// BG Color 3
		if (properties.bgcolor4)		{	bgColor[4] = fetchC(properties.bgcolor4.value); ChangeBgColorStyle();		}	// BG Color 4
		if (properties.bgcolor5)		{	bgColor[5] = fetchC(properties.bgcolor5.value); ChangeBgColorStyle();		}	// BG Color 5
		if (properties.bgcolor6)		{	bgColor[6] = fetchC(properties.bgcolor6.value); ChangeBgColorStyle();		}	// BG Color 6
		if (properties.bgcolor7)		{	bgColor[7] = fetchC(properties.bgcolor7.value); ChangeBgColorStyle();		}	// BG Color 7
		if (properties.bgcolor8)		{	bgColor[8] = fetchC(properties.bgcolor8.value); ChangeBgColorStyle();		}	// BG Color 8
		if (properties.bgcolor9)		{	bgColor[9] = fetchC(properties.bgcolor9.value); ChangeBgColorStyle();		}	// BG Color 9
		if (properties.bgcolor10)		{	bgColor[10] = fetchC(properties.bgcolor10.value); ChangeBgColorStyle();		}	// BG Color 10
	
	
		//Clock
		if (properties.clocktype)				{	clockType = properties.clocktype.value;				clock.bgupdate=true;}	//  Clock Type (0N,1D,2A)
		if (properties.clockfont)				{	clockFont = properties.clockfont.value;				clock.bgupdate=true;}	//  Clock Font (name)
		if (properties.clockbold)				{	clockBold = properties.clockbold.value;				clock.bgupdate=true;}	//  Clock Bold)
		if (properties.clocksize)				{	clockSize = properties.clocksize.value;				clock.bgupdate=true;}	//  Clock size (0-100)
		if (properties.clockfontspacing)		{	clockSpacing = properties.clockfontspacing.value;	clock.bgupdate=true;}	//  Clock Font spacing (0-100)
		if (properties.clockfontsize)			{	clock.fSize = properties.clockfontsize.value;		clock.bgupdate=true;}	//  Adjust Font Size 
		if (properties.clockunits)				{	clock.U = properties.clockunits.value;				clock.bgupdate=true;}	//  Clock Units (0=num, 1=rom, 2=hex)
		if (properties.clock24)					{	clock.H24 = properties.clock24.value;				clock.bgupdate=true;}	//  Clock 24 (true/false)
		if (properties.clockadjust)				{	clock.Adjust = properties.clockadjust.value;		clock.bgupdate=true;}	//  Clock Adjust hours manually
		if (properties.clocksec)				{	clockSec = properties.clocksec.value;				clock.bgupdate=true;}	//  Clock Seconds (true/false)
		if (properties.clockmsec)				{	clockMsec = properties.clockmsec.value;				clock.bgupdate=true;}	//  Clock MilliSeconds (true/false)
		if (properties.clocksmooth)				{	clock.Smooth = properties.clocksmooth.value;		clock.bgupdate=true;}	//  Clock smooth flow
		if (properties.clockupdatesps)			{	clock.Ups = properties.clockupdatesps.value;		clock.bgupdate=true;}	//  Clock updates per second (without MS)
		if (properties.clocksolid)				{	clockSolid = properties.clocksolid.value;			clock.bgupdate=true;}	//  Clock Solid (true/false)
		if (properties.clockfonttilt)			{	clock.FT = properties.clockfonttilt.value;			clock.bgupdate=true;}	//  Clock number tilt (t/f)
		if (properties.clockangle)				{	clock.Angle = properties.clockangle.value;			clock.bgupdate=true;}	//  Clock tilt (0-360)
		if (properties.clockback)				{	clock.Back = properties.clockback.value;			clock.bgupdate=true;}	//  Clock BG shape/style
		if (properties.clockx)					{	clock.X = properties.clockx.value;					clock.bgupdate=true;}	//  Clock x (-200-> 200)
		if (properties.clocky)					{	clock.Y = properties.clocky.value;					clock.bgupdate=true;}	//  Clock y (-200-> 200)
		if (properties.clockop)					{	clock.OP = properties.clockop.value/100;			clock.bgupdate=true;}	//  FG Opacity (0-100)
		if (properties.clockbop)				{	clock.BOP = properties.clockbop.value/100;			clock.bgupdate=true;}	//  BG Opacity (0-100)
		if (properties.clockbsize)				{	clock.bgS = properties.clockbsize.value;			clock.bgupdate=true;}	//  Clock BG size			
		if (properties.clockfontlinew)			{	clock.FLW = properties.clockfontlinew.value;		clock.bgupdate=true;}	//  Clock Font Line Width			
		if (properties.clocksplit)				{	clock.Split = properties.clocksplit.value;			clock.bgupdate=true;}	//  Clock Face split (pacmaning)			
		if (properties.clockvariation)			{	clock.Var = properties.clockvariation.value;		clock.bgupdate=true;}	//  Clock Face split (pacmaning)			
		//Clock Colors
		if (properties.clockglow)				{	clock.Glow = properties.clockglow.value;				clock.bgupdate=true;}	//  Clock Glow/Shadow (0-100)
		if (properties.clockbgglow)				{	clock.bgGlow = properties.clockbgglow.value;			clock.bgupdate=true;}	//  Clock BG Glow/Shadow (0-100)
		if (properties.clockcolorfg)			{	clock.fgC[0] = fetchC(properties.clockcolorfg.value);	clock.bgupdate=true;}	//  Clock Font color			
		if (properties.clockcolorh)				{	clock.fgC[1] = fetchC(properties.clockcolorh.value);	clock.bgupdate=true;}	//  Clock Font color			
		if (properties.clockcolorm)				{	clock.fgC[2] = fetchC(properties.clockcolorm.value);	clock.bgupdate=true;}	//  Clock Font color			
		if (properties.clockcolors)				{	clock.fgC[3] = fetchC(properties.clockcolors.value);	clock.bgupdate=true;}	//  Clock Font color			
		if (properties.clockcolorms)			{	clock.fgC[4] = fetchC(properties.clockcolorms.value);	clock.bgupdate=true;}	//  Clock Font color			
		if (properties.clockglowfg)				{	clock.gC[0]  = fetchC(properties.clockglowfg.value);	clock.bgupdate=true;}	//  Clock Glow color			
		if (properties.clockglowh)				{	clock.gC[1]  = fetchC(properties.clockglowh.value);		clock.bgupdate=true;}	//  Clock Glow color			
		if (properties.clockglowm)				{	clock.gC[2]  = fetchC(properties.clockglowm.value);		clock.bgupdate=true;}	//  Clock Glow color			
		if (properties.clockglows)				{	clock.gC[3]  = fetchC(properties.clockglows.value);		clock.bgupdate=true;}	//  Clock Glow color			
		if (properties.clockglowms)				{	clock.gC[4]  = fetchC(properties.clockglowms.value);	clock.bgupdate=true;}	//  Clock Glow color			
		if (properties.clockcolorbg)			{	clock.bgC = fetchC(properties.clockcolorbg.value);		clock.bgupdate=true;}	//  Clock BG color			
		if (properties.clockglowbg)				{	clock.bggC = fetchC(properties.clockglowbg.value);		clock.bgupdate=true;}	//  Clock BG Glow color			
	
	
		// Viz Color Amount
        if (properties.vizcoloramount) {
			vizAmount = properties.vizcoloramount.value;
			//re-adjust vizGradOffset
			for(var i = 0; i < vizAmount; i++){	vizGradOffset[i] = i/(vizAmount);	}
			vizGradOffset["First"] = 0;
			refreshVCM()
			}
		
		// Viz Color Style
		if (properties.vizcolorstyle) {
			vizColorStyle[0] = properties.vizcolorstyle.value;
			if(vizColorStyle[0] == 3){hasGradient = true}	else{	hasGradient = false		}
			refreshVCM();
		}
		if (properties.vizcolorstylec)		{	vizColorStyle[1] = properties.vizcolorstylec.value;		refreshVCM();	}	// Viz Color Style (C)ustom Colors
		if (properties.vizcolorstylea)		{	vizColorStyle[2] = properties.vizcolorstylea.value;		refreshVCM();	}	// Viz Color Style (A)lgorythms
		if (properties.vizcolorstyleg)		{	vizColorStyle[3] = properties.vizcolorstyleg.value;		refreshVCM();	}	// Viz Color Style (G)radients
		if (properties.vupeakcolorstyle)	{	vizColorStyle.vp = properties.vupeakcolorstyle.value;	refreshVCM();	}	// Vu Peak Color Style
		if (properties.vizgradanim)			{	vizGradAnim = properties.vizgradanim.value;						}	// Viz Color Animate
		if (properties.vizgradanimspeed)	{	vizGradAnimSpeed = properties.vizgradanimspeed.value;			}	// Viz Color Animation Speed
		
		// Viz Colors
		if (properties.vizcolor1)		{	vizColor[1]  = fetchC(properties.vizcolor1.value); refreshVCM();	}	// Viz Color 1 
		if (properties.vizcolor2)		{	vizColor[2]  = fetchC(properties.vizcolor2.value); refreshVCM();	}	// Viz Color 2
		if (properties.vizcolor3)		{	vizColor[3]  = fetchC(properties.vizcolor3.value); refreshVCM();	}	// Viz Color 3
		if (properties.vizcolor4)		{	vizColor[4]  = fetchC(properties.vizcolor4.value); refreshVCM();	}	// Viz Color 4
		if (properties.vizcolor5)		{	vizColor[5]  = fetchC(properties.vizcolor5.value); refreshVCM();	}	// Viz Color 5
		if (properties.vizcolor6)		{	vizColor[6]  = fetchC(properties.vizcolor6.value); refreshVCM();	}	// Viz Color 6
		if (properties.vizcolor7)		{	vizColor[7]  = fetchC(properties.vizcolor7.value); refreshVCM();	}	// Viz Color 7
		if (properties.vizcolor8)		{	vizColor[8]  = fetchC(properties.vizcolor8.value); refreshVCM();	}	// Viz Color 8
		if (properties.vizcolor9)		{	vizColor[9]  = fetchC(properties.vizcolor9.value); refreshVCM();	}	// Viz Color 9
		if (properties.vizcolor10)		{	vizColor[10] = fetchC(properties.vizcolor10.value); refreshVCM();	}	// Viz Color 10 
		if (properties.vizcolor11)		{	vizColor[11] = fetchC(properties.vizcolor11.value); refreshVCM();	}	// Viz Color 11 
		if (properties.vizcolor12)		{	vizColor[12] = fetchC(properties.vizcolor12.value); refreshVCM();	}	// Viz Color 12
		if (properties.vizcolor13)		{	vizColor[13] = fetchC(properties.vizcolor13.value); refreshVCM();	}	// Viz Color 13
		if (properties.vizcolor14)		{	vizColor[14] = fetchC(properties.vizcolor14.value); refreshVCM();	}	// Viz Color 14
		if (properties.vizcolor15)		{	vizColor[15] = fetchC(properties.vizcolor15.value); refreshVCM();	}	// Viz Color 15
		if (properties.vizcolor16)		{	vizColor[16] = fetchC(properties.vizcolor16.value); refreshVCM();	}	// Viz Color 16
		if (properties.vizcolor17)		{	vizColor[17] = fetchC(properties.vizcolor17.value); refreshVCM();	}	// Viz Color 17
		if (properties.vizcolor18)		{	vizColor[18] = fetchC(properties.vizcolor18.value); refreshVCM();	}	// Viz Color 18
		if (properties.vizcolor19)		{	vizColor[19] = fetchC(properties.vizcolor19.value); refreshVCM();	}	// Viz Color 19
		if (properties.vizcolor20)		{	vizColor[20] = fetchC(properties.vizcolor20.value); refreshVCM();	}	// Viz Color 20 
		
		if (properties.vizglow1)		{	LglowColor  = fetchC(properties.vizglow1.value); 	}	// Viz Glow color 1	
		if (properties.vizglow2)		{	CglowColor  = fetchC(properties.vizglow2.value); 	}	// Viz Glow color 2	
		if (properties.vizglow3)		{	RglowColor  = fetchC(properties.vizglow3.value); 	}	// Viz Glow color 3	
		
		if (properties.vizglowblur)				{	glowBlur = properties.vizglowblur.value;		}	// Viz glow blur (shadow)
			
		if (properties.displaywidth)			{	displayWidth = properties.displaywidth.value;		CAN.a.style.width = displayWidth.toFixed(1) + "%";	CAN.a.style.left = ((100-displayWidth)/2).toFixed(1) + "%";	acW = CAN.a.style.width;	}	// Viz Display width
		if (properties.displayheight)			{	displayHeight = properties.displayheight.value;		CAN.a.style.height = displayHeight.toFixed(1) + "%";	CAN.a.style.top = ((100-displayHeight)/2).toFixed(1) + "%";	acH = CAN.a.style.height;	}	// Viz Display height
		//if (properties.displayvertical)			{	var customInt = properties.displayvertical.value;	displayVertical = -customInt;	CAN.a.style.top = displayVertical.toFixed(1) + "%";		}	// Read display vertical position
		//if (properties.displayhorizontal)		{	var customInt = properties.displayhorizontal.value;	displayHorizontal = customInt;	CAN.a.style.left = displayHorizontal.toFixed(1) + "%";	}	// Read display horizontal position
		if (properties.vizx)					{	vizX = properties.vizx.value;			}	// Viz X position
		if (properties.vizy)					{	vizY = properties.vizy.value * -1;		}	// Viz Y position
		if (properties.vizlr)					{	vizLR = properties.vizlr.value;			}	// Viz Split into LR?
		if (properties.vizlrinv)				{	vizLRInv = properties.vizlrinv.value;	}	// Invert Sound Display?
		if (properties.vizlx)					{	vizLX = properties.vizlx.value;			}	// Viz LX position
		if (properties.vizly)					{	vizLY = properties.vizly.value * -1;	}	// Viz LY position
		if (properties.vizrx)					{	vizRX = properties.vizrx.value;			}	// Viz RX position
		if (properties.vizry)					{	vizRY = properties.vizry.value * -1;	}	// Viz RY position

		if (properties.visualizertype)			{	vizType = properties.visualizertype.value; 			}	// Vizualizer
		if (properties.viztypevariation)		{	vizTypeVar = properties.viztypevariation.value; 	}	// Viz Variation
		if (properties.vizshape)				{	vizShape = properties.vizshape.value; 				}	// Viz Shape Variation
		if (properties.vizfade)					{	vizFade = properties.vizfade.value; 				}	// Viz Audio Representation Style
		if (properties.vizpattern)				{	vizPat = properties.vizpattern.value; 				}	// Viz Pattern		
		if (properties.vizsplit)				{	vizSplit = properties.vizsplit.value; 				}	// Viz Split		
		if (properties.vizsplitl)				{	vizSplitL = properties.vizsplitl.value; 			}	// Viz Split		
		if (properties.vizsplitr)				{	vizSplitR = properties.vizsplitr.value; 			}	// Viz Split		
		if (properties.vizengine)				{
			vizEngine = properties.vizengine.value;
			if(vizEngine == 0)	{ clear('agl');} //clear aGL when not in use
			else				{ clear('a'); } // clear a when not in use
			}	// Viz Renderer? (0=Canvas, 1=WebGL)
		if (properties.vizsolid)				{	vizSolid = properties.vizsolid.value;				}	// Viz Solid or Hollow? (true/false)
		if (properties.gotsmoothv)				{	gotSmoothV = properties.gotsmoothv.value;			}	// Viz Vertical Smoothing
		if (properties.gotsmoothh)				{	gotSmoothH = properties.gotsmoothh.value;			}	// Viz Horizontal Smoothing
		if (properties.vizmode)					{	vizMode = properties.vizmode.value;					}	// Viz Mode? (Normal, vu+, vu-, vu+ & vu-)
		if (properties.vizopacity)				{	vizOpacity = properties.vizopacity.value/100;	CAN.a.style.opacity = vizOpacity;	}	// Viz Opacity
		
		// Quantity
		if (properties.quantity) {
			var customInt = properties.quantity.value;
            Quantity = Math.pow(2, customInt)
			qGroups = 128/Quantity	//determine number per group
			for(var x = 0; x < Quantity; x++){	drops[x] = Math.random()*2500;	stars[x] = Math.random();	ripples[x] = Math.random();} //setup Matrix columns and star positions
			refreshVCM()
		}


		if (properties.vucolorbreak1)			{	vuCB1 = properties.vucolorbreak1.value/200;	}	//  Vu Color Break 1
		if (properties.vucolorbreak2)			{	vuCB2 = properties.vucolorbreak2.value/200;	}	//  Vu Color Break 2
		if (properties.vucolorbreak3)			{	vuCB3 = properties.vucolorbreak3.value/200;	}	//  Vu Color Break 3
        if (properties.vustack)					{	vuStack = properties.vustack.value;			}	//  Vu Stack height
        if (properties.vuboing)					{	vuBoing = properties.vuboing.value;			}	//  Vu Boing?
        if (properties.vushape1)				{	vuShape[0] = properties.vushape1.value;		}	//  Vu Shape		
        if (properties.vushape2)				{	vuShape[1] = properties.vushape2.value;		}	//  Vu Cap Shape UP
        if (properties.vushape3)				{	vuShape[2] = properties.vushape3.value;		}	//  Vu Cap Shape Down
        if (properties.vuh)						{	vuH = properties.vuh.value/10;				}	//  Vu height
		
		if (properties.vizthickness)			{	vThickness = properties.vizthickness.value;			}	//  Viz Thickness		
		if (properties.vizcenterthickness)		{	vcThickness = properties.vizcenterthickness.value;	}	//  Viz Circle Center Thickness		
		if (properties.vizcenterthicknessl)		{	vcThicknessL = properties.vizcenterthicknessl.value;}	//  Viz L Circle Center Thickness		
		if (properties.vizcenterthicknessr)		{	vcThicknessR = properties.vizcenterthicknessr.value;}	//  Viz R Circle Center Thickness		
		if (properties.vizinnerheight)			{	vinH = properties.vizinnerheight.value;				}	//  Viz Circle Inner Height		
		if (properties.vizouterheight)			{	voutH = properties.vizouterheight.value;			}	//  Viz Circle Outer Height		
        if (properties.vizpadding)				{	vizPad = properties.vizpadding.value;				}	//  Viz padding
        if (properties.vizstroke)				{	vizStroke = properties.vizstroke.value;				}	//  Viz Stroke Width
        if (properties.vizbaitshape)			{	snake.bait.shape = properties.vizbaitshape.value;	}	//  Viz Bait Shape
        if (properties.vizsnakeshape)			{	snake.shape = properties.vizsnakeshape.value;		}	//  Viz Snake Shape
        if (properties.vizsnakepath)			{	snake.path = properties.vizsnakepath.value;			}	//  Viz Snake Path
        if (properties.vizsnakewrap)			{	snake.wrap = properties.vizsnakewrap.value;			}	//  Viz Snake Boundry
        if (properties.vizfallrate)				{	vizFallRate = properties.vizfallrate.value/30;		}	//  Viz Fall Rate
        if (properties.vizrotatespeed)			{	rotateSpeed = properties.vizrotatespeed.value;		}	//  Viz Rotate Rate	
        if (properties.viziterations)			{	vizIterations = properties.viziterations.value;		}	//  Num of Iterations	
        if (properties.vizvibe)					{	vizVibe = properties.vizvibe.value;					}	//  Size of Vibrations	
		if (properties.vizrippleshape)			{	ripples.shape = properties.vizrippleshape.value;	}	//  Viz Snake Shape
		
	    //  Viz Rotation Pos (Manual)
        if (properties.vizrotatepos) {
			clear('a');
 			//Reset Orientation
			CTX.a.translate(CAN.a.width/2, CAN.a.height/2);  // Move registration point to the center of the canvas
			CTX.a.rotate(-vRotatePos*Math.PI/180); //affects future renders only
			CTX.a.translate(-CAN.a.width/2, -CAN.a.height/2);  // Move registration point to default position
			//Assign new Value
            vRotatePos = properties.vizrotatepos.value*5;
			//Rotate to new Position
			CTX.a.translate(CAN.a.width/2, CAN.a.height/2);  // Move registration point to the center of the canvas
			CTX.a.rotate(vRotatePos*Math.PI/180); //affects future renders only
			CTX.a.translate(-CAN.a.width/2, -CAN.a.height/2);  // Move registration point to default position
        }		
		if (properties.vizrotateposl)			{	vRotatePosL = properties.vizrotateposl.value;	}	//  Manual Rotation of L Viz
		if (properties.vizrotateposr)			{	vRotatePosR = properties.vizrotateposr.value;	}	//  Manual Rotation of R Viz


        if (properties.weatheron)				{	weatherOn = properties.weatheron.value;						displayWeather();	}	//  Weather On?
		if (properties.weatherupdate)			{	wUpdate = 300000*properties.weatherupdate.value;			displayWeather();	}	//  Weather Update Freq (convert to milliseconds. 300000 = 5 minutes.)
		if (properties.weatheranim)				{	wAnim = properties.weatheranim.value;						displayWeather();	}	//  Weather Animate?
		if (properties.weatherfontshadowblur)	{	wfsBlur = properties.weatherfontshadowblur.value;			displayWeather();	}	//  Weather Font Shadow Blur
		if (properties.weatherfontshadowoffset)	{	wfsOffset = properties.weatherfontshadowoffset.value;		displayWeather();	}	//  Weather Font Shadow Offset
		if (properties.weatherbgopacity)		{	wbgOpacity = properties.weatherbgopacity.value;				displayWeather();	}	//  Weather Bg Opacity
		if (properties.weatherbgopacity2)		{	wbgOpacity2 = properties.weatherbgopacity2.value;			displayWeather();	}	//  Weather Bg Opacity 2
		if (properties.weatherwidget)			{	wWidget = properties.weatherwidget.value;					displayWeather();	}	//  Weather Widget Type
		if (properties.weatherbg)				{	wBg = properties.weatherbg.value;							displayWeather();	}	//  Weather Widget BG
		if (properties.weatherbgwidthadjust)	{	wbgwAdjust = properties.weatherbgwidthadjust.value;			displayWeather();	}	//  Weather BG Width Adjust
		if (properties.weathertrim)				{	wTrim = properties.weathertrim.value;						displayWeather();	}	//  Weather Widget Trim
		if (properties.weatherdays)				{	wDays = properties.weatherdays.value;						displayWeather();	}	//  Weather # Days
		if (properties.weatherunits)			{	wUnits = properties.weatherunits.value;						displayWeather();	}	//  Weather Units (0=f, 1=c)
		if (properties.weathersize)				{	wSize = properties.weathersize.value;						displayWeather();	}	//  Weather widget size
		if (properties.weathericonshadowblur)	{	wisBlur = properties.weathericonshadowblur.value;			displayWeather();	}	//  Weather Icon Shadow Blur
		if (properties.weathericonshadowoffset)	{	wisOffset = properties.weathericonshadowoffset.value;		displayWeather();	}	//  Weather Icon Shadow Offset		
		if (properties.weatherx)				{	weatherX = properties.weatherx.value;	CAN.w.style.left = weatherX.toFixed(1) + "%";	}	//  Weather X
		if (properties.weathery)				{	weatherY = -properties.weathery.value;	CAN.w.style.top = weatherY.toFixed(1) + "%";	}	//  Weather Y
		if (properties.weatherfont)				{	weatherFont = properties.weatherfont.value;					displayWeather();	setTimeout(function(){displayWeather()}, 500);	}	//  Weather Font (stutter to load web font)
		if (properties.weathericons)			{	wIconSet = properties.weathericons.value;					displayWeather();	setTimeout(function(){displayWeather()}, 500);	}	//  Weather Icon Set
		if (properties.weathericons2)			{	wIconSet2 = properties.weathericons2.value;					displayWeather();	setTimeout(function(){displayWeather()}, 500);	}	//  Weather Icon Set 2
	    //  Weather Location?
        if (properties.weatherloc)				{	if(weatherOn == true && properties.weatherloc.value == true){weatherLoc = prompt("Enter your location:\nExamples: 90210  or  Austin, TX", "99705");}
			fetchWeather(weatherLoc);
        }	

		if (properties.weatherfontcolor)		{	wfColor  = fetchC(properties.weatherfontcolor.value); 			displayWeather();	}	// Weather Font color
		if (properties.weatherfontcolor2)		{	wfColor2  = fetchC(properties.weatherfontcolor2.value); 		displayWeather();	}	// Weather Font color 2
		if (properties.weatherfontshadowcolor)	{	wfsColor  = fetchC(properties.weatherfontshadowcolor.value); 	displayWeather();	}	// Weather Font Shadow color
		if (properties.weatherfontshadowcolor2)	{	wfsColor2  = fetchC(properties.weatherfontshadowcolor2.value); 	displayWeather();	}	// Weather Font Shadow color 2
		if (properties.weatherbgcolor)			{	wbgColor  = fetchC(properties.weatherbgcolor.value); 			displayWeather();	}	// Weather BG color
		if (properties.weathericonshadowcolor)	{	wisColor  = fetchC(properties.weathericonshadowcolor.value); 	displayWeather();	}	// Weather Icon Shadow color

		
		//  FPS Throttle
		if (properties.fpsthrottle)				{	setFPS = properties.fpsthrottle.value*10;	}
    }
	/*applyGeneralProperties: function(properties) {
		// Read FPS Throttle
        if (properties.fps) {
            setFPS = properties.fps.value;
			if(setFPS == 0){setFPS = 500}
        }
	}*/
}

//============================================================ Variables =====================================
var parent, parent2;
var gl, vidBox;
var CAN=[], CTX=[], GL=[]; //a=audio, b=bg, c=clock, w=weather;
var acH, acW, bcH, bcW, ccH, ccW, wcH, wcW;
var vidLoc, vidMute, vidPlay, vidURL;
var LastViz = ""
var vCanNum = 1;

var stamp=[]; stamp[0] = new Date(); stamp["wFetch"] = Date.now(), stamp["wDisplay"] = Date.now(), stamp["aTicker"] = Date.now();

var patURL = "https://cdn.pixabay.com/photo/2016/04/16/10/33/mandala-1332790_960_720.png", imgURL = "https://apod.nasa.gov/apod/image/1702/CygX1_HaOIIIRGB_eder_web.jpg";
var audioSamples = [], aSamples = [], sortSamples=[], midPoints=[]; var ampLow, ampMid, ampHigh, ampQuiet;
for(i=0;i<28;i++){
	aSamples[i] = [];
	aSamples[i]["av"] = 0;
	sortSamples[i] = [];
}

var musicPlaying=false; var intFPS=0, startFPS=0, curFPS=0, secFPS=0, setFPS=120, rotatePos=0, rotateSpeed=1, refreshVU = 9999;
var spS, spM, bpS, bpM, sCounter=0, bCounter=0, av28 = 	0, Tempo;

//bg
var schemeColor, bgType, bgPatNum, bgImageNum, imageURL, bgGS, bgGC=110, bgGradAnim, bgGradAnimSpeed, bgRotation, bgAmount, bgcA, bgCX, bgCY, bgR1, bgR2, bgOX, bgOY, bgIT=60;
var bgColor=[];			for(i=1;i<=10;i++){	bgColor[i]=[]; bgColor[i][3] ="#000";	}
var bgGradOffset=[]; 	for(i=0;i<=360;i++){	bgGradOffset[i]=[];	}
var bgc=[], bgcM=[]; bgcM.r=[];bgcM.g=[];bgcM.b=[];bgcM.h=[];bgcM.s=[];bgcM.l=[];bgcM.x=[];
var bgRain=[];bgRain.on=false, bgRain.int=0, bgRain.started=false, bgRain.n=[], bgRain.x=[], bgRain.y=[], bgRain.r=[],  bgRain.v=[], bgRain.splat=[], bgRain.move=[];

//viz
var vizX, vizY, vizLR, vizLRInv, vizLX, vizLY, vizRX, vizRY, vizPat, vizSplit, vizSplitL, vizSplitR, vRotatePosL, vRotatePosR;
var vizEngine=0, vRotatePos=0, vizColorStyle=[], vizGradAnim, vizGradAnimSpeed, vizGradOffset=[], LglowColor=[], CglowColor=[], RglowColor=[], glowBlur, displayWidth, displayHeight, displayVertical, displayHorizontal, vizType, vizTypeVar, vizShape, vizFade, vizSolid, hasGradient=false, gotSmoothV, gotSmoothH, vizOpacity, Quantity, qGroups;
var vizAmount, vizColor=[]; for (var i = 0; i < 50; i++) {	vizColor[i]=[];	}// Probably will never reach 50
var vc=[], vcM=[]; vcM.r=[];vcM.g=[];vcM.b=[];vcM.h=[];vcM.s=[];vcM.l=[];vcM.x=[];
var vucPM=[]; vucPM.r=[];vucPM.g=[];vucPM.b=[];vucPM.h=[];vucPM.s=[];vucPM.l=[];

//vu
var vuStack, vuH, vizPad, vizStroke, vuShape=[], vuBars=[], vuPeakBars=[], vuPeakSpeed=[]; vuBars[0]=[]; vuBars[1]=[]; var vuBoing = false, vuCB1 = .5, vuCB2 = .7, vuCB3 = .9, vizFallRate=0, vThickness=0, vcThickness=10, vizMode=0, peakValues=[], peakSpeed=[];
var vuC=[];

//Matrices (Matrix adapted from http://thecodeplayer.com/walkthrough/matrix-rain-animation-html5-canvas-javascript )
var chinese = "祈祷诚实谦虚种子剑三明治零壹贰叁肆伍陆柒捌玖拾佰仟萬億的一是不了人我在有他这中大来上国个到们为子和你地出道也时年得就那要下以生会自着去之过家学对可她里后小么心多天而能好都然没日于起还发成事只作当想看文无开手十用主行方又如前所本见经头面公同三已老从动两长鸡信仰永恒海洋捕鱼火山风水地球闪电神力量我所有的心灵和魂都爱着你漂亮的女人穿着红色的衣服如还有疑请访问百度帮助中心获得解决方法也可以去百度吧留下您的意见或建议田由甲申甴电甶男甸甹町画甼甽甾甿畀畁畂畃畄畅畆畇畈畉畊畋界畍畎畏畐畑㰝㳛㹜㽵䆧䏉䙚"; //chinese characters - taken from the unicode charset
chinese = chinese.split("");	//converting the string into an array of single characters
var moveInterval = 0;
var drops = [], stars = [], ripples = [], mTails =[]; mTails[0] =[]; var mTailLength, vizIterations=20, vizVibe=0; drops.sway=[]; ripples.a=[];	//Columns & Stars
for (var i = 0; i < 128; i++) {	ripples.a[i]=[];	} //prepare amp history arrays
for (var i = 0; i < 200; i++){	mTails[i]=[];	mTails[i]["sv"]=[];		}
//snake
var snake=[];snake.shape=0;snake.path=0;snake.wrap=0;snake.bait=[0,0];snake.amp=[];snake.x=[];snake.y=[];snake.x1=[];snake.y1=[];snake.x2=[];snake.y2=[];snake.d=[];snake.bait.shape=0;
for (var i = 0; i < 128; i++) {	snake.x[i]=0;	snake.y[i]=0;	snake.d[i]=0;	}
//fish
var fish = []; fish.d=[];fish.f=[];fish.bD=[];fish.s=[];fish.td=[];fish.sh=[];fish.sh.b=[];fish.sh.f=[];

	
//clock
var clock=[]; clock.gC=[]; clock.fgC=[]; clock.bgC=[]; clock.bgupdate=true;  //clock.X, clock.Y, clock.U, clock.H24, clock.OP, clock.Adjust
var clockSize, clockType, clockFont, clockSpacing, clockBold,  clockSec, clockMsec, clockIsClear, gtM, gtM2, gtH, gtH2, gtS, gtMS, gtMS2, gtS2, colorSolid;
clock.N=[]; clock.N[0]=[]; clock.N[1]=[]; clock.N[2]=[];
for(var i = 0; i < 1000; i++){
	clock.N[0][i] = i;
	clock.N[1][i] = toRoman(i);
	clock.N[2][i] = toHex(i);
}
clock.wall=[];clock.wall.h=[[],[]];clock.wall.m=[[],[]];clock.wall.s=[[],[]];clock.wall.ms=[[],[],[]]; clock.wall.t=[];clock.wall.n=[[],[],[],[],[],[],[],[],[],[]]
for(var i = 0; i < 24; i++){
	clock.wall.h[0][i] = [0, 0, 0, 0, 0, 0]; //d1, d2, nd1, nd2, v1, v2
	clock.wall.h[1][i] = [0, 0, 0, 0, 0, 0];
	clock.wall.m[0][i] = [0, 0, 0, 0, 0, 0];
	clock.wall.m[1][i] = [0, 0, 0, 0, 0, 0];
	clock.wall.s[0][i] = [0, 0, 0, 0, 0, 0];
	clock.wall.s[1][i] = [0, 0, 0, 0, 0, 0];
	clock.wall.ms[0][i] = [0, 0, 0, 0, 0, 0];
	clock.wall.ms[1][i] = [0, 0, 0, 0, 0, 0];
	clock.wall.ms[2][i] = [0, 0, 0, 0, 0, 0];
}
clock.wall.n[0][0] = [90, 90, 90, 180, 		0, 180, -90, 180, 	0, 0, 180, 180, 	0, 0, 180, 180, 	0, 90, 0, 180,		0, -90, -90, -90];	//number shapes - hand 1
clock.wall.n[0][1] = [180, -90, -90, -90, 	180, 90, 180, 0, 	180, 180, 0, 0, 	180, 180, 0, 0, 	180, 0, -90, 0, 	90, 90, 90, 0];		// hand 2
clock.wall.n[1][0] = [90, 90, 180, -135, 	0, 180, 180, -135, 	45, 0, 180, -135, 	45, 0, 180, -135, 	90, -90, 0, 180, 	0, -90, -90, -90];
clock.wall.n[1][1] = [180, -90, -90, -135, 	90, -90, 0, -135, 	45, 180, 0, -135, 	45, 180, 0, -135, 	180, 0, 90, -90, 	90, 90, 90, 0];
clock.wall.n[2][0] = [90, 90, 90, 180, 		0, 90, 180, 180, 	90, 90, 0, 180, 	0, 180, -90, -90, 	0, 0, -90, 180, 	0, -90, -90, -90];
clock.wall.n[2][1] = [180, -90, -90, -90, 	90, -90, -90, 0, 	180, -90, -90, 0, 	180, 90, 90, 0, 	180, 90, 90, -90, 	90, 90, 90, 0];
clock.wall.n[3][0] = [90, 90, 90, 180, 		0, 90, 180, 180, 	90, 90, 0, 180, 	0, 90, 180, 180, 	90, 90, 0, 180, 	0, -90, -90, -90];
clock.wall.n[3][1] = [180, -90, -90, -90, 	90, -90, -90, 0, 	180, -90, -90, 0, 	90, -90, -90, 0, 	180, -90, -90, 0, 	90, 90, 90, 0];
clock.wall.n[4][0] = [90, 180, 90, 180, 	0, 180, 0, 180, 	0, 0, -90, 180, 	0, 90, 180, 180, 	45, 45, 0, 180, 	45, 45, 0, -90];
clock.wall.n[4][1] = [180, -90, 180, -90, 	180, 0, 180, 0, 	180, 90, 0, 0, 		90, -90, -90, 0, 	45, 45, 180, 0, 	45, 45, 90, 0];
clock.wall.n[5][0] = [90, 90, 90, 180, 		0, 180, -90, -90, 	0, 0, -90, 180, 	0, 90, 180, 180, 	90, 90, 0, 180, 	0, -90, -90, -90];
clock.wall.n[5][1] = [180, -90, -90, -90, 	180, 90, 90, 0, 	180, 90, 90, -90, 	90, -90, -90, 0, 	180, -90, -90, 0, 	90, 90, 90, 0];
clock.wall.n[6][0] = [90, 90, 90, 180, 		0, 180, -90, -90, 	0, 0, -90, 180, 	0, 90, 180, 180, 	0, 90, 0, 180, 		0, -90, -90, -90];
clock.wall.n[6][1] = [180, -90, -90, -90, 	180, 90, 90, 0, 	180, 90, 90, -90, 	180, 180, -90, 0, 	180, 0, -90, 0, 	90, 90, 90, 0];
clock.wall.n[7][0] = [90, 90, 90, 180, 		0, -90, -90, 180, 	45, 45, 180, 180, 	45, 45, 180, 180, 	45, 45, 0, 180, 	45, 45, 0, -90];
clock.wall.n[7][1] = [180, -90, -90, -90, 	90, 90, 180, 0, 	45, 45, 0, 0, 		45, 45, 0, 0, 		45, 45, 180, 0, 	45, 45, 90, 0];
clock.wall.n[8][0] = [90, 90, 90, 180, 		0, 180, -90, 180, 	0, 0, -90, -135, 	45, 90, 180, 180, 	0, 90, 0, 180, 		0, -90, -90, -90];
clock.wall.n[8][1] = [180, -90, -90, -90, 	180, 90, 180, 0, 	135, 90, 0, 0, 		180, 180, -90, -45, 180, 0, -90, 0, 	90, 90, 90, 0];
clock.wall.n[9][0] = [90, 90, 90, 180, 		0, 180, -90, 180, 	0, 0, -90, 180, 	0, 90, 180, 180, 	90, 90, 0, 180, 	0, -90, -90, -90];
clock.wall.n[9][1] = [180, -90, -90, -90, 	180, 90, 180, 0, 	180, 90, 0, 0, 		90, -90, -90, 0, 	180, -90, -90, 0, 	90, 90, 90, 0];
clock.wall.n.a=[];clock.wall.n.b=[];clock.wall.n.c=[];clock.wall.n.d=[];clock.wall.n.e=[];clock.wall.n.f=[];
clock.wall.n.a[0] = [90, 90, 90, 180, 		0, 180, -90, 180, 	0, 0, -90, 180, 	0, 90, 180, 180, 	0, 180, 0, 180, 	0, -90, 0, -90];
clock.wall.n.a[1] = [180, -90, -90, -90, 	180, 90, 180, 0, 	180, 90, 0, 0, 		180, 180, -90, 0, 	180, 0, 180, 0, 	90, 0, 90, 0];
clock.wall.n.b[0] = [90, 90, 135, -135, 	0, 180, -90, 180, 	0, 0, -90, -135, 	0, 90, 180, 180, 	0, 90, 0, -135, 	0, -90, -90, -45];
clock.wall.n.b[1] = [180, -90, -90, -135, 	180, 90, 180, -45, 	180, 90, 0, 0, 		180, 180, -90, -45, 180, 0, -90, 0, 	90, 90, 45, -45];
clock.wall.n.c[0] = [90, 90, 90, 180, 		0, 180, -90, -90, 	0, 0, -135, -135, 	0, 0,-135,-135, 	0, 90, 90, 180, 	0, -90, -90, -90];
clock.wall.n.c[1] = [180, -90, -90, -90, 	180, 90, 90, 0, 	180, 180,-135,-135,	180, 180,-135,-135, 180, 0, -90, -90,	90, 90, 90, 0];
clock.wall.n.d[0] = [90, 90, 135, -135, 	0, 180, -90, 180, 	0, 0, 180, 180, 	0, 0, 180, 180, 	0, 90, 0, -135, 	0, -90, -90, -45];
clock.wall.n.d[1] = [180, -90, -90, -135, 	180, 90, 180, -45, 	180, 180, 0, 0, 	180, 180, 0, 0, 	180, 0, -90, 0, 	90, 90, 45, -45];
clock.wall.n.e[0] = [90, 90, 90, 180, 		0, 180, -90, 0, 	0, 0, -90, 180, 	0, 90, 90, 0, 		0, 90, 90, 180, 	0, -90, -90, -90];
clock.wall.n.e[1] = [180, -90, -90, -90, 	180, 90, 90, -90, 	180, 90, 90, -90, 	180, 180, -90, -90, 180, 0, -90, -90, 	90, 90, 90, 0];
clock.wall.n.f[0] = [90, 90, 90, 180, 		0, 180, -90, 0, 	0, 0, -90, 180, 	0, 90, 90, 0, 		0, 180, -45, -45, 	0, -90, -45, -45];
clock.wall.n.f[1] = [180, -90, -90, -90, 	180, 90, 90, -90, 	180, 90, 90, -90, 	180, 180, -90, -90, 180, 0, -45, -45, 	90, 0, -45, -45];



var DebugDisplay = document.getElementById('Ldisplay');
var DebugDisplay2 = document.getElementById('Rdisplay');


//weather
var dayNames=[], dayTemps=[]; unitNames =["F","C", "K", "R", "De", "N", "Ré", "Rø"];
var weatherOn, weatherLoc="99705", wAnim, wUpdate=300000, wData=[], wIconSet, wIconSet2, wIcons=[], weatherFont, wfsBlur, wisBlur, wfsOffset, wisOffset, wfColor=[], wfColor2=[], wfsColor=[], wfsColor2=[], wisColor=[], wbgColor=[];
var wbgOpacity, wbgOpacity2, wbgwAdjust, weatherX, weatherY, wWidget, wSize, wDays, wUnits, midDay, midNight, dawn, dusk, wBg, wTrim;
stamp["time"]=[], stamp["time"]["wFetch"] = stamp[0].toTimeString(), stamp["time"]["wDisplay"] = stamp[0].toTimeString();

var skyVis = [ //0=no visibility, 1=partly cloudy, 2=clear
0,0,0,0,0,
0,0,0,0,0,
0,0,0,0,0,
0,0,0,0,0,
0,0,0,1,1,
2,0,1,1,1,
1,2,2,2,2,
0,2,1,1,1,
1,0,1,0,1,
0,0,1
];
skyVis[3200] = 1;

for(i=1;i<=3;i++){
	wIcons[i]=[];
	wIcons[i][0]="WeatherWidget/Icons/"+i+"/Tornado.svg";//Tornado
	wIcons[i][1]="WeatherWidget/Icons/"+i+"/SevereThunder.svg";//Tropical Storm
	wIcons[i][2]="WeatherWidget/Icons/"+i+"/Hurricane.svg";//Hurricane
	wIcons[i][3]="WeatherWidget/Icons/"+i+"/SevereThunder.svg";//Severe Thunderstorms
	wIcons[i][4]="WeatherWidget/Icons/"+i+"/Thunder.svg";//Thunderstorms
	wIcons[i][5]="WeatherWidget/Icons/"+i+"/Hail.svg";//Mixed Rain and Snow
	wIcons[i][6]="WeatherWidget/Icons/"+i+"/Hail.svg";//Mixed Rain and Sleet
	wIcons[i][7]="WeatherWidget/Icons/"+i+"/Hail.svg";//Mixed Snow and Sleet
	wIcons[i][8]="WeatherWidget/Icons/"+i+"/FreezingDrizzle.svg";//Freezing Drizzle
	wIcons[i][9]="WeatherWidget/Icons/"+i+"/Drizzle.svg";//Drizzle
	wIcons[i][10]="WeatherWidget/Icons/"+i+"/FreezingRain.svg";//Freezing Rain
	wIcons[i][11]="WeatherWidget/Icons/"+i+"/Rain.svg";//Showers
	wIcons[i][12]="WeatherWidget/Icons/"+i+"/Rain.svg";//Showers
	wIcons[i][13]="WeatherWidget/Icons/"+i+"/Snow.svg";//Snow Flurries
	wIcons[i][14]="WeatherWidget/Icons/"+i+"/Snow.svg";//Light Snow Showers
	wIcons[i][15]="WeatherWidget/Icons/"+i+"/HeavySnow.svg";//Blowing Snow
	wIcons[i][16]="WeatherWidget/Icons/"+i+"/Snow.svg";//Snow
	wIcons[i][17]="WeatherWidget/Icons/"+i+"/Hail.svg";//Hail
	wIcons[i][18]="WeatherWidget/Icons/"+i+"/Hail.svg";//Sleet
	wIcons[i][19]="WeatherWidget/Icons/"+i+"/Dust.svg";//Dust
	wIcons[i][20]="WeatherWidget/Icons/"+i+"/Foggy.svg";//Foggy
	wIcons[i][21]="WeatherWidget/Icons/"+i+"/Haze.svg";//Haze
	wIcons[i][22]="WeatherWidget/Icons/"+i+"/Foggy.svg";//Smoky
	wIcons[i][23]="WeatherWidget/Icons/"+i+"/Windy.svg";//Blustery
	wIcons[i][24]="WeatherWidget/Icons/"+i+"/Windy.svg";//Windy
	wIcons[i][25]="WeatherWidget/Icons/"+i+"/Cold.svg";//Cold
	wIcons[i][26]="WeatherWidget/Icons/"+i+"/Cloudy.svg";//Cloudy
	wIcons[i][27]="WeatherWidget/Icons/"+i+"/MCloudyNight.svg";//Mostly Cloudy Night
	wIcons[i][28]="WeatherWidget/Icons/"+i+"/MCloudyDay.svg";//Mostly Cloudy Day
	wIcons[i][29]="WeatherWidget/Icons/"+i+"/PCloudyNight.svg";//Partly Cloudy Night
	wIcons[i][30]="WeatherWidget/Icons/"+i+"/PCloudyDay.svg";//Partly Cloudy Day
	wIcons[i][31]="WeatherWidget/Icons/"+i+"/ClearNight.svg";//Clear Night
	wIcons[i][32]="WeatherWidget/Icons/"+i+"/Sunny.svg";//Sunny
	wIcons[i][33]="WeatherWidget/Icons/"+i+"/FairNight.svg";//Fair Night
	wIcons[i][34]="WeatherWidget/Icons/"+i+"/FairDay.svg";//Fair Day
	wIcons[i][35]="WeatherWidget/Icons/"+i+"/Hail.svg";//Mixed Rain and Hail
	wIcons[i][36]="WeatherWidget/Icons/"+i+"/HeatWave.svg";//Hot
	wIcons[i][37]="WeatherWidget/Icons/"+i+"/Thunder.svg";//Isolated Thunderstorms
	wIcons[i][38]="WeatherWidget/Icons/"+i+"/Thunder.svg";//Scattered Thunderstorms
	wIcons[i][39]="WeatherWidget/Icons/"+i+"/Thunder.svg";//Scattered Thunderstorms
	wIcons[i][40]="WeatherWidget/Icons/"+i+"/Rain.svg";//Scattered Showers
	wIcons[i][41]="WeatherWidget/Icons/"+i+"/HeavySnow.svg";//Heavy Snow
	wIcons[i][42]="WeatherWidget/Icons/"+i+"/Snow.svg";//Scattered Snow Showers
	wIcons[i][43]="WeatherWidget/Icons/"+i+"/HeavySnow.svg";//Heavy Snow
	wIcons[i][44]="WeatherWidget/Icons/"+i+"/PartlyCloudy.svg";//Partly Cloudy
	wIcons[i][45]="WeatherWidget/Icons/"+i+"/Thunder.svg";//Thundershowers
	wIcons[i][46]="WeatherWidget/Icons/"+i+"/Snow.svg";//Snow Showers
	wIcons[i][47]="WeatherWidget/Icons/"+i+"/Thunder.svg";//Isolated Thunderstorms
	wIcons[i][3200]="WeatherWidget/Icons/"+i+"/NA.svg";//Not Available
}


//On window resize, resize everything
function onWindowResized() {
	CAN.a.width = CAN.a.offsetWidth;		CAN.a.height = CAN.a.offsetHeight;
	CAN.agl.width = CAN.agl.clientWidth;	CAN.agl.height = CAN.agl.clientHeight; CTX['agl'].viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
	CAN.vu.width = CAN.vu.offsetWidth;		CAN.vu.height = CAN.vu.offsetHeight;
	CAN.b.width = CAN.b.offsetWidth;		CAN.b.height = CAN.b.offsetHeight;
	CAN.rp.width = CAN.rp.offsetWidth;		CAN.rp.height = CAN.rp.offsetHeight;
	CAN.rd.width = CAN.rd.offsetWidth;		CAN.rd.height = CAN.rd.offsetHeight;
	CAN.r.width = CAN.r.offsetWidth;		CAN.r.height = CAN.r.offsetHeight;
	CAN.c.width = CAN.c.offsetWidth;		CAN.c.height = CAN.c.offsetHeight;
	CAN.cb.width = CAN.cb.offsetWidth;		CAN.cb.height = CAN.cb.offsetHeight;
	CAN.w.width = CAN.w.offsetWidth;		CAN.w.height = CAN.w.offsetHeight;
	ChangeBgColorStyle()
}

//============================================================ Audio Listener =====================================
function wallpaperAudioListener(audioArray) {
    //DebugDisplay.textContent = audioArray[0];
	
	//Test for activity before proceeding
	if (aSamples[3][0] != 0){
		musicPlaying = true;
		
		//Create Audio Data Matrixs
		for (var i = 0; i < audioArray.length; i++) {
			for (var ii = 27; ii > 0; ii--) {		
				aSamples[ii][i] = 0+aSamples[ii-1][i];
				aSamples[ii]["av"] = 0+aSamples[ii-1]["av"]
				sortSamples[ii][i] = 0+sortSamples[ii-1][i];
			}	
		}		
		
		//Record Average Energy Output
		aSamples[0]["av"] = 0;
		for(var i = 0; i < 128; i++){ //Low Left		
			aSamples[0]["av"] += audioArray[i];
		}
		aSamples[0]["av"] /= 128;
		
		//Average past 28 Energy Outputs (about 1 second worth)
		av28 = 	0;
		for(var i = 0; i < 28; i++){ //Low Left		
			av28 += aSamples[i]["av"];
		}
		av28 /= 28;
		
		//AMP it up (or down)
		for(var i = 0; i < 21; i++){	aSamples[0][i]  = audioArray[i]*(0.2*ampLow);	}//Low Left
		for(var i = 21; i < 43; i++){	aSamples[0][i]  = audioArray[i]*(0.2*ampMid);	}//Mid Left
		for(var i = 43; i < 64; i++){	aSamples[0][i]  = audioArray[i]*(0.2*ampHigh);	}//High Left
		for(var i = 64; i < 85; i++){	aSamples[0][i]  = audioArray[i]*(0.2*ampLow);	}//Low Right
		for(var i = 85; i < 107; i++){	aSamples[0][i]  = audioArray[i]*(0.2*ampMid);	}//Mid Right
		for(var i = 107; i < 128; i++){	aSamples[0][i]  = audioArray[i]*(0.2*ampHigh);	}//High Right
		
		//Equalizer
		for(var i = 0; i < 128; i++){ //Increase quiet notes, decrease loud ones
			if(aSamples[0][i] > 0 && aSamples[0][i] < 0.016){	aSamples[0][i]  = aSamples[0][i]*(1/10*ampQuiet);	}
			if(aSamples[0][i] > 0 && aSamples[0][i] > 0.016){	aSamples[0][i]  = aSamples[0][i]*(10*1/ampQuiet);	}		
		}		

		
		//Vertical Smoothing (Averaging multiple time instances for a smoother visual)
		for (var i = 0; i < aSamples[0].length; i++) {
			audioSamples[i]=0;
			for (var ii = 0; ii <= gotSmoothV; ii++) {		
				audioSamples[i] += aSamples[ii][i];
			}	
			audioSamples[i] /= (gotSmoothV+1);
		}
		
		//Horizontal Smoothing
		if(gotSmoothH > 0 && Quantity > (1+gotSmoothH*2)){
			var tempAudioSamples = [];
			// smooth edges
			if(gotSmoothH == 2){

			}
			//smooth middle
			for(var i = gotSmoothH; i < 128-gotSmoothH; i++){
				if(gotSmoothH == 1){tempAudioSamples[i] = (audioSamples[i-1]+audioSamples[i]+audioSamples[i+1])/2.5}
				if(gotSmoothH == 2){tempAudioSamples[i] = (audioSamples[i-2]+audioSamples[i-1]+audioSamples[i]+audioSamples[i+1]+audioSamples[i+2])/4}
			}
			// smooth edges (left, right, middle)
			if(gotSmoothH == 1){
				tempAudioSamples[0] = (audioSamples[0]+audioSamples[1])/2;
				tempAudioSamples[63] = (audioSamples[62]+audioSamples[63]+audioSamples[127])/2.5;
				tempAudioSamples[64] = (audioSamples[64]+audioSamples[65])/2;
				tempAudioSamples[127] = (audioSamples[126]+audioSamples[127]+audioSamples[63])/2.5;
			}
			if(gotSmoothH == 2){
				tempAudioSamples[0] = (audioSamples[0]+audioSamples[1]+audioSamples[2])/2.5;
				tempAudioSamples[1] = (audioSamples[0]+audioSamples[1]+audioSamples[2]+audioSamples[3])/3;
				tempAudioSamples[62] = (audioSamples[60]+audioSamples[61]+audioSamples[62]+audioSamples[63]+audioSamples[127])/4;
				tempAudioSamples[63] = (audioSamples[61]+audioSamples[62]+audioSamples[63]+audioSamples[126]+audioSamples[127])/4;

				tempAudioSamples[64] = (audioSamples[64]+audioSamples[65]+audioSamples[66])/2.5;
				tempAudioSamples[65] = (audioSamples[64]+audioSamples[65]+audioSamples[66]+audioSamples[67])/3;
				tempAudioSamples[126] = (audioSamples[124]+audioSamples[125]+audioSamples[126]+audioSamples[127]+audioSamples[63])/4;
				tempAudioSamples[127] = (audioSamples[125]+audioSamples[126]+audioSamples[127]+audioSamples[62]+audioSamples[63])/4;

			}			
			
			audioSamples = tempAudioSamples;
		}
	
		//Segregate into Quantity of groups, find largest number in each, produce new Sample List
		if (Quantity < 128){
			var tempAudioSamples = [];
			for(var i = 0; i < Quantity; i++){
				var theVictor= 0;
				for(var ii = 0; ii < qGroups; ii++){
				theVictor = Math.max(theVictor, audioSamples[ii+(i*qGroups)]);
				}
			tempAudioSamples[i] =  theVictor;
			}

		audioSamples = tempAudioSamples;
		}

		// Sort Samples (LL->LH, RH->RL)
		var halfCount = Math.floor(Quantity / 2);
		sortSamples[0] = []; //Rearrange audio samples to be in order
		for (var i = 0; i < Quantity; i++) {
			if(i<halfCount){sortSamples[0][i]=audioSamples[i];}
			else{sortSamples[0][i]=audioSamples[Quantity-(i-halfCount)-1];}
		}
		
		//Count Samples & Beats per Second
		if(refreshCheck("aTicker", 1000)){
			spS = sCounter
			spM = spS*60;
			sCounter=0;
			
			bpS = bCounter;
			bpM = bpS*60;
			bCounter=0;
			//DebugDisplay.textContent = "A: "+spS+":"+spM + "  B: "+bpS+":"+bpM
			}	
		else{
			sCounter++
			if(aSamples[0]["av"] > av28*1.3){bCounter++}
		}
		

		
	}
	else{
		musicPlaying = false;
		if(audioArray[0] != 0){
			aSamples[3][0] = 0.00001
		}
	}
	
	
    //DebugDisplay.textContent = musicPlaying +" : "+ aSamples[0][64]		
};

//============================================================ Main Program Loop =====================================
function run() {
	if(setFPS == 250){
		if(musicPlaying==true){ //Cuts down cpu usage when nothing is playing
			//Animate Visualizations
			pv();
			if(vizEngine == 0){	if( LastViz != "Canvas"){LastViz != "Canvas"; vCanvas()	}	}
			else{				if( LastViz != "WebGL") {LastViz != "WebGL";  vWebGL()	}else{}	}
		}
		else{if(rotatePos>0){rotatePos=0}}
		
		//Animate Clock
		updateClock()
		
		//Animate BG Gradient
		if(bgGradAnim){ChangeBgColorStyle()}

		//Animate/Fetch Weather
		if(refreshCheck("wFetch", wUpdate)){displayWeather()}		
		//if(wAnim && refreshCheck("wDisplay", 500)){displayWeather()} //If I ever decide to animate it		
		
		//Loop
		window.requestAnimationFrame(run)		
	}
	else{
		setTimeout(function() { //FPS Throttle

			if(musicPlaying==true){ //Cuts down cpu usage when nothing is playing

				//FPS Counter
				/*if(intFPS == 0){ startFPS = new Date();	}
				curFPS = new Date();
				secFPS = (curFPS - startFPS)/1000
				if(secFPS >= .5){
					DebugDisplay2.textContent = "FPS: "+ intFPS/.5 + " : " + secFPS;
					intFPS=0;
				}
				else{	intFPS++	}	*/
				//End FPS 
				
				//Animate Visualizations
				pv();
				if(vizEngine == 0){	if( LastViz != "Canvas"){LastViz != "Canvas"; vCanvas()	}	}
				else{				if( LastViz != "WebGL") {LastViz != "WebGL";  vWebGL()	}else{}	}
				
			}
			else{if(rotatePos>0){rotatePos=0}}
			
			//Animate Clock
			updateClock()
			
			//Animate BG Gradient
			if(bgGradAnim){ChangeBgColorStyle()}

			//Animate/Fetch Weather
			if(refreshCheck("wFetch", wUpdate)){displayWeather()}		
			//if(wAnim && refreshCheck("wDisplay", 500)){displayWeather()} //If I ever decide to animate it		
			
			//Loop
			window.requestAnimationFrame(run)		
		}, 1000 / setFPS);
	}
}

//============================================================ Prep Color Matrix =====================================

function fetchC(c){
	// Convert the custom color to an array [r,g,b,hex,h,s,l]
	var tempC = c.split(' ');
	tempC = tempC.map(function(c) {	return Math.ceil(c * 255);});
	tempC[3] = rgbToHex(tempC[0],tempC[1],tempC[2]);
	
	var	hslC = rgbToHsl(tempC[0],tempC[1],tempC[2]);				
	tempC[4] = hslC[0] *=360;
	tempC[5] = hslC[1] *=100;
	tempC[6] = hslC[2] *=100;
	return tempC
}

function refreshVCM(){
	//Create Custom Color Data Matrix
	vc.split=[];vc.r=[];vc.g=[];vc.b=[];vc.h=[];vc.s=[];vc.l=[];
	for(var i = 1; i <= vizAmount; i++){
		vc.r[i]	= vizColor[i][0];
		vc.g[i]	= vizColor[i][1];
		vc.b[i]	= vizColor[i][2];
		vc[i] 	= vizColor[i][3]; //Hex Color
		vc.h[i]	= vizColor[i][4];
		vc.s[i]	= vizColor[i][5];
		vc.l[i]	= vizColor[i][6];
		vc.split[i] = r10("floor", (i-1)/(vizAmount-1), -4);	//color offset	
	} 
	
	if(vizColorStyle[0] == 1){	vcM = fetchCP(vizColorStyle[1], Quantity);	}
	if(vizColorStyle[0] == 2){	vcM = fetchCP(vizColorStyle[2], Quantity);	}	
	if(vizColorStyle.vp > 0){	vucPM = fetchCP(vizColorStyle.vp, Quantity);	}	//Vu Peak Bar Pattern
	//DebugDisplay.textContent = vc.split;		
}

function fetchCP(p, q){
	var newMatrix=[]; newMatrix.r=[];newMatrix.g=[];newMatrix.b=[];newMatrix.h=[];newMatrix.s=[];newMatrix.l=[],newMatrix.x=[];
	//Create Appliable Color Matrices (Patterns)

		if(p == 10){ //Grouped Sections
			var sectionWidth = (q/vizAmount)
			for(var i=0; i < q; i++){
				var ticker = Math.ceil((i+1)/sectionWidth)		
				
				newMatrix[i]	= vc[ticker];
				newMatrix.r[i] = vc.r[ticker];	newMatrix.g[i] = vc.g[ticker];	newMatrix.b[i] = vc.b[ticker];
				newMatrix.h[i] = vc.h[ticker];	newMatrix.s[i] = vc.s[ticker];	newMatrix.l[i] = vc.l[ticker];		
			}		
		}
		else if(p == 11){ //Wallpaper (sections with semi-random luminosity)
			var sectionWidth = (q/vizAmount)
			for(var i=0; i < q; i++){
				var ticker = Math.ceil((i+1)/sectionWidth)		

				newMatrix.h[i] = vc.h[ticker];
				newMatrix.s[i] = vc.s[ticker];
				newMatrix.l[i] = Math.max(0, Math.min(100, vc.l[ticker]-20+(+Math.random()*0.4)*100 ))
				var newColor = hslToRgb(newMatrix.h[i]/360, newMatrix.s[i], newMatrix.l[i])
				newMatrix.r[i] = newColor[0];	newMatrix.g[i] = newColor[1];	newMatrix.b[i] = newColor[2];
				newMatrix[i] = 'hsl('+ newMatrix.h[i] +','+ newMatrix.s[i] +'%,'+ newMatrix.l[i] +'%)';
			}		
		}
		else if(p == 12){ //Wallpaper 2 (sections with random luminosity)
			var sectionWidth = (q/vizAmount)
			for(var i=0; i < q; i++){
				var ticker = Math.ceil((i+1)/sectionWidth)		

				newMatrix.h[i] = vc.h[ticker];
				newMatrix.s[i] = vc.s[ticker];
				newMatrix.l[i] = (Math.random()*0.6+0.06)*100
				var newColor = hslToRgb(newMatrix.h[i]/360, newMatrix.s[i], newMatrix.l[i])
				newMatrix.r[i] = newColor[0];	newMatrix.g[i] = newColor[1];	newMatrix.b[i] = newColor[2];
				newMatrix[i] = 'hsl('+ newMatrix.h[i] +','+ newMatrix.s[i] +'%,'+ newMatrix.l[i] +'%)';
			}		
		}
		else if(p == 13){ //Columns (dark edges, bright middle)
			var sectionWidth = (q/vizAmount)
			for(var i=0; i < q; i++){
				var ticker = Math.ceil((i+1)/sectionWidth)		
				if(((i+1) % sectionWidth) <= sectionWidth/2)	{ var ticker2 = ((i+1) % sectionWidth)/sectionWidth	}
				else											{ var ticker2 = (sectionWidth-((i+1) % sectionWidth))/sectionWidth }

				newMatrix.h[i] = vc.h[ticker];
				newMatrix.s[i] = vc.s[ticker];
				newMatrix.l[i] = ticker2*98+2
				var newColor = hslToRgb(newMatrix.h[i]/360, newMatrix.s[i], newMatrix.l[i])
				newMatrix.r[i] = newColor[0];	newMatrix.g[i] = newColor[1];	newMatrix.b[i] = newColor[2];
				newMatrix[i] = 'hsl('+ newMatrix.h[i] +','+ newMatrix.s[i] +'%,'+ newMatrix.l[i] +'%)';
			}		
		}
		else if(p == 14){ //Columns 2 (lighter edges)
			var sectionWidth = (q/vizAmount)
			for(var i=0; i < q; i++){
				var ticker = Math.ceil((i+1)/sectionWidth)		
				if(((i+1) % sectionWidth) <= sectionWidth/2)	{ var ticker2 = ((i+1) % sectionWidth)/sectionWidth	}
				else											{ var ticker2 = (sectionWidth-((i+1) % sectionWidth))/sectionWidth }

				newMatrix.h[i] = vc.h[ticker];
				newMatrix.s[i] = vc.s[ticker];
				newMatrix.l[i] = vc.l[ticker]/3+ticker2*2/3*100
				var newColor = hslToRgb(newMatrix.h[i]/360, newMatrix.s[i], newMatrix.l[i])
				newMatrix.r[i] = newColor[0];	newMatrix.g[i] = newColor[1];	newMatrix.b[i] = newColor[2];
				newMatrix[i] = 'hsl('+ newMatrix.h[i] +','+ newMatrix.s[i] +'%,'+ newMatrix.l[i] +'%)';
			}		
		}
		else if(p == 20){ //fade
			var sectionWidth = (q-1)/(vizAmount-1)
			for(var i=0; i < q; i++){
				//determine L&R colors
				var fc=[-1, -1];
				for(ii=1; ii<=vizAmount; ii++){
					if(i >= vc.split[ii]*(q-1)){		fc=[ii, ii+1];		}
				}
				if(fc[1] == vizAmount+1){fc = [vizAmount, vizAmount];}

				//determine difference
				var cdiff= [(i%sectionWidth) /sectionWidth];
				cdiff[1] = vc.r[fc[1]]-vc.r[fc[0]];
				cdiff[2] = vc.g[fc[1]]-vc.g[fc[0]];
				cdiff[3] = vc.b[fc[1]]-vc.b[fc[0]];					

				cdiff[4] = vc.r[fc[0]] +Math.round(cdiff[1] *cdiff[0]);
				cdiff[5] = vc.g[fc[0]] +Math.round(cdiff[2] *cdiff[0]);						
				cdiff[6] = vc.b[fc[0]] +Math.round(cdiff[3] *cdiff[0]);	
				
				//assign colors
				newMatrix.r[i] = cdiff[4];
				newMatrix.g[i] = cdiff[5];
				newMatrix.b[i] = cdiff[6];
				var	newColor = rgbToHsl(newMatrix.r[i], newMatrix.g[i], newMatrix.b[i]);				
				newMatrix.h[i] = newColor[0] *=360;
				newMatrix.s[i] = newColor[1] *=100;
				newMatrix.l[i] = newColor[2] *=100;
				newMatrix[i] = 'hsl('+ newMatrix.h[i] +','+ newMatrix.s[i] +'%,'+ newMatrix.l[i] +'%)';	
			}		
		}
		else if(p == 30){ //stripes
			var ticker = 1
			for(var i=0; i < q; i++){
				if(ticker > vizAmount){ticker=1}
				
				newMatrix[i] = vc[ticker];
				newMatrix.r[i] = vc.r[ticker];	newMatrix.g[i] = vc.g[ticker];	newMatrix.b[i] = vc.b[ticker];
				newMatrix.h[i] = vc.h[ticker];	newMatrix.s[i] = vc.s[ticker];	newMatrix.l[i] = vc.l[ticker];		
				
				ticker++
			}		
		}
		else if(p == 31){ //aged stripes
			var ticker = 1
			for(var i=0; i < q; i++){
				if(ticker > vizAmount){ticker=1}
				
				newMatrix.h[i] = vc.h[ticker];
				newMatrix.s[i] = vc.s[ticker];
				newMatrix.l[i] = Math.max(0, Math.min(100, vc.l[ticker]-20+(+Math.random()*0.4)*100 ))
				var newColor = hslToRgb(newMatrix.h[i]/360, newMatrix.s[i], newMatrix.l[i])
				newMatrix.r[i] = newColor[0];	newMatrix.g[i] = newColor[1];	newMatrix.b[i] = newColor[2];
				newMatrix[i] = 'hsl('+ newMatrix.h[i] +','+ newMatrix.s[i] +'%,'+ newMatrix.l[i] +'%)';	
				
				ticker++
			}		
		}

		else if(p == 110){ //Rainbow 
			for(var i=0; i < q; i++){
				
				newMatrix.h[i] = i/q*360;;
				newMatrix.s[i] = 100;
				newMatrix.l[i] = 50;		
				var	newColor = hslToRgb(newMatrix.h[i]/360, newMatrix.s[i], newMatrix.l[i])			
				newMatrix.r[i] = newColor[0];	newMatrix.g[i] = newColor[1];	newMatrix.b[i] = newColor[2];	
				newMatrix[i] = 'hsl('+ newMatrix.h[i] +','+ newMatrix.s[i] +'%,'+ newMatrix.l[i] +'%)';
				
			}		
		}
		else if(p == 111){ //Aged Rainbow (random luminosity) 
			for(var i=0; i < q; i++){

				newMatrix.h[i] = i/q*360;
				newMatrix.s[i] = 100;
				newMatrix.l[i] = (Math.random()*0.6+0.06)*100
				var	newColor = hslToRgb(newMatrix.h[i]/360, newMatrix.s[i], newMatrix.l[i])			
				newMatrix.r[i] = newColor[0];	newMatrix.g[i] = newColor[1];	newMatrix.b[i] = newColor[2];	
				newMatrix[i] = 'hsl('+ newMatrix.h[i] +','+ newMatrix.s[i] +'%,'+ newMatrix.l[i] +'%)';
		
			}		
		}
		else if(p == 112){ //Emo Rainbow (darker)
			for(var i=0; i < q; i++){

				newMatrix.h[i] = i/q*360;
				newMatrix.s[i] = 100;
				newMatrix.l[i] = 25;		
				var	newColor = hslToRgb(newMatrix.h[i]/360, newMatrix.s[i], newMatrix.l[i])			
				newMatrix.r[i] = newColor[0];	newMatrix.g[i] = newColor[1];	newMatrix.b[i] = newColor[2];	
				newMatrix[i] = 'hsl('+ newMatrix.h[i] +','+ newMatrix.s[i] +'%,'+ newMatrix.l[i] +'%)';

			}		
		}
		else if(p == 113){ //Easter Rainbow (lighter)
			for(var i=0; i < q; i++){

				newMatrix.h[i] = i/q*360;
				newMatrix.s[i] = 100;
				newMatrix.l[i] = 75;		
				var	newColor = hslToRgb(newMatrix.h[i]/360, newMatrix.s[i], newMatrix.l[i])			
				newMatrix.r[i] = newColor[0];	newMatrix.g[i] = newColor[1];	newMatrix.b[i] = newColor[2];	
				newMatrix[i] = 'hsl('+ newMatrix.h[i] +','+ newMatrix.s[i] +'%,'+ newMatrix.l[i] +'%)';

			}		
		}
		else if(p == 114){ //Aged Easter
			for(var i=0; i < q; i++){

				newMatrix.h[i] = i/q*360;
				newMatrix.s[i] = 100;
				newMatrix.l[i] = (Math.random()*0.25+0.575)*100
				var	newColor = hslToRgb(newMatrix.h[i]/360, newMatrix.s[i], newMatrix.l[i])			
				newMatrix.r[i] = newColor[0];	newMatrix.g[i] = newColor[1];	newMatrix.b[i] = newColor[2];	
				newMatrix[i] = 'hsl('+ newMatrix.h[i] +','+ newMatrix.s[i] +'%,'+ newMatrix.l[i] +'%)';

			}		
		}
		else if(p == 115){ //Double Rainbow
			for(var i=0; i < q; i++){

				if(i%2 == 0){	newMatrix.h[i] = i/q*360;}
				else		{	newMatrix.h[i] = i/q*360-50;}
				newMatrix.s[i] = 100;
				newMatrix.l[i] = 50;		
				var	newColor = hslToRgb(newMatrix.h[i]/360, newMatrix.s[i], newMatrix.l[i])			
				newMatrix.r[i] = newColor[0];	newMatrix.g[i] = newColor[1];	newMatrix.b[i] = newColor[2];	
				newMatrix[i] = 'hsl('+ newMatrix.h[i] +','+ newMatrix.s[i] +'%,'+ newMatrix.l[i] +'%)';

			}		
		}
		else if(p == 116){ //Rainbow Blend
			for(var i=0; i < q; i++){

				if(i%2 == 0){	newMatrix.h[i] = i/q*360;}
				else		{	newMatrix.h[i] = i/q*360-20;}
				newMatrix.s[i] = 100;
				newMatrix.l[i] = 50;		
				var	newColor = hslToRgb(newMatrix.h[i]/360, newMatrix.s[i], newMatrix.l[i])			
				newMatrix.r[i] = newColor[0];	newMatrix.g[i] = newColor[1];	newMatrix.b[i] = newColor[2];	
				newMatrix[i] = 'hsl('+ newMatrix.h[i] +','+ newMatrix.s[i] +'%,'+ newMatrix.l[i] +'%)';

			}		
		}
		else if(p == 120){ //Skittles (random colors) 
			for(var i=0; i < q; i++){

				newMatrix.h[i] = 360*Math.random();
				newMatrix.s[i] = 100;
				newMatrix.l[i] = 50;		
				var	newColor = hslToRgb(newMatrix.h[i]/360, newMatrix.s[i], newMatrix.l[i])			
				newMatrix.r[i] = newColor[0];	newMatrix.g[i] = newColor[1];	newMatrix.b[i] = newColor[2];	
				newMatrix[i] = 'hsl('+ newMatrix.h[i] +','+ newMatrix.s[i] +'%,'+ newMatrix.l[i] +'%)';
				
			}		
		}
		else if(p == 121){ //Aged Skittles (random colors & luminosity) 
			for(var i=0; i < q; i++){

				newMatrix.h[i] = 360*Math.random();
				newMatrix.s[i] = 100;
				newMatrix.l[i] = (Math.random()*0.6+0.06)*100;
				var	newColor = hslToRgb(newMatrix.h[i]/360, newMatrix.s[i], newMatrix.l[i])			
				newMatrix.r[i] = newColor[0];	newMatrix.g[i] = newColor[1];	newMatrix.b[i] = newColor[2];	
				newMatrix[i] = 'hsl('+ newMatrix.h[i] +','+ newMatrix.s[i] +'%,'+ newMatrix.l[i] +'%)';
					
			}		
		}
		else if(p == 122){ //Emo Skittles (dark colors) 
			for(var i=0; i < q; i++){

				newMatrix.h[i] = 360*Math.random();
				newMatrix.s[i] = 100;
				newMatrix.l[i] = 25;		
				var	newColor = hslToRgb(newMatrix.h[i]/360, newMatrix.s[i], newMatrix.l[i])			
				newMatrix.r[i] = newColor[0];	newMatrix.g[i] = newColor[1];	newMatrix.b[i] = newColor[2];	
				newMatrix[i] = 'hsl('+ newMatrix.h[i] +','+ newMatrix.s[i] +'%,'+ newMatrix.l[i] +'%)';
				
			}		
		}
		else if(p == 123){ //Easter Eggs (Lighter) 
			for(var i=0; i < q; i++){

				newMatrix.h[i] = 360*Math.random();
				newMatrix.s[i] = 100;
				newMatrix.l[i] = 75;		
				var	newColor = hslToRgb(newMatrix.h[i]/360, newMatrix.s[i], newMatrix.l[i])			
				newMatrix.r[i] = newColor[0];	newMatrix.g[i] = newColor[1];	newMatrix.b[i] = newColor[2];	
				newMatrix[i] = 'hsl('+ newMatrix.h[i] +','+ newMatrix.s[i] +'%,'+ newMatrix.l[i] +'%)';
				
			}		
		}
		else if(p == 124){ //Aged Easter Eggs 
			for(var i=0; i < q; i++){

				newMatrix.h[i] = 360*Math.random();
				newMatrix.s[i] = 100;
				newMatrix.l[i] = (Math.random()*0.25+0.575)*100;
				var	newColor = hslToRgb(newMatrix.h[i]/360, newMatrix.s[i], newMatrix.l[i])			
				newMatrix.r[i] = newColor[0];	newMatrix.g[i] = newColor[1];	newMatrix.b[i] = newColor[2];	
				newMatrix[i] = 'hsl('+ newMatrix.h[i] +','+ newMatrix.s[i] +'%,'+ newMatrix.l[i] +'%)';
				
			}		
		}
		else if(p == 130){ //Piano 
			var ticker = 0;
			var pk = [1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0];	//wbwwbwbwwbwb
			for(var i=0; i < q; i++){
				if(ticker > 11){ticker=0}
				newMatrix.h[i] = 1
				newMatrix.s[i] = 0;
				newMatrix.l[i] = pk[ticker]*100;
				newMatrix.r[i] = pk[ticker]*255
				newMatrix.g[i] = pk[ticker]*255
				newMatrix.b[i] = pk[ticker]*255
				newMatrix[i] = 'hsl('+ newMatrix.h[i] +','+ newMatrix.s[i] +'%,'+ newMatrix.l[i] +'%)';
				
				ticker++
			}		
		}
		for(var i=0; i < q; i++){	newMatrix.x[i] = rgbToHex(newMatrix.r[i], newMatrix.g[i], newMatrix.b[i]);		}		
			
	return newMatrix
}

function setVizColor(iN, cN, aN){
	if(!hasGradient){
		var A = Math.max( vizFade/10, Math.min(1, aN));	//Fade Amount (Opacity)
		if(vizColorStyle[0] > 0){	var newcStyle='rgba('+vcM.r[iN]+', '+vcM.g[iN]+', '+vcM.b[iN]+', '+A+')';	}				
		else					{	var newcStyle='rgba('+vc.r[cN]+', '+vc.g[cN]+', '+vc.b[cN]+', '+A+')';		}
		CTX.a.strokeStyle= newcStyle;	CTX.a.fillStyle = newcStyle; 
		if(vizColorStyle[0] > 0){	CTX.a.shadowColor = newcStyle;	}
	}	
}

function VizColorGL(iN, cN, aN){
	var A = Math.max( vizFade/10, Math.min(1, aN));	//Fade Amount (Opacity)
	var newcStyle = [1, 1, 1, A];
	if(!hasGradient){
		if(vizColorStyle[0] > 0){	newcStyle= [vcM.r[iN]/255, vcM.g[iN]/255, vcM.b[iN]/255, A];	}				
		else					{	newcStyle= [vc.r[cN]/255,  vc.g[cN]/255,  vc.b[cN]/255,  A];	}
	}
	
	return newcStyle;
}

//============================================================ Viz Code - Canvas =====================================
function clear(c){
	if(c=='agl')	{	gl.clearColor(0, 0, 0, 0); gl.clear(gl.COLOR_BUFFER_BIT); }
	else if(['a', 'c', 'cb'].indexOf(c) > -1)	{	W = CAN[c].width; H = CAN[c].height;	CTX[c].clearRect(0,0, W, H); }
}

function pv(){
	var halfCount = Math.floor(Quantity / 2);
	var defaultPoint = 0.0;
	
	if(vizMode == 1){	//Regular Vu (desc)
		for(var i=0; i < Quantity; i++){
			if(!peakValues[i]){peakValues[i]=defaultPoint}
			peakValues[i] -= vizFallRate/50 //fall rate
			peakValues[i] = Math.max(peakValues[i], sortSamples[0][i]);
		}
	}
	else if(vizMode == 2){	//Negative Vu (asc)
		for(var i=0; i < Quantity; i++){
			/*if(!peakSpeed[i]){peakSpeed[i]=0}
			else if(peakValues>0){}*/
			
			if(!peakValues[i]){peakValues[i]=defaultPoint}
			peakValues[i] += vizFallRate/50 //rise rate
			if(sortSamples[0][i] < peakValues[i]){
				var midVal = (peakValues[i] + sortSamples[0][i])/2
				var midVal2= (midVal-sortSamples[0][i])/2
				peakValues[i] = Math.min(peakValues[i], midVal-midVal2);
			}
			else{
			peakValues[i] = Math.min(peakValues[i], sortSamples[0][i]);				
			}
		}
	}
	else if(vizMode == 3){	//Flow toward audio value
		for(var i=0; i < Quantity; i++){
			if(!peakValues[i]){peakValues[i]=defaultPoint}
			if(sortSamples[0][i] < peakValues[i]){
				if(sortSamples[0][i] > peakValues[i]-vizFallRate/50){peakValues[i] = sortSamples[0][i]}
				else{peakValues[i] -= vizFallRate/50} //Fall toward audiosample
			}
			else{
				if(sortSamples[0][i] < peakValues[i]+vizFallRate/50){peakValues[i] = sortSamples[0][i]}
				else{peakValues[i] += vizFallRate/50} //Rise toward audiosample
			}
		}
	}
	else{	//Normal, no adjustment
		for(var i=0; i < Quantity; i++){
			peakValues[i] = sortSamples[0][i];
		}
	}
}

function vCanvas(){
	acW = CAN.a.width
	acH = CAN.a.height

	CTX.a.shadowBlur= glowBlur;
	CTX.a.lineWidth= vizStroke;	

	
	//========== Animate Gradient color =========
	if(vizColorStyle[0] == 3){
		var vCanvasDiameter = findDist(0, 0, acW, acH);
		if(vizGradAnim){
			if		(vizColorStyle[3] == 101){var gradient=CTX.a.createLinearGradient(-100,0,acW+100,0);}	//LH
			else if (vizColorStyle[3] == 102){var gradient=CTX.a.createLinearGradient(0,-100,0,acH+100);}	//LV
			else if (vizColorStyle[3] == 103){var gradient=CTX.a.createLinearGradient(0,acW,acW,0);	} 		//Gradient - Linear D
			else if (vizColorStyle[3] == 104){var gradient=CTX.a.createLinearGradient(0,0,acW,acW);	} 		//Gradient - Linear D2
			else if (vizColorStyle[3] == 110){var gradient=CTX.a.createRadialGradient(acW/2,acH/2,0,acW/2,acH/2,acH);}	//RM	
			else if (vizColorStyle[3] == 111){var gradient=CTX.a.createRadialGradient(0,0,0,0,0,vCanvasDiameter);	} 	//Gradient - Radial -TL
			else if (vizColorStyle[3] == 112){var gradient=CTX.a.createRadialGradient(acW,0,0,acW,0,vCanvasDiameter);	} 	//Gradient - Radial -TR
			else if (vizColorStyle[3] == 113){var gradient=CTX.a.createRadialGradient(0,acH,0,0,acH,vCanvasDiameter);	} 	//Gradient - Radial -BL
			else if (vizColorStyle[3] == 114){var gradient=CTX.a.createRadialGradient(acW,acH,0,acW,acH,vCanvasDiameter);} 	//Gradient - Radial -BR
			else if (vizColorStyle[3] == 115){var gradient=CTX.a.createRadialGradient(acW/2,acH*1.1,0,acW/2,acH*1.1,(acH+acW+vCanvasDiameter)/3);	} //Gradient -RB
			else if (vizColorStyle[3] == 116){var gradient=CTX.a.createRadialGradient(acW*-0.1,acH/2,0,acW*-0.1,acH/2,vCanvasDiameter);	} //Gradient -RL
			else if (vizColorStyle[3] == 117){var gradient=CTX.a.createRadialGradient(acW/2,acH*-0.1,0,acW/2,acH*-0.1,(acH+acW+vCanvasDiameter)/3);	} //Gradient -RT
			else if (vizColorStyle[3] == 118){var gradient=CTX.a.createRadialGradient(acW*1.1,acH/2,0,acW*1.1,acH/2,vCanvasDiameter);	} //Gradient -RR
		
			for(var i=0; i < vizAmount; i++){
				vizGradOffset[i]+= vizGradAnimSpeed/1000;
				vizGradOffset[i] = r10("floor", vizGradOffset[i], -4)
				if(vizGradOffset[i]>0.999){vizGradOffset[i]=0.001; vizGradOffset["First"] = i;}
				if(vizGradOffset[i]<0.001){vizGradOffset[i]=0.999; vizGradOffset["Last"] = i;}
				}
			if(vizGradAnimSpeed > 0){
				vizGradOffset["Last"] = vizGradOffset["First"] - 1; if(vizGradOffset["Last"]<0){vizGradOffset["Last"] = vizAmount-1;}			
			}	
			else if(vizGradAnimSpeed < 0){
				vizGradOffset["First"] = vizGradOffset["Last"] + 1; if(vizGradOffset["First"] > vizAmount-1){vizGradOffset["First"] = 0;}			
			}	

			
			gradient.addColorStop("0",vc[vizGradOffset["Last"]+1]);
			gradient.addColorStop("1",vc[vizGradOffset["First"]+1]);
			
			for(var i = 0; i < vizAmount; i++){	gradient.addColorStop(""+vizGradOffset[i]+"",vc[i+1]);}
			
		}
		else{
			if		(vizColorStyle[3] == 101){var gradient=CTX.a.createLinearGradient(0,0,acW,0);}	//LH	
			else if	(vizColorStyle[3] == 102){var gradient=CTX.a.createLinearGradient(0,0,0,acH);}	//LV
			else if	(vizColorStyle[3] == 103){var gradient=CTX.a.createLinearGradient(0,acW,acW,0);	} 		//Gradient - Linear D
			else if	(vizColorStyle[3] == 104){var gradient=CTX.a.createLinearGradient(0,0,acW,acW);	} 		//Gradient - Linear D2
			else if	(vizColorStyle[3] == 110){var gradient=CTX.a.createRadialGradient(acW/2,acH/2,0,acW/2,acH/2,acH);}		//RM
			else if (vizColorStyle[3] == 111){var gradient=CTX.a.createRadialGradient(0,0,0,0,0,vCanvasDiameter);	} 		//Gradient - Radial -TL
			else if (vizColorStyle[3] == 112){var gradient=CTX.a.createRadialGradient(acW,0,0,acW,0,vCanvasDiameter);	} 	//Gradient - Radial -TR
			else if (vizColorStyle[3] == 113){var gradient=CTX.a.createRadialGradient(0,acH,0,0,acH,vCanvasDiameter);	} 	//Gradient - Radial -BL
			else if (vizColorStyle[3] == 114){var gradient=CTX.a.createRadialGradient(acW,acH,0,acW,acH,vCanvasDiameter);} 	//Gradient - Radial -BR
			else if (vizColorStyle[3] == 115){var gradient=CTX.a.createRadialGradient(acW/2,acH*1.1,0,acW/2,acH*1.1,(acH+acW+vCanvasDiameter)/3);	} //Gradient -RB
			else if (vizColorStyle[3] == 116){var gradient=CTX.a.createRadialGradient(acW*-0.1,acH/2,0,acW*-0.1,acH/2,vCanvasDiameter);	} //Gradient -RL
			else if (vizColorStyle[3] == 117){var gradient=CTX.a.createRadialGradient(acW/2,acH*-0.1,0,acW/2,acH*-0.1,(acH+acW+vCanvasDiameter)/3);	} //Gradient -RT
			else if (vizColorStyle[3] == 118){var gradient=CTX.a.createRadialGradient(acW*1.1,acH/2,0,acW*1.1,acH/2,vCanvasDiameter);	} //Gradient -RR

			for(var i = 1; i <= vizAmount; i++){	gradient.addColorStop(""+vc.split[i]+"",vc[i]);}
		
		}

		CTX.a.strokeStyle=gradient; CTX.a.fillStyle=gradient;//unfortunately, can't apply gradient to shadow	
	}
	//DebugDisplay.textContent = vizGradAnim  +' : '+ vizAmount +' : '+ vizGradOffset;		
	
	var halfCount = Math.floor(Quantity / 2);


	
	//================= Start Viz =================
	var vX = vizX * acW/2000, vY = vizY * acH/2000; //Adjustable positioning system
	var vLX = vizLX * acW/2000, vLY = vizLY * acH/2000; //Left half of LR
	var vRX = vizRX * acW/2000, vRY = vizRY * acH/2000; //Right half of LR

	
	if(vizType == 0){ //None - clear canvas
		refreshVU++
		if(refreshVU >= setFPS){ //Refresh sprite canvas only occasionally.
			refreshVU=0;
			clear('a');
		}
	}
	else if(vizType == 10){ // Render bars along the full width of the canvas (Adapted from https://steamcommunity.com/sharedfiles/filedetails/?id=786006047 )
		clear('a');  //Transparent BG
		var vizBarPad = vizPad*2;
		var barThickness = acW/Quantity-vizBarPad;
		
		if(vizTypeVar == 0){
			// Begin with the left side 
			CTX.a.shadowColor = LglowColor[3];
			for (var i = 0; i <= halfCount; i++) {
				setVizColor(i, 1, 10*peakValues[i]*0.75);

				var height = (acH)* peakValues[i];
				if(vizSolid){CTX.a.fillRect  (vX +vizBarPad/2+(barThickness+vizBarPad) * i, vY +acH - height, barThickness-vizBarPad/2, height);}
				else		{CTX.a.strokeRect(vX +vizBarPad/2+(barThickness+vizBarPad) * i, vY +acH - height, barThickness-vizBarPad/2, height);}
			}

			// Now draw the right side 
			CTX.a.shadowColor = RglowColor[3];
			for (var i = halfCount+isOdd(Quantity); i < Quantity; i++) {
				setVizColor(i, 2, 10*peakValues[i]*0.75);
				
				var height = (acH)* peakValues[i];
			if(vizSolid){CTX.a.fillRect  (vX +vizBarPad/2+(barThickness+vizBarPad) * i, vY +acH - height, barThickness-vizBarPad/2, height);}
			else		{CTX.a.strokeRect(vX +vizBarPad/2+(barThickness+vizBarPad) * i, vY +acH - height, barThickness-vizBarPad/2, height);}
			}			
		}
		
		else if(vizTypeVar == 1){ //Domed Bars
			var domeR = (barThickness-vizBarPad/2)/2;	if(domeR < 0){domeR *= -1}
			// Begin with the left side 
			CTX.a.shadowColor = LglowColor[3];
			for (var i = 0; i <= halfCount; i++) {
				setVizColor(i, 1, 10*peakValues[i]*0.75);

				var height = (acH)* peakValues[i];
				var vibeX = vX +vizBarPad/2+(barThickness+vizBarPad) *i;
				
				CTX.a.beginPath();
				CTX.a.moveTo(vibeX, vY +acH);
				CTX.a.lineTo(vibeX, vY +acH-height);		
				CTX.a.arc   (vibeX +(barThickness-vizBarPad/2)/2, vY +acH-height, domeR, 1*Math.PI, 2*Math.PI);	
				CTX.a.lineTo(vibeX +barThickness-vizBarPad/2, vY +acH);					
				CTX.a.lineTo(vibeX, vY +acH);
				if(vizSolid){CTX.a.fill();	}	else	{CTX.a.stroke();	}
				CTX.a.closePath();	
			}

			
			// Now draw the right side 
			CTX.a.shadowColor = RglowColor[3];
			for (var i = halfCount+isOdd(Quantity); i < Quantity; i++) {
				setVizColor(i, 2, 10*peakValues[i]*0.75);

				var height = (acH)* peakValues[i];
				var vibeX = vX +vizBarPad/2+(barThickness+vizBarPad) *i;
				
				CTX.a.beginPath();
				CTX.a.moveTo(vibeX, vY +acH);
				CTX.a.lineTo(vibeX, vY +acH-height);		
				CTX.a.arc   (vibeX +(barThickness-vizBarPad/2)/2, vY +acH-height, domeR, 1*Math.PI, 2*Math.PI);	
				CTX.a.lineTo(vibeX +barThickness-vizBarPad/2, vY +acH);					
				CTX.a.lineTo(vibeX, vY +acH);
				if(vizSolid){CTX.a.fill();	}	else	{CTX.a.stroke();	}
				CTX.a.closePath();	
			}			
		}
		
		else if(vizTypeVar == 2){	// Render bars with a curved top
			midPoints = []; //halfway height marks between node and adjacent nodes. These will be curve ends. Curve top will be the amplitude. Adjust when padding is used.
			for (var i = 0; i < Quantity; i++) {
				var lSlant, rSlant; //determine whether side is pointed up or down
				if(peakValues[i-1]-peakValues[i]<0){lSlant = 0.3/(peakValues[i]/peakValues[i-1]);}	else{lSlant = -0.3/(peakValues[i+1]/peakValues[i]);}
				if(peakValues[i+1]-peakValues[i]<0){rSlant = 0.3/(peakValues[i]/peakValues[i-1]);}	else{rSlant = -0.3/(peakValues[i+1]/peakValues[i]);}

				if(i==0){
					if(i==Quantity-1){	midPoints[i]=[0,0];	}
					else{	midPoints[i]=[0, acH* (peakValues[i]+peakValues[i+1])/2];	}
				}
				else if(i==Quantity-1){	midPoints[i]=[acH* (peakValues[i-1]+peakValues[i])/2, 0];	}
				else{	midPoints[i]=[acH* (peakValues[i-1]+peakValues[i])/2+vizBarPad/2*lSlant, acH* (peakValues[i]+peakValues[i+1])/2+vizBarPad/2*rSlant];		}
			}
			
			// Begin with the left side 
			CTX.a.shadowColor = LglowColor[3];
			for (var i = 0; i <= halfCount; i++) {
				setVizColor(i, 1, 10*peakValues[i]*0.75);
			
				var height = (acH)* peakValues[i];
				var vibeX = vX +vizBarPad/2+(barThickness+vizBarPad) *i;
				
				CTX.a.beginPath();
				CTX.a.moveTo			 (vibeX, vY +acH);
				CTX.a.lineTo			 (vibeX, vY +acH-midPoints[i][0]);		
				CTX.a.quadraticCurveTo(vibeX+(barThickness-vizBarPad/2)/2, vY +acH - height, vibeX+(barThickness-vizBarPad/2), vY +acH-midPoints[i][1]);
				CTX.a.lineTo			 (vibeX+(barThickness-vizBarPad/2), vY +acH);
				CTX.a.closePath();	
				
				if(vizSolid){CTX.a.fill();	}
				else		{CTX.a.stroke();	}
			}

			
			// Now draw the right side 
			CTX.a.shadowColor = RglowColor[3];	
			for (var i = halfCount+isOdd(Quantity); i < Quantity; i++) {
				setVizColor(i, 2, 10*peakValues[i]*0.75);
		
				var height = (acH)* peakValues[i];
				var vibeX = vX +vizBarPad/2+(barThickness+vizBarPad) *i;
				
				CTX.a.beginPath();
				CTX.a.moveTo			 (vibeX, vY +acH);
				CTX.a.lineTo			 (vibeX, vY +acH-midPoints[i][0]);		
				CTX.a.quadraticCurveTo(vibeX+(barThickness-vizBarPad/2)/2, vY +acH - height, vibeX+(barThickness-vizBarPad/2), vY +acH-midPoints[i][1]);
				CTX.a.lineTo			 (vibeX+(barThickness-vizBarPad/2), vY +acH);
				CTX.a.closePath();					
				
				if(vizSolid){CTX.a.fill();	}
				else		{CTX.a.stroke();	}
			}
		//DebugDisplay.textContent = sortSamples[0];	
		}
	}
	
	else if(vizType == 20){ // Render Vu Bars "New Copy paste version" *Main bars only
		clear('a');  //Transparent BG
		CTX.a.shadowBlur= 0; CTX.vu.shadowBlur= glowBlur;	CTX.vu.shadowColor= RglowColor[3];	
		CTX.vu.lineWidth= vizStroke;	
	
		var gradient=CTX.vu.createLinearGradient(0,acH,0,0);
		gradient.addColorStop(vuCB1,vizColor[1][3]);	gradient.addColorStop(vuCB2,vizColor[2][3]);	gradient.addColorStop(vuCB3,vizColor[3][3]);				
		var vuPad = vizPad;
		var dbLevels = vuStack+2;
		var vuBarH = acH/dbLevels*(vuH*0.1);
		var barThickness = acW/Quantity-vuPad;	
		var safeRadius = Math.min(barThickness/2, vuBarH/2)//Determine smallest distance (for radius purposes)
		
		//Convert to dB
		for(var i = 0; i < Quantity; i++){
			vuBars[0][i] = 60-Math.round(-20 * Math.log10(peakValues[i])); //Decibel equation
		}				
		
		var Xshift=[];
		Xshift[0]=0;
		Xshift[1]=1.3;
		Xshift[2]=2.6;
		
		//=======Draw sprites on CTX.vu(offscreen). Will copy these to CTX.a=======
		refreshVU++
		if(refreshVU >= setFPS/3){ //Refresh sprite canvas only occasionally.
			refreshVU=0;
			CTX.vu.clearRect(0,0, CAN.vu.width, CAN.vu.height);  //Transparent BG		
			
			//Draw sprite column from bottom to top 
			for(var ii=2; ii<dbLevels; ii++){ //start in the 20s where things are 
				if(!hasGradient){
					if(vizColorStyle[0] > 0){	CTX.a.strokeStyle= vcM[i];	CTX.a.fillStyle = vcM[i];  CTX.a.shadowColor = vcM[i];}				
					else{
						if(ii<=dbLevels*vuCB1*5)		{CTX.a.strokeStyle= vizColor[1][3];	CTX.a.fillStyle = vizColor[1][3];}
						else if(ii<=dbLevels*vuCB2*5)	{CTX.a.strokeStyle= vizColor[2][3];	CTX.a.fillStyle = vizColor[2][3];}							
						else 							{CTX.a.strokeStyle= vizColor[3][3];	CTX.a.fillStyle = vizColor[3][3];}
					}
				}
				else{CTX.a.strokeStyle=gradient;	CTX.a.fillStyle=gradient;}
				
				if(!hasGradient){
					if(ii<=dbLevels*vuCB1*5)		{CTX.vu.strokeStyle= vizColor[1][3];	CTX.vu.fillStyle = vizColor[1][3];}
					else if(ii<=dbLevels*vuCB2*5)	{CTX.vu.strokeStyle= vizColor[2][3];	CTX.vu.fillStyle = vizColor[2][3];}							
					else 							{CTX.vu.strokeStyle= vizColor[3][3];	CTX.vu.fillStyle = vizColor[3][3];}				
				}
				else{CTX.vu.strokeStyle=gradient;	CTX.vu.fillStyle=gradient;}				
				
				if(vuShape[0]==-1){} //none
				if(vuShape[0]==0){ //bars
					CTX.vu.fillRect(vuPad/2+(barThickness+vuPad )* Xshift[0], acH-vuPad/2-((vuBarH+vuPad)*(ii-1)), barThickness, vuBarH);
					CTX.vu.strokeRect(vuPad/2+(barThickness+vuPad) * Xshift[1], acH-vuPad/2-((vuBarH+vuPad)*(ii-1)), barThickness, vuBarH);
				}
				else if(vuShape[0]==1){ //SemiCircles long
					CTX.vu.beginPath();
					CTX.vu.moveTo(vuPad/2+(barThickness+vuPad )* Xshift[0],acH-vuPad/2-((vuBarH+vuPad)*(ii-1))+vuBarH);
					CTX.vu.bezierCurveTo(vuPad/2+(barThickness+vuPad )* Xshift[0], acH-vuPad/2-((vuBarH+vuPad)*(ii-1)),vuPad/2+(barThickness+vuPad )* Xshift[0]+barThickness,acH-vuPad/2-((vuBarH+vuPad)*(ii-1)),vuPad/2+(barThickness+vuPad )* Xshift[0]+barThickness,acH-vuPad/2-((vuBarH+vuPad)*(ii-1))+vuBarH);
					CTX.vu.closePath();				
					CTX.vu.fill();
					CTX.vu.beginPath();
					CTX.vu.moveTo(vuPad/2+(barThickness+vuPad )* Xshift[1],acH-vuPad/2-((vuBarH+vuPad)*(ii-1))+vuBarH);
					CTX.vu.bezierCurveTo(vuPad/2+(barThickness+vuPad )* Xshift[1], acH-vuPad/2-((vuBarH+vuPad)*(ii-1)),vuPad/2+(barThickness+vuPad )* Xshift[1]+barThickness,acH-vuPad/2-((vuBarH+vuPad)*(ii-1)),vuPad/2+(barThickness+vuPad )* Xshift[1]+barThickness,acH-vuPad/2-((vuBarH+vuPad)*(ii-1))+vuBarH);
					CTX.vu.closePath();	
					CTX.vu.stroke();
				}
				else if(vuShape[0]==2){ //triangles
					CTX.vu.beginPath();
					CTX.vu.moveTo(vuPad/2+(barThickness+vuPad )* Xshift[0],acH-vuPad/2-((vuBarH+vuPad)*(ii-1))+vuBarH);
					CTX.vu.lineTo(vuPad/2+(barThickness+vuPad )* Xshift[0]+barThickness/2,acH-vuPad/2-((vuBarH+vuPad)*(ii-1)));		
					CTX.vu.lineTo(vuPad/2+(barThickness+vuPad )* Xshift[0]+barThickness,acH-vuPad/2-((vuBarH+vuPad)*(ii-1))+vuBarH);
					CTX.vu.closePath();						
					CTX.vu.fill();
					CTX.vu.beginPath();
					CTX.vu.moveTo(vuPad/2+(barThickness+vuPad )* Xshift[1],acH-vuPad/2-((vuBarH+vuPad)*(ii-1))+vuBarH);
					CTX.vu.lineTo(vuPad/2+(barThickness+vuPad )* Xshift[1]+barThickness/2,acH-vuPad/2-((vuBarH+vuPad)*(ii-1)));		
					CTX.vu.lineTo(vuPad/2+(barThickness+vuPad )* Xshift[1]+barThickness,acH-vuPad/2-((vuBarH+vuPad)*(ii-1))+vuBarH);
					CTX.vu.closePath();						
					CTX.vu.stroke();
				}
				else if(vuShape[0]==3){ //Chevron
					CTX.vu.beginPath();
					CTX.vu.moveTo(vuPad/2+(barThickness+vuPad )* Xshift[0],acH-vuPad/2-((vuBarH+vuPad)*(ii-1))+vuBarH);
					CTX.vu.lineTo(vuPad/2+(barThickness+vuPad )* Xshift[0]+barThickness/2,acH-vuPad/2-((vuBarH+vuPad)*(ii-1)));		
					CTX.vu.lineTo(vuPad/2+(barThickness+vuPad )* Xshift[0]+barThickness,acH-vuPad/2-((vuBarH+vuPad)*(ii-1))+vuBarH);
					CTX.vu.lineTo(vuPad/2+(barThickness+vuPad )* Xshift[0]+barThickness/2,acH-vuPad/2-((vuBarH+vuPad)*(ii-1))+vuBarH/2);
					CTX.vu.closePath();						
					CTX.vu.fill();
					CTX.vu.beginPath();
					CTX.vu.moveTo(vuPad/2+(barThickness+vuPad )* Xshift[1],acH-vuPad/2-((vuBarH+vuPad)*(ii-1))+vuBarH);
					CTX.vu.lineTo(vuPad/2+(barThickness+vuPad )* Xshift[1]+barThickness/2,acH-vuPad/2-((vuBarH+vuPad)*(ii-1)));		
					CTX.vu.lineTo(vuPad/2+(barThickness+vuPad )* Xshift[1]+barThickness,acH-vuPad/2-((vuBarH+vuPad)*(ii-1))+vuBarH);
					CTX.vu.lineTo(vuPad/2+(barThickness+vuPad )* Xshift[1]+barThickness/2,acH-vuPad/2-((vuBarH+vuPad)*(ii-1))+vuBarH/2);
					CTX.vu.closePath();		
					CTX.vu.stroke();
				}
				else if(vuShape[0]==4){ //Chevron 2
					CTX.vu.beginPath();
					CTX.vu.moveTo(vuPad/2+(barThickness+vuPad )* Xshift[0],acH-vuPad/2-((vuBarH+vuPad)*(ii-1))+vuBarH);
					CTX.vu.lineTo(vuPad/2+(barThickness+vuPad )* Xshift[0],acH-vuPad/2-((vuBarH+vuPad)*(ii-1))+vuBarH/2);
					CTX.vu.lineTo(vuPad/2+(barThickness+vuPad )* Xshift[0]+barThickness/2,acH-vuPad/2-((vuBarH+vuPad)*(ii-1)));		
					CTX.vu.lineTo(vuPad/2+(barThickness+vuPad )* Xshift[0]+barThickness,acH-vuPad/2-((vuBarH+vuPad)*(ii-1))+vuBarH/2);
					CTX.vu.lineTo(vuPad/2+(barThickness+vuPad )* Xshift[0]+barThickness,acH-vuPad/2-((vuBarH+vuPad)*(ii-1))+vuBarH);
					CTX.vu.lineTo(vuPad/2+(barThickness+vuPad )* Xshift[0]+barThickness/2,acH-vuPad/2-((vuBarH+vuPad)*(ii-1))+vuBarH/2);
					CTX.vu.closePath();						
					CTX.vu.fill();
					CTX.vu.beginPath();
					CTX.vu.moveTo(vuPad/2+(barThickness+vuPad )* Xshift[1],acH-vuPad/2-((vuBarH+vuPad)*(ii-1))+vuBarH);
					CTX.vu.lineTo(vuPad/2+(barThickness+vuPad )* Xshift[1],acH-vuPad/2-((vuBarH+vuPad)*(ii-1))+vuBarH/2);
					CTX.vu.lineTo(vuPad/2+(barThickness+vuPad )* Xshift[1]+barThickness/2,acH-vuPad/2-((vuBarH+vuPad)*(ii-1)));		
					CTX.vu.lineTo(vuPad/2+(barThickness+vuPad )* Xshift[1]+barThickness,acH-vuPad/2-((vuBarH+vuPad)*(ii-1))+vuBarH/2);
					CTX.vu.lineTo(vuPad/2+(barThickness+vuPad )* Xshift[1]+barThickness,acH-vuPad/2-((vuBarH+vuPad)*(ii-1))+vuBarH);
					CTX.vu.lineTo(vuPad/2+(barThickness+vuPad )* Xshift[1]+barThickness/2,acH-vuPad/2-((vuBarH+vuPad)*(ii-1))+vuBarH/2);
					CTX.vu.closePath();		
					CTX.vu.stroke();
				}
				else if(vuShape[0]==5){ //Pentagon
					CTX.vu.beginPath();
					CTX.vu.moveTo(vuPad/2+(barThickness+vuPad )* Xshift[0],acH-vuPad/2-((vuBarH+vuPad)*(ii-1))+vuBarH);
					CTX.vu.lineTo(vuPad/2+(barThickness+vuPad )* Xshift[0],acH-vuPad/2-((vuBarH+vuPad)*(ii-1))+vuBarH/2);
					CTX.vu.lineTo(vuPad/2+(barThickness+vuPad )* Xshift[0]+barThickness/2,acH-vuPad/2-((vuBarH+vuPad)*(ii-1)));		
					CTX.vu.lineTo(vuPad/2+(barThickness+vuPad )* Xshift[0]+barThickness,acH-vuPad/2-((vuBarH+vuPad)*(ii-1))+vuBarH/2);
					CTX.vu.lineTo(vuPad/2+(barThickness+vuPad )* Xshift[0]+barThickness,acH-vuPad/2-((vuBarH+vuPad)*(ii-1))+vuBarH);
					CTX.vu.closePath();						
					CTX.vu.fill();
					CTX.vu.beginPath();
					CTX.vu.moveTo(vuPad/2+(barThickness+vuPad )* Xshift[1],acH-vuPad/2-((vuBarH+vuPad)*(ii-1))+vuBarH);
					CTX.vu.lineTo(vuPad/2+(barThickness+vuPad )* Xshift[1],acH-vuPad/2-((vuBarH+vuPad)*(ii-1))+vuBarH/2);
					CTX.vu.lineTo(vuPad/2+(barThickness+vuPad )* Xshift[1]+barThickness/2,acH-vuPad/2-((vuBarH+vuPad)*(ii-1)));		
					CTX.vu.lineTo(vuPad/2+(barThickness+vuPad )* Xshift[1]+barThickness,acH-vuPad/2-((vuBarH+vuPad)*(ii-1))+vuBarH/2);
					CTX.vu.lineTo(vuPad/2+(barThickness+vuPad )* Xshift[1]+barThickness,acH-vuPad/2-((vuBarH+vuPad)*(ii-1))+vuBarH);
					CTX.vu.closePath();		
					CTX.vu.stroke();
				}
				else if(vuShape[0]==6){ //Samus
					CTX.vu.beginPath();
					CTX.vu.moveTo(vuPad/2+(barThickness+vuPad )* Xshift[0]+barThickness*0,acH-vuPad/2-((vuBarH+vuPad)*(ii-1))+vuBarH*0);						
					CTX.vu.lineTo(vuPad/2+(barThickness+vuPad )* Xshift[0]+barThickness*0,acH-vuPad/2-((vuBarH+vuPad)*(ii-1))+vuBarH*7.5/10);						
					CTX.vu.lineTo(vuPad/2+(barThickness+vuPad )* Xshift[0]+barThickness*7.5/10,acH-vuPad/2-((vuBarH+vuPad)*(ii-1))+vuBarH*0);	
					CTX.vu.lineTo(vuPad/2+(barThickness+vuPad )* Xshift[0]+barThickness*2.5/10,acH-vuPad/2-((vuBarH+vuPad)*(ii-1))+vuBarH*1);						
					CTX.vu.lineTo(vuPad/2+(barThickness+vuPad )* Xshift[0]+barThickness*1,acH-vuPad/2-((vuBarH+vuPad)*(ii-1))+vuBarH*2.5/10);						
					CTX.vu.lineTo(vuPad/2+(barThickness+vuPad )* Xshift[0]+barThickness*1,acH-vuPad/2-((vuBarH+vuPad)*(ii-1))+vuBarH*1);	
					CTX.vu.closePath();						
					CTX.vu.fill();
					CTX.vu.beginPath();
					CTX.vu.moveTo(vuPad/2+(barThickness+vuPad )* Xshift[1]+barThickness*0,acH-vuPad/2-((vuBarH+vuPad)*(ii-1))+vuBarH*0);						
					CTX.vu.lineTo(vuPad/2+(barThickness+vuPad )* Xshift[1]+barThickness*0,acH-vuPad/2-((vuBarH+vuPad)*(ii-1))+vuBarH*7.5/10);						
					CTX.vu.lineTo(vuPad/2+(barThickness+vuPad )* Xshift[1]+barThickness*7.5/10,acH-vuPad/2-((vuBarH+vuPad)*(ii-1))+vuBarH*0);	
					CTX.vu.lineTo(vuPad/2+(barThickness+vuPad )* Xshift[1]+barThickness*2.5/10,acH-vuPad/2-((vuBarH+vuPad)*(ii-1))+vuBarH*1);						
					CTX.vu.lineTo(vuPad/2+(barThickness+vuPad )* Xshift[1]+barThickness*1,acH-vuPad/2-((vuBarH+vuPad)*(ii-1))+vuBarH*2.5/10);						
					CTX.vu.lineTo(vuPad/2+(barThickness+vuPad )* Xshift[1]+barThickness*1,acH-vuPad/2-((vuBarH+vuPad)*(ii-1))+vuBarH*1);	
					CTX.vu.closePath();		
					CTX.vu.stroke();
				}
				else if(vuShape[0]==7){ //SemiCircles standard
					drawS("vu", "circle", "F", vuPad/2+(barThickness+vuPad )* Xshift[0]+barThickness/2, acH-vuPad/2-((vuBarH+vuPad)*(ii-1))+vuBarH, safeRadius, CTX.vu.strokeStyle, 0, 0, 1, 2);
					drawS("vu", "circle", "S", vuPad/2+(barThickness+vuPad )* Xshift[1]+barThickness/2, acH-vuPad/2-((vuBarH+vuPad)*(ii-1))+vuBarH, safeRadius, CTX.vu.strokeStyle, 0, 0, 1, 2);
				}
				else if(vuShape[0]==8){ //circles
					drawS("vu", "circle", "F", vuPad/2+(barThickness+vuPad )* Xshift[0]+barThickness/2, acH-vuPad/2-((vuBarH+vuPad)*(ii-1))+vuBarH/2, safeRadius, CTX.vu.strokeStyle, 0, 0, 0, 2);
					drawS("vu", "circle", "S", vuPad/2+(barThickness+vuPad )* Xshift[1]+barThickness/2, acH-vuPad/2-((vuBarH+vuPad)*(ii-1))+vuBarH/2, safeRadius, CTX.vu.strokeStyle, 0, 0, 0, 2);
				}
				else if(vuShape[0]==9){ //smiley
					drawS("vu", "smiley", "F", vuPad/2+(barThickness+vuPad )* Xshift[0]+barThickness/2, acH-vuPad/2-((vuBarH+vuPad)*(ii-1))+vuBarH/2, safeRadius, CTX.vu.strokeStyle, CglowColor[3]);
					drawS("vu", "smiley", "S", vuPad/2+(barThickness+vuPad )* Xshift[1]+barThickness/2, acH-vuPad/2-((vuBarH+vuPad)*(ii-1))+vuBarH/2, safeRadius, CTX.vu.strokeStyle, CglowColor[3]);
				}
				else if(vuShape[0]==10){ //devil
					drawS("vu", "devil", "F", vuPad/2+(barThickness+vuPad )* Xshift[0]+barThickness/2, acH-vuPad/2-((vuBarH+vuPad)*(ii-1))+vuBarH/2, safeRadius, CTX.vu.strokeStyle, CglowColor[3], 0, 9, -90);
					drawS("vu", "devil", "S", vuPad/2+(barThickness+vuPad )* Xshift[1]+barThickness/2, acH-vuPad/2-((vuBarH+vuPad)*(ii-1))+vuBarH/2, safeRadius, CTX.vu.strokeStyle, CglowColor[3], 0, 9, -90);
				}	
				else if(vuShape[0]==11){ //triangle
					drawS("vu", "star", "F", vuPad/2+(barThickness+vuPad )* Xshift[0]+barThickness/2, acH-vuPad/2-((vuBarH+vuPad)*(ii-1))+vuBarH/2, safeRadius, CTX.vu.strokeStyle, 0, 0, 3, -90);
					drawS("vu", "star", "S", vuPad/2+(barThickness+vuPad )* Xshift[1]+barThickness/2, acH-vuPad/2-((vuBarH+vuPad)*(ii-1))+vuBarH/2, safeRadius, CTX.vu.strokeStyle, 0, 0, 3, -90);
				}
				else if(vuShape[0]==12){ //diamond
					drawS("vu", "star", "F", vuPad/2+(barThickness+vuPad )* Xshift[0]+barThickness/2, acH-vuPad/2-((vuBarH+vuPad)*(ii-1))+vuBarH/2, safeRadius, CTX.vu.strokeStyle, 0, 0, 4, -90);
					drawS("vu", "star", "S", vuPad/2+(barThickness+vuPad )* Xshift[1]+barThickness/2, acH-vuPad/2-((vuBarH+vuPad)*(ii-1))+vuBarH/2, safeRadius, CTX.vu.strokeStyle, 0, 0, 4, -90);
				}
				else if(vuShape[0]==13){ //square
					drawS("vu", "star", "F", vuPad/2+(barThickness+vuPad )* Xshift[0]+barThickness/2, acH-vuPad/2-((vuBarH+vuPad)*(ii-1))+vuBarH/2, safeRadius, CTX.vu.strokeStyle, 0, 0, 4, -45);
					drawS("vu", "star", "S", vuPad/2+(barThickness+vuPad )* Xshift[1]+barThickness/2, acH-vuPad/2-((vuBarH+vuPad)*(ii-1))+vuBarH/2, safeRadius, CTX.vu.strokeStyle, 0, 0, 4, -45);
				}
				else if(vuShape[0]==14){ //star5
					drawS("vu", "star", "F", vuPad/2+(barThickness+vuPad )* Xshift[0]+barThickness/2, acH-vuPad/2-((vuBarH+vuPad)*(ii-1))+vuBarH/2, safeRadius, CTX.vu.strokeStyle, 0, 0, 5, -90);
					drawS("vu", "star", "S", vuPad/2+(barThickness+vuPad )* Xshift[1]+barThickness/2, acH-vuPad/2-((vuBarH+vuPad)*(ii-1))+vuBarH/2, safeRadius, CTX.vu.strokeStyle, 0, 0, 5, -90);
				}
				else if(vuShape[0]==15){ //star7
					drawS("vu", "star", "F", vuPad/2+(barThickness+vuPad )* Xshift[0]+barThickness/2, acH-vuPad/2-((vuBarH+vuPad)*(ii-1))+vuBarH/2, safeRadius, CTX.vu.strokeStyle, 0, 0, 7, -90);
					drawS("vu", "star", "S", vuPad/2+(barThickness+vuPad )* Xshift[1]+barThickness/2, acH-vuPad/2-((vuBarH+vuPad)*(ii-1))+vuBarH/2, safeRadius, CTX.vu.strokeStyle, 0, 0, 7, -90);
				}
				else if(vuShape[0]==16){ //star9
					drawS("vu", "star", "F", vuPad/2+(barThickness+vuPad )* Xshift[0]+barThickness/2, acH-vuPad/2-((vuBarH+vuPad)*(ii-1))+vuBarH/2, safeRadius, CTX.vu.strokeStyle, 0, 0, 9, -90);
					drawS("vu", "star", "S", vuPad/2+(barThickness+vuPad )* Xshift[1]+barThickness/2, acH-vuPad/2-((vuBarH+vuPad)*(ii-1))+vuBarH/2, safeRadius, CTX.vu.strokeStyle, 0, 0, 9, -90);
				}
				else if(vuShape[0]==17){ //bubble
					drawS("vu", "bubble", "F", vuPad/2+(barThickness+vuPad )* Xshift[0]+barThickness/2, acH-vuPad/2-((vuBarH+vuPad)*(ii-1))+vuBarH/2, safeRadius, CTX.vu.strokeStyle, 0, 0, vizStroke/3, -90);
					drawS("vu", "bubble", "S", vuPad/2+(barThickness+vuPad )* Xshift[1]+barThickness/2, acH-vuPad/2-((vuBarH+vuPad)*(ii-1))+vuBarH/2, safeRadius, CTX.vu.strokeStyle, 0, 0, vizStroke/3, -90);
				}
			}
			
			// Draw Peak Sprites offscreen
			//CTX.vu.fillStyle = LglowColor[3];
			if(vuShape[1]==0){ //bars
				//CTX.vu.fillRect(vuPad/2+(barThickness+vuPad )* Xshift[2], acH-vuPad/2-((vuBarH+vuPad)*(10)), barThickness, vuBarH); //Obsolete copy paste script. Only use it for main parts now.
			}
		}
		
		
		//===Draw Quantity bars dbLevels high=== Copy FROM "vu" TO "a"
		for(var i=0; i < Quantity; i++){

			//Draw column from bottom to top
			for(var ii=2; ii<dbLevels; ii++){ //start in the 20s where things are 
				if(!hasGradient){
					if(vizColorStyle[0] > 0){	CTX.a.strokeStyle= vcM[i];	CTX.a.fillStyle = vcM[i];  CTX.a.shadowColor = vcM[i];}				
					else{
						if(ii<=dbLevels*vuCB1*5)		{CTX.a.strokeStyle= vizColor[1][3];	CTX.a.fillStyle = vizColor[1][3];}
						else if(ii<=dbLevels*vuCB2*5)	{CTX.a.strokeStyle= vizColor[2][3];	CTX.a.fillStyle = vizColor[2][3];}							
						else 							{CTX.a.strokeStyle= vizColor[3][3];	CTX.a.fillStyle = vizColor[3][3];}
					}
				}
				else{CTX.a.strokeStyle=gradient;	CTX.a.fillStyle=gradient;}
				var vuX = vX +vuPad/2+(barThickness+vuPad )* i;
				var vuY = vY +acH-vuPad/2-((vuBarH+vuPad)*(ii-1));
				
				if(vuShape[0]==-1){ //none
					if(vuBars[0][i] >= (ii*60/dbLevels)){ vuBars[1][i]=ii; }
				}
				else if(vuShape[0]==0 && glowBlur==0){ //Bars... Apparently drawing them is quicker than copying them if there is no shadow/glow to calculate
					if(vuBars[0][i] >= (ii*60/dbLevels)){
						CTX.a.fillRect(vuX, vuY, barThickness, vuBarH);
						vuBars[1][i]=ii;
					}
					else if(vizSolid){CTX.a.strokeRect(vuX, vuY, barThickness, vuBarH);}
				}
				else{ //Everything else
					if(vuBars[0][i] >= (ii*60/dbLevels)){
						CTX.a.drawImage(CTX.vu.canvas,vuPad/2+(barThickness+vuPad )* Xshift[0]-vuPad, vuY-vY, barThickness+vuPad*2, vuBarH, vuX -vuPad, vuY, barThickness+vuPad*2, vuBarH);
						vuBars[1][i]=ii;
					}
					else if(vizSolid){
						CTX.a.drawImage(CTX.vu.canvas,vuPad/2+(barThickness+vuPad )* Xshift[1]-vuPad, vuY-vY, barThickness+vuPad*2, vuBarH, vuX -vuPad, vuY, barThickness+vuPad*2, vuBarH);
						}					
				}
				
			}
			
		}
		
		//Reconcile Peak Caps : Copy FROM "vu" TO "a", implement physics

		for(var i=0; i < Quantity; i++){
			if(!vuPeakBars[i]){vuPeakBars[i]=1}
			if(!vuPeakSpeed[i]){vuPeakSpeed[i]=0}
			
			//Calculate Physics
			if(vuBoing == 1){ // Vu + Gravity
				vuPeakSpeed[i]+= -vizFallRate/6;	 //Assign Fall Speed
				vuPeakBars[i] += vuPeakSpeed[i]; //Implement Fall Speed
				if(vuPeakBars[i] <= vuBars[1][i]){
					vuPeakBars[i] = vuBars[1][i];
					vuPeakSpeed[i] = 0;
				}	
			}
			else if(vuBoing == 2){ // Parachute (Fling up, Float down)
				var vuDiff = Math.floor(vuBars[1][i] - vuPeakBars[i]);
				var nextY = Math.floor(vuPeakBars[i]+ vizFallRate*vuPeakSpeed[i]);
				
				if(vuBars[1][i] >= nextY){ // Toss
					vuPeakSpeed[i] = Math.min(vuDiff*1.1, 15); //New speed, but cap it
					vuPeakBars[i] = vuBars[1][i];					
				}

				if(vuPeakSpeed[i] >= 0){ // Up Momentum
					vuPeakBars[i] += vizFallRate*vuPeakSpeed[i];	
					vuPeakSpeed[i] -= vizFallRate;
				}
				else{ // Peak and Fall
					vuPeakSpeed[i] = -vizFallRate;	 //Assign Fall Speed
					vuPeakBars[i] += vuPeakSpeed[i]; //Implement Fall Speed
				}			
			}
			
			else if(vuBoing == 3){ // Gravity (Fling up, Fall down)
				var vuDiff = Math.floor(vuBars[1][i] - vuPeakBars[i]);
				var nextY = Math.floor(vuPeakBars[i]+ vizFallRate*vuPeakSpeed[i]);
				
				if(vuBars[1][i] >= nextY){
					vuPeakSpeed[i] = Math.min(vuDiff, 15); //New speed, but cap it
					vuPeakBars[i] = vuBars[1][i];					
				}
				vuPeakBars[i] += vizFallRate*vuPeakSpeed[i];	
				vuPeakSpeed[i] -= vizFallRate;					
			}
			
			else if(vuBoing == 4){ // Gravity + Bounce on land
				var vuDiff = Math.floor(vuBars[1][i] - vuPeakBars[i]);
				var nextY = Math.floor(vuPeakBars[i]+ vizFallRate*vuPeakSpeed[i]);
				
				if(vuBars[1][i] >= nextY){
					vuPeakSpeed[i] = -vuPeakSpeed[i]*(9/10) + Math.min(vuDiff, 15); //Reverse portion of old speed, then add additional force, but cap it
					if(vuPeakSpeed[i]<0.13){vuPeakSpeed[i]=0} // Lessen Vibrations
					vuPeakBars[i] = vuBars[1][i];					
				}
				vuPeakBars[i] += vizFallRate*vuPeakSpeed[i];	
				vuPeakSpeed[i] -= vizFallRate;					
			}
			
			else{ // Normal Vu Mode
				vuPeakSpeed[i] = -vizFallRate;
				vuPeakBars[i] -= vizFallRate; //fall rate
				vuPeakBars[i] = Math.max(vuPeakBars[i], vuBars[1][i]);
			}

			//Draw Peaks
			if(vizColorStyle.vp > 0){	CTX.a.strokeStyle= vucPM[i];	CTX.a.fillStyle = vucPM[i];  CTX.a.shadowColor = vucPM[i];}				
			else{						CTX.a.fillStyle = LglowColor[3];		}
//			CTX.a.fillRect(vuPad/2+(barThickness+vuPad )* i, acH-vuPad/2-((vuBarH+vuPad)*(ii-1)), barThickness, vuBarH);
			var vPB = Math.ceil(vuPeakBars[i]);
			var Px = [vX +vuPad/2 +(barThickness+vuPad) *i, vX +vuPad/2 +(barThickness+vuPad) *(i+.5)];
			var Py = vY +acH-vuPad/2-((vuBarH+vuPad) * vPB)
			
			var theShape = 0;
			if(vuPeakSpeed[i] >= 0){theShape = vuShape[1]}
			if(vuPeakSpeed[i] < 0){theShape = vuShape[2]}
			
			if(theShape==-1){ }//none// <(o.0)>
			else if(theShape==0){
				CTX.a.fillRect(Px[0], Py, barThickness, vuBarH);			}
			else if(theShape==1){ //semicircles long
				CTX.a.beginPath();	CTX.a.moveTo(Px[0], Py + vuBarH);
				CTX.a.bezierCurveTo(Px[0], Py, Px[0] +barThickness, Py, Px[0] +barThickness, Py +vuBarH);
				CTX.a.closePath();	CTX.a.fill();
			}
			else if(theShape==2){ //triangles
				CTX.a.beginPath();	CTX.a.moveTo(Px[0], Py +vuBarH);
				CTX.a.lineTo(Px[0] +barThickness/2, Py);		
				CTX.a.lineTo(Px[0] +barThickness, Py +vuBarH);
				CTX.a.closePath();	CTX.a.fill();
			}
			else if(theShape==3){ //chevron
				CTX.a.beginPath();	CTX.a.moveTo(Px[0], Py +vuBarH);
				CTX.a.lineTo(Px[0] +barThickness/2, Py );		
				CTX.a.lineTo(Px[0] +barThickness, Py +vuBarH);
				CTX.a.lineTo(Px[0] +barThickness/2, Py +vuBarH/2);
				CTX.a.closePath();	CTX.a.fill();
			}
			else if(theShape==4){ //chevron 2
				CTX.a.beginPath();	CTX.a.moveTo(Px[0], Py +vuBarH);
				CTX.a.lineTo(Px[0], Py +vuBarH/2);				
				CTX.a.lineTo(Px[0] +barThickness/2, Py );	
				CTX.a.lineTo(Px[0] +barThickness, Py +vuBarH/2);						
				CTX.a.lineTo(Px[0] +barThickness, Py +vuBarH);
				CTX.a.lineTo(Px[0] +barThickness/2, Py +vuBarH/2);
				CTX.a.closePath();	CTX.a.fill();
			}
			else if(theShape==5){ //Pentagon
				CTX.a.beginPath();	CTX.a.moveTo(Px[0], Py +vuBarH);
				CTX.a.lineTo(Px[0], Py +vuBarH/2);				
				CTX.a.lineTo(Px[0] +barThickness/2, Py );	
				CTX.a.lineTo(Px[0] +barThickness, Py +vuBarH/2);						
				CTX.a.lineTo(Px[0] +barThickness, Py +vuBarH);
				CTX.a.closePath();	CTX.a.fill();
			}
			else if(theShape==6){ //Samus
				CTX.a.beginPath();	
				CTX.a.moveTo(Px[0] +barThickness*0, Py +vuBarH*0);						
				CTX.a.lineTo(Px[0] +barThickness*0, Py +vuBarH*7.5/10);						
				CTX.a.lineTo(Px[0] +barThickness*7.5/10, Py +vuBarH*0);	
				CTX.a.lineTo(Px[0] +barThickness*2.5/10, Py +vuBarH*1);						
				CTX.a.lineTo(Px[0] +barThickness*1, Py +vuBarH*2.5/10);						
				CTX.a.lineTo(Px[0] +barThickness*1, Py +vuBarH*1);						
				CTX.a.closePath();	CTX.a.fill();
			}
			else if(theShape==7){ 	drawS("a", "circle", "F",	Px[1], Py +vuBarH,	  safeRadius, CTX.a.fillStyle, 0, 0, 1, 2);		}	//semicircles standard
			else if(theShape==8){ 	drawS("a", "circle", "F",	Px[1], Py +vuBarH/2, safeRadius, CTX.a.fillStyle, 0, 0, 0, 2);		}	//circles
			else if(theShape==9){ 	drawS("a", "smiley", "F",	Px[1], Py +vuBarH/2, safeRadius, CTX.a.fillStyle, CglowColor[3]);	}	//smiley
			else if(theShape==10){ 	drawS("a", "devil", "F",	Px[1], Py +vuBarH/2, safeRadius, CTX.a.fillStyle, CglowColor[3]);	}	//devil
			else if(theShape==11){ 	drawS("a", "star", "F",		Px[1], Py +vuBarH/2, safeRadius, CTX.a.fillStyle, 0, 0, 3, -90);		}	//triangle
			else if(theShape==12){ 	drawS("a", "star", "F",		Px[1], Py +vuBarH/2, safeRadius, CTX.a.fillStyle, 0, 0, 4, -90);		}	//diamond
			else if(theShape==13){ 	drawS("a", "star", "F",		Px[1], Py +vuBarH/2, safeRadius, CTX.a.fillStyle, 0, 0, 4, -45);		}	//square
			else if(theShape==14){	drawS("a", "star", "F",		Px[1], Py +vuBarH/2, safeRadius, CTX.a.fillStyle, 0, 0, 5, -90);		}	//star5
			else if(theShape==15){	drawS("a", "star", "F",		Px[1], Py +vuBarH/2, safeRadius, CTX.a.fillStyle, 0, 0, 7, -90);		}	//star7
			else if(theShape==16){	drawS("a", "star", "F",		Px[1], Py +vuBarH/2, safeRadius, CTX.a.fillStyle, 0, 0, 9, -90);		}	//star9
			else if(theShape==17){ 	drawS("a", "bubble", "S",	Px[1], Py +vuBarH/2, safeRadius, CTX.a.fillStyle, 0, 0, vizStroke/3, -90);	}		//bubble
			else{ //Copy from vu canvas (obsolete for peaks)
				//CTX.a.drawImage(CTX.vu.canvas,vuPad/2+(barThickness+vuPad )* Xshift[2]-vuPad, acH-vuPad/2-((vuBarH+vuPad)*(10)), barThickness+vuPad*2, vuBarH,vuPad/2+(barThickness+vuPad )* i-vuPad, acH-vuPad/2-((vuBarH+vuPad) * vPB), barThickness+vuPad*2, vuBarH);
			}
		}
		if(vuBars[0][0]==-Infinity){	clear('a');	}
	
	//DebugDisplay2.textContent = vuBars[0][0];	
		
	}
	else if(vizType == 21){ // Render Vu Circle(s)
		clear('a');  //Transparent BG
		CTX.a.shadowBlur= 0; CTX.a.shadowBlur= glowBlur;	CTX.a.shadowColor= RglowColor[3];	
		CTX.a.lineWidth= vizStroke;	
	
		//var gradient=CTX.a.createRadialGradient(acW/2,acH/2,0,acW/2,acH/2,acH);	
		//gradient.addColorStop(vuCB1,vizColor[1][3]);	gradient.addColorStop(vuCB2,vizColor[2][3]);	gradient.addColorStop(vuCB3,vizColor[3][3]);				
		var vuPad = vizPad, vuPadW = vizPad/20
		var dbLevels = vuStack+2;
		var vuBarH = acH/dbLevels*(vuH*0.1);
		var barThickness = acW/Quantity-vuPad;	
				
		//Convert to dB
		for(var i = 0; i < Quantity; i++){
			vuBars[0][i] = 60-Math.round(-20 * Math.log10(peakValues[i])); //Decibel equation
			if(!vuBars[1][i]){vuBars[1][i]=2}
		}				
		
		var Xshift=[];
		Xshift[0]=0;
		Xshift[1]=1.2;
		Xshift[2]=2.4;
		
		//Create Coordiante Matrix
		vuC.x	 =	acW/2 +vX;
		vuC.y	 =	acH/2 +vY;
		vuC.circR = Math.max(vcThickness/25 * acH/15 -vuPad, 10); //Smaller than 10px crashes the viz
		vuC.barH = acW/(dbLevels*4)*(vuH/3)-vuPad;
		vuC.rowH = vuC.barH+vuPad
		vuC.topR = vuC.circR +vuC.barH/2;
		vuC.botR = vuC.circR -vuC.barH/2;
		vuC.C=[];	for(var i=0; i < Quantity; i++){vuC.C[i]=[]}
		
	
		for(var i=0; i < Quantity; i++){
			for(var ii=0; ii<dbLevels; ii++){ //start in the 20s where things are 
				if(Quantity == 1 && vuShape[0]==1){ //single circles
					vuC.C[i][ii] = [circPoint(vuC.x, vuC.y, vuC.rowH *ii + vuC.circR,i+0.5,	Quantity, 90), //0:c
									circPoint(vuC.x, vuC.y, vuC.rowH *ii + vuC.topR, i,		Quantity, 90), //1:lt
									circPoint(vuC.x, vuC.y, vuC.rowH *ii + vuC.topR, i+1,	Quantity, 90), //2:rt
									circPoint(vuC.x, vuC.y, vuC.rowH *ii + vuC.botR, i+1,	Quantity, 90), //3:rb
									circPoint(vuC.x, vuC.y, vuC.rowH *ii + vuC.botR, i,		Quantity, 90), //4:lb
									circPoint(vuC.x, vuC.y, vuC.rowH *ii + vuC.topR, i+0.5,	Quantity, 90), //5:ct
									circPoint(vuC.x, vuC.y, vuC.rowH *ii + vuC.circR,i,		Quantity, 90), //6:cl
									circPoint(vuC.x, vuC.y, vuC.rowH *ii + vuC.botR, i+0.5,	Quantity, 90), //7:cb
									circPoint(vuC.x, vuC.y, vuC.rowH *ii + vuC.circR,i+1,	Quantity, 90)];//8:cr
				}
				else{
					vuC.C[i][ii] = [circPoint(vuC.x, vuC.y, vuC.rowH *ii + vuC.circR,i+0.5,		Quantity, 90), //0:c
									circPoint(vuC.x, vuC.y, vuC.rowH *ii + vuC.topR, i+vuPadW,	Quantity, 90), //1:lt
									circPoint(vuC.x, vuC.y, vuC.rowH *ii + vuC.topR, i+1-vuPadW,Quantity, 90), //2:rt
									circPoint(vuC.x, vuC.y, vuC.rowH *ii + vuC.botR, i+1-vuPadW,Quantity, 90), //3:rb
									circPoint(vuC.x, vuC.y, vuC.rowH *ii + vuC.botR, i+vuPadW,	Quantity, 90), //4:lb
									circPoint(vuC.x, vuC.y, vuC.rowH *ii + vuC.topR, i+0.5,		Quantity, 90), //5:ct
									circPoint(vuC.x, vuC.y, vuC.rowH *ii + vuC.circR,i+vuPadW,	Quantity, 90), //6:cl
									circPoint(vuC.x, vuC.y, vuC.rowH *ii + vuC.botR, i+0.5,		Quantity, 90), //7:cb
									circPoint(vuC.x, vuC.y, vuC.rowH *ii + vuC.circR,i+1-vuPadW,Quantity, 90)];//8:cr
				}
								
				
				//Record other useful info
				vuC.C[i][ii].safeR = Math.min(findDist(vuC.C[i][ii][7][0], vuC.C[i][ii][7][1], vuC.C[i][ii][3][0], vuC.C[i][ii][3][1]), findDist(vuC.C[i][ii][7][0], vuC.C[i][ii][7][1], vuC.C[i][ii][0][0], vuC.C[i][ii][0][1]))
				vuC.C[i][ii].topR = vuC.rowH *ii + vuC.topR;
				vuC.C[i][ii].botR = vuC.rowH *ii + vuC.botR;
			}
		}

			

		
		//Draw Vu
		for(var i=0; i < Quantity; i++){
			//Draw column from bottom to top
			for(var ii=0; ii<dbLevels; ii++){ //start in the 20s where things are 
				if(vuBars[0][i] >= (ii*60/dbLevels)){var fill="F"}
				else if(vizSolid){	var fill="S"	}
				else{	var fill="N"	}
				
				if(!hasGradient){
					if(vizColorStyle[0] > 0){	CTX.a.strokeStyle= vcM[i];	CTX.a.fillStyle = vcM[i];  CTX.a.shadowColor = vcM[i];}				
					else{
						if(ii<=dbLevels*vuCB1*5)		{CTX.a.strokeStyle= vizColor[1][3];	CTX.a.fillStyle = vizColor[1][3];}
						else if(ii<=dbLevels*vuCB2*5)	{CTX.a.strokeStyle= vizColor[2][3];	CTX.a.fillStyle = vizColor[2][3];}							
						else 							{CTX.a.strokeStyle= vizColor[3][3];	CTX.a.fillStyle = vizColor[3][3];}
					}
				}
				else{CTX.a.strokeStyle=gradient;	CTX.a.fillStyle=gradient;}

				if(vuShape[0]==-1){} //none				
				else if(vuShape[0]==1){ //Curved Bars
					CTX.a.beginPath();
					CTX.a.arc( vuC.x, vuC.y, vuC.C[i][ii].topR, (vuC.C[i][ii][1][2]+90)* Math.PI/180, (vuC.C[i][ii][2][2]+90)* Math.PI/180, false);
					CTX.a.arc( vuC.x, vuC.y, vuC.C[i][ii].botR, (vuC.C[i][ii][3][2]+90)* Math.PI/180, (vuC.C[i][ii][4][2]+90)* Math.PI/180, true);
					CTX.a.closePath();					
				}
				else if(vuShape[0]==2){ //triangles
					CTX.a.beginPath();
					CTX.a.moveTo(vuC.C[i][ii][4][0], vuC.C[i][ii][4][1]);
					CTX.a.lineTo(vuC.C[i][ii][5][0], vuC.C[i][ii][5][1]);		
					CTX.a.lineTo(vuC.C[i][ii][3][0], vuC.C[i][ii][3][1]);
					CTX.a.lineTo(vuC.C[i][ii][4][0], vuC.C[i][ii][4][1]);
					CTX.a.closePath();						
				}
				else if(vuShape[0]==3){ //chevron
					CTX.a.beginPath();
					CTX.a.moveTo(vuC.C[i][ii][4][0], vuC.C[i][ii][4][1]);
					CTX.a.lineTo(vuC.C[i][ii][5][0], vuC.C[i][ii][5][1]);	
					CTX.a.lineTo(vuC.C[i][ii][3][0], vuC.C[i][ii][3][1]);
					CTX.a.lineTo(vuC.C[i][ii][0][0], vuC.C[i][ii][0][1]);	
					CTX.a.lineTo(vuC.C[i][ii][4][0], vuC.C[i][ii][4][1]);
					CTX.a.closePath();		
				}
				else if(vuShape[0]==4){ //chevron 2
					CTX.a.beginPath();
					CTX.a.moveTo(vuC.C[i][ii][4][0], vuC.C[i][ii][4][1]);
					CTX.a.lineTo(vuC.C[i][ii][6][0], vuC.C[i][ii][6][1]);	
					CTX.a.lineTo(vuC.C[i][ii][5][0], vuC.C[i][ii][5][1]);	
					CTX.a.lineTo(vuC.C[i][ii][8][0], vuC.C[i][ii][8][1]);	
					CTX.a.lineTo(vuC.C[i][ii][3][0], vuC.C[i][ii][3][1]);
					CTX.a.lineTo(vuC.C[i][ii][0][0], vuC.C[i][ii][0][1]);	
					CTX.a.lineTo(vuC.C[i][ii][4][0], vuC.C[i][ii][4][1]);
					CTX.a.closePath();		
				}
				else if(vuShape[0]==5){ //Curved chevron
					CTX.a.beginPath();
					CTX.a.moveTo(vuC.C[i][ii][4][0], vuC.C[i][ii][4][1]);
					CTX.a.lineTo(vuC.C[i][ii][6][0], vuC.C[i][ii][6][1]);	
					CTX.a.lineTo(vuC.C[i][ii][5][0], vuC.C[i][ii][5][1]);	
					CTX.a.lineTo(vuC.C[i][ii][8][0], vuC.C[i][ii][8][1]);	
					CTX.a.arc( vuC.x, vuC.y, vuC.C[i][ii].botR, (vuC.C[i][ii][3][2]+90)* Math.PI/180, (vuC.C[i][ii][4][2]+90)* Math.PI/180, true);
					CTX.a.closePath();		
				}				
				else if(vuShape[0]==6){ //Spiral
					CTX.a.beginPath();
					CTX.a.moveTo(vuC.C[i][ii][4][0], vuC.C[i][ii][4][1]);
					CTX.a.lineTo(vuC.C[i][ii][2][0], vuC.C[i][ii][2][1]);				
					CTX.a.lineTo(vuC.C[(i+1)%Quantity][ii][5][0], vuC.C[(i+1)%Quantity][ii][5][1]);	
					CTX.a.lineTo(vuC.C[i][ii][7][0], vuC.C[i][ii][7][1]);	
					CTX.a.closePath();		
				}				
				else if(vuShape[0]==7){ 	drawS("a", "circle", fill,	vuC.C[i][ii][7][0], vuC.C[i][ii][7][1], vuC.C[i][ii].safeR, CTX.a.fillStyle, 0, 0, vuC.C[i][ii][0][2]/180, vuC.C[i][ii][0][2]/180+1);		}	//semicircles standard
				else if(vuShape[0]==8){ 	drawS("a", "circle", fill,	vuC.C[i][ii][0][0], vuC.C[i][ii][0][1], vuC.C[i][ii].safeR, CTX.a.fillStyle, 0, 0, 0, 2);		}								//circles
				else if(vuShape[0]==9){ 	drawS("a", "smiley", fill,	vuC.C[i][ii][0][0], vuC.C[i][ii][0][1], vuC.C[i][ii].safeR, CTX.a.fillStyle, CglowColor[3],0,0,vuC.C[i][ii][0][2]+90);	}	//smiley
				else if(vuShape[0]==10){ 	drawS("a", "devil", fill,	vuC.C[i][ii][0][0], vuC.C[i][ii][0][1], vuC.C[i][ii].safeR, CTX.a.fillStyle, CglowColor[3],0,0,vuC.C[i][ii][0][2]+90);	}	//devil
				else if(vuShape[0]==11){ 	drawS("a", "star", fill,	vuC.C[i][ii][0][0], vuC.C[i][ii][0][1], vuC.C[i][ii].safeR, CTX.a.fillStyle, 0, 0, 3, vuC.C[i][ii][0][2]+90);	}			//triangle
				else if(vuShape[0]==12){ 	drawS("a", "star", fill,	vuC.C[i][ii][0][0], vuC.C[i][ii][0][1], vuC.C[i][ii].safeR, CTX.a.fillStyle, 0, 0, 4, vuC.C[i][ii][0][2]+90);	}			//diamond
				else if(vuShape[0]==13){ 	drawS("a", "star", fill,	vuC.C[i][ii][0][0], vuC.C[i][ii][0][1], vuC.C[i][ii].safeR, CTX.a.fillStyle, 0, 0, 4, vuC.C[i][ii][0][2]+45);	}			//square
				else if(vuShape[0]==14){ 	drawS("a", "star", fill,	vuC.C[i][ii][0][0], vuC.C[i][ii][0][1], vuC.C[i][ii].safeR, CTX.a.fillStyle, 0, 0, 5, vuC.C[i][ii][0][2]+90);	}			//star 5
				else if(vuShape[0]==15){ 	drawS("a", "star", fill,	vuC.C[i][ii][0][0], vuC.C[i][ii][0][1], vuC.C[i][ii].safeR, CTX.a.fillStyle, 0, 0, 7, vuC.C[i][ii][0][2]+90);	}			//star 7
				else if(vuShape[0]==16){ 	drawS("a", "star", fill,	vuC.C[i][ii][0][0], vuC.C[i][ii][0][1], vuC.C[i][ii].safeR, CTX.a.fillStyle, 0, 0, 9, vuC.C[i][ii][0][2]+90);	}			//star 9
				else if(vuShape[0]==17){ 	drawS("a", "bubble", fill,	vuC.C[i][ii][0][0], vuC.C[i][ii][0][1], vuC.C[i][ii].safeR, CTX.a.fillStyle, 0, 0, vizStroke/3, vuC.C[i][ii][0][2]+90);	}	//bubble
				else{
					CTX.a.beginPath();
					CTX.a.moveTo(vuC.C[i][ii][1][0], vuC.C[i][ii][1][1]);
					CTX.a.lineTo(vuC.C[i][ii][2][0], vuC.C[i][ii][2][1]);		
					CTX.a.lineTo(vuC.C[i][ii][3][0], vuC.C[i][ii][3][1]);
					CTX.a.lineTo(vuC.C[i][ii][4][0], vuC.C[i][ii][4][1]);		
					CTX.a.lineTo(vuC.C[i][ii][1][0], vuC.C[i][ii][1][1]);
					CTX.a.closePath();	
				}



				if(vuShape[0] > -1){
					if(vuBars[0][i] >= (ii*60/dbLevels)){
						if(vuShape[0] < 7){CTX.a.fill();}
						vuBars[1][i]=ii;
					}
					else if(vizSolid){ 	CTX.a.stroke();	}					
				}
				else if(vuBars[0][i] >= (ii*60/dbLevels)){	vuBars[1][i]=ii;	}
								
				
				
				
				
			}
		}
	
		if(vuShape[1] > -1){
			//Reconcile Peak Caps : Copy FROM "vu" TO "a", implement physics
			for(var i=0; i < Quantity; i++){

				if(!vuPeakBars[i]){vuPeakBars[i]=1}
				if(!vuPeakSpeed[i]){vuPeakSpeed[i]=0}
				
				// Start Physics Calculations
				if(vuBoing == 1){ // Vu + Gravity
					vuPeakSpeed[i]+= -vizFallRate/6;	 //Assign Fall Speed
					vuPeakBars[i] += vuPeakSpeed[i]; //Implement Fall Speed
					if(vuPeakBars[i] <= vuBars[1][i]){
						vuPeakBars[i] = vuBars[1][i]+1;
						vuPeakSpeed[i] = 0;
					}	
				}
				else if(vuBoing == 2){ // Parachute (Fling up, Float down)
					var vuDiff = Math.floor(vuBars[1][i] - vuPeakBars[i]);
					var nextY = Math.floor(vuPeakBars[i]+ vizFallRate*vuPeakSpeed[i]);
					
					if(vuBars[1][i] >= nextY){ // Toss
						vuPeakSpeed[i] = Math.min(vuDiff*1.1, 15); //New speed, but cap it
						vuPeakBars[i] = vuBars[1][i]+1;					
					}

					if(vuPeakSpeed[i] >= 0){ // Up Momentum
						vuPeakBars[i] += vizFallRate*vuPeakSpeed[i];	
						vuPeakSpeed[i] -= vizFallRate;
					}
					else{ // Peak and Fall
						vuPeakSpeed[i] = -vizFallRate;	 //Assign Fall Speed
						vuPeakBars[i] += vuPeakSpeed[i]; //Implement Fall Speed
					}			
				}
				
				else if(vuBoing == 3){ // Gravity (Fling up, Fall down)
					var vuDiff = Math.floor(vuBars[1][i] - vuPeakBars[i]);
					var nextY = Math.floor(vuPeakBars[i]+ vizFallRate*vuPeakSpeed[i]);
					
					if(vuBars[1][i] >= nextY){
						vuPeakSpeed[i] = Math.min(vuDiff, 15); //New speed, but cap it
						vuPeakBars[i] = vuBars[1][i]+1;					
					}
					vuPeakBars[i] += vizFallRate*vuPeakSpeed[i];	
					vuPeakSpeed[i] -= vizFallRate;					
				}
				
				else if(vuBoing == 4){ // Gravity + Bounce on land
					var vuDiff = Math.floor(vuBars[1][i] - vuPeakBars[i]);
					var nextY = Math.floor(vuPeakBars[i]+ vizFallRate*vuPeakSpeed[i]);
					
					if(vuBars[1][i] >= nextY){
						vuPeakSpeed[i] = -vuPeakSpeed[i]*(9/10) + Math.min(vuDiff, 15); //Reverse portion of old speed, then add additional force, but cap it
						if(vuPeakSpeed[i]<0.13){vuPeakSpeed[i]=0} // Lessen Vibrations
						vuPeakBars[i] = vuBars[1][i]+1;					
					}
					vuPeakBars[i] += vizFallRate*vuPeakSpeed[i];	
					vuPeakSpeed[i] -= vizFallRate;					
				}
				
				else{ // Normal Vu Mode
					vuPeakSpeed[i] = -vizFallRate;
					vuPeakBars[i] -= vizFallRate; //fall rate
					vuPeakBars[i] = Math.max(vuPeakBars[i], vuBars[1][i]+1);
				}
	
				//Make sure there is Drawing data for outside the matrix
				var vPB = Math.ceil(vuPeakBars[i])
				if(vPB >= dbLevels){ //start in the 20s where things are 

					if(Quantity == 1 && vuShape[1]==1){ //single circles
						vuC.C[i][vPB] = [circPoint(vuC.x, vuC.y, vuC.rowH *vPB + vuC.circR,i+0.5,	Quantity, 90), //0:c
											circPoint(vuC.x, vuC.y, vuC.rowH *vPB + vuC.topR, i,	Quantity, 90), //1:lt
											circPoint(vuC.x, vuC.y, vuC.rowH *vPB + vuC.topR, i+1,	Quantity, 90), //2:rt
											circPoint(vuC.x, vuC.y, vuC.rowH *vPB + vuC.botR, i+1,	Quantity, 90), //3:rb
											circPoint(vuC.x, vuC.y, vuC.rowH *vPB + vuC.botR, i,	Quantity, 90), //4:lb
											circPoint(vuC.x, vuC.y, vuC.rowH *vPB + vuC.topR, i+0.5,Quantity, 90), //5:ct
											circPoint(vuC.x, vuC.y, vuC.rowH *vPB + vuC.circR,i,	Quantity, 90), //6:cl
											circPoint(vuC.x, vuC.y, vuC.rowH *vPB + vuC.botR, i+0.5,Quantity, 90), //7:cb
											circPoint(vuC.x, vuC.y, vuC.rowH *vPB + vuC.circR,i+1,	Quantity, 90)];//8:cr
					}
					else{
						vuC.C[i][vPB] = [circPoint(vuC.x, vuC.y, vuC.rowH *vPB + vuC.circR,	i+0.5,			Quantity, 90), //0:c
											circPoint(vuC.x, vuC.y, vuC.rowH *vPB + vuC.topR, i+vuPadW,		Quantity, 90), //1:lt
											circPoint(vuC.x, vuC.y, vuC.rowH *vPB + vuC.topR, i+1-vuPadW,	Quantity, 90), //2:rt
											circPoint(vuC.x, vuC.y, vuC.rowH *vPB + vuC.botR, i+1-vuPadW,	Quantity, 90), //3:rb
											circPoint(vuC.x, vuC.y, vuC.rowH *vPB + vuC.botR, i+vuPadW,		Quantity, 90), //4:lb
											circPoint(vuC.x, vuC.y, vuC.rowH *vPB + vuC.topR, i+0.5,		Quantity, 90), //5:ct
											circPoint(vuC.x, vuC.y, vuC.rowH *vPB + vuC.circR,i+vuPadW,		Quantity, 90), //6:cl
											circPoint(vuC.x, vuC.y, vuC.rowH *vPB + vuC.botR, i+0.5,		Quantity, 90), //7:cb
											circPoint(vuC.x, vuC.y, vuC.rowH *vPB + vuC.circR,i+1-vuPadW,	Quantity, 90)];//8:cr
					}

					
					//Record other useful info
					vuC.C[i][vPB].safeR = findDist(vuC.C[i][vPB][7][0], vuC.C[i][vPB][7][1], vuC.C[i][vPB][3][0], vuC.C[i][vPB][3][1])
					vuC.C[i][vPB].topR = vuC.rowH *vPB + vuC.topR;
					vuC.C[i][vPB].botR = vuC.rowH *vPB + vuC.botR;
				}

			
				//Draw Peaks
				if(vizColorStyle.vp > 0){	CTX.a.strokeStyle= vucPM[i];	CTX.a.fillStyle = vucPM[i];  CTX.a.shadowColor = vucPM[i];}				
				else{						CTX.a.fillStyle = LglowColor[3];		}

				var theShape = 0;
				if(vuPeakSpeed[i] >= 0){theShape = vuShape[1]}
				if(vuPeakSpeed[i] < 0){theShape = vuShape[2]}
				
				if(theShape==-1){ //none
					// <(o.0)>
				}
				else if(theShape==1){ //Curved bars
					CTX.a.beginPath();
					CTX.a.arc( vuC.x, vuC.y, vuC.C[i][vPB].topR, (vuC.C[i][vPB][1][2]+90)* Math.PI/180, (vuC.C[i][vPB][2][2]+90)* Math.PI/180, false);
					CTX.a.arc( vuC.x, vuC.y, vuC.C[i][vPB].botR, (vuC.C[i][vPB][3][2]+90)* Math.PI/180, (vuC.C[i][vPB][4][2]+90)* Math.PI/180, true);
					CTX.a.closePath();	
					CTX.a.fill();
					}
				else if(theShape==2){ //triangles
					CTX.a.beginPath();
					CTX.a.moveTo(vuC.C[i][vPB][4][0], vuC.C[i][vPB][4][1]);
					CTX.a.lineTo(vuC.C[i][vPB][0][0], vuC.C[i][vPB][0][1]);		
					CTX.a.lineTo(vuC.C[i][vPB][3][0], vuC.C[i][vPB][3][1]);
					CTX.a.lineTo(vuC.C[i][vPB][4][0], vuC.C[i][vPB][4][1]);
					CTX.a.closePath();	
					CTX.a.fill();
				}
				else if(theShape==3){ //chevron
					CTX.a.beginPath();
					CTX.a.moveTo(vuC.C[i][vPB][4][0], vuC.C[i][vPB][4][1]);
					CTX.a.lineTo(vuC.C[i][vPB][5][0], vuC.C[i][vPB][5][1]);	
					CTX.a.lineTo(vuC.C[i][vPB][3][0], vuC.C[i][vPB][3][1]);
					CTX.a.lineTo(vuC.C[i][vPB][0][0], vuC.C[i][vPB][0][1]);	
					CTX.a.lineTo(vuC.C[i][vPB][4][0], vuC.C[i][vPB][4][1]);
					CTX.a.closePath();		
					CTX.a.fill();
				}
				else if(theShape==4){ //chevron 2
					CTX.a.beginPath();
					CTX.a.moveTo(vuC.C[i][vPB][4][0], vuC.C[i][vPB][4][1]);
					CTX.a.lineTo(vuC.C[i][vPB][6][0], vuC.C[i][vPB][6][1]);	
					CTX.a.lineTo(vuC.C[i][vPB][5][0], vuC.C[i][vPB][5][1]);	
					CTX.a.lineTo(vuC.C[i][vPB][8][0], vuC.C[i][vPB][8][1]);	
					CTX.a.lineTo(vuC.C[i][vPB][3][0], vuC.C[i][vPB][3][1]);
					CTX.a.lineTo(vuC.C[i][vPB][0][0], vuC.C[i][vPB][0][1]);	
					CTX.a.lineTo(vuC.C[i][vPB][4][0], vuC.C[i][vPB][4][1]);
					CTX.a.closePath();		
					CTX.a.fill();
				}
				else if(theShape==5){ //Curved chevron
					CTX.a.beginPath();
					CTX.a.moveTo(vuC.C[i][vPB][4][0], vuC.C[i][vPB][4][1]);
					CTX.a.lineTo(vuC.C[i][vPB][6][0], vuC.C[i][vPB][6][1]);	
					CTX.a.lineTo(vuC.C[i][vPB][5][0], vuC.C[i][vPB][5][1]);	
					CTX.a.lineTo(vuC.C[i][vPB][8][0], vuC.C[i][vPB][8][1]);	
					CTX.a.arc( vuC.x, vuC.y, vuC.C[i][vPB].botR, (vuC.C[i][vPB][3][2]+90)* Math.PI/180, (vuC.C[i][vPB][4][2]+90)* Math.PI/180, true);
					CTX.a.closePath();		
					CTX.a.fill();
				}	
				else if(theShape==6){ //Spiral
					CTX.a.beginPath();
					CTX.a.moveTo(vuC.C[i][vPB][4][0], vuC.C[i][vPB][4][1]);
					CTX.a.lineTo(vuC.C[i][vPB][2][0], vuC.C[i][vPB][2][1]);				
					CTX.a.lineTo(vuC.C[(i+1)%Quantity][vPB][5][0], vuC.C[(i+1)%Quantity][vPB][5][1]);	
					CTX.a.lineTo(vuC.C[i][vPB][7][0], vuC.C[i][vPB][7][1]);	
					CTX.a.closePath();		
					CTX.a.fill();
				}				
				else if(theShape==7){ 	drawS("a", "circle", "F",	vuC.C[i][vPB][7][0], vuC.C[i][vPB][7][1], vuC.C[i][vPB].safeR, CTX.a.fillStyle, 0, 0, vuC.C[i][vPB][0][2]/180, vuC.C[i][vPB][0][2]/180+1);		}	//semicircles standard
				else if(theShape==8){ 	drawS("a", "circle", "F",	vuC.C[i][vPB][0][0], vuC.C[i][vPB][0][1], vuC.C[i][vPB].safeR, CTX.a.fillStyle, 0, 0, 0, 2);		}								//circles
				else if(theShape==9){ 	drawS("a", "smiley", "F",	vuC.C[i][vPB][0][0], vuC.C[i][vPB][0][1], vuC.C[i][vPB].safeR, CTX.a.fillStyle, CglowColor[3],0,0,vuC.C[i][vPB][0][2]+90);	}	//smiley
				else if(theShape==10){ 	drawS("a", "devil", "F",	vuC.C[i][vPB][0][0], vuC.C[i][vPB][0][1], vuC.C[i][vPB].safeR, CTX.a.fillStyle, CglowColor[3],0,0,vuC.C[i][vPB][0][2]+90);	}	//devil
				else if(theShape==11){ 	drawS("a", "star", "F",		vuC.C[i][vPB][0][0], vuC.C[i][vPB][0][1], vuC.C[i][vPB].safeR, CTX.a.fillStyle, 0, 0, 3, vuC.C[i][vPB][0][2]+90);	}				//triangle
				else if(theShape==12){ 	drawS("a", "star", "F",		vuC.C[i][vPB][0][0], vuC.C[i][vPB][0][1], vuC.C[i][vPB].safeR, CTX.a.fillStyle, 0, 0, 4, vuC.C[i][vPB][0][2]+90);	}				//diamond
				else if(theShape==13){ 	drawS("a", "star", "F",		vuC.C[i][vPB][0][0], vuC.C[i][vPB][0][1], vuC.C[i][vPB].safeR, CTX.a.fillStyle, 0, 0, 4, vuC.C[i][vPB][0][2]+45);	}				//square
				else if(theShape==14){ 	drawS("a", "star", "F",		vuC.C[i][vPB][0][0], vuC.C[i][vPB][0][1], vuC.C[i][vPB].safeR, CTX.a.fillStyle, 0, 0, 5, vuC.C[i][vPB][0][2]+90);	}				//star 5
				else if(theShape==15){ 	drawS("a", "star", "F",		vuC.C[i][vPB][0][0], vuC.C[i][vPB][0][1], vuC.C[i][vPB].safeR, CTX.a.fillStyle, 0, 0, 7, vuC.C[i][vPB][0][2]+90);	}				//star 7
				else if(theShape==16){ 	drawS("a", "star", "F",		vuC.C[i][vPB][0][0], vuC.C[i][vPB][0][1], vuC.C[i][vPB].safeR, CTX.a.fillStyle, 0, 0, 9, vuC.C[i][vPB][0][2]+90);	}				//star 9
				else if(theShape==17){ 	drawS("a", "bubble", "S",	vuC.C[i][vPB][0][0], vuC.C[i][vPB][0][1], vuC.C[i][vPB].safeR, CTX.a.fillStyle, 0, 0, vizStroke/3, vuC.C[i][vPB][0][2]+90);	}		//bubble
				else{ //Bars
					CTX.a.beginPath();
					CTX.a.moveTo(vuC.C[i][vPB][4][0], vuC.C[i][vPB][4][1]);
					CTX.a.lineTo(vuC.C[i][vPB][1][0], vuC.C[i][vPB][1][1]);		
					CTX.a.lineTo(vuC.C[i][vPB][2][0], vuC.C[i][vPB][2][1]);
					CTX.a.lineTo(vuC.C[i][vPB][3][0], vuC.C[i][vPB][3][1]);
					CTX.a.lineTo(vuC.C[i][vPB][4][0], vuC.C[i][vPB][4][1]);
					CTX.a.closePath();	
					CTX.a.fill();
				}
			}
		}
		if(vuBars[0][0]==-Infinity){	clear('a');	}
	
	//DebugDisplay2.textContent = vuC.C[1][2][0][0] +" : "+ vuBars[1][0] +" : "+ vuPeakBars[0] +" : "+vuC.C[1][vuBars[1][0]][0][0];	
		
	}
	
	else if(vizType == 25){ // Render Vu Meters
		clear('a');  //Transparent BG
		CTX.a.shadowBlur= 0; CTX.vu.shadowBlur= glowBlur;	CTX.vu.shadowColor= RglowColor[3];	
		CTX.vu.lineWidth= vizStroke;	
	
		var gradient=CTX.vu.createLinearGradient(0,acH,0,0);
		gradient.addColorStop(vuCB1,vizColor[1][3]);	gradient.addColorStop(vuCB2,vizColor[2][3]);	gradient.addColorStop(vuCB3,vizColor[3][3]);				
		var vuPad = vizPad;
		var dbLevels = vuStack+2;
		var vuSizeAdjust = vuH/3;
		var barThickness = (acW/Quantity)*vuSizeAdjust-vuPad;	
		var safeRadius = Math.min(barThickness/2, vuBarH/2)//Determine smallest distance (for radius purposes)
		
		//Convert to dB
		for(var i = 0; i < Quantity; i++){
			vuBars[0][i] = 60-Math.round(-20 * Math.log10(sortSamples[0][i])); //Decibel equation
		}				
		
		var backX = 0;
		var backY = 0;
		var circX = backX+barThickness*1/2;
		var circY = backY+barThickness*2/3;
		var circR = barThickness*5/12;
		var circR2= circR*11/10;
		var circSw= qGroups/8*vuSizeAdjust;
		
		var frontX = vuPad/2+(barThickness+vuPad )* 2;
		var frontY = 0;
		
		//=======Draw sprites on CTX.vu(offscreen). Will copy these to CTX.a=======
		refreshVU++
		if(refreshVU >= setFPS/3){ //Refresh sprite canvas only occasionally.
			refreshVU=0;
			CTX.vu.clearRect(0,0, CAN.vu.width, CAN.vu.height);  //Transparent BG		
			
			
			//Goal will be to eventually draw Back -> draw Needle -> draw Front -> Draw warning light
			//Draw Meter backing to Sprite canvas (CTX.vu)
			//if(hasGradient == false){	CTX.vu.strokeStyle= vizColor[1][3];	CTX.vu.fillStyle= vizColor[1][3];}	
			//else{						CTX.vu.strokeStyle=gradient;			CTX.vu.fillStyle=gradient;}	


			CTX.vu.shadowColor= "#000"; CTX.vu.shadowBlur=0;
			//BG
			CTX.vu.fillStyle= "#fdec90"
			CTX.vu.fillRect(backX, backY, barThickness, barThickness);	
			//Black Curve
			CTX.vu.lineWidth= qGroups/3*vuSizeAdjust;	
			CTX.vu.strokeStyle= "#000"			
			CTX.vu.beginPath();
				CTX.vu.arc(circX, circY, circR, 1.25*Math.PI, 1.6*Math.PI) 
			CTX.vu.stroke();	
			//Black Strokes
			var cp1 = circPoint(circX, circY, circR, 8, 180, 270);
			var cp2 = circPoint(circX, circY, circR2, 8, 180, 270);
			drawLine("vu", cp1[0], cp1[1], cp2[0], cp2[1], circSw, CTX.vu.lineWidth)
				cp1 = circPoint(circX, circY, circR, 4, 180, 270);
				cp2 = circPoint(circX, circY, circR2, 4, 180, 270);
			drawLine("vu", cp1[0], cp1[1], cp2[0], cp2[1], circSw, CTX.vu.lineWidth)
				cp1 = circPoint(circX, circY, circR, 0, 180, 270);
				cp2 = circPoint(circX, circY, circR2, 0, 180, 270);
			drawLine("vu", cp1[0], cp1[1], cp2[0], cp2[1], circSw, CTX.vu.lineWidth)
				cp1 = circPoint(circX, circY, circR, -4, 180, 270);
				cp2 = circPoint(circX, circY, circR2, -4, 180, 270);
			drawLine("vu", cp1[0], cp1[1], cp2[0], cp2[1], circSw, CTX.vu.lineWidth)			
				cp1 = circPoint(circX, circY, circR, -8, 180, 270);
				cp2 = circPoint(circX, circY, circR2, -8, 180, 270);
			drawLine("vu", cp1[0], cp1[1], cp2[0], cp2[1], circSw, CTX.vu.lineWidth)			
				cp1 = circPoint(circX, circY, circR, -12, 180, 270);
				cp2 = circPoint(circX, circY, circR2, -12, 180, 270);
			drawLine("vu", cp1[0], cp1[1], cp2[0], cp2[1], circSw, CTX.vu.lineWidth)			
				cp1 = circPoint(circX, circY, circR, -16, 180, 270);
				cp2 = circPoint(circX, circY, circR2, -16, 180, 270);
			drawLine("vu", cp1[0], cp1[1], cp2[0], cp2[1], circSw, CTX.vu.lineWidth)			
				cp1 = circPoint(circX, circY, circR, -20, 180, 270);
				cp2 = circPoint(circX, circY, circR2, -20, 180, 270);
			drawLine("vu", cp1[0], cp1[1], cp2[0], cp2[1], circSw, CTX.vu.lineWidth)			
			//Red Curve
			CTX.vu.strokeStyle= "#f00"			
			CTX.vu.beginPath();
				CTX.vu.arc(backX+barThickness/2,backY+barThickness*2/3,barThickness*5/12,1.6*Math.PI,1.75*Math.PI) 
			CTX.vu.stroke();			
			//Red Strokes
				cp1 = circPoint(circX, circY, circR, 12, 180, 270);
				cp2 = circPoint(circX, circY, circR2, 12, 180, 270);
			drawLine("vu", cp1[0], cp1[1], cp2[0], cp2[1], circSw, CTX.vu.lineWidth)
				cp1 = circPoint(circX, circY, circR, 16, 180, 270);
				cp2 = circPoint(circX, circY, circR2, 16, 180, 270);
			drawLine("vu", cp1[0], cp1[1], cp2[0], cp2[1], circSw, CTX.vu.lineWidth)
				cp1 = circPoint(circX, circY, circR, 20, 180, 270);
				cp2 = circPoint(circX, circY, circR2, 20, 180, 270);
			drawLine("vu", cp1[0], cp1[1], cp2[0], cp2[1], circSw, CTX.vu.lineWidth)
			//Text
			CTX.vu.fillStyle="#000"; CTX.vu.font= 9*circSw*vuSizeAdjust+"px Arial";
				CTX.vu.fillText("-20", backX+barThickness*12/128, backY+barThickness*36/128); 
				CTX.vu.fillText("10", backX+barThickness*23/128, backY+barThickness*30/128); 
				CTX.vu.fillText("7", backX+barThickness*35/128, backY+barThickness*27/128); 
				CTX.vu.fillText("5", backX+barThickness*43/128, backY+barThickness*24/128); 
				CTX.vu.fillText("3", backX+barThickness*52/128, backY+barThickness*23/128); 
				CTX.vu.fillText("2", backX+barThickness*62/128, backY+barThickness*22/128); 
				CTX.vu.fillText("1", backX+barThickness*72/128, backY+barThickness*23/128); 
				CTX.vu.fillText("0", backX+barThickness*81/128, backY+barThickness*24/128); 
			CTX.vu.fillStyle="#f00"; 
				CTX.vu.fillText("1", backX+barThickness*90/128, backY+barThickness*27/128); 
				CTX.vu.fillText("2", backX+barThickness*98/128, backY+barThickness*30/128); 
				CTX.vu.fillText("3", backX+barThickness*106/128, backY+barThickness*36/128); 	
			CTX.vu.fillStyle="#dc6"; CTX.vu.font= 30*circSw*vuSizeAdjust+"px Arial";
				CTX.vu.fillText("dB", backX+barThickness*49/128, backY+barThickness*70/128); 
			

			//Draw Meter foreground to Sprite canvas (CTX.vu)
			CTX.vu.strokeStyle= vizColor[2][3];	CTX.vu.fillStyle= vizColor[2][3];
			CTX.vu.fillRect(frontX, frontY, barThickness, barThickness);
			CTX.vu.globalCompositeOperation="xor"		//Cutting
				//Rectangle
				CTX.vu.fillRect(frontX+barThickness*2/32, frontY+barThickness*2/32, barThickness*28/32, barThickness*19/32);			
				//Diamond
				/*CTX.vu.beginPath();
				CTX.vu.moveTo(frontX+barThickness*2/32, frontY+barThickness*9/32);
				CTX.vu.lineTo(frontX+barThickness/2, frontY+barThickness*2/32);		
				CTX.vu.lineTo(frontX+barThickness*30/32, frontY+barThickness*9/32);
				CTX.vu.lineTo(frontX+barThickness/2, frontY+barThickness*24/32);
				CTX.vu.closePath();	
				CTX.vu.fill();*/
			CTX.vu.globalCompositeOperation="source-over"	//Default setting		
				
			
		}
		
		//=====Draw Vu to canvas===== (back+needle+front+light)
		for(var i=0; i < Quantity; i++){
			if(!vuPeakBars[i]){vuPeakBars[i]=1}
			vuPeakBars[i] -= vizFallRate //fall rate
			vuPeakBars[i] = Math.max(vuPeakBars[i], vuBars[0][i]*3/4);
		}
		
		//Back
		CTX.a.shadowBlur= 0;	CTX.a.shadowOffsetX= 0;	CTX.a.shadowOffsetY= 0;
		for(var i=0; i < Quantity; i++){		
			CTX.a.drawImage(CTX.vu.canvas,backX, backY, barThickness, barThickness, vX +i*(acW/Quantity)+vuPad*1.5, vY +acH-barThickness, barThickness-vuPad*2, barThickness-vuPad*2);
		}
		
		//Needle
		var shadow = Math.floor(64/Quantity*vuSizeAdjust)
		CTX.a.lineWidth = circSw;	CTX.a.strokeStyle= "#000";	CTX.a.shadowColor= "#000";
		CTX.a.shadowBlur= shadow;	CTX.a.shadowOffsetX= shadow;	CTX.a.shadowOffsetY= shadow;
		var meterR  = circR2*5/6-vuPad
		var nAdjust = 205;		
		for(var i=0; i < Quantity; i++){		
			var meterCX = vX +i*(acW/Quantity)+vuPad*1.5+barThickness*1/2-vuPad;
			var meterCY = vY +acH-barThickness+barThickness*2/3-vuPad;

			cp1 = circPoint(meterCX, meterCY, meterR*9/10, Math.ceil(vuPeakBars[i]), 180, nAdjust);
			CTX.a.beginPath();
			CTX.a.arc(cp1[0], cp1[1], circSw*2, 0, 2 * Math.PI)
			CTX.a.stroke();
			cp2 = circPoint(meterCX, meterCY, meterR, Math.ceil(vuPeakBars[i]), 180, nAdjust);
			drawLine("a", meterCX, meterCY, cp2[0], cp2[1], circSw*2, CTX.a.lineWidth)			
		}
		
		//Front
		CTX.a.shadowBlur= shadow;	CTX.a.shadowOffsetX= shadow/2;	CTX.a.shadowOffsetY= shadow/2;
		
		for(var i=0; i < Quantity; i++){					
			CTX.a.drawImage(CTX.vu.canvas,frontX, frontY, barThickness, barThickness, vX +i*(acW/Quantity)+vuPad*1.5, vY +acH-barThickness, barThickness-vuPad*2, barThickness-vuPad*2);
		}
		
		//Light
		CTX.a.shadowBlur= shadow;	CTX.a.shadowOffsetX= shadow/5;	CTX.a.shadowOffsetY= shadow/5;		
		for(var i=0; i < Quantity; i++){		
			var meterCX = vX +i*(acW/Quantity)+vuPad*1.5+barThickness*1/2-vuPad;
			var meterCY = vY +acH-barThickness+barThickness*2/3-vuPad;
			CTX.a.fillStyle= vizColor[2][3];
			CTX.a.beginPath();	
			CTX.a.arc(meterCX, meterCY, circSw*15*vuSizeAdjust, 0, 2 * Math.PI)
			CTX.a.fill();	
			if(vuPeakBars[i] > 40) {CTX.a.fillStyle= "#ff0000"}
			else if(vuPeakBars[i] > 35) {CTX.a.fillStyle= "#cc0"}
			else if(vuPeakBars[i] > 32) {CTX.a.fillStyle= "#380"}
			else if(vuPeakBars[i] > 30) {CTX.a.fillStyle= "#270"}
			else if(vuPeakBars[i] > 25) {CTX.a.fillStyle= "#160"}
			else if(vuPeakBars[i] > 20) {CTX.a.fillStyle= "#050"}
			else if(vuPeakBars[i] > 17) {CTX.a.fillStyle= "#032"}
			else{					CTX.a.fillStyle= "#005"}
			CTX.a.beginPath();	
			CTX.a.arc(meterCX, meterCY, circSw*7*vuSizeAdjust, 0, 2 * Math.PI)
			CTX.a.fill();			
		}
		//if(vuBars[0][0]==-Infinity){	clear('a');	}	

			
	//DebugDisplay2.textContent = vuBars[0][0];	
		
	}
	
	else if(vizType == 30 && !vizLR){ // Render vertical vibe
		clear('a');  //Transparent BG
		var vizBarPad = vizPad*2;
		var barThickness = acH/Quantity-vizBarPad;
		
		var vibeX = vX +acW/2;
		if(vizSolid){var seam = 0.75} else {var seam = 0} // cover cracks
			
		if(vizTypeVar == 0){
			// Top
			CTX.a.shadowColor = LglowColor[3];
			for (var i = 0; i <= halfCount; i++) {
				setVizColor(i, 1, 10*peakValues[i]*0.75);
	
				var amplitude = (acW)* peakValues[i];
				var vibeY = vY +vizBarPad/2+(barThickness+vizBarPad) *i;
				
				if(vizSolid){CTX.a.fillRect	(vibeX - amplitude/2, vibeY, amplitude, barThickness-vizBarPad/2+seam);}
				else		{CTX.a.strokeRect(vibeX - amplitude/2, vibeY, amplitude, barThickness-vizBarPad/2+seam);}
			}
			// Bottom 
			CTX.a.shadowColor = RglowColor[3];
			for (var i = halfCount+isOdd(Quantity); i < Quantity; i++) {
				setVizColor(i, 2, 10*peakValues[i]*0.75);

				var amplitude = (acW)* peakValues[i];
				var vibeY = vY +vizBarPad/2+(barThickness+vizBarPad) *i;

				if(vizSolid){CTX.a.fillRect	(vibeX - amplitude/2, vibeY, amplitude, barThickness-vizBarPad/2+seam);}
				else		{CTX.a.strokeRect(vibeX - amplitude/2, vibeY, amplitude, barThickness-vizBarPad/2+seam);}
			}			
		}
		
		else if(vizTypeVar == 1){ //Domed Bars
			var domeR = (barThickness-vizBarPad/2)/2+seam;	if(domeR < 0){domeR *= -1}
			// Top 
			CTX.a.shadowColor = LglowColor[3];
			for (var i = 0; i <= halfCount; i++) {
				setVizColor(i, 1, 10*peakValues[i]*0.75);

				var amplitude = (acW)* peakValues[i];
				var vibeY = vY +vizBarPad/2+(barThickness+vizBarPad) *i;
				
				CTX.a.beginPath();
				CTX.a.moveTo(vibeX+amplitude/2, vibeY);
				CTX.a.lineTo(vibeX-amplitude/2, vibeY);		
				CTX.a.arc   (vibeX-amplitude/2, vibeY +(barThickness-vizBarPad/2)/2+seam, domeR, 1.5*Math.PI, 0.5*Math.PI, true);	
				CTX.a.arc   (vibeX+amplitude/2, vibeY +(barThickness-vizBarPad/2)/2+seam, domeR, 0.5*Math.PI, 1.5*Math.PI, true);	
				if(vizSolid){CTX.a.fill();	}	else	{CTX.a.stroke();	}
				CTX.a.closePath();	
			}

			// Bottom 
			CTX.a.shadowColor = RglowColor[3];
			for (var i = halfCount+isOdd(Quantity); i < Quantity; i++) {
				setVizColor(i, 2, 10*peakValues[i]*0.75);

				var amplitude = (acW)* peakValues[i];
				var vibeY = vY +vizBarPad/2+(barThickness+vizBarPad) *i;
				
				CTX.a.beginPath();
				CTX.a.moveTo(vibeX+amplitude/2, vibeY);
				CTX.a.lineTo(vibeX-amplitude/2, vibeY);		
				CTX.a.arc   (vibeX-amplitude/2, vibeY +(barThickness-vizBarPad/2)/2+seam, domeR, 1.5*Math.PI, 0.5*Math.PI, true);	
				CTX.a.arc   (vibeX+amplitude/2, vibeY +(barThickness-vizBarPad/2)/2+seam, domeR, 0.5*Math.PI, 1.5*Math.PI, true);	
				if(vizSolid){CTX.a.fill();	}	else	{CTX.a.stroke();	}
				CTX.a.closePath();	
			}			
		}
		
		else if(vizTypeVar == 2){	// Render bars with a curved top
			midPoints = []; //halfway height marks between node and adjacent nodes. These will be curve ends. Curve top will be the amplitude. Adjust when padding is used.
			for (var i = 0; i < Quantity; i++) {
				var lSlant, rSlant; //determine whether side is pointed up or down
				if(peakValues[i-1]-peakValues[i]<0){lSlant = 0.3/(peakValues[i]/peakValues[i-1]);}	else{lSlant = -0.3/(peakValues[i+1]/peakValues[i]);}
				if(peakValues[i+1]-peakValues[i]<0){rSlant = 0.3/(peakValues[i]/peakValues[i-1]);}	else{rSlant = -0.3/(peakValues[i+1]/peakValues[i]);}

				if(i==0){
					if(i==Quantity-1){	midPoints[i]=[0,0];	}
					else			{	midPoints[i]=[0, acW* (peakValues[i]+peakValues[i+1])/2];	}
				}
				else if(i==Quantity-1){	midPoints[i]=[acW* (peakValues[i-1]+peakValues[i])/2, 0];	}
				else				{	midPoints[i]=[acW* (peakValues[i-1]+peakValues[i])/2+vizBarPad/2*lSlant, acW* (peakValues[i]+peakValues[i+1])/2+vizBarPad/2*rSlant];		}
			}
			
			// Top 
			CTX.a.shadowColor = LglowColor[3];
			for (var i = 0; i <= halfCount; i++) {
				if(!hasGradient){
					var A = Math.max( vizFade/10, Math.min(1, 10*peakValues[i]*0.75));	//Fade
					if(vizColorStyle[0] > 0){	var newcStyle='rgba('+vcM.r[i]+', '+vcM.g[i]+', '+vcM.b[i]+', '+A+')';	}				
					else					{	var newcStyle='rgba('+vc.r[1]+', '+vc.g[1]+', '+vc.b[1]+', '+A+')';		}
					CTX.a.strokeStyle= newcStyle;	CTX.a.fillStyle = newcStyle; 
					if(vizColorStyle[0] > 0){	CTX.a.shadowColor = newcStyle;	}
				}	
				var amplitude = (acW)* peakValues[i]/3;
				var vibeY = vY +vizBarPad/2+(barThickness+vizBarPad) *i;
				
				CTX.a.beginPath();
				CTX.a.moveTo(vibeX+midPoints[i][0]/3, vibeY);
				CTX.a.lineTo(vibeX-midPoints[i][0]/3, vibeY);		
				CTX.a.quadraticCurveTo(vibeX - amplitude, vibeY+(barThickness-vizBarPad/2)/2, vibeX-midPoints[i][1]/3, vibeY+(barThickness-vizBarPad/2)+seam);
				CTX.a.moveTo(vibeX+midPoints[i][0]/3, vibeY);
				CTX.a.quadraticCurveTo(vibeX + amplitude, vibeY+(barThickness-vizBarPad/2)/2, vibeX+midPoints[i][1]/3, vibeY+(barThickness-vizBarPad/2)+seam);
				CTX.a.lineTo(vibeX-midPoints[i][1]/3, vibeY+(barThickness-vizBarPad/2)+seam);					
			
				if(vizSolid){	CTX.a.closePath(); CTX.a.fill();	}	else	{	CTX.a.stroke();	}
			}

			
			// Bottom 
			CTX.a.shadowColor = RglowColor[3];	
			for (var i = halfCount+isOdd(Quantity); i < Quantity; i++) {
				if(!hasGradient){
					var A = Math.max( vizFade/10, Math.min(1, 10*peakValues[i]*0.75));	//Fade
					if(vizColorStyle[0] > 0){	var newcStyle='rgba('+vcM.r[i]+', '+vcM.g[i]+', '+vcM.b[i]+', '+A+')';	}				
					else					{	var newcStyle='rgba('+vc.r[2]+', '+vc.g[2]+', '+vc.b[2]+', '+A+')';		}
					CTX.a.strokeStyle= newcStyle;	CTX.a.fillStyle = newcStyle; 
					if(vizColorStyle[0] > 0){	CTX.a.shadowColor = newcStyle;	}
				}	
				var amplitude = (acW)* peakValues[i]/3;
				var vibeY = vY +vizBarPad/2+(barThickness+vizBarPad) *i;
				
				CTX.a.beginPath();
				CTX.a.moveTo(vibeX+midPoints[i][0]/3, vibeY);
				CTX.a.lineTo(vibeX-midPoints[i][0]/3, vibeY);		
				CTX.a.quadraticCurveTo(vibeX - amplitude, vibeY+(barThickness-vizBarPad/2)/2, vibeX-midPoints[i][1]/3, vibeY+(barThickness-vizBarPad/2)+seam);
				CTX.a.moveTo(vibeX+midPoints[i][0]/3, vibeY);
				CTX.a.quadraticCurveTo(vibeX + amplitude, vibeY+(barThickness-vizBarPad/2)/2, vibeX+midPoints[i][1]/3, vibeY+(barThickness-vizBarPad/2)+seam);
				CTX.a.lineTo(vibeX-midPoints[i][1]/3, vibeY+(barThickness-vizBarPad/2)+seam);					
			
				if(vizSolid){CTX.a.closePath(); CTX.a.fill();	}	else	{	CTX.a.stroke();	}
			}
		//DebugDisplay.textContent = sortSamples[0];	
		}

	}
	
	else if(vizType == 30 && vizLR){ // Render vertical vibe LR
		clear('a');  //Transparent BG
		if(vizSolid){var seam = 0.75} else {var seam = 0} // cover cracks
		
		// Make data Matrix
		var vizBarPad = vizPad*5;
		var barThickness = acH/Quantity;
		var vibeH = 2*barThickness-vizBarPad;
		var vibeLengthL =[], vibeLengthR =[], vibeY =[];
		var midP =[]; midP.L =[]; midP.R =[]; midP.L.slant =[];  midP.R.slant =[]; //halfway height marks between node and adjacent nodes. These will be curve ends. Curve top will be the amplitude. Adjust when padding is used.
		for (var i = 0; i < halfCount; i++) {
			var iL = halfCount +isOdd(Quantity) -1 -i;
			var iR = halfCount +isOdd(Quantity) +i;
			vibeLengthL[i] = (acW)* peakValues[iL];
			vibeLengthR[i] = (acW)* peakValues[iR];
			vibeY[i] = [vLY +vizBarPad/2+(vibeH+vizBarPad) * i, vRY +vizBarPad/2+(vibeH+vizBarPad) * i];
			
			//Prepare Midpoints
			if(peakValues[iL+1]-peakValues[iL]<0){midP.L.slant[0] = 0.3/(peakValues[iL]/peakValues[iL-1]);}	else{midP.L.slant[0] = -0.3/(peakValues[iL+1]/peakValues[iL]);}
			if(peakValues[iL-1]-peakValues[iL]<0){midP.L.slant[1] = 0.3/(peakValues[iL]/peakValues[iL-1]);}	else{midP.L.slant[1] = -0.3/(peakValues[iL+1]/peakValues[iL]);}
			if(peakValues[iR-1]-peakValues[iR]<0){midP.R.slant[0] = 0.3/(peakValues[iR]/peakValues[iR-1]);}	else{midP.R.slant[0] = -0.3/(peakValues[iR+1]/peakValues[iR]);}
			if(peakValues[iR+1]-peakValues[iR]<0){midP.R.slant[1] = 0.3/(peakValues[iR]/peakValues[iR-1]);}	else{midP.R.slant[1] = -0.3/(peakValues[iR+1]/peakValues[iR]);}

			
			if(i==0){
				if(i==halfCount-1)	{	midP.L[i]=[0,0];
										midP.R[i]=[0,0];	}
				else				{	midP.L[i]=[0, acW* (peakValues[iL]+peakValues[iL-1])/2];
										midP.R[i]=[0, acW* (peakValues[iR]+peakValues[iR+1])/2];	}
			}
			else if(i==halfCount-1)	{	midP.L[i]=[acW* (peakValues[iL+1]+peakValues[iL])/2, 0];
										midP.R[i]=[acW* (peakValues[iR-1]+peakValues[iR])/2, 0];	}
			else					{	midP.L[i]=[acW* (peakValues[iL+1]+peakValues[iL])/2+vizBarPad/2*midP.L.slant[0], acW* (peakValues[iL]+peakValues[iL-1])/2+vizBarPad/2*midP.L.slant[1]];
										midP.R[i]=[acW* (peakValues[iR-1]+peakValues[iR])/2+vizBarPad/2*midP.R.slant[0], acW* (peakValues[iR]+peakValues[iR+1])/2+vizBarPad/2*midP.R.slant[1]];		}			
			
		}

					
		// Begin with the left top (high)
		CTX.a.shadowColor= LglowColor[3]; 	
		for (var i = 0; i < halfCount; i++) {
			var iL = halfCount +isOdd(Quantity) -1 -i;
			var iR = halfCount +isOdd(Quantity) +i;
			setVizColor(i*2, 1, 10*peakValues[iL]*0.75);
			
			if(vizPat == 0)	{	var vibeX  = vLX +acW/2 - vibeLengthL[i];			}
			else if(vizPat == 1){	var vibeX1 = vLX +acW*9/24 - vibeLengthL[i]/2;	var vibeX2 = vRX +acW*15/24 - vibeLengthR[i]/2;	}	
			else if(vizPat == 2){	var vibeX1 = vLX +acW*1/3 - vibeLengthL[i]/2;	var vibeX2 = vRX +acW*2/3 - vibeLengthR[i]/2;	}	
			else if(vizPat == 3){	var vibeX1 = vLX +acW*1/4 - vibeLengthL[i]/2;	var vibeX2 = vRX +acW*3/4 - vibeLengthR[i]/2;	}	
			else if(vizPat == 4){	var vibeX1 = vLX +acW*1/5 - vibeLengthL[i]/2;	var vibeX2 = vRX +acW*4/5 - vibeLengthR[i]/2;	}	
			else if(vizPat == 5){	var vibeX1 = vLX +acW*1/6 - vibeLengthL[i]/2;	var vibeX2 = vRX +acW*5/6 - vibeLengthR[i]/2;	}	
			else if(vizPat == 6){	var vibeX1 = vLX +acW*1/7 - vibeLengthL[i]/2;	var vibeX2 = vRX +acW*6/7 - vibeLengthR[i]/2;	}	
			else if(vizPat == 7){	var vibeX1 = vLX +acW*1/8 - vibeLengthL[i]/2;	var vibeX2 = vRX +acW*7/8 - vibeLengthR[i]/2;	}	
			else if(vizPat >= 8){	var vibeX1 = vLX +0;							var vibeX2 = vRX +acW - vibeLengthR[i];			}					
			
			if(vizTypeVar == 0){ // bars
				if(vizPat == 0){
					if(vizSolid){CTX.a.fillRect	(vibeX, vibeY[i][0], vibeLengthL[i]+vibeLengthR[i], vibeH+seam);}
					else		{CTX.a.strokeRect(vibeX, vibeY[i][0], vibeLengthL[i]+vibeLengthR[i], vibeH);}
				}
				else {
					//L
					if(vizSolid){CTX.a.fillRect	(vibeX1, vibeY[i][0], vibeLengthL[i], vibeH+seam);}
					else		{CTX.a.strokeRect(vibeX1, vibeY[i][0], vibeLengthL[i], vibeH);}
					
					setVizColor(i*2, 2, 10*peakValues[iR]*0.75);
					//R
					if(vizSolid){CTX.a.fillRect	(vibeX2, vibeY[i][1], vibeLengthR[i], vibeH+seam);}
					else		{CTX.a.strokeRect(vibeX2, vibeY[i][1], vibeLengthR[i], vibeH);}
				}
			}
			else if(vizTypeVar == 1){ // domed
				var domeR = (barThickness-vizBarPad/2)+seam;	if(domeR < 0){domeR *= -1}
				if(vizPat == 0){
					CTX.a.beginPath();
					CTX.a.moveTo(vibeX+vibeLengthL[i]+vibeLengthR[i], vibeY[i][0]);
					CTX.a.lineTo(vibeX, vibeY[i][0]);		
					CTX.a.arc   (vibeX, vibeY[i][0] +(barThickness-vizBarPad/2)+seam, domeR, 1.5*Math.PI, 0.5*Math.PI, true);	
					CTX.a.arc   (vibeX+vibeLengthL[i]+vibeLengthR[i], vibeY[i][0] +(barThickness-vizBarPad/2)+seam, domeR, 0.5*Math.PI, 1.5*Math.PI, true);	
					if(vizSolid){CTX.a.fill();	}	else	{CTX.a.stroke();	}
					CTX.a.closePath();	
				}
				else {
					//L
					CTX.a.beginPath();
					CTX.a.moveTo(vibeX1+vibeLengthL[i], vibeY[i][0]);
					CTX.a.lineTo(vibeX1, vibeY[i][0]);	
					if(vizPat >= 8){	CTX.a.lineTo(vibeX1, vibeY[i][0] +(barThickness-vizBarPad/2)*2+seam);	}
					else			{	CTX.a.arc   (vibeX1, vibeY[i][0] +(barThickness-vizBarPad/2)+seam, domeR, 1.5*Math.PI, 0.5*Math.PI, true);	}
					CTX.a.arc   (vibeX1+vibeLengthL[i], vibeY[i][0] +(barThickness-vizBarPad/2)+seam, domeR, 0.5*Math.PI, 1.5*Math.PI, true);	
					if(vizSolid){CTX.a.fill();	}	else	{CTX.a.stroke();	}
					CTX.a.closePath();	
					
					setVizColor(i*2, 2, 10*peakValues[iR]*0.75);
					
					//R
					CTX.a.beginPath();
					CTX.a.moveTo(vibeX2+vibeLengthR[i], vibeY[i][1]);
					CTX.a.lineTo(vibeX2, vibeY[i][1]);		
					CTX.a.arc   (vibeX2, vibeY[i][1] +(barThickness-vizBarPad/2)+seam, domeR, 1.5*Math.PI, 0.5*Math.PI, true);	
					if(vizPat >= 8){	CTX.a.lineTo(vibeX2+vibeLengthR[i], vibeY[i][1] +(barThickness-vizBarPad/2)*2+seam);	}
					else			{	CTX.a.arc   (vibeX2+vibeLengthR[i], vibeY[i][1] +(barThickness-vizBarPad/2)+seam, domeR, 0.5*Math.PI, 1.5*Math.PI, true);	}
					CTX.a.closePath();	
					if(vizSolid){CTX.a.fill();	}	else	{CTX.a.stroke();	}

				}
			}
			else if(vizTypeVar == 2){ // curved
				if(vizPat == 0){
					vibeX = acW/2
					//L
					CTX.a.beginPath();
					CTX.a.moveTo(vibeX+midP.R[i][0]/3, vibeY[i][0]);
					CTX.a.lineTo(vibeX-midP.L[i][0]/3, vibeY[i][0]);	
					CTX.a.quadraticCurveTo(vibeX - vibeLengthL[i]/3, vibeY[i][0]+(barThickness-vizBarPad/2), vibeX-midP.L[i][1]/3, vibeY[i][0]+(barThickness-vizBarPad/2)*2+seam);	
					if(vizSolid){	CTX.a.closePath(); CTX.a.fill();	}	else	{	CTX.a.stroke();	}						

					//R
					CTX.a.moveTo(vibeX+midP.R[i][0]/3, vibeY[i][0]);
					CTX.a.quadraticCurveTo(vibeX + vibeLengthR[i]/3, vibeY[i][0]+(barThickness-vizBarPad/2), vibeX+midP.R[i][1]/3, vibeY[i][0]+(barThickness-vizBarPad/2)*2+seam);
					CTX.a.lineTo(vibeX-midP.L[i][1]/3, vibeY[i][0]+(barThickness-vizBarPad/2)*2+seam);					
					if(vizSolid){	CTX.a.closePath(); CTX.a.fill();	}	else	{	CTX.a.stroke();	}

				}
				else {
					if(vizPat >= 8){	vibeX2 += vibeLengthR[i];} // correction for side walls
					else	{			vibeX1 += vibeLengthL[i]/2;	vibeX2 += vibeLengthR[i]/2;		}
					//L
					CTX.a.beginPath();
					CTX.a.moveTo(vibeX1+midP.L[i][0]/3, vibeY[i][0]);
					CTX.a.lineTo(vibeX1-midP.L[i][0]/3, vibeY[i][0]);					
					if(vizPat < 8){	CTX.a.quadraticCurveTo(vibeX1 - vibeLengthL[i]/3, vibeY[i][0]+(barThickness-vizBarPad/2), vibeX1-midP.L[i][1]/3, vibeY[i][0]+(barThickness-vizBarPad/2)*2+seam);	}
					else			{	CTX.a.lineTo(vibeX1-midP.L[i][1]/3, vibeY[i][0]+(barThickness-vizBarPad/2)*2+seam);}
					if(vizSolid){	}	else	{	CTX.a.stroke();	}					
					CTX.a.moveTo(vibeX1+midP.L[i][0]/3, vibeY[i][0]);
					CTX.a.quadraticCurveTo(vibeX1 + vibeLengthL[i]/3, vibeY[i][0]+(barThickness-vizBarPad/2), vibeX1+midP.L[i][1]/3, vibeY[i][0]+(barThickness-vizBarPad/2)*2+seam);
					CTX.a.lineTo(vibeX1-midP.L[i][1]/3, vibeY[i][0]+(barThickness-vizBarPad/2)*2+seam);	
					if(vizSolid){	CTX.a.closePath(); CTX.a.fill();	}	else	{	CTX.a.stroke();	}
					
					setVizColor(i*2, 2, 10*peakValues[iR]*0.75);

					//R	
					CTX.a.beginPath();
					CTX.a.moveTo(vibeX2+midP.R[i][0]/3, vibeY[i][1]);
					CTX.a.lineTo(vibeX2-midP.R[i][0]/3, vibeY[i][1]);					
					CTX.a.quadraticCurveTo(vibeX2 - vibeLengthR[i]/3, vibeY[i][1]+(barThickness-vizBarPad/2), vibeX2-midP.R[i][1]/3, vibeY[i][1]+(barThickness-vizBarPad/2)*2+seam);	
					if(vizSolid){	}	else	{	CTX.a.stroke();	}	
					CTX.a.moveTo(vibeX2+midP.R[i][0]/3, vibeY[i][1]);
					if(vizPat < 8){	CTX.a.quadraticCurveTo(vibeX2 + vibeLengthR[i]/3, vibeY[i][1]+(barThickness-vizBarPad/2), vibeX2+midP.R[i][1]/3, vibeY[i][1]+(barThickness-vizBarPad/2)*2+seam);	}
					else			{	CTX.a.lineTo(vibeX2+midP.R[i][1]/3, vibeY[i][1]+(barThickness-vizBarPad/2)*2+seam);	}
					CTX.a.lineTo(vibeX2-midP.R[i][1]/3, vibeY[i][1]+(barThickness-vizBarPad/2)*2+seam);	
					if(vizSolid){	CTX.a.closePath(); CTX.a.fill();	}	else	{	CTX.a.stroke();	}
				}
			}
			
		}

		
	}
	
	else if(vizType == 40){ // Render a line along the full width of the canvas
		clear('a');  //Transparent BG
		if(vizTypeVar == 0){
			var barThickness = acW/Quantity;
			CTX.a.lineCap= "round";

			
			//Left side
			CTX.a.shadowColor= LglowColor[3]; 
			for (var i = 0; i < halfCount; i++) {
				setVizColor(i, 1, 10*peakValues[i]*0.75);
				if(hasGradient){CTX.a.strokeStyle=gradient;	CTX.a.fillStyle=gradient;}	
				
				var height = 10 + (acH)* peakValues[i];
				CTX.a.beginPath();
				if(i == 0){CTX.a.moveTo(vX +0,vY +acH);} else {CTX.a.moveTo(lastX,lastY);}
				var lastX = vX +barThickness * (i+.5); var lastY = vY +(acH - height);
				CTX.a.lineTo(lastX,lastY);

				if(vizSolid){		//Make solid
					CTX.a.lineTo(lastX,acH);		
					CTX.a.lineTo(lastX-barThickness,acH);		
					CTX.a.fill();
				}
				else{	CTX.a.stroke(); }			

			}

			//Right Side
			CTX.a.shadowColor= RglowColor[3]; 
			for (var i = halfCount+isOdd(Quantity); i < Quantity; i++) {
				setVizColor(i, 2, 10*peakValues[i]*0.75);
				if(hasGradient){CTX.a.strokeStyle=gradient;	CTX.a.fillStyle=gradient;}	
				
				var height = 10 + (acH)* peakValues[i];
				CTX.a.beginPath();
				CTX.a.moveTo(lastX,lastY);
				var lastX = vX +barThickness * (i +isOdd(Quantity)+.5); var lastY = vY +(acH - height);
				CTX.a.lineTo(lastX, lastY);
				
				if(vizSolid){		//Make solid
					if(i == Quantity-1){CTX.a.lineTo(vX +acW, vY +acH);} else {CTX.a.lineTo(lastX, vY +acH);}			
					CTX.a.lineTo(lastX-barThickness,acH);		
					CTX.a.fill();
				}
				else{	CTX.a.stroke(); }	
			}
			
			if(!vizSolid){	CTX.a.lineTo(vX +acW, vY +acH); CTX.a.stroke(); }
			
			CTX.a.closePath();
			CTX.a.lineCap= "butt";
		}
	
		else if(vizTypeVar > 0){ // Render curvy wire
			var vizBarPad = vizPad*5;
			var barThickness = acW/Quantity-vizBarPad;
			
			midPoints = []; //halfway height marks between node and adjacent nodes. These will be curve ends. Curve top will be the amplitude. Adjust when padding is used.
			for (var i = 0; i < Quantity; i++) {
				var lSlant, rSlant; //determine whether side is pointed up or down
				if(peakValues[i-1]-peakValues[i]<0){lSlant = 0.3/(peakValues[i]/peakValues[i-1]);}	else{lSlant = -0.3/(peakValues[i+1]/peakValues[i]);}
				if(peakValues[i]-peakValues[i+1]<0){rSlant = -0.3/(peakValues[i]/peakValues[i-1]);}	else{rSlant = 0.3/(peakValues[i+1]/peakValues[i]);}

				if(i==0){
					if(i==Quantity-1){	midPoints[i]=[0,0];	}
					else{	midPoints[i]=[0, acH* (peakValues[i]+peakValues[i+1])/2];	}
				}
				else if(i==Quantity-1){	midPoints[i]=[acH* (peakValues[i-1]+peakValues[i])/2, 0];	}
				else{	midPoints[i]=[acH* (peakValues[i-1]+peakValues[i])/2+vizBarPad/2*lSlant, acH* (peakValues[i]+peakValues[i+1])/2+vizBarPad/2*rSlant];		}
			}
			
			// Begin with the left side 
			CTX.a.shadowColor= LglowColor[3]; 	
			CTX.a.moveTo(vX +0, vY +acH);
			for (var i = 0; i <= halfCount; i++) {
				setVizColor(i, 1, 10*peakValues[i]*0.75);
				if(hasGradient){CTX.a.strokeStyle=gradient;	CTX.a.fillStyle=gradient;}	
				
				var height = (acH)* peakValues[i];
				var pX = vX +vizBarPad/2+(barThickness+vizBarPad )* i;
				CTX.a.beginPath();
				CTX.a.lineTo(pX, vY +acH-midPoints[i][0]);		
				CTX.a.quadraticCurveTo(pX +(barThickness-vizBarPad/2)/2, vY +acH - height, pX +(barThickness-vizBarPad/2), vY +acH-midPoints[i][1]);
				
				if(vizSolid){
					CTX.a.lineTo(pX +(barThickness-vizBarPad/2), vY +acH-midPoints[i][1]/2);	
					CTX.a.quadraticCurveTo(pX +(barThickness-vizBarPad/2)/2, vY +acH - height/2, pX, vY +acH-midPoints[i][0]/2);
					CTX.a.fill();
				}
				else		{CTX.a.stroke();	}
			}

			// Now draw the right side 
			CTX.a.shadowColor= RglowColor[3];		
			for (var i = halfCount+isOdd(Quantity); i < Quantity; i++) {
				setVizColor(i, 2, 10*peakValues[i]*0.75);
				if(hasGradient){CTX.a.strokeStyle=gradient;	CTX.a.fillStyle=gradient;}	
				
				var height = (acH)* peakValues[i];
				var pX = vX +vizBarPad/2+(barThickness+vizBarPad )* i;
				CTX.a.beginPath();
				CTX.a.lineTo(pX, vY +acH-midPoints[i][0]);		
				CTX.a.quadraticCurveTo(pX +(barThickness-vizBarPad/2)/2, vY +acH - height, pX +(barThickness-vizBarPad/2), vY +acH-midPoints[i][1]);
				
				if(vizSolid){
					CTX.a.lineTo(pX +(barThickness-vizBarPad/2), vY +acH-midPoints[i][1]/2);	
					CTX.a.quadraticCurveTo(pX +(barThickness-vizBarPad/2)/2, vY +acH - height/2, pX, vY +acH-midPoints[i][0]/2);
					CTX.a.fill();
				}
				else		{CTX.a.stroke();	}
			}
			//DebugDisplay.textContent = sortSamples[0];		
		}
		
	}
	
	else if(vizType == 50 && !vizLR){ // Render a wire vibe
		clear('a');  //Transparent BG
		var barThickness = acH/Quantity;
		//CTX.a.lineWidth= 3;
		
		//Create Array of Points to reference/manipulate
		var coord= [];
		for (var i = 0; i < Quantity; i++) {
			var Amplitude = (acW)* peakValues[i]*.75;
			coord[i]=[vX +(acW/2 - Amplitude),	vY +barThickness * (i+.5),	Amplitude];
		}
		
		//Draw it
		if(vizSolid || vizTypeVar < 2){
			CTX.a.shadowColor= LglowColor[3];
			
			for(var i = 0; i< Quantity; i++){
				setVizColor(i, 1, 10*peakValues[i]*0.75);
				if(hasGradient){CTX.a.strokeStyle=gradient;	CTX.a.fillStyle=gradient;}	
				
				CTX.a.beginPath();
				if(i==0){CTX.a.moveTo(vX +acW/2,vY +0);}	else{CTX.a.moveTo(coord[i-1][0],coord[i-1][1]);}//Start Point
				CTX.a.lineTo(coord[i][0], coord[i][1]+1); //Left Line
				
				if(!vizSolid){
					CTX.a.stroke(); CTX.a.closePath();CTX.a.beginPath();
					if(i==0){CTX.a.moveTo(vX +acW/2, vY +0);}	else{CTX.a.moveTo(coord[i-1][0]+coord[i-1][2]*2,coord[i-1][1]);}//Start Point
				}
				else{
					CTX.a.lineTo(vX +acW/2+1.5,coord[i][1]+1);				
					if(i==0){CTX.a.lineTo(vX +acW/2+1, vY +0);}	else{CTX.a.lineTo(vX +acW/2+1,coord[i-1][1]-1);}
					CTX.a.fill();	
					CTX.a.closePath();CTX.a.beginPath();	
					CTX.a.moveTo(vX +acW/2+1,coord[i][1]+1);
				}
				if(!hasGradient && vizColorStyle[0] == 0){	CTX.a.strokeStyle= vc[2];	CTX.a.fillStyle = vc[2];	}
				
				CTX.a.lineTo(coord[i][0]+coord[i][2]*2, coord[i][1]); //Right Line
				
				if(vizSolid){
					if(i==0){CTX.a.lineTo(vX +acW/2, vY +0);}	else{CTX.a.lineTo(coord[i-1][0]+coord[i-1][2]*2, coord[i-1][1]-1);CTX.a.lineTo(vX +acW/2,coord[i-1][1]-1);}
					CTX.a.fill();
				}
				else{CTX.a.stroke(); }
				CTX.a.closePath();
			}
			
			if(!hasGradient && vizColorStyle[0] == 0){	CTX.a.strokeStyle= vc[1];	CTX.a.fillStyle = vc[1];}
			
			CTX.a.beginPath();
			CTX.a.moveTo(coord[Quantity-1][0], coord[Quantity-1][1]);
			CTX.a.lineTo(vX +acW/2, vY +acH);//End point
			
			if(vizSolid){
				CTX.a.lineTo(vX +acW/2, coord[Quantity-1][1]);
				CTX.a.fill();
				}
			else		{	CTX.a.stroke();	}
			CTX.a.closePath(); CTX.a.beginPath();
			
			if(!hasGradient && vizColorStyle[0] == 0){	CTX.a.strokeStyle= vc[2];	CTX.a.fillStyle = vc[2];}
			
			CTX.a.moveTo(vX +acW/2, vY +acH);//End point
			CTX.a.lineTo(coord[Quantity-1][0]+coord[Quantity-1][2]*2, coord[Quantity-1][1]);
			
			if(vizSolid){
				CTX.a.lineTo(vX +acW/2, coord[Quantity-1][1]);
				CTX.a.fill();
				}
			else		{	CTX.a.stroke();	}
			CTX.a.closePath();
		}
		
		if(vizTypeVar > 0 && !vizSolid){	//Add cross lines
			CTX.a.shadowBlur= 0; //remove middle glow to make it hollow
			CTX.a.lineCap= "round";
			for(var i = 0; i< Quantity; i++){
				setVizColor(i, 3, 10*peakValues[i]*0.75);
				if(hasGradient){CTX.a.strokeStyle=gradient;	CTX.a.fillStyle=gradient;}
				
				CTX.a.beginPath();
				CTX.a.moveTo(coord[i][0],coord[i][1]);//Start Point
				CTX.a.lineTo(coord[i][0]+coord[i][2]*2,coord[i][1]); //Attach coordinates together
				CTX.a.stroke(); 
				CTX.a.closePath();
			}					
			CTX.a.shadowBlur= glowBlur;
			CTX.a.lineCap= "butt";
		}
	}
	
	else if(vizType == 50 && vizLR){ // Render a wire vibe LR
		clear('a');  //Transparent BG
		
		// Make data Matrix
		var barThickness = acH/Quantity;
		var vibeLengthL=[], vibeLengthR=[], vibeY=[];
		var coord= []; coord.la=[]; coord.lb=[]; coord.ra=[]; coord.rb=[];
		for (var i = 0; i < halfCount; i++) {
			vibeLengthL[i] = (acW)* peakValues[halfCount +isOdd(Quantity) -1 -i];
			vibeLengthR[i] = (acW)* peakValues[halfCount +isOdd(Quantity) +i]
			vibeY[i] = [vLY +barThickness * (i+.5) * 2, vRY +barThickness * (i+.5) * 2];
		}


		if(vizPat == 0)		{	var vibeLX = vLX +acW/2;	var vibeRX = vRX +acW/2;		}
		else if(vizPat == 1)	{	var vibeLX = vLX +acW*9/24;	var vibeRX = vRX +acW*15/24;	}
		else if(vizPat == 2)	{	var vibeLX = vLX +acW*1/3;	var vibeRX = vRX +acW*2/3;		}
		else if(vizPat == 3)	{	var vibeLX = vLX +acW*1/4;	var vibeRX = vRX +acW*3/4;		}
		else if(vizPat == 4)	{	var vibeLX = vLX +acW*1/5;	var vibeRX = vRX +acW*4/5;		}
		else if(vizPat == 5)	{	var vibeLX = vLX +acW*1/6;	var vibeRX = vRX +acW*5/6;		}
		else if(vizPat == 6)	{	var vibeLX = vLX +acW*1/7;	var vibeRX = vRX +acW*6/7;		}
		else if(vizPat == 7)	{	var vibeLX = vLX +acW*1/8;	var vibeRX = vRX +acW*7/8;		}
		else if(vizPat >= 8)	{	var vibeLX = vLX +0;		var vibeRX = vRX +acW;			}
		
		for (var i = 0; i < halfCount; i++) {
			if(vizPat == 0)		{	var vibeX1 = vibeLX - vibeLengthL[i];	var vibeX2 = vibeRX;					}
			else if(vizPat < 8)	{	var vibeX1 = vibeLX - vibeLengthL[i]/2;	var vibeX2 = vibeRX - vibeLengthR[i]/2;	}
			else if(vizPat >= 8)	{	var vibeX1 = vibeLX;					var vibeX2 = vibeRX - vibeLengthR[i];	}
			
			coord.la[i] = vibeX1;
			coord.lb[i] = vibeX1+vibeLengthL[i];
			coord.ra[i] = vibeX2;
			coord.rb[i] = vibeX2+vibeLengthR[i];
		}

		
		//Draw it
		if(vizSolid || vizTypeVar < 2){
			//Left
			for(var i = 0; i < halfCount; i++){
				if(!hasGradient){
					if(vizColorStyle[0] > 0){	CTX.a.strokeStyle= vcM[i];	CTX.a.fillStyle = vcM[i];  CTX.a.shadowColor = vcM[i];}				
					else					{	CTX.a.strokeStyle= vc[1];	CTX.a.fillStyle = vc[1];}
				}
				CTX.a.beginPath();			
				if(i == 0){CTX.a.moveTo(vibeLX, vLY +0);} 	else{CTX.a.moveTo(coord.la[i-1], vibeY[i-1][0]);}
				CTX.a.lineTo(coord.la[i], vibeY[i][0]); 
				
				if(!vizSolid){
					if(vizPat > 0){
						CTX.a.moveTo(coord.lb[i], vibeY[i][0]); 			
						if(i == 0){CTX.a.lineTo(vibeLX, vLY +0);} 	else{CTX.a.lineTo(coord.lb[i-1], vibeY[i-1][0]);}
					}
					CTX.a.stroke();
					}
				else{
					CTX.a.lineTo(coord.lb[i], vibeY[i][0]); 			
					if(i == 0){CTX.a.lineTo(vibeLX, vLY +0);} 	else{CTX.a.lineTo(coord.lb[i-1], vibeY[i-1][0]);}
					CTX.a.fill();		
				}
				CTX.a.closePath();
			}
			
			//Bottom Left Tip
			CTX.a.beginPath();
			CTX.a.moveTo(coord.la[halfCount-1], vibeY[halfCount-1][0]); 		
			CTX.a.lineTo(vibeLX, vLY +acH);//End point
			CTX.a.shadowColor= LglowColor[3]; 
			if(vizPat > 0 || vizSolid){	CTX.a.lineTo(coord.lb[halfCount-1], vibeY[halfCount-1][0]-1);	}
			if(vizSolid){	CTX.a.fill();	}	else	{	CTX.a.stroke();	}
			CTX.a.closePath();

			//Right
			for(var i = 0; i< halfCount; i++){
				if(!hasGradient){
					if(vizColorStyle[0] > 0){	CTX.a.strokeStyle= vcM[Quantity-1-i];	CTX.a.fillStyle = vcM[Quantity-1-i];  CTX.a.shadowColor = vcM[Quantity-1-i];}				
					else					{	CTX.a.strokeStyle= vc[2];	CTX.a.fillStyle = vc[2];}
				}

				CTX.a.beginPath();			
				if(i == 0){CTX.a.moveTo(vibeRX, vRY +0);} 	else{CTX.a.moveTo(coord.rb[i-1], vibeY[i-1][1]);}
				CTX.a.lineTo(coord.rb[i], vibeY[i][1]); 
		
				if(!vizSolid){
					if(vizPat > 0){
						CTX.a.moveTo(coord.ra[i], vibeY[i][1]); 			
						if(i == 0){CTX.a.lineTo(vibeRX, vRY +0);} 	else{CTX.a.lineTo(coord.ra[i-1], vibeY[i-1][1]);}
					}
					CTX.a.stroke();
					}
				else{
					CTX.a.lineTo(coord.ra[i], vibeY[i][1]); 			
					if(i == 0){CTX.a.lineTo(vibeRX, vRY +0);} 	else{CTX.a.lineTo(coord.ra[i-1], vibeY[i-1][1]);}
					CTX.a.fill();		
				}
				CTX.a.closePath();
			}
			
			//Bottom Right Tip
			CTX.a.beginPath();
			CTX.a.moveTo(coord.rb[halfCount-1], vibeY[halfCount-1][1]); 		
			CTX.a.lineTo(vibeRX, vRY +acH);//End point
			CTX.a.shadowColor= RglowColor[3]; 
			if(vizPat > 0 || vizSolid){	CTX.a.lineTo(coord.ra[halfCount-1], vibeY[halfCount-1][1]-1);	}
			if(vizSolid){	CTX.a.fill();	}	else	{	CTX.a.stroke();	}
			CTX.a.closePath();
		}
		
		if(vizTypeVar > 0 && !vizSolid){	//Add cross lines
			CTX.a.shadowBlur= 0; //remove middle glow to make it hollow
			CTX.a.shadowColor= CglowColor[3]; 
			CTX.a.lineCap= "round";

			for(var i = 0; i< halfCount; i++){
				if(!hasGradient){
					if(vizColorStyle[0] > 0){	CTX.a.strokeStyle= vcM[i];	CTX.a.fillStyle = vcM[i];  CTX.a.shadowColor = vcM[i];}				
					else					{	CTX.a.strokeStyle= vc[3];	CTX.a.fillStyle = vc[3];}
				}
				CTX.a.beginPath();
				CTX.a.moveTo(coord.la[i], vibeY[i][0]);//Start Point
				if(vizColorStyle[0] > 0){
					CTX.a.lineTo(coord.lb[i], vibeY[i][0]); 
					CTX.a.stroke();	CTX.a.closePath();	CTX.a.beginPath();
					CTX.a.moveTo(coord.ra[i], vibeY[i][1]);
					CTX.a.strokeStyle= vcM[Quantity-1-i];	CTX.a.fillStyle = vcM[Quantity-1-i];  CTX.a.shadowColor = vcM[Quantity-1-i];					
				}				
				CTX.a.lineTo(coord.rb[i], vibeY[i][1]); //Attach coordinates together
				CTX.a.stroke(); 
				CTX.a.closePath();
			}					
			CTX.a.shadowBlur= glowBlur;
			CTX.a.lineCap= "butt";
		}

	}
	
	else if(vizType == 60 && !vizLR){ // Render a wire circle
		clear('a');  //Transparent BG
		var circX = acW/2 +vX; var circY = acH/2 +vY;
		var circIrad = vcThickness /300 *acH; 
		var circOrad = circIrad *(1+ vThickness/50);
		var inH = vinH/35; var outH = voutH/35;
		var newQ = Quantity +vizSplit *Quantity/45;
		
		if(Quantity>1){
			//create array of circle points
			var outCircPoints=[], inCircPoints=[], inMCPs=[]; outMCPs=[]; var Amp = []; Amp.f=[];
			for(i=0;i<halfCount;i++){
				Amp[i] = (acW)* peakValues[i]*.75;
				Amp.f[i] = peakValues[i];
				var inP = Math.max(circIrad-Amp[i] *inH, 0); //lines should not cross circle center
				var outP = circOrad+Amp[i] *outH;
				outCircPoints[i]=circPoint(circX, circY, outP, i, newQ, rotatePos/25);
				inCircPoints[i]	=circPoint(circX, circY, inP, i, newQ, rotatePos/25);
				
				if(vizShape > 0){
					inMCPs[i]	= [circPoint(circX, circY, circIrad, i-0.5+vizPad/20, newQ, rotatePos/25), circPoint(circX, circY, circIrad, i+0.5-vizPad/20, newQ, rotatePos/25) ];
					outMCPs[i]	= [circPoint(circX, circY, circOrad, i-0.5+vizPad/20, newQ, rotatePos/25), circPoint(circX, circY, circOrad, i+0.5-vizPad/20, newQ, rotatePos/25) ];
				}
			}
			for(i=halfCount+isOdd(Quantity);i<Quantity;i++){
				var iRev = Quantity +halfCount -1 -i; //Reverse
				Amp[i] = (acW)* peakValues[iRev]*.75;
				Amp.f[i] = peakValues[iRev];
				var inP = Math.max(circIrad-Amp[i] *inH, 0); //lines should not cross circle center
				var outP = 	circOrad+Amp[i] *outH;		
				outCircPoints[i]=circPoint(circX, circY, outP, i, newQ, rotatePos/25);
				inCircPoints[i]	=circPoint(circX, circY, inP, i, newQ, rotatePos/25);
				
				if(vizShape > 0){
					inMCPs[i]	= [circPoint(circX, circY, circIrad, i-0.5+vizPad/20, newQ, rotatePos/25), circPoint(circX, circY, circIrad, i+0.5-vizPad/20, newQ, rotatePos/25) ];
					outMCPs[i]	= [circPoint(circX, circY, circOrad, i-0.5+vizPad/20, newQ, rotatePos/25), circPoint(circX, circY, circOrad, i+0.5-vizPad/20, newQ, rotatePos/25) ];
				}
			}
				
			//Draw in Sections
			for(var i = 0; i< Quantity; i++){
				//Inner Lines
				if((vizSolid && vizShape == 0)|| vizTypeVar > 0){
					setVizColor(i, 1, 1);
					CTX.a.beginPath();
					if(i==0 && vizSplit == 0){CTX.a.moveTo(inCircPoints[Quantity-1][0],inCircPoints[Quantity-1][1]);}
					else if(i==0){
						if(vizTypeVar > 1){CTX.a.moveTo(outCircPoints[i][0],outCircPoints[i][1]);}
						else{CTX.a.moveTo(inCircPoints[i][0],inCircPoints[i][1]);}
					}
					else{CTX.a.moveTo(inCircPoints[i-1][0],inCircPoints[i-1][1]);} 
					CTX.a.lineTo(inCircPoints[i][0],inCircPoints[i][1]); 

					if(!vizSolid){
						CTX.a.stroke();CTX.a.closePath();CTX.a.beginPath();
						CTX.a.moveTo(outCircPoints[i][0],outCircPoints[i][1]);
						}
					else{
					}					
				}
				else{
					CTX.a.beginPath();
					CTX.a.moveTo(outCircPoints[i][0],outCircPoints[i][1]);					
				}
				
				//Cross lines/shapes
				if((!vizSolid || vizShape > 0) && vizTypeVar < 2){
					CTX.a.shadowBlur= glowBlur/2;
					setVizColor(i, 3, 10*Amp.f[i]*0.75);
		
					if(vizShape == 0)		{	CTX.a.lineTo(inCircPoints[i][0],inCircPoints[i][1]); }
					else if(vizShape == 1)	{ //pointy
						CTX.a.lineTo(outMCPs[i][0][0],outMCPs[i][0][1]);
						CTX.a.lineTo(inMCPs[i][0][0],inMCPs[i][0][1]);
						CTX.a.lineTo(inCircPoints[i][0],inCircPoints[i][1]);
						CTX.a.lineTo(inMCPs[i][1][0],inMCPs[i][1][1]);
						CTX.a.lineTo(outMCPs[i][1][0],outMCPs[i][1][1]);
						CTX.a.lineTo(outCircPoints[i][0],outCircPoints[i][1]);					
					}
					else if(vizShape == 2)	{ //curvy
						CTX.a.moveTo(outMCPs[i][1][0],outMCPs[i][1][1]);
						CTX.a.quadraticCurveTo(outCircPoints[i][0],outCircPoints[i][1], outMCPs[i][0][0],outMCPs[i][0][1]);
						CTX.a.lineTo(inMCPs[i][0][0],inMCPs[i][0][1]);
						CTX.a.quadraticCurveTo(inCircPoints[i][0],inCircPoints[i][1], inMCPs[i][1][0],inMCPs[i][1][1]);
						CTX.a.lineTo(outMCPs[i][1][0],outMCPs[i][1][1]);
					}

					if(!vizSolid)			{	CTX.a.stroke();CTX.a.closePath();CTX.a.beginPath();	}
					else if(vizShape > 0)	{	CTX.a.fill();CTX.a.closePath();CTX.a.beginPath();		}
					
					if(i==0 && vizSplit == 0){CTX.a.lineTo(outCircPoints[Quantity-1][0],outCircPoints[Quantity-1][1]);}
					else if(i==0){CTX.a.lineTo(outCircPoints[i][0],outCircPoints[i][1]);}
					else{CTX.a.lineTo(outCircPoints[i-1][0],outCircPoints[i-1][1]);} 	
				}
				else{
					if(!vizSolid){
						if(i==0 && vizSplit == 0){CTX.a.lineTo(outCircPoints[Quantity-1][0],outCircPoints[Quantity-1][1]);}
						else if(i==0){CTX.a.lineTo(outCircPoints[i][0],outCircPoints[i][1]);}
						else{CTX.a.lineTo(outCircPoints[i-1][0],outCircPoints[i-1][1]);} 	
					}
				}
				if(!vizSolid){			CTX.a.shadowBlur= glowBlur;}			
				
				//Outer Lines
				if((vizSolid && vizShape == 0)|| vizTypeVar > 0){
					setVizColor(i, 2, 1);

					CTX.a.lineTo(outCircPoints[i][0],outCircPoints[i][1]); 

					if(!vizSolid){
						if(i==Quantity-1 && vizTypeVar > 1){CTX.a.lineTo(inCircPoints[i][0],inCircPoints[i][1]);}
						CTX.a.stroke();
					}
					else{
						setVizColor(i, 2, 10*Amp.f[i]*0.75);
						if(i==0 && vizSplit == 0){CTX.a.lineTo(outCircPoints[Quantity-1][0],outCircPoints[Quantity-1][1]);}
						else if(i==0){CTX.a.lineTo(outCircPoints[i][0],outCircPoints[i][1]);}
						else{CTX.a.lineTo(outCircPoints[i-1][0],outCircPoints[i-1][1]);} 		
						CTX.a.fill();
						}	
					CTX.a.closePath();
				}				
				
			}			

			rotatePos += rotateSpeed;			
			
		}
		else{
			if(!hasGradient){
				if(vizColorStyle[0] > 0){	CTX.a.strokeStyle= vcM[0];	CTX.a.fillStyle = vcM[0];	CTX.a.shadowColor = vcM[0];}				
				else					{	CTX.a.strokeStyle= vc[1];	CTX.a.fillStyle = vc[1];		CTX.a.shadowColor = vc[1];}
			}
			var Amp = (acW)* peakValues[0]*.75;
			CTX.a.beginPath();
			CTX.a.arc(circX, circY, vcThickness*4 +Amp/3,0,2*Math.PI);
			if(!vizSolid){	CTX.a.stroke(); }
			else{

				CTX.a.fill();
				CTX.a.closePath();			
				CTX.a.beginPath();
				CTX.a.globalCompositeOperation="xor"		//Cutting
				CTX.a.arc(circX, circY, vcThickness*4 -Amp/20,0,2*Math.PI);				
				CTX.a.fill();
				CTX.a.globalCompositeOperation="source-over"	//Default setting
			}
			
			CTX.a.closePath();			
		}
	}
	
	else if(vizType == 60 && vizLR){ // Wire circles LR
		clear('a');  //Transparent BG
		var circX1 = acW*1/3 +vLX; var circY1 = acH/2 +vLY;
		var circX2 = acW*2/3 +vRX; var circY2 = acH/2 +vRY;
		var circIradL = vcThicknessL /300 *acH, circIradR = vcThicknessR /300 *acH;
		var circOradL = circIradL *(1+ vThickness/50), circOradR = circIradR *(1+ vThickness/50);
		var inH = vinH/35; var outH = voutH/35;
		var leftArray  = Quantity/2 +vizSplitL *Quantity/90;
		var rightArray = Quantity/2 +vizSplitR *Quantity/90;
		if(rotateSpeed == 0){var rotPos = 1} else {var rotPos = rotatePos/25}
		
		if(Quantity>1){
			//create array of circle points
			var outCircPoints=[], inCircPoints=[], inMCPs=[]; outMCPs=[]; var Amp = []; Amp.f=[];
			for(i=0;i<halfCount;i++){
				if(vizLRInv){var iRev = halfCount -1 -i;}//Reverse
				else {var iRev = i;}
				
				Amp[i] = (acW)* peakValues[iRev]*.75;
				Amp.f[i] = peakValues[iRev];
				var inP = Math.max(circIradL-Amp[i] *inH, 0); //lines should not cross circle center
				var outP = circOradL+Amp[i] *outH;
				outCircPoints[i]=circPoint(circX1, circY1, outP, i, leftArray, vRotatePosL +rotPos);
				inCircPoints[i]	=circPoint(circX1, circY1, inP, i, leftArray, vRotatePosL +rotPos);
				
				if(vizShape > 0){
					inMCPs[i]	= [circPoint(circX1, circY1, circIradL, i-0.5+vizPad/20, leftArray, vRotatePosL +rotPos), circPoint(circX1, circY1, circIradL, i+0.5-vizPad/20, leftArray, vRotatePosL +rotPos) ];
					outMCPs[i]	= [circPoint(circX1, circY1, circOradL, i-0.5+vizPad/20, leftArray, vRotatePosL +rotPos), circPoint(circX1, circY1, circOradL, i+0.5-vizPad/20, leftArray, vRotatePosL +rotPos) ];
				}
			}
			for(i=halfCount+isOdd(Quantity);i<Quantity;i++){
				if(vizLRInv){var iRev = Quantity +halfCount -1 -i;}//Reverse
				else {var iRev = i;}

				Amp[i] = (acW)* peakValues[iRev]*.75;
				Amp.f[i] = peakValues[iRev];
				var inP = Math.max(circIradR-Amp[i] *inH, 0); //lines should not cross circle center
				var outP = 	circOradR+Amp[i] *outH;		
				outCircPoints[i]=circPoint(circX2, circY2, outP, i, rightArray, vRotatePosR +rotPos);
				inCircPoints[i]	=circPoint(circX2, circY2, inP, i, rightArray, vRotatePosR +rotPos);
				
				if(vizShape > 0){
					inMCPs[i]	= [circPoint(circX2, circY2, circIradR, i-0.5+vizPad/20, rightArray, vRotatePosR +rotPos), circPoint(circX2, circY2, circIradR, i+0.5-vizPad/20, rightArray, vRotatePosR +rotPos) ];
					outMCPs[i]	= [circPoint(circX2, circY2, circOradR, i-0.5+vizPad/20, rightArray, vRotatePosR +rotPos), circPoint(circX2, circY2, circOradR, i+0.5-vizPad/20, rightArray, vRotatePosR +rotPos) ];
				}
			}
				
			//Draw in Sections
			for(var i = 0; i< Quantity; i++){
				//Inner Lines
				if((vizSolid && vizShape == 0)|| vizTypeVar > 0){
					setVizColor(i, 1, 1);
					CTX.a.beginPath();
					if(i==0 && vizSplitL==0){CTX.a.moveTo(inCircPoints[halfCount-1][0],inCircPoints[halfCount-1][1]);}
					else if(i==halfCount && vizSplitR==0){CTX.a.moveTo(inCircPoints[Quantity-1][0],inCircPoints[Quantity-1][1]);}
					else if(i==0 || i==halfCount){
						if(vizTypeVar > 1){CTX.a.moveTo(outCircPoints[i][0],outCircPoints[i][1]);}
						else{CTX.a.moveTo(inCircPoints[i][0],inCircPoints[i][1]);}
						}
					else{CTX.a.moveTo(inCircPoints[i-1][0],inCircPoints[i-1][1]);} 
					CTX.a.lineTo(inCircPoints[i][0],inCircPoints[i][1]); 

					if(!vizSolid){
						CTX.a.stroke();CTX.a.closePath();CTX.a.beginPath();
						CTX.a.moveTo(outCircPoints[i][0],outCircPoints[i][1]);
						}
					else{
					}					
				}
				else{
					CTX.a.beginPath();
					CTX.a.moveTo(outCircPoints[i][0],outCircPoints[i][1]);					
				}
				
				//Cross lines/shapes
				if((!vizSolid || vizShape > 0) && vizTypeVar < 2){
					CTX.a.shadowBlur= glowBlur/2;
					setVizColor(i, 3, 10*Amp.f[i]*0.75);
		
					if(vizShape == 0)		{	CTX.a.lineTo(inCircPoints[i][0],inCircPoints[i][1]); }
					else if(vizShape == 1)	{ //pointy
						CTX.a.lineTo(outMCPs[i][0][0],outMCPs[i][0][1]);
						CTX.a.lineTo(inMCPs[i][0][0],inMCPs[i][0][1]);
						CTX.a.lineTo(inCircPoints[i][0],inCircPoints[i][1]);
						CTX.a.lineTo(inMCPs[i][1][0],inMCPs[i][1][1]);
						CTX.a.lineTo(outMCPs[i][1][0],outMCPs[i][1][1]);
						CTX.a.lineTo(outCircPoints[i][0],outCircPoints[i][1]);					
					}
					else if(vizShape == 2)	{ //curvy
						CTX.a.moveTo(outMCPs[i][1][0],outMCPs[i][1][1]);
						CTX.a.quadraticCurveTo(outCircPoints[i][0],outCircPoints[i][1], outMCPs[i][0][0],outMCPs[i][0][1]);
						CTX.a.lineTo(inMCPs[i][0][0],inMCPs[i][0][1]);
						CTX.a.quadraticCurveTo(inCircPoints[i][0],inCircPoints[i][1], inMCPs[i][1][0],inMCPs[i][1][1]);
						CTX.a.lineTo(outMCPs[i][1][0],outMCPs[i][1][1]);
					}

					if(!vizSolid)			{	CTX.a.stroke();CTX.a.closePath();CTX.a.beginPath();		}
					else if(vizShape > 0)	{	CTX.a.fill();CTX.a.closePath();CTX.a.beginPath();			}
						
					if(i==0 && vizSplitL==0){CTX.a.lineTo(outCircPoints[halfCount-1][0],outCircPoints[halfCount-1][1]);}
					else if(i==halfCount && vizSplitR==0){CTX.a.lineTo(outCircPoints[Quantity-1][0],outCircPoints[Quantity-1][1]);}
					else if(i==0 || i==halfCount){CTX.a.lineTo(outCircPoints[i][0],outCircPoints[i][1]);}
					else{CTX.a.lineTo(outCircPoints[i-1][0],outCircPoints[i-1][1]);} 						
					
				}
				else{
					if(!vizSolid)			{
						if(i==0 && vizSplitL==0){CTX.a.lineTo(outCircPoints[halfCount-1][0],outCircPoints[halfCount-1][1]);}
						else if(i==halfCount && vizSplitR==0){CTX.a.lineTo(outCircPoints[Quantity-1][0],outCircPoints[Quantity-1][1]);}
						else if(i==0 || i==halfCount){CTX.a.lineTo(outCircPoints[i][0],outCircPoints[i][1]);}
						else{CTX.a.lineTo(outCircPoints[i-1][0],outCircPoints[i-1][1]);} 								
					}
					
				}
	
				
				
				if(!vizSolid){			CTX.a.shadowBlur= glowBlur;}			
				
				//Outer Lines
				if((vizSolid && vizShape == 0)|| vizTypeVar > 0){
					setVizColor(i, 2, 1);

					CTX.a.lineTo(outCircPoints[i][0],outCircPoints[i][1]); 

					if(!vizSolid){
						if((i==halfCount-1 || i==Quantity-1) && vizTypeVar > 1){CTX.a.lineTo(inCircPoints[i][0],inCircPoints[i][1]);}
						CTX.a.stroke();
						}
					else{
						setVizColor(i, 2, 10*Amp.f[i]*0.75);
						if(i==0 && vizSplitL==0){CTX.a.lineTo(outCircPoints[halfCount-1][0],outCircPoints[halfCount-1][1]);}
						else if(i==halfCount && vizSplitR==0){CTX.a.lineTo(outCircPoints[Quantity-1][0],outCircPoints[Quantity-1][1]);}
						else if(i==0 || i==halfCount){CTX.a.lineTo(outCircPoints[i][0],outCircPoints[i][1]);}
						else{CTX.a.lineTo(outCircPoints[i-1][0],outCircPoints[i-1][1]);} 	
						
						CTX.a.fill();
						}	
					CTX.a.closePath();
				}				
				
			}			

			rotatePos += rotateSpeed;			
			
		}
		else{
			if(!hasGradient){
				if(vizColorStyle[0] > 0){	CTX.a.strokeStyle= vcM[0];	CTX.a.fillStyle = vcM[0];	CTX.a.shadowColor = vcM[0];}				
				else					{	CTX.a.strokeStyle= vc[1];	CTX.a.fillStyle = vc[1];		CTX.a.shadowColor = vc[1];}
			}
			var Amp = (acW)* peakValues[0]*.75;
			CTX.a.beginPath();
			CTX.a.arc(circX1, circY1, vcThickness*4 +Amp/3,0,2*Math.PI);
			if(!vizSolid){	CTX.a.stroke(); }
			else{

				CTX.a.fill();
				CTX.a.closePath();			
				CTX.a.beginPath();
				CTX.a.globalCompositeOperation="xor"		//Cutting
				CTX.a.arc(circX1, circY1, vcThickness*4 -Amp/20,0,2*Math.PI);				
				CTX.a.fill();
				CTX.a.globalCompositeOperation="source-over"	//Default setting
			}
			
			CTX.a.closePath();			
		}
	}
	
	else if(vizType == 70){ // Render a diamond on the canvas
		clear('a');  //Transparent BG
		var barThickness = acH/Quantity*(vcThickness)/75;
		CTX.a.lineCap= "round";

		//Create Array of Points to reference/manipulate
		var coord= [];
		var mD =[];
		mD.x = vX +acW/2;
		mD.y = vY +acH/2;
		mD.l = mD.x - barThickness*Quantity/4;
		mD.r = mD.x + barThickness*Quantity/4;
		mD.t = mD.y - barThickness*Quantity/4;
		mD.b = mD.y + barThickness*Quantity/4;
		var lastX0 = acW/2;
		var lastY0 = acH * .92;
		
		for (var i = 0; i < Quantity; i++) {
			var height = (acH)* peakValues[i];
			if(i<halfCount/2)		{ 	var i2 = barThickness * i;						var lastX1 = (mD.x - i2);	var lastY1 = (mD.b - i2);	coord[i]=[lastX1 - height, lastY1 + height];	} //LB
			else if(i<halfCount)	{ 	var i2 = (barThickness * (i-halfCount/2));		var lastX2 = (mD.l + i2);	var lastY2 = (mD.y - i2);	coord[i]=[lastX2 - height, lastY2 - height];	} //LT
			else if(i<halfCount *1.5){ 	var i2 = (barThickness * (i-halfCount));		var lastX3 = (mD.x + i2);	var lastY3 = (mD.t + i2);	coord[i]=[lastX3 + height, lastY3 - height];	} //RT
			else					{ 	var i2 = (barThickness * (i-halfCount*1.5));	var lastX4 = (mD.r - i2);	var lastY4 = (mD.y + i2);	coord[i]=[lastX4 + height, lastY4 + height];	} //RB
		}		
		
		//Draw Diamond
		CTX.a.beginPath();		
		CTX.a.moveTo(coord[Quantity-1][0],coord[Quantity-1][1]);
		//LB
		for (var i = 0; i < Quantity; i++) {
			if(!hasGradient && vizColorStyle[0] > 0){	CTX.a.strokeStyle= vcM[i];	CTX.a.fillStyle = vcM[i];  CTX.a.shadowColor = vcM[i];}	
			
			if(i<halfCount/2)		{ 	if(!hasGradient && vizColorStyle[0] == 0){	CTX.a.strokeStyle= vc[1];	CTX.a.fillStyle = vc[1];	CTX.a.shadowColor = vc[1];}	} //LB
			else if(i<halfCount)	{	if(!hasGradient && vizColorStyle[0] == 0){	CTX.a.strokeStyle= vc[2];	CTX.a.fillStyle = vc[2];	CTX.a.shadowColor = vc[2];}	} //LT
			else if(i<halfCount *1.5){	if(!hasGradient && vizColorStyle[0] == 0){	CTX.a.strokeStyle= vc[3];	CTX.a.fillStyle = vc[3];	CTX.a.shadowColor = vc[3];}	} //RT
			else 					{	if(!hasGradient && vizColorStyle[0] == 0){	CTX.a.strokeStyle= vc[4];	CTX.a.fillStyle = vc[4];	CTX.a.shadowColor = vc[4];}	} //RB			
			
			CTX.a.lineTo(coord[i][0],coord[i][1]);
			
			if(vizSolid || vizTypeVar > 0){	CTX.a.lineTo(mD.x, mD.y); 	}
			if(!vizSolid){
				CTX.a.closePath();	CTX.a.stroke();	CTX.a.beginPath();	CTX.a.moveTo(coord[i][0],coord[i][1]);
				}
			else{	CTX.a.fill();	CTX.a.closePath();	CTX.a.beginPath();	CTX.a.moveTo(coord[i][0],coord[i][1]);	}
		}

		
		if(vizSolid || vizTypeVar == 2){		
			CTX.a.fill();	CTX.a.closePath();	CTX.a.beginPath();				
			// cover seam
			CTX.a.shadowColor= CglowColor[3]; 
			if(!hasGradient){
				CTX.a.strokeStyle= vc[5];	CTX.a.fillStyle = vc[5];	CTX.a.shadowColor = vc[5];
			}
			if(vizTypeVar > 0){CTX.a.globalCompositeOperation="destination-out"	}	//Cutting

			if(vizTypeVar == 2){
				CTX.a.moveTo(mD.x, mD.y);
				CTX.a.arc(mD.x, mD.y, barThickness*Quantity/6, 0*Math.PI,2*Math.PI);				
			}
			else{
				CTX.a.moveTo(mD.l,mD.y);
				CTX.a.lineTo(mD.x,mD.t);
				CTX.a.lineTo(mD.r,mD.y);
				CTX.a.lineTo(mD.x,mD.b);
				CTX.a.lineTo(mD.l,mD.y);				
			}

			CTX.a.fill();
			CTX.a.closePath();
			if(vizTypeVar > 0){CTX.a.globalCompositeOperation="source-over"}	//Default setting					
		}
		CTX.a.lineCap= "butt";
	}
	
	else if(vizType == 80){ // Render a Snake
		clear('a');  //Transparent BG
		var barThickness = acH/100;
		
		var moveAmount=vizFallRate*30
		var biteR = moveAmount*2.5
		
		//Record Amplitudes
		for (var i = 0; i < Quantity; i++) {
			snake.amp[i] = (acW)* peakValues[i]*0.5;
		}		
		
		//Check if bait is bit
		if(snake.x[0] > snake.bait[0]-biteR && snake.x[0] < snake.bait[0]+biteR){
			if(snake.y[0] > snake.bait[1]-biteR && snake.y[0] < snake.bait[1]+biteR){
				snake.bait[0] = Math.round(Math.random()*(acW-barThickness)+barThickness/2);
				snake.bait[1] = Math.round(Math.random()*(acH-barThickness)+barThickness/2);
			}
		}
		
		//Draw Bait
		if	  (snake.bait.shape == -1){} //none
		else if(snake.bait.shape == 0){	drawS("a", "circle", "F", snake.bait[0], snake.bait[1], barThickness/2, LglowColor[3], CglowColor[3], 0, 1, 2);	} //SemiCircles standard
		else if(snake.bait.shape == 1){	drawS("a", "circle", "F", snake.bait[0], snake.bait[1], barThickness/2, LglowColor[3], CglowColor[3], 0, 0, 2);	} //circles
		else if(snake.bait.shape == 2){	drawS("a", "smiley", "F", snake.bait[0], snake.bait[1], barThickness/2, LglowColor[3], CglowColor[3], 0, 0, 2);	} //smiley
		else if(snake.bait.shape == 3){	drawS("a", "devil",	 "F", snake.bait[0], snake.bait[1], barThickness/2, LglowColor[3], CglowColor[3], 0, 9, -90);	} //devil
		else if(snake.bait.shape == 4){	drawS("a", "star",	 "F", snake.bait[0], snake.bait[1], barThickness/2, LglowColor[3], CglowColor[3], 0, 5, -90);	} //star5
		else if(snake.bait.shape == 5){	drawS("a", "star",	 "F", snake.bait[0], snake.bait[1], barThickness/2, LglowColor[3], CglowColor[3], 0, 7, -90);	} //star7
		else if(snake.bait.shape == 6){	drawS("a", "star",	 "F", snake.bait[0], snake.bait[1], barThickness/2, LglowColor[3], CglowColor[3], 0, 9, -90);	} //star9

		//Calculate Distance (for proximaty functions)
		snake.bD = findDist(snake.bait[0], snake.bait[1], snake.x[0], snake.y[0])
		
		//Shift Tail Data
		// Shift tail directions
		for (var i = Quantity-1; i > 0; i--) {
			snake["d"][i]=0+snake["d"][i-1];
		}
		
		// Shift Tail Pos
		for (var i = Quantity-1; i > 0; i--) {
			snake.x[i]=0+snake.x[i-1];
			snake.y[i]=0+snake.y[i-1];
		}		
		//DebugDisplay2.textContent = "Pos: "+snake["x"][0]+", "+snake["y"][0]+" Bait: "+snake.bait[0]+", "+snake.bait[1];
		
		//Update Snake Head Data and Behavior
		if(snake.path == 0){ // Angled
			// Change Head Direction
			snake.d[0]=Math.round(Math.atan2(snake.bait[1] - snake.y[0], snake.bait[0] - snake.x[0]) * (180 / Math.PI));

			// Move head
			if	   (snake.bait[0] < snake.x[0]){	snake.x[0]-=moveAmount;	if(snake.x[0] < snake.bait[0]){snake.x[0] = snake.bait[0]}	}
			else if(snake.bait[0] > snake.x[0]){	snake.x[0]+=moveAmount;	if(snake.x[0] > snake.bait[0]){snake.x[0] = snake.bait[0]}	}
			
			if	   (snake.bait[1] < snake.y[0]){	snake.y[0]-=moveAmount;	if(snake.y[0] < snake.bait[1]){snake.y[0] = snake.bait[1]}	}
			else if(snake.bait[1] > snake.y[0]){	snake.y[0]+=moveAmount;	if(snake.y[0] > snake.bait[1]){snake.y[0] = snake.bait[1]}	}

		}
		else if(snake.path == 1){ // Direct
			// Change Head Direction
			snake.d[0]=Math.round(Math.atan2(snake.bait[1] - snake.y[0], snake.bait[0] - snake.x[0]) * (180 / Math.PI));

			// Move head
			var nPos = circPoint(snake.x[0], snake.y[0], moveAmount, snake.d[0], 360, 0);
			snake.x[0] = nPos[0];
			snake.y[0] = nPos[1];
		}
		else if(snake.path == 2){ // Curvy
			// Change Head Direction
			var goalD = Math.round(Math.atan2(snake.bait[1] - snake.y[0], snake.bait[0] - snake.x[0]) * (180 / Math.PI));
			
			if		(snake.bD < 0.5*acW/10){snake.turn = 5}
			else if (snake.bD < 1*acW/10){snake.turn = 4}
			else if (snake.bD < 2*acW/10){snake.turn = 3}
			else if (snake.bD < 8*acW/10){snake.turn = 2}
			else	{snake.turn = 1}
		
			if 		(goalD > snake.d[0]){snake.d[0]+=snake.turn}
			else if (goalD < snake.d[0]){snake.d[0]-=snake.turn}


			// Move head
			var nPos = circPoint(snake.x[0], snake.y[0], moveAmount, snake.d[0], 360, 0);
			snake.x[0] = nPos[0];
			snake.y[0] = nPos[1];
			
			//Screen Wrap or Bounce
			if(snake.wrap == 0 || snake.wrap == 2){ //Wrap X
				if(snake.x[0] < -20)	{snake.x[0] = acW+10}
				if(snake.x[0] > acW+20)	{snake.x[0] = -10}
			}
			if(snake.wrap == 0 || snake.wrap == 3){ //Wrap Y
				if(snake.y[0] < -20)	{snake.y[0] = acH+10}
				if(snake.y[0] > acH+20)	{snake.y[0] = -10}
			}
			if(snake.wrap == 1 || snake.wrap == 3){ //Bounce X
				if(snake.x[0] < 0 || snake.x[0] > acW)		{
					if(snake.d[0] < 0) {	snake.d[0] = -180 - snake.d[0]}	
					if(snake.d[0] >= 0){	snake.d[0] = 180 - snake.d[0]}						
				}
			}
			if(snake.wrap == 1 || snake.wrap == 2){ //Bounce Y
				if(snake.y[0] < 0 || snake.y[0] > acH)		{
					snake.d[0] *= -1						
				}
			}			
			
			//DebugDisplay2.textContent = "Pos: "+snake["x"][0]+", "+snake["y"][0]+" Bait: "+snake.bait[0]+", "+snake.bait[1]+" Angle: "+snake.d[0]+", "+goalD;	

		}
		
					
		//Create Array of Points that are the sides of the snake (has to be updated each time as amplitudes change)
		for (var i = 0; i < Quantity; i++) {
			var p1 = circPoint(snake.x[i], snake.y[i], snake.amp[i]/2, snake.d[i], 360, -90);
			var p2 = circPoint(snake.x[i], snake.y[i], snake.amp[i]/2, snake.d[i]+180, 360, -90);
			snake.x1[i] = p1[0];
			snake.y1[i] = p1[1];
			snake.x2[i] = p2[0];
			snake.y2[i] = p2[1];
		}
		
		//Draw Snake
		if(hasGradient == false){	CTX.a.strokeStyle= LglowColor[3]; CTX.a.fillStyle= LglowColor[3];	}
		else{CTX.a.strokeStyle=gradient;CTX.a.fillStyle= gradient;}
		
		if(snake.shape == -1){} // No Body
		else if(snake.shape == 0){ //Outline
			CTX.a.beginPath();
			for(var i = 1; i< Quantity; i++){
				if(!hasGradient){
					if(vizColorStyle[0] > 0){	CTX.a.strokeStyle= vcM[i];	CTX.a.fillStyle = vcM[i];  CTX.a.shadowColor = vcM[i];}				
					else					{	CTX.a.strokeStyle= vc[1];	CTX.a.fillStyle = vc[1];}
				}
				if(vizTypeVar < 2 || vizSolid){	// Left Side	
					CTX.a.moveTo(snake.x1[i-1],snake.y1[i-1]);			
					CTX.a.lineTo(snake.x1[i],snake.y1[i]);
					if(!vizSolid){
						CTX.a.stroke();	CTX.a.closePath(); CTX.a.beginPath();
						CTX.a.moveTo(snake.x1[i], snake.y1[i]);						
					}
				}
				if(vizTypeVar > 0 || vizSolid){ //Spokes
					if(!hasGradient){	if(vizColorStyle[0] == 0){	CTX.a.strokeStyle= vc[3];	CTX.a.fillStyle = vc[3];}	}
					CTX.a.lineTo(snake.x2[i],snake.y2[i]);
					if(!vizSolid){
						CTX.a.stroke();	CTX.a.closePath(); CTX.a.beginPath();
						if(vizTypeVar == 2){CTX.a.moveTo(snake.x1[i+1], snake.y1[i+1]);}
						else{CTX.a.moveTo(snake.x2[i], snake.y2[i]);}						
					}
				}
				else{CTX.a.moveTo(snake.x2[i], snake.y2[i]);}
				if(vizTypeVar < 2 || vizSolid){	// Right Side
					if(!hasGradient){	if(vizColorStyle[0] == 0){	CTX.a.strokeStyle= vc[2];	CTX.a.fillStyle = vc[2];}	}
					CTX.a.lineTo(snake.x2[i-1],snake.y2[i-1]);
					if(!vizSolid)	{	CTX.a.stroke();	}
					else			{	CTX.a.fill(); 	}
					CTX.a.closePath();CTX.a.beginPath();
				}

			}

		}
		else if(snake.shape == 1){ //Circles
			for(var i = 0; i< Quantity; i++){
				if(!hasGradient){
					if(vizColorStyle[0] > 0){	CTX.a.strokeStyle= vcM[i];	CTX.a.fillStyle = vcM[i];  CTX.a.shadowColor = vcM[i];}				
					else{					CTX.a.strokeStyle= vizColor[1][3];		CTX.a.fillStyle = vizColor[1][3];}
				}
				if(vizSolid){ drawS("a", "circle", "F", snake.x[i], snake.y[i], snake.amp[i]/2, CTX.a.strokeStyle, 0, 0, 0, 2);	}
				else		{ drawS("a", "circle", "S", snake.x[i], snake.y[i], snake.amp[i]/2, CTX.a.strokeStyle, 0, 0, 0, 2);	}
			}
		}
		else if(snake.shape == 2){ //Diamond
			for(var i = 0; i< Quantity; i++){
				if(!hasGradient){
					if(vizColorStyle[0] > 0){	CTX.a.strokeStyle= vcM[i];	CTX.a.fillStyle = vcM[i];  CTX.a.shadowColor = vcM[i];}				
					else{					CTX.a.strokeStyle= vizColor[1][3];		CTX.a.fillStyle = vizColor[1][3];}
				}
				if(vizSolid){ drawS("a", "star", "F", snake.x[i], snake.y[i], snake.amp[i]/2, CTX.a.strokeStyle, 0, 0, 4, snake["d"][i]);	}
				else		{ drawS("a", "star", "S", snake.x[i], snake.y[i], snake.amp[i]/2, CTX.a.strokeStyle, 0, 0, 4, snake["d"][i]);	}
			}
		}
		else if(snake.shape == 3){ //Square
			for(var i = 0; i< Quantity; i++){
				if(!hasGradient){
					if(vizColorStyle[0] > 0){	CTX.a.strokeStyle= vcM[i];	CTX.a.fillStyle = vcM[i];  CTX.a.shadowColor = vcM[i];}				
					else{					CTX.a.strokeStyle= vizColor[1][3];		CTX.a.fillStyle = vizColor[1][3];}
				}
				if(vizSolid){ drawS("a", "star", "F", snake.x[i], snake.y[i], snake.amp[i]/2, CTX.a.strokeStyle, 0, 0, 4, snake["d"][i]+45);	}
				else		{ drawS("a", "star", "S", snake.x[i], snake.y[i], snake.amp[i]/2, CTX.a.strokeStyle, 0, 0, 4, snake["d"][i]+45);	}
			}
		}
		else if(snake.shape == 4){ //Stars 5
			for(var i = 0; i< Quantity; i++){
				if(!hasGradient){
					if(vizColorStyle[0] > 0){	CTX.a.strokeStyle= vcM[i];	CTX.a.fillStyle = vcM[i];  CTX.a.shadowColor = vcM[i];}				
					else{					CTX.a.strokeStyle= vizColor[1][3];		CTX.a.fillStyle = vizColor[1][3];}
				}
				if(vizSolid){ drawS("a", "star", "F", snake.x[i], snake.y[i], snake.amp[i]/2, CTX.a.strokeStyle, 0, 0, 5, snake["d"][i]);	}
				else		{ drawS("a", "star", "S", snake.x[i], snake.y[i], snake.amp[i]/2, CTX.a.strokeStyle, 0, 0, 5, snake["d"][i]);	}
			}
		}
		
		//Draw Head
		if(vizSolid){drawS("a", "snakehead", "F", snake.x[0], snake.y[0], barThickness*1.2, CglowColor[3], RglowColor[3], 0, 3, snake["d"][0]);}
		else		{drawS("a", "snakehead", "S", snake.x[0], snake.y[0], barThickness*1.2, CglowColor[3], RglowColor[3], 0, 3, snake["d"][0]);}
	
				
	}
	
	else if(vizType == 85){ // Render Fishies!
		clear('a');  //Transparent BG
		var barThickness = acW/Quantity;
		var baitSize = acW/128 * 0.3;
		if(!vizSolid){	var fill="S"	}	else	{	var fill="F"	}
		
		// Notes: Speed determined by pitch
		// Animated tale (at least 3 frames)
		// various fish styles

		var qFrames = 48;//fFrames = Math.round(128/2.666)
		
		// Create Fish Array
		for (var i = 0; i < Quantity; i++) {
			if(!fish[i])  							{	fish[i] = [barThickness *i, Math.round(Math.random()*acH)];	} //Establish Fish Position		
			if(!fish.d[i] 	 && fish.d[i] != 0)		{	fish.d[i] = Math.round(Math.random()*360-180);	} //Establish Fish Direction (-180 -> 180)
			if(!fish.sh.b[i] && fish.sh.b[i] != 0)	{	fish.sh.b[i] = Math.round(Math.random()*0);		} //Establish Fish Body Type 
			if(!fish.sh.f[i] && fish.sh.f[i] != 0)	{	fish.sh.f[i] = Math.round(Math.random()*6);		} //Establish Fish Fin Type 
			if(!fish.f[i]	 && fish.f[i] != 0)		{	fish.f[i] = Math.round(Math.random()*qFrames);		} //Establish Fish Tale Frame (0 -> 3) [l, m, r, m]
			if(i < halfCount){	fish.s[i] = (25+i)*(vizFallRate*5)/(halfCount/2)	}	else	{	fish.s[i] = (25+(Quantity-i))*(vizFallRate*5)/(halfCount/2)	} //Establish Fish Speed
			
			fish.f[i] += fish.s[i] *qFrames/70; if(fish.f[i] > qFrames + 0.3){fish.f[i] = 0.7}	// Animate tailfins
			fish.bD[i] = findDist(snake.bait[0], snake.bait[1], fish[i][0], fish[i][0]) //Calculate Distance (for proximaty functions)

			//Update Fish Data and Behavior
			if(snake.path == 0){ // Angled
				// Change Direction
				fish.d[i]=Math.round(Math.atan2(snake.bait[1] - fish[i][1], snake.bait[0] - fish[i][0]) * (180 / Math.PI));
				fish.td[i] = 0;
				
				// Move 
				if	   (snake.bait[0] < fish[i][0]){	fish[i][0] -=fish.s[i];	if(fish[i][0] < snake.bait[0]){fish[i][0] = snake.bait[0]}	}
				else if(snake.bait[0] > fish[i][0]){	fish[i][0] +=fish.s[i];	if(fish[i][0] > snake.bait[0]){fish[i][0] = snake.bait[0]}	}
				
				if	   (snake.bait[1] < fish[i][1]){	fish[i][1] -=fish.s[i];	if(fish[i][1] < snake.bait[1]){fish[i][1] = snake.bait[1]}	}
				else if(snake.bait[1] > fish[i][1]){	fish[i][1] +=fish.s[i];	if(fish[i][1] > snake.bait[1]){fish[i][1] = snake.bait[1]}	}

			}
			else if(snake.path == 1){ // Direct
				// Change Direction
				fish.d[i]=Math.round(Math.atan2(snake.bait[1] - fish[i][1], snake.bait[0] - fish[i][0]) * (180 / Math.PI));
				fish.td[i] = 0;
				
				// Move 
				var nPos = circPoint(fish[i][0], fish[i][1], fish.s[i], fish.d[i], 360, 0);
				fish[i][0] = nPos[0];
				fish[i][1] = nPos[1];
			}
			else if(snake.path == 2){ // Curvy
				// Change  Direction
				var goalD = Math.round(Math.atan2(snake.bait[1] - fish[i][1], snake.bait[0] - fish[i][0]) * (180 / Math.PI));
				
				if		(fish.bD[i] < 0.10*acW/10)	{fish.turn = 12}
				else if (fish.bD[i] < 0.25*acW/10)	{fish.turn = 6}
				else if (fish.bD[i] < 0.5*acW/10)	{fish.turn = 4}
				else if (fish.bD[i] < 0.75*acW/10)	{fish.turn = 3}
				else if (fish.bD[i] < 1.5*acW/10)	{fish.turn = 2}
				else if (fish.bD[i] < 3*acW/10)		{fish.turn = 1}
				else if (fish.bD[i] < 6*acW/10)		{fish.turn = 0.75}
				else if (fish.bD[i] < 8*acW/10)		{fish.turn = 0.5}
				else								{fish.turn = 0.25}
			
				if 		(goalD > fish.d[i]){fish.d[i]+=fish.turn;fish.td[i] = 1}
				else if (goalD < fish.d[i]){fish.d[i]-=fish.turn;fish.td[i] = -1}
				else	{fish.td[i] = 0}


				// Move 
				var nPos = circPoint(fish[i][0], fish[i][1], fish.s[i], fish.d[i], 360, 0);
				fish[i][0] = nPos[0];
				fish[i][1] = nPos[1];
				
				//Screen Wrap or Bounce
				if(snake.wrap == 0 || snake.wrap == 2){ //Wrap X
					if(fish[i][0] < -20)	{fish[i][0] = acW+10}
					if(fish[i][0] > acW+20)	{fish[i][0] = -10}
				}
				if(snake.wrap == 0 || snake.wrap == 3){ //Wrap Y
					if(fish[i][1] < -20)	{fish[i][1] = acH+10}
					if(fish[i][1] > acH+20)	{fish[i][1] = -10}
				}
				if(snake.wrap == 1 || snake.wrap == 3){ //Bounce X
					if(fish[i][0] < 0 || fish[i][0] > acW)		{
						if(fish.d[i] < 0) {	fish.d[i] = -180 - fish.d[i]}	
						if(fish.d[i] >= 0){	fish.d[i] = 180 - fish.d[i]}						
					}
				}
				if(snake.wrap == 1 || snake.wrap == 2){ //Bounce Y
					if(fish[i][1] < 0 || fish[i][1] > acH)		{
						fish.d[i] *= -1						
					}
				}			
				
			}
			
			
			//Check if bait is bit
			var biteR = fish.s[i]*2.5;
			if(fish[i][0] > snake.bait[0]-biteR && fish[i][0] < snake.bait[0]+biteR){
				if(fish[i][1] > snake.bait[1]-biteR && fish[i][1] < snake.bait[1]+biteR){
					snake.bait[0] = Math.round(Math.random()*(acW-baitSize)+baitSize/2);
					snake.bait[1] = Math.round(Math.random()*(acH-baitSize)+baitSize/2);
				}
			}			
			
		
		}

		//Draw Bait
		if	  (snake.bait.shape == -1){} //none
		else if(snake.bait.shape == 0){	drawS("a", "circle", "F", snake.bait[0], snake.bait[1], baitSize, LglowColor[3], CglowColor[3], 0, 1, 2);		} //SemiCircles standard
		else if(snake.bait.shape == 1){	drawS("a", "circle", "F", snake.bait[0], snake.bait[1], baitSize, LglowColor[3], CglowColor[3], 0, 0, 2);		} //circles
		else if(snake.bait.shape == 2){	drawS("a", "smiley", "F", snake.bait[0], snake.bait[1], baitSize, LglowColor[3], CglowColor[3], 0, 0, 2);		} //smiley
		else if(snake.bait.shape == 3){	drawS("a", "devil",	 "F", snake.bait[0], snake.bait[1], baitSize, LglowColor[3], CglowColor[3], 0, 9, -90);	} //devil
		else if(snake.bait.shape == 4){	drawS("a", "star",	 "F", snake.bait[0], snake.bait[1], baitSize, LglowColor[3], CglowColor[3], 0, 5, -90);	} //star5
		else if(snake.bait.shape == 5){	drawS("a", "star",	 "F", snake.bait[0], snake.bait[1], baitSize, LglowColor[3], CglowColor[3], 0, 7, -90);	} //star7
		else if(snake.bait.shape == 6){	drawS("a", "star",	 "F", snake.bait[0], snake.bait[1], baitSize, LglowColor[3], CglowColor[3], 0, 9, -90);	} //star9

		
		// Draw Fish 
		for (var i = 0; i < Quantity; i++) {
			setVizColor(i, 1, 10*peakValues[i]*0.75);
			if(hasGradient){CTX.a.strokeStyle=gradient;	CTX.a.fillStyle=gradient;}	
	
			var height = 20+ acH * peakValues[i]/3;
			if		(vizTypeVar == 0){	drawS("a", "fish",  fill, fish[i][0], fish[i][1], height/2, CTX.a.fillStyle, 0, vizStroke/3, fish.td[i], 180+fish.d[i], Math.round(fish.f[i]), fish.sh.b[i], fish.sh.f[i]);	} //Draw it direct
			else if	(vizTypeVar == 1){	drawS("a", "ghost", fill, fish[i][0], fish[i][1], height/2, CTX.a.fillStyle, 0, vizStroke/3, fish.td[i], 180+fish.d[i], Math.round(fish.f[i]), fish.sh.b[i], fish.sh.f[i]);	} //Draw it direct

		
		}

		
	
	}
	
	else if(vizType == 90){ // Render the Matrix - Advanced
		font_size = acW/Quantity;
		CTX.a.font = font_size + 'px Microsoft YaHei New, Microsoft Yahei, 微软雅黑, 宋体, SimSun, STXihei, 华文细黑, serif';
		CTX.a.shadowColor= LglowColor[3]; 	

		mTailLength = Math.min(200, vizIterations+1);
		clear('a');	
		if(vizTypeVar==2){
			CTX.a.fillStyle = "rgba("+CglowColor[0]+","+CglowColor[1]+","+CglowColor[2]+","+0.9+")";			
			CTX.a.shadowBlur=0;
			CTX.a.fillRect(0, 0, acW, acH);
			}
				


		//Shift tail info to make room for next set
		for(i=mTailLength-1;i>-1;i--){
			mTails[i+1]		 =mTails[i].toString().split(','); //adding nothing breaks reference and so only transfers values
			mTails[i+1]["sv"]=mTails[i]["sv"].toString().split(','); //adding nothing breaks reference and so only transfers values
		}
		
		//Assign first set
		for(var i = 0; i < Quantity; i++){
			mTails[0][i] = chinese[Math.floor(Math.random()*chinese.length)];	//a random chinese character to print
		}

		
		//Find difference between colors 1 and 2. Use audio amplitude to jump towards 2 from 1
		var difColor = [];
		if(vizColorStyle[0] == 0){
			difColor[0] = LglowColor[0]-vizColor[1][0];
			difColor[1] = LglowColor[1]-vizColor[1][1];
			difColor[2] = LglowColor[2]-vizColor[1][2];
		}

		//DebugDisplay2.textContent = mTails[1]["sv"][0];
		//DebugDisplay2.textContent = drops[1];
		//looping over drops
		for(var i = -1; i < Quantity; i++){ //Must be -1 or the first column screws up...
			for(var ii = 0; ii < mTailLength; ii++){
				if(ii==0){
					mTails[0]["sv"][i] = minmax(0, 1, 55 *peakValues[i] *peakValues[i]); // ShineValue, 	exagerating the amplitudes				
				}

				if(vizSolid){	var shineValue = mTails[0]["sv"][i];	}
				else{			var shineValue = mTails[ii]["sv"][i];	}
				if(vizTypeVar==0 || vizTypeVar==2){shineValue = shineValue* (1-vizFade/10) +vizFade/10;}
				
				//Calculate color value for instance
				if(vizColorStyle[0] == 0){
					if(vizTypeVar==0){	difColor[3] = vizColor[1][0];	difColor[4] = vizColor[1][1];	difColor[5] = vizColor[1][2];	}
					else{
						difColor[3] = vizColor[1][0] +Math.round(difColor[0]*shineValue);
						difColor[4] = vizColor[1][1] +Math.round(difColor[1]*shineValue);						
						difColor[5] = vizColor[1][2] +Math.round(difColor[2]*shineValue);
					}
				}
				else if(!hasGradient){
					if(vizTypeVar==0){	difColor[3] = vcM.r[i];	difColor[4] = vcM.g[i];	difColor[5] = vcM.b[i];	}
					else{
						difColor[0] = LglowColor[0]-vcM.r[i];
						difColor[1] = LglowColor[1]-vcM.g[i];
						difColor[2] = LglowColor[2]-vcM.b[i];					
						
						difColor[3] = vcM.r[i] +Math.round(difColor[0]*shineValue);
						difColor[4] = vcM.g[i] +Math.round(difColor[1]*shineValue);						
						difColor[5] = vcM.b[i] +Math.round(difColor[2]*shineValue);					
					}
				}
				
				CTX.a.shadowBlur= Math.min(glowBlur, 1)*Math.round(shineValue); //Add glow but discourage lag
				if(vizTypeVar==1){		if(!hasGradient){	CTX.a.fillStyle = "rgba("+difColor[3]+","+difColor[4]+","+difColor[5]+","+(mTailLength-ii)/mTailLength+")"; 				CTX.a.shadowColor = CTX.a.fillStyle;	}	}
				else if(vizTypeVar==0){	if(!hasGradient){	CTX.a.fillStyle = "rgba("+difColor[3]+","+difColor[4]+","+difColor[5]+","+shineValue*(mTailLength-ii)/mTailLength+")";		CTX.a.shadowColor = CTX.a.fillStyle;	}	}
				else if(vizTypeVar==2){
					CTX.a.fillStyle = "rgba("+255+","+255+","+255+","+shineValue*(mTailLength-ii)/mTailLength+")";
					CTX.a.shadowColor = CTX.a.fillStyle;
					CTX.a.globalCompositeOperation="destination-out";
					}
	
				if(mTails[ii][i] != undefined && mTails[ii][i] !=  0){
					CTX.a.fillText(mTails[ii][i], i*font_size, 0.9*drops[i]*font_size-ii*font_size);	//x = i*font_size, y = value of drops[i]*Tail Position*font_size
				}
				
				if(vizTypeVar==2){CTX.a.globalCompositeOperation="source-over";}
				
				//sending the drop back to the top randomly after it has crossed the screen
				//adding a randomness to the reset to make the drops scattered on the Y axis
				if(0.9*drops[i]*font_size-mTailLength*font_size > acH && Math.random() > 0.975)
					drops[i] = 0 - Math.round(Math.random()*acH/20);
					
			}

			drops[i]++;
		}
	}

	else if(vizType == 100){ // Render Bubbles that grow/shrink, and slowly float up/down
		clear('a');  //Transparent BG
		var barThickness = acW/Quantity;
		
		// Begin with the left side 
		CTX.a.shadowColor= LglowColor[3]; 	

		for (var i = 0; i <= halfCount; i++) {
			if(!hasGradient){
				if(vizColorStyle[0] > 0){	CTX.a.strokeStyle= vcM[i];	CTX.a.fillStyle = vcM[i];  CTX.a.shadowColor = vcM[i];}				
				else					{	CTX.a.strokeStyle= vc[1];	CTX.a.fillStyle = vc[1];}
			}

			if(!drops.sway[i]){drops.sway[i]=[]; drops.sway[i].pos=0;drops.sway[i].up= 0.2+Math.random();drops.sway[i].vel=drops.sway[i].up/2;drops.sway[i].max=20*Math.random();}				
			if (vizTypeVar == 0)	{
				//set sway
				if(drops.sway[i].pos > drops.sway[i].max || drops.sway[i].pos < 0-drops.sway[i].max){drops.sway[i].vel *= -1;}
				drops.sway[i].pos += drops.sway[i].vel;	
				//set upward momentum
				if(drops[i] < -10){	drops[i] = acH+Math.random()*acH/6;} //Return lost bubbles
				drops[i] -= drops.sway[i].up * vizFallRate*10//Float bubbles			
			}
			else{
				if(drops[i] < -10){	drops[i] = acH+Math.random()*acH/3;} //Return lost bubbles
				drops[i] -= ((Math.random()-Math.random())+.5) * vizFallRate*5 //Float bubbles				
			}
			
			var height = 2+ acH * peakValues[i]/3;
			var bX = drops.sway[i].pos + barThickness * i;
			if		(vizTypeVar > 1)	{	CTX.a.drawImage(Bubble, bX - height/2,drops[i]-height/2,height,height);				} //Bubble is hidden image in index.html
			else if (vizTypeVar < 2)	{	drawS("a", "bubble", "S", bX, drops[i], height/2, CTX.a.fillStyle, 0, 0, vizStroke/3, 0);	} //Draw it direct
			

		}

		
		// Now draw the right side 
		CTX.a.shadowColor= RglowColor[3];		

		for (var i = halfCount+1; i < Quantity; i++) {
			if(!hasGradient){
				if(vizColorStyle[0] > 0){	CTX.a.strokeStyle= vcM[i];	CTX.a.fillStyle = vcM[i];  CTX.a.shadowColor = vcM[i];}				
				else					{	CTX.a.strokeStyle= vc[2];	CTX.a.fillStyle = vc[2];}
			}

			if(!drops.sway[i]){drops.sway[i]=[]; drops.sway[i].pos=0;drops.sway[i].up= 0.2+Math.random();drops.sway[i].vel=drops.sway[i].up/2;drops.sway[i].max=20*Math.random();}				
			if (vizTypeVar == 0)	{
				//set sway
				if(drops.sway[i].pos > drops.sway[i].max || drops.sway[i].pos < 0-drops.sway[i].max){drops.sway[i].vel *= -1;}
				drops.sway[i].pos += drops.sway[i].vel;	
				//set upward momentum
				if(drops[i] < -10){	drops[i] = acH+Math.random()*acH/6;} //Return lost bubbles
				drops[i] -= drops.sway[i].up * vizFallRate*10//Float bubbles			
			}
			else{
				if(drops[i] < -10){	drops[i] = acH+Math.random()*acH/3;} //Return lost bubbles
				drops[i] -= ((Math.random()-Math.random())+.5) * vizFallRate*5 //Float bubbles				
			}
			
			var height = 2+ acH * peakValues[i]/3;
			var bX = drops.sway[i].pos + barThickness * i;
			if		(vizTypeVar > 1)	{	CTX.a.drawImage(Bubble, bX - height/2,drops[i]-height/2,height,height);				} //Bubble is hidden image in index.html
			else if (vizTypeVar < 2)	{	drawS("a", "bubble", "S", bX, drops[i], height/2, CTX.a.fillStyle, 0, 0, vizStroke/3, 0);	} //Draw it direct
			
		}

	}
	else if(vizType == 110){ // Render stars that twinkle in place
		clear('a');  //Transparent BG
		CTX.a.lineWidth= 0.5;
		var barThickness = acW/Quantity;
		if(!vizSolid){	var fill="S"	}	else	{	var fill="F"	}
				
		// Begin with the left side 
		CTX.a.shadowColor= LglowColor[3]; 	
		for (var i = 0; i <= halfCount; i++) {
			if(!hasGradient){
				if(vizColorStyle[0] > 0){	CTX.a.strokeStyle= vcM[i];	CTX.a.fillStyle = vcM[i];  CTX.a.shadowColor = vcM[i];}				
				else					{	CTX.a.strokeStyle= vc[1];	CTX.a.fillStyle = vc[1];}
			}
			var Amplitude = 5+ acH * peakValues[i]/3;
			var bX = barThickness * (i+0.5);
			
			if		(vizTypeVar == 2)	{	CTX.a.drawImage(Star,bX - Amplitude/2,stars[i]*acH- Amplitude/2,Amplitude,Amplitude);} //Star is hidden image in index.html
			else if	(vizTypeVar == 1)	{	drawS("a", "star", fill, bX, stars[i]*acH, Amplitude/4, CTX.a.fillStyle, 0, 0, 12, -90, "Real");	} // Draw Realistic Star
			else						{	drawS("a", "star", fill, bX, stars[i]*acH, Amplitude/4, CTX.a.fillStyle, 0, 0, 8, -90, "Real");	} // Draw Realistic Star
		}
	
	
		// Now draw the right side 
		CTX.a.shadowColor= RglowColor[3];		
		for (var i = halfCount+1; i < Quantity; i++) {
			if(!hasGradient){
				if(vizColorStyle[0] > 0){	CTX.a.strokeStyle= vcM[i];	CTX.a.fillStyle = vcM[i];  CTX.a.shadowColor = vcM[i];}				
				else					{	CTX.a.strokeStyle= vc[2];	CTX.a.fillStyle = vc[2];}
			}
			var Amplitude = 5+ acH * peakValues[i]/3;
			var bX = barThickness * (i+0.5);
			
			if		(vizTypeVar == 2)	{	CTX.a.drawImage(Star,bX - Amplitude/2,stars[i]*acH- Amplitude/2,Amplitude,Amplitude);} //Star is hidden image in index.html
			else if	(vizTypeVar == 1)	{	drawS("a", "star", fill, bX, stars[i]*acH, Amplitude/4, CTX.a.fillStyle, 0, 0, 12, -90, "Real");	} // Draw Realistic Star
			else						{	drawS("a", "star", fill, bX, stars[i]*acH, Amplitude/4, CTX.a.fillStyle, 0, 0, 8, -90, "Real");	} // Draw Realistic Star
		}
	}
	else if(vizType == 120){ // Speakers (with ripple effect)
		clear('a');  //Transparent BG
		CTX.a.lineWidth= vizStroke;
		var barThickness = acW/Quantity;
		if(!vizSolid){	var fill="S"	}	else	{	var fill="F"	}
		mTailLength = vizIterations+1;
		var vcTH = vcThickness/3
		
		// Shift Old Amps
		for (var i = 0; i < Quantity; i++) {
			for(ii=mTailLength-1;ii>-1;ii--){
				ripples.a[i][ii+1]	= 0+ripples.a[i][ii]; //adding nothing breaks reference and so only transfers values
			}
		}
			
		// Records New Amps
		for (var i = 0; i < Quantity; i++) {	ripples.a[i][0] = Math.min(1, peakValues[i]*7);		}//Make sure number <= 1. Alpha channel max is 1
			
		// Draw it 
		CTX.a.shadowColor= LglowColor[3]; 	
		for (var i = 0; i < Quantity; i++) {
			var rX = barThickness * (i+0.5);

			if		(vizPat == 0)	{	var rY = ripples[i]*acH;	} // Random placement
			else if (vizPat == 1)	{	var rY = acH/2;				} // -
			else if (vizPat == 2)	{ // A
				if(i < halfCount){	var rY = acH - (i+0.5)*2*acH/Quantity;	}
				else			 {	var rY = acH - (Quantity-(i+0.5))*2*acH/Quantity;	}
			}
			else if (vizPat == 3)	{ // ||
				if(i < halfCount){	var rY = acH - (i+0.5)*2*acH/Quantity;				var rX = acW*1/3;}
				else			 {	var rY = acH - (Quantity-(i+0.5))*2*acH/Quantity;	var rX = acW*2/3;}
			}
			else if (vizPat == 4)	{ // V
				if(i < halfCount){	var rY = acH - (i+0.5)*2*acH/Quantity;				var rX = barThickness * (halfCount-i-0.5);}
				else			 {	var rY = acH - (Quantity-(i+0.5))*2*acH/Quantity;	var rX = barThickness * (halfCount*3-i-0.5);}
			}
			else if (vizPat == 5)	{ //Diamond skinny
				if(i < halfCount/2)			{	var rY = acH - (i+0.5)*2*acH/Quantity;				var rX = barThickness * (halfCount-i-1);}
				else if(i < halfCount)		{	var rY = acH - (i+0.5)*2*acH/Quantity;				var rX = barThickness * (i+0.);}
				else if(i < halfCount*1.5)	{	var rY = acH - (Quantity-(i+0.5))*2*acH/Quantity;	var rX = barThickness * (i+1);}
				else			 			{	var rY = acH - (Quantity-(i+0.5))*2*acH/Quantity;	var rX = barThickness * (halfCount*3-i-0);}
			}
			else if (vizPat == 6)	{ // Diamond fat
				if(i < halfCount/2)			{	var rY = acH - (i+0.5)*2*acH/Quantity;				var rX = barThickness * (halfCount-i*2-1);}
				else if(i < halfCount)		{	var rY = acH - (i+0.5)*2*acH/Quantity;				var rX = barThickness * (i*2+1-halfCount);}
				else if(i < halfCount*1.5)	{	var rY = acH - (Quantity-(i+0.5))*2*acH/Quantity;	var rX = barThickness * (i*2+1-halfCount);}
				else			 			{	var rY = acH - (Quantity-(i+0.5))*2*acH/Quantity;	var rX = barThickness * (halfCount*5-i*2-1);}
			}
			else if (vizPat == 7)	{ // X
				if(i < halfCount/2)			{	var rY = acH - (i+0.5)*2*acH/Quantity;				var rX = barThickness * (i*2+1);}
				else if(i < halfCount)		{	var rY = acH - (i+0.5)*2*acH/Quantity;				var rX = barThickness * (halfCount*2-i*2-1);}
				else if(i < halfCount*1.5)	{	var rY = acH - (Quantity-(i+0.5))*2*acH/Quantity;	var rX = barThickness * (halfCount*4-i*2-1);}
				else			 			{	var rY = acH - (Quantity-(i+0.5))*2*acH/Quantity;	var rX = barThickness * (i*2+1-halfCount*2);}
			}
			else if (vizPat == 8)	{ // O
				var rCoord = circPoint(acW/2, acH/2, acH/2*0.9, i, Quantity, +90 +2*90/Quantity);
				var rX = rCoord[0];	var rY = rCoord[1];
			}
			else if (vizPat == 9)	{ // n
				var rCoord = circPoint(acW/2, acH, acH*0.8, i, Quantity*2, +180 +2*45/Quantity);
				var rX = rCoord[0];	var rY = rCoord[1];
			}
			else if (vizPat >= 10){ // U
				var rCoord = circPoint(acW/2, 0, acW/2, Quantity-1-i, Quantity*2, 0 +2*45/Quantity);
				var rX = rCoord[0];	var rY = rCoord[1];
			}

			rX += vX;
			rY += vY;
			
			for(ii=0; ii<mTailLength; ii++){
				if(ii==0){var F = fill} else {var F = "S"}
				var rR = vcTH +vizVibe *ripples.a[i][0]	+ii *(vizStroke+vizPad); // Add slight vibration

				if(!hasGradient){
					if(vizColorStyle[0] > 0){	var newcStyle='rgba('+vcM.r[i]+', '+vcM.g[i]+', '+vcM.b[i]+', '+ripples.a[i][ii]+')';	}				
					else					{	var newcStyle='rgba('+vc.r[1]+', '+vc.g[1]+', '+vc.b[1]+', '+ripples.a[i][ii]+')';		}
					CTX.a.strokeStyle= newcStyle;	CTX.a.fillStyle = newcStyle;  CTX.a.shadowColor = newcStyle;
				}	
				
				if(ripples.shape == 1)		{	drawS("a", "star",   F, rX, rY, rR, CTX.a.fillStyle, 0, 0, 3, -90);	}	// Triangle
				else if(ripples.shape == 2)	{	drawS("a", "star",   F, rX, rY, rR, CTX.a.fillStyle, 0, 0, 3, +90);	}	// Triangle
				else if(ripples.shape == 3)	{	drawS("a", "star",   F, rX, rY, rR, CTX.a.fillStyle, 0, 0, 4, -90);	}	// Diamond
				else if(ripples.shape == 4)	{	drawS("a", "star",   F, rX, rY, rR, CTX.a.fillStyle, 0, 0, 4, -45);	}	// Square
				else if(ripples.shape == 5)	{	drawS("a", "star",   F, rX, rY, rR, CTX.a.fillStyle, 0, 0, 5, -90);	}	// Star 5
				else if(ripples.shape == 6)	{	drawS("a", "star",   F, rX, rY, rR, CTX.a.fillStyle, 0, 0, 7, -90);	}	// Star 7
				else if(ripples.shape == 7)	{	drawS("a", "star",   F, rX, rY, rR, CTX.a.fillStyle, 0, 0, 9, -90);	}	// Star 9
				else if(ripples.shape == 8)	{	drawS("a", "star",   F, rX, rY, rR, CTX.a.fillStyle, 0, 0, 3, ripples.a[i][ii]*180);	}	// Amp determined Triangle
				else if(ripples.shape == 9)	{	drawS("a", "star",   F, rX, rY, rR, CTX.a.fillStyle, 0, 0, 4, ripples.a[i][ii]*180);	}	// Amp determined Square
				else if(ripples.shape == 10){	drawS("a", "star",   F, rX, rY, rR, CTX.a.fillStyle, 0, 0, 5, ripples.a[i][ii]*180);	}	// Amp determined Star 5
				else if(ripples.shape == 11){	drawS("a", "star",   F, rX, rY, rR, CTX.a.fillStyle, 0, 0, 7, ripples.a[i][ii]*180);	}	// Amp determined Star 7
				else if(ripples.shape == 12){	drawS("a", "star",   F, rX, rY, rR, CTX.a.fillStyle, 0, 0, 9, ripples.a[i][ii]*180);	}	// Amp determined Star 9
				else if(ripples.shape == 13){ 	drawS("a", "devil", F,	rX, rY, rR, CTX.a.fillStyle, 0, vizStroke/3, 0, -90);	}		// Devil
				else if(ripples.shape == 14){ 	drawS("a", "smiley", F,	rX, rY, rR, CTX.a.fillStyle, 0, vizStroke/3, 0, -90);	}		// Smiley
				else						{	drawS("a", "circle", F, rX, rY, rR, CTX.a.fillStyle, 0, 0, 4, -90);	}

			}

		}
	
	}
	else if(vizType == 130){ // Waterfall
		clear('a');  //Transparent BG
		CTX.a.lineWidth= vizStroke;
		var barThickness = acW/Quantity;
		if(!vizSolid){	var fill="F"	}	else	{	var fill="S"	} //opposite :P
		mTailLength = vizIterations+1;
		var vcTH = vcThickness/3
		
		// Shift Old Amps
		for (var i = 0; i < Quantity; i++) {
			for(ii=mTailLength-1;ii>-1;ii--){
				ripples.a[i][ii+1]	= 0+ripples.a[i][ii]; //adding nothing breaks reference and so only transfers values
			}
		}
			
		// Records New Amps
		for (var i = 0; i < Quantity; i++) {	ripples.a[i][0] = Math.min(1, peakValues[i]*7);		}//Make sure number <= 1. Alpha channel max is 1
			
		// Draw it 
		CTX.a.shadowColor= LglowColor[3]; 	
		for (var i = 0; i < Quantity; i++) {
			var rX = barThickness * (i+0.5);

			if		(vizPat == 0)	{	var rY = ripples[i]*acH - acH/4;	} // Random placement
			else if (vizPat == 1)	{	var rY = acH/2;				} // -
			else if (vizPat == 2)	{	var rY = 0;				} // ¯
			else if (vizPat == 3)	{ // A
				if(i < halfCount){	var rY = acH - (i+0.5)*2*acH/Quantity;	}
				else			 {	var rY = acH - (Quantity-(i+0.5))*2*acH/Quantity;	}
			}
			else if (vizPat == 4)	{ // V
				if(i < halfCount){	var rY = acH - (i+0.5)*2*acH/Quantity;							var rX = barThickness * (halfCount-i-0.5);}
				else			 {	var rY = acH - (Quantity-(i+0.5))*2*acH/Quantity;				var rX = barThickness * (halfCount*3-i-0.5);}
			}
			else if (vizPat == 5)	{ //Diamond skinny
				if(i < halfCount/2)			{	var rY = acH - (i+0.5)*2*acH/Quantity;				var rX = barThickness * (halfCount-i-1);}
				else if(i < halfCount)		{	var rY = acH - (i+0.5)*2*acH/Quantity;				var rX = barThickness * (i+0.);}
				else if(i < halfCount*1.5)	{	var rY = acH - (Quantity-(i+0.5))*2*acH/Quantity;	var rX = barThickness * (i+1);}
				else			 			{	var rY = acH - (Quantity-(i+0.5))*2*acH/Quantity;	var rX = barThickness * (halfCount*3-i-0);}
			}
			else if (vizPat == 6)	{ // Diamond fat
				if(i < halfCount/2)			{	var rY = acH - (i+0.5)*2*acH/Quantity;				var rX = barThickness * (halfCount-i*2-1);}
				else if(i < halfCount)		{	var rY = acH - (i+0.5)*2*acH/Quantity;				var rX = barThickness * (i*2+1-halfCount);}
				else if(i < halfCount*1.5)	{	var rY = acH - (Quantity-(i+0.5))*2*acH/Quantity;	var rX = barThickness * (i*2+1-halfCount);}
				else			 			{	var rY = acH - (Quantity-(i+0.5))*2*acH/Quantity;	var rX = barThickness * (halfCount*5-i*2-1);}
			}
			else if (vizPat == 7)	{ // X
				if(i < halfCount/2)			{	var rY = acH - (i+0.5)*2*acH/Quantity;				var rX = barThickness * (i*2+1);}
				else if(i < halfCount)		{	var rY = acH - (i+0.5)*2*acH/Quantity;				var rX = barThickness * (halfCount*2-i*2-1);}
				else if(i < halfCount*1.5)	{	var rY = acH - (Quantity-(i+0.5))*2*acH/Quantity;	var rX = barThickness * (halfCount*4-i*2-1);}
				else			 			{	var rY = acH - (Quantity-(i+0.5))*2*acH/Quantity;	var rX = barThickness * (i*2+1-halfCount*2);}
			}
			else if (vizPat == 8)	{ // O
				var rCoord = circPoint(acW/2, acH/2, acH/2*0.9, i, Quantity, +90 +2*90/Quantity);
				var rX = rCoord[0];	var rY = rCoord[1];
			}
			else if (vizPat == 9)	{ // n
				var rCoord = circPoint(acW/2, acH, acW/2, i, Quantity*2, +180 +2*45/Quantity);
				var rX = rCoord[0];	var rY = rCoord[1];
			}
			else if (vizPat >= 10){ // U
				var rCoord = circPoint(acW/2, 0, acW/2, Quantity-1-i, Quantity*2, 0 +2*45/Quantity);
				var rX = rCoord[0];	var rY = rCoord[1];
			}
			
			rX += vX;
			rY += vY;
			
			for(ii=0; ii<mTailLength; ii++){
				rY += ii

				if(ii==0){
					var F = fill
					var rR = vcTH +vizVibe *ripples.a[i][0]	+ii *(vizStroke+vizPad); // Add slight vibration
				} else {
					var F = fill
					var rR = vcTH ; // Add slight vibration
				}

				if(!hasGradient){
					if(vizColorStyle[0] > 0){	var newcStyle='rgba('+vcM.r[i]+', '+vcM.g[i]+', '+vcM.b[i]+', '+ripples.a[i][ii]+')';	}				
					else					{	var newcStyle='rgba('+vc.r[1]+', '+vc.g[1]+', '+vc.b[1]+', '+ripples.a[i][ii]+')';		}
					CTX.a.strokeStyle= newcStyle;	CTX.a.fillStyle = newcStyle;  CTX.a.shadowColor = newcStyle;
				}	
				
				if(ripples.shape == 1)		{	drawS("a", "star",   F, rX, rY, rR, CTX.a.fillStyle, 0, 0, 3, -90);	}	// Triangle
				else if(ripples.shape == 2)	{	drawS("a", "star",   F, rX, rY, rR, CTX.a.fillStyle, 0, 0, 3, +90);	}	// Triangle
				else if(ripples.shape == 3)	{	drawS("a", "star",   F, rX, rY, rR, CTX.a.fillStyle, 0, 0, 4, -90);	}	// Diamond
				else if(ripples.shape == 4)	{	drawS("a", "star",   F, rX, rY, rR, CTX.a.fillStyle, 0, 0, 4, -45);	}	// Square
				else if(ripples.shape == 5)	{	drawS("a", "star",   F, rX, rY, rR, CTX.a.fillStyle, 0, 0, 5, -90);	}	// Star 5
				else if(ripples.shape == 6)	{	drawS("a", "star",   F, rX, rY, rR, CTX.a.fillStyle, 0, 0, 7, -90);	}	// Star 7
				else if(ripples.shape == 7)	{	drawS("a", "star",   F, rX, rY, rR, CTX.a.fillStyle, 0, 0, 9, -90);	}	// Star 9
				else if(ripples.shape == 8)	{	drawS("a", "star",   F, rX, rY, rR, CTX.a.fillStyle, 0, 0, 3, ripples.a[i][ii]*180);	}	// Amp determined Triangle
				else if(ripples.shape == 9)	{	drawS("a", "star",   F, rX, rY, rR, CTX.a.fillStyle, 0, 0, 4, ripples.a[i][ii]*180);	}	// Amp determined Square
				else if(ripples.shape == 10){	drawS("a", "star",   F, rX, rY, rR, CTX.a.fillStyle, 0, 0, 5, ripples.a[i][ii]*180);	}	// Amp determined Star 5
				else if(ripples.shape == 11){	drawS("a", "star",   F, rX, rY, rR, CTX.a.fillStyle, 0, 0, 7, ripples.a[i][ii]*180);	}	// Amp determined Star 7
				else if(ripples.shape == 12){	drawS("a", "star",   F, rX, rY, rR, CTX.a.fillStyle, 0, 0, 9, ripples.a[i][ii]*180);	}	// Amp determined Star 9
				else if(ripples.shape == 13){ 	drawS("a", "devil", F,	rX, rY, rR, CTX.a.fillStyle, 0, vizStroke/3, 0, -90);	}		// Devil
				else if(ripples.shape == 14){ 	drawS("a", "smiley", F,	rX, rY, rR, CTX.a.fillStyle, 0, vizStroke/3, 0, -90);	}		// Smiley
				else						{	drawS("a", "circle", F, rX, rY, rR, CTX.a.fillStyle, 0, 0, 4, -90);	}
			}

		}
	
	}
	



	//DebugDisplay.textContent = displayWidth.toFixed(1) + "%";
	//DebugDisplay2.textContent = vizType;	
}

//============================================================ Viz Code - WebGL =====================================

function shaderProgram(gl, vs, fs) {
	//https://sites.google.com/site/progyumming/javascript/shortest-webgl
	var prog = gl.createProgram();
	var addshader = function(type, source) {
		var s = gl.createShader((type == 'vertex') ? gl.VERTEX_SHADER : gl.FRAGMENT_SHADER);
		gl.shaderSource(s, source);
		gl.compileShader(s);
		if (!gl.getShaderParameter(s, gl.COMPILE_STATUS)) {
			throw "Could not compile "+type+ " shader:\n\n"+gl.getShaderInfoLog(s);
		}
		gl.attachShader(prog, s);
	};
	addshader('vertex', vs);
	addshader('fragment', fs);
	gl.linkProgram(prog);
	if (!gl.getProgramParameter(prog, gl.LINK_STATUS)) {		throw "Could not link the shader program!";		}
	return prog;
}

function attributeSetFloats(gl, prog, attr_name, rsize, arr) {
	//https://sites.google.com/site/progyumming/javascript/shortest-webgl
	gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
	gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(arr), gl.STATIC_DRAW);
	var attr = gl.getAttribLocation(prog, attr_name);
	gl.enableVertexAttribArray(attr);
	gl.vertexAttribPointer(attr, rsize, gl.FLOAT, false, 0, 0); //void gl.vertexAttribPointer(index, size(1-4), type, normalized, stride, offset);
	
}

function dGL(glc, sh, f, p, x, y, w, h) { // draw shape using webGL
	var gl = CTX[glc];
	var paint = p; //[0.5, 0.5, 1.0, 1.0]; rgba

	switch (sh) { // shape
		case 'rect':
			// xy1 ->  xy2
			if(f=='f'){
				var trace = p2C(CAN.agl.width, CAN.agl.height, 2, [x, y, x+w, y, x, y+h, x+w, y+h]);
				rGL(gl, 'ts', 2, trace, paint);			
			}
			if(f=='s'){
				var trace = p2C(CAN.agl.width, CAN.agl.height, 2, [x, y, x+w, y, x+w, y+h, x, y+h]);
				rGL(gl, 'll', 2, trace, paint);	
			}

			
			
		break;  
		case 'samplediamond': // sample shape
			var trace=[
				-1, 0, 0,
				0, 1, 0,
				0, -1, 0,
				1, 0, 0
			]
			rgl = 'ts';
			
			rGL(gl, rgl, 3, trace, paint)
		break;  

	}	

}

function p2C(w, h, d, m){
	// (canvas.w, canvas.h, #dim, matrix)
	// convert pixel matrix to clipspace matrix (for rendering)
	var nm=[];
	for(var i=0; i<m.length; i+=d){
		nm[i] = 2* m[i]/w -1;
		nm[i+1] = -1* (m[i+1]/h);
	}

	return new Float32Array(nm);
}

function rGL(gl, r, d, t, p){ //render shape using webGL
	//(gl, render, #dimensions, trace, paint)
	switch (r) { // set render type
		case 't':	render = gl.TRIANGLES;		break;  // triangles (every 3 coord)
		case 'tf':	render = gl.TRIANGLE_FAN;	break;  // center of pie to outside, then around (chinese fan)
		case 'ts':	render = gl.TRIANGLE_STRIP;	break;  // Tesselation. ( 3 coord = triangle 1, each subsequent coord is a new triangle attached to the last)
		case 'p':	render = gl.POINTS;			break;	// dots
		case 'ls':	render = gl.LINE_STRIP;		break;  // connect dots
		case 'll':	render = gl.LINE_LOOP;		break;  // connect dots, loop to start
		case 'l':	render = gl.LINES;			break;  // single lines (every 2 coord)
	}	
	
	var prog = shaderProgram(gl,
		"attribute vec3 pos;"+	"void main() {"+ "	gl_Position = vec4(pos, 1);"+	"}",
								"void main() {"+ "	gl_FragColor = vec4("+ p +");"+	"}"
	);
	gl.useProgram(prog);
	attributeSetFloats(gl, prog, "pos", d, t);
	gl.drawArrays(render, 0, t.length/d);
}

function vWebGL(){
	//================= Variables =================
	var acW = CAN.agl.width
	var acH = CAN.agl.height
	var halfCount = Math.floor(Quantity / 2);
	var vX = vizX * acW/2000, vY = vizY * acH/2000; //Adjustable positioning system
	var vLX = vizLX * acW/2000, vLY = vizLY * acH/2000; //Left half of LR
	var vRX = vizRX * acW/2000, vRY = vizRY * acH/2000; //Right half of LR	
	
	
	//================= Start Viz =================
	//dGL('agl', 'rect', 'f', [0.5, 0.5, 1.0, 1.0], 300, 300, 200, 400);
	if(vizType == 0){ //None - clear canvas
		refreshVU++
		if(refreshVU >= setFPS){ //Refresh sprite canvas only occasionally.
			refreshVU=0;
			clear('agl');
		}
	}
	else if(vizType == 10){ // Render bars along the full width of the canvas (Adapted from https://steamcommunity.com/sharedfiles/filedetails/?id=786006047 )
		clear('agl');  //Transparent BG
		var vizBarPad = vizPad*2;
		var barThickness = acW/Quantity-vizBarPad;
		if(vizSolid){var fill='f'}	else	{var fill='s'}
		
		if(vizTypeVar == 0){
			for (var i = 0; i < Quantity; i++) {
				var height = (acH)* peakValues[i];
				dGL('agl', 'rect', fill, VizColorGL(i, 1, 10*peakValues[i]*0.75), vX +vizBarPad/2+(barThickness+vizBarPad) * i, vY +acH - height, barThickness-vizBarPad/2, height);
			}

		}
		
	/*	else if(vizTypeVar == 1){ //Domed Bars
			var domeR = (barThickness-vizBarPad/2)/2;	if(domeR < 0){domeR *= -1}
			// Begin with the left side 
			CTX.a.shadowColor = LglowColor[3];
			for (var i = 0; i <= halfCount; i++) {
				setVizColor(i, 1, 10*peakValues[i]*0.75);

				var height = (acH)* peakValues[i];
				var vibeX = vX +vizBarPad/2+(barThickness+vizBarPad) *i;
				
				CTX.a.beginPath();
				CTX.a.moveTo(vibeX, vY +acH);
				CTX.a.lineTo(vibeX, vY +acH-height);		
				CTX.a.arc   (vibeX +(barThickness-vizBarPad/2)/2, vY +acH-height, domeR, 1*Math.PI, 2*Math.PI);	
				CTX.a.lineTo(vibeX +barThickness-vizBarPad/2, vY +acH);					
				CTX.a.lineTo(vibeX, vY +acH);
				if(vizSolid){CTX.a.fill();	}	else	{CTX.a.stroke();	}
				CTX.a.closePath();	
			}

			
			// Now draw the right side 
			CTX.a.shadowColor = RglowColor[3];
			for (var i = halfCount+isOdd(Quantity); i < Quantity; i++) {
				setVizColor(i, 2, 10*peakValues[i]*0.75);

				var height = (acH)* peakValues[i];
				var vibeX = vX +vizBarPad/2+(barThickness+vizBarPad) *i;
				
				CTX.a.beginPath();
				CTX.a.moveTo(vibeX, vY +acH);
				CTX.a.lineTo(vibeX, vY +acH-height);		
				CTX.a.arc   (vibeX +(barThickness-vizBarPad/2)/2, vY +acH-height, domeR, 1*Math.PI, 2*Math.PI);	
				CTX.a.lineTo(vibeX +barThickness-vizBarPad/2, vY +acH);					
				CTX.a.lineTo(vibeX, vY +acH);
				if(vizSolid){CTX.a.fill();	}	else	{CTX.a.stroke();	}
				CTX.a.closePath();	
			}			
		}
		
		else if(vizTypeVar == 2){	// Render bars with a curved top
			midPoints = []; //halfway height marks between node and adjacent nodes. These will be curve ends. Curve top will be the amplitude. Adjust when padding is used.
			for (var i = 0; i < Quantity; i++) {
				var lSlant, rSlant; //determine whether side is pointed up or down
				if(peakValues[i-1]-peakValues[i]<0){lSlant = 0.3/(peakValues[i]/peakValues[i-1]);}	else{lSlant = -0.3/(peakValues[i+1]/peakValues[i]);}
				if(peakValues[i+1]-peakValues[i]<0){rSlant = 0.3/(peakValues[i]/peakValues[i-1]);}	else{rSlant = -0.3/(peakValues[i+1]/peakValues[i]);}

				if(i==0){
					if(i==Quantity-1){	midPoints[i]=[0,0];	}
					else{	midPoints[i]=[0, acH* (peakValues[i]+peakValues[i+1])/2];	}
				}
				else if(i==Quantity-1){	midPoints[i]=[acH* (peakValues[i-1]+peakValues[i])/2, 0];	}
				else{	midPoints[i]=[acH* (peakValues[i-1]+peakValues[i])/2+vizBarPad/2*lSlant, acH* (peakValues[i]+peakValues[i+1])/2+vizBarPad/2*rSlant];		}
			}
			
			// Begin with the left side 
			CTX.a.shadowColor = LglowColor[3];
			for (var i = 0; i <= halfCount; i++) {
				setVizColor(i, 1, 10*peakValues[i]*0.75);
			
				var height = (acH)* peakValues[i];
				var vibeX = vX +vizBarPad/2+(barThickness+vizBarPad) *i;
				
				CTX.a.beginPath();
				CTX.a.moveTo			 (vibeX, vY +acH);
				CTX.a.lineTo			 (vibeX, vY +acH-midPoints[i][0]);		
				CTX.a.quadraticCurveTo(vibeX+(barThickness-vizBarPad/2)/2, vY +acH - height, vibeX+(barThickness-vizBarPad/2), vY +acH-midPoints[i][1]);
				CTX.a.lineTo			 (vibeX+(barThickness-vizBarPad/2), vY +acH);
				CTX.a.closePath();	
				
				if(vizSolid){CTX.a.fill();	}
				else		{CTX.a.stroke();	}
			}

			
			// Now draw the right side 
			CTX.a.shadowColor = RglowColor[3];	
			for (var i = halfCount+isOdd(Quantity); i < Quantity; i++) {
				setVizColor(i, 2, 10*peakValues[i]*0.75);
		
				var height = (acH)* peakValues[i];
				var vibeX = vX +vizBarPad/2+(barThickness+vizBarPad) *i;
				
				CTX.a.beginPath();
				CTX.a.moveTo			 (vibeX, vY +acH);
				CTX.a.lineTo			 (vibeX, vY +acH-midPoints[i][0]);		
				CTX.a.quadraticCurveTo(vibeX+(barThickness-vizBarPad/2)/2, vY +acH - height, vibeX+(barThickness-vizBarPad/2), vY +acH-midPoints[i][1]);
				CTX.a.lineTo			 (vibeX+(barThickness-vizBarPad/2), vY +acH);
				CTX.a.closePath();					
				
				if(vizSolid){CTX.a.fill();	}
				else		{CTX.a.stroke();	}
			}
		//DebugDisplay.textContent = sortSamples[0];	
		}*/
	}
	else{
		dGL('agl', 'samplediamond', 'f', [0.5, 0.5, 1.0, 1.0], 300, 300, 200, 400);
	}
}


//============================================================ Clock Code =====================================
function setClockColor(cv, c, c2, a, sb){
	switch (c) {
		case 'f': 
			var newC = 'rgba(' +clock.fgC[c2][0]+', '+clock.fgC[c2][1]	+', '+clock.fgC[c2][2]	+', '+ a +')';
			if(cv=='c'){	CTX.c.shadowColor = clock.gC[c2][3];	}
		break;
		case 'b':
			var newC = 'rgba(' +clock.bgC[0]	+', '+clock.bgC[1]		+', '+clock.bgC[2]		+', '+ a +')';	
		break;
	}
	if(sb !=NaN){CTX[cv].shadowBlur = sb}
	CTX[cv].fillStyle = CTX[cv].strokeStyle = newC;
}

var TV=[];
function timer(tv, tps, uv){
	var tn = Date.now();
	if(!TV[tv]){TV[tv]=0}
	var td = tn-TV[tv];
	if(tps>=0){var ti = 1000/tps}	else {var ti = -tps*250} // -#s indicate intervals in 1/4 seconds ( if tps= -5, ti = 1.25 seconds)
	var tr = false;
	if(td > ti){
		tr=true;
		if(uv){TV[tv] = tn}		//update timer var if desired
	}
	//DebugDisplay.textContent = 'hi. TV[tv] ==' +TV[tv] +', td==' +td+ ', ti==' +ti+ ', tr==' +tr;
	
	return tr;
}

function updateClock(){
	ccW = CAN.c.width;
	ccH = CAN.c.height;
	var clockCX = ccW/2 + clock.X/200 *ccW/2;
	var clockCY = ccH/2 + clock.Y/200 *ccH/2;
	var bgu = clock.bgupdate;
	
	CTX.c.lineWidth= Math.max(0.1, 0.75*clockSize/40 +clock.FLW);
	var fWeight = "";
	if(clockBold){fWeight="bold"}
	var getTheTime = new Date(); gtH = getTheTime.getHours()+clock.Adjust; gtM = getTheTime.getMinutes(); gtS = getTheTime.getSeconds();gtMS = getTheTime.getMilliseconds()
	var amPm = "am"; var numHours = 24;
			if(clock.H24 && gtH > 24){	gtH -= 24;	}
			if(!clock.H24){	numHours -= 12;	}
			if(!clock.H24 && gtH > 12){	gtH -= 12; amPm = "pm"	}
			if(!clock.H24 && gtH > 12){	gtH -= 12; amPm = "am"	}
			if(!clock.H24 && gtH == 0){	gtH += 12;	}
			CTX.c.shadowBlur = clock.Glow;
	
	switch (clockType) {
		case 0: //None
			if(!clockIsClear){ //prevent unnecessary wipes
				clear('c');
				clear('cb');			
				clockIsClear = true;
			}
		break;
		case 10: //Digital
			if(gtS != gtS2 || clockMsec == true){	//prevent unnecessary writes
				clear('c');
				if(bgu){	clear('cb');clock.bgupdate=false;	}				
				
				// Draw BG
				if(bgu){
					if(clock.Back > 0) {
						setClockColor('cb', 'b', 0, clock.BOP, clock.bgGlow); CTX.cb.shadowColor = clock.bggC[3];
						var bgS = Math.max(10*clockSize +clock.bgS * ccW/2000);
					}
					if(clock.Back == 1){	drawS('cb', "box", "F", clockCX -bgS*5.5/10, clockCY-bgS*3/10, 0, clock.bgC, 0, 0, clockCX +bgS*5.5/10, clockCY+bgS*3/10 );	} // long rect
					if(clock.Back == 2){	drawS('cb', "box", "F", clockCX -bgS*5/10, clockCY-bgS*4/10, 0, clock.bgC, 0, 0, clockCX +bgS*5/10, clockCY+bgS*4/10 );		} // rect
					if(clock.Back == 3){	drawS('cb', "circle", "F", clockCX, clockCY, bgS/2, clock.bgC, 0, 2, 0, -90);	} // cir
					if(clock.Back == 4){	drawS('cb', "peanut", "F", clockCX, clockCY, bgS/2, clock.bgC, 0, 2, 0, -90); 	} // peanut
					if(clock.Back == 5){	drawS('cb', "star", "F", clockCX, clockCY, bgS, clock.bgC, 0, 0, 3, -90);		} // tri
					if(clock.Back == 6){	drawS('cb', "star", "F", clockCX, clockCY, bgS*3/4, clock.bgC, 0, 0, 4, -90);	} // diam
					if(clock.Back == 7){	drawS('cb', "poly", "F", clockCX, clockCY, bgS*3/4, clock.bgC, 0, 0, 5, -90);	} // 5
					if(clock.Back == 8){	drawS('cb', "poly", "F", clockCX, clockCY, bgS*3/4, clock.bgC, 0, 0, 6, -90);	} // 6
					if(clock.Back == 9){	drawS('cb', "poly", "F", clockCX, clockCY, bgS*3/4, clock.bgC, 0, 0, 7, -90);	} // 7
					if(clock.Back == 10){	drawS('cb', "poly", "F", clockCX, clockCY, bgS*3/4, clock.bgC, 0, 0, 8, -90);	} // 8
					if(clock.Back == 11){	drawS('cb', "poly", "F", clockCX, clockCY, bgS*3/4, clock.bgC, 0, 0, 10, -90);	} // 10
					if(clock.Back == 12){	drawS('cb', "poly", "F", clockCX, clockCY, bgS*3/4, clock.bgC, 0, 0, 12, -90);	} // 12
				}
				
				// Prep Data
				if(clock.U == 1){ //Roman
					timeString = toRoman(gtH)+":"+toRoman(gtM);
					if(clockSec){	timeString+=":"+toRoman(gtS)	}
					if(clockMsec){	timeString+="."+toRoman(gtMS)	}					
				}
				else if(clock.U == 2){ //Hex
					timeString = toHex(gtH)+":"+toHex(gtM);
					if(clockSec){	timeString+=":"+toHex(gtS)	}
					if(clockMsec){	timeString+="."+toHex(gtMS)	}					
				}
				else{ //Regular Numbers
					if(gtM < 10){	gtM = "0"+gtM }
					if(gtS < 10){	gtS = "0"+gtS }
					if(gtMS < 10){	gtMS = "0"+gtS }
					if(gtMS < 100){	gtMS = "0"+gtS }			
					
					var timeString = gtH+":"+gtM;
					if(clockSec){	timeString+=":"+gtS	}
					if(clockMsec){	timeString+="."+gtMS	}
				}

				if(clock.H24 == false){	timeString+= " "+amPm;	}
				//DebugDisplay2.textContent = 	clock.fSize;						
				CTX.c.font= fWeight +' '+ (clock.fSize +250*clockSize/100) +'px '+ clockFont +', algerian, serif';
				setClockColor('c', 'f', 0, clock.OP);	
				CTX.c.textAlign="center";	CTX.c.textBaseline="middle";
				if(clockSolid){	CTX.c.fillText(timeString, clockCX, clockCY);}
				else		{	CTX.c.strokeText(timeString, clockCX, clockCY);}
				CTX.c.textAlign="start"; 	CTX.c.textBaseline="alphabetic"; 	
				
				clockIsClear = false;
			}
		break;
		case 11: //Clock of clocks (numbers made using hands from 4x6 clocks)
			if(gtS != gtS2 || clockMsec == true || (gtS == gtS2 && gtMS-gtMS2 > 15)){	//prevent unnecessary writes
				clear('c');
				if(bgu){	clear('cb');clock.bgupdate=false;	}				

				// vars
				CTX.c.lineWidth= Math.max(1, 4+clock.FLW)
				var clw		= CTX.c.lineWidth;		
				if(!clock.Smooth){ //alternate movement
					var cwn=[]; var flip = 1;
					for(var i=0; i<10; i++){ 
						cwn[i]=[];
						if(flip==1)	{	cwn[i][0] = clock.wall.n[i][0];	cwn[i][1] = clock.wall.n[i][1];	}
						else		{	cwn[i][0] = clock.wall.n[i][1];	cwn[i][1] = clock.wall.n[i][0];	}
						flip *= -1;
					}
				}
				else {var cwn		= clock.wall.n;}
				var cwt		= clock.wall.t;
				var cwh		= clock.wall.h;
				var cwm		= clock.wall.m;
				var cws		= clock.wall.s;
				var cwms	= clock.wall.ms;
				
				
				var fontHeight = (clockSize)*25/10+clockSpacing-50;
				
				//setup clock data
				if(clockMsec && (gtMS2 != gtMS || !cwt[1]))	{ var upMS=true } else { var upMS=false	}
				if(clockSec && (gtS2  != gtS || !cwt[1]))	{ var upS =true	} else { var upS =false	}
				if(gtM2  != gtM || !cwt[1])					{ var upM =true	} else { var upM =false	}
				if(gtH2  != gtH || !cwt[1])					{ var upH =true	} else { var upH =false	}
				if((clock.wall.u != clock.U) || (clock.wall.h24 != clock.H24) || (clock.wall.adj != clock.Adjust)){
					clock.wall.u = clock.U;
					clock.wall.h24 = clock.H24;
					clock.wall.adj = clock.Adjust;
					upMS=true; upS =true; upM =true; upH =true;
					}
				var speed=31-clock.Ups/2;

				if(upH){
					//update hour
					if(clock.U == 2){t = clock.N[2][gtH]} else {t = gtH}
					if(t.toString().length == 1){	cwt[0]=0; 						cwt[1]=t.toString().charAt(0);	}
					else						{	cwt[0]=t.toString().charAt(0); cwt[1]=t.toString().charAt(1);	}
					
					for(var i=0; i<24; i++){
						//update target direction
						cwh[0][i][2] = cwn[cwt[0]][0][i];
						cwh[0][i][3] = cwn[cwt[0]][1][i];
						cwh[1][i][2] = cwn[cwt[1]][0][i];
						cwh[1][i][3] = cwn[cwt[1]][1][i];
						
						//update curved velocity
						cD = circDist(cwh[0][i][0], cwh[0][i][2]);			cwh[0][i][4] = Math.round(cD/speed);
						cD = circDist(cwh[0][i][1], cwh[0][i][3]);			cwh[0][i][5] = Math.round(cD/speed);
						cD = circDist(cwh[1][i][0], cwh[1][i][2]);			cwh[1][i][4] = Math.round(cD/speed);
						cD = circDist(cwh[1][i][1], cwh[1][i][3]);			cwh[1][i][5] = Math.round(cD/speed);			
					}	
				}
				else{
					for(var i=0; i<24; i++){
						//update current direction if not too close
						if(cwh[0][i][4] != 0){
							if(circDist(cwh[0][i][0], cwh[0][i][2], true) < Math.abs(cwh[0][i][4])){	cwh[0][i][0]=cwh[0][i][2];	cwh[0][i][4]=0;	}
							else{	cwh[0][i][0] += cwh[0][i][4];	}
						}
						if(cwh[0][i][5] != 0){
							if(circDist(cwh[0][i][1], cwh[0][i][3], true) < Math.abs(cwh[0][i][5])){	cwh[0][i][1]=cwh[0][i][3];	cwh[0][i][5]=0;	}
							else{	cwh[0][i][1] += cwh[0][i][5];	}
						}
						if(cwh[1][i][4] != 0){
							if(circDist(cwh[1][i][0], cwh[1][i][2], true) < Math.abs(cwh[1][i][4])){	cwh[1][i][0]=cwh[1][i][2];	cwh[1][i][4]=0;	}
							else{	cwh[1][i][0] += cwh[1][i][4];	}
						}
						if(cwh[1][i][5] != 0){
							if(circDist(cwh[1][i][1], cwh[1][i][3], true) < Math.abs(cwh[1][i][5])){	cwh[1][i][1]=cwh[1][i][3];	cwh[1][i][5]=0;	}
							else{	cwh[1][i][1] += cwh[1][i][5];	}
						}
							
					}
				}
				if(upM){
					//update minute
					if(clock.U == 2){t = clock.N[2][gtM]} else {t = gtM}
					if(t.toString().length == 1){	cwt[2]=0; cwt[3]=t.toString().charAt(0);				}
					else						{	cwt[2]=t.toString().charAt(0); cwt[3]=t.toString().charAt(1);	}

					for(var i=0; i<24; i++){
						//update target direction
						cwm[0][i][2] = cwn[cwt[2]][0][i];
						cwm[0][i][3] = cwn[cwt[2]][1][i];
						cwm[1][i][2] = cwn[cwt[3]][0][i];
						cwm[1][i][3] = cwn[cwt[3]][1][i];
						
						//update curved velocity
						cD = circDist(cwm[0][i][0], cwm[0][i][2]);			cwm[0][i][4] = Math.round(cD/speed);
						cD = circDist(cwm[0][i][1], cwm[0][i][3]);			cwm[0][i][5] = Math.round(cD/speed);
						cD = circDist(cwm[1][i][0], cwm[1][i][2]);			cwm[1][i][4] = Math.round(cD/speed);
						cD = circDist(cwm[1][i][1], cwm[1][i][3]);			cwm[1][i][5] = Math.round(cD/speed);			
					}	
				}
				else{
					for(var i=0; i<24; i++){
						//update current direction if not too close
						if(cwm[0][i][4] != 0){
							if(circDist(cwm[0][i][0], cwm[0][i][2], true) < Math.abs(cwm[0][i][4])){	cwm[0][i][0]=cwm[0][i][2];	cwm[0][i][4]=0;	}
							else{	cwm[0][i][0] += cwm[0][i][4];	}
						}
						if(cwm[0][i][5] != 0){
							if(circDist(cwm[0][i][1], cwm[0][i][3], true) < Math.abs(cwm[0][i][5])){	cwm[0][i][1]=cwm[0][i][3];	cwm[0][i][5]=0;	}
							else{	cwm[0][i][1] += cwm[0][i][5];	}
						}
						if(cwm[1][i][4] != 0){
							if(circDist(cwm[1][i][0], cwm[1][i][2], true) < Math.abs(cwm[1][i][4])){	cwm[1][i][0]=cwm[1][i][2];	cwm[1][i][4]=0;	}
							else{	cwm[1][i][0] += cwm[1][i][4];	}
						}
						if(cwm[1][i][5] != 0){
							if(circDist(cwm[1][i][1], cwm[1][i][3], true) < Math.abs(cwm[1][i][5])){	cwm[1][i][1]=cwm[1][i][3];	cwm[1][i][5]=0;	}
							else{	cwm[1][i][1] += cwm[1][i][5];	}
						}
							
					}
				}
				if(upS){
					//update second
					if(clock.U == 2){t = clock.N[2][gtS]} else {t = gtS}
					if(t.toString().length == 1){	cwt[4]=0; cwt[5]=t.toString().charAt(0);				}
					else						{	cwt[4]=t.toString().charAt(0); cwt[5]=t.toString().charAt(1);	}

					for(var i=0; i<24; i++){
						//update target direction
						cws[0][i][2] = cwn[cwt[4]][0][i];
						cws[0][i][3] = cwn[cwt[4]][1][i];
						cws[1][i][2] = cwn[cwt[5]][0][i];
						cws[1][i][3] = cwn[cwt[5]][1][i];
						
						//update curved velocity
						cD = circDist(cws[0][i][0], cws[0][i][2]);			cws[0][i][4] = Math.round(cD/speed);
						cD = circDist(cws[0][i][1], cws[0][i][3]);			cws[0][i][5] = Math.round(cD/speed);
						cD = circDist(cws[1][i][0], cws[1][i][2]);			cws[1][i][4] = Math.round(cD/speed);
						cD = circDist(cws[1][i][1], cws[1][i][3]);			cws[1][i][5] = Math.round(cD/speed);			
					}	
				}
				else{
					for(var i=0; i<24; i++){
						//update current direction if not too close
						if(cws[0][i][4] != 0){
							if(circDist(cws[0][i][0], cws[0][i][2], true) < Math.abs(cws[0][i][4])){	cws[0][i][0]=cws[0][i][2];	cws[0][i][4]=0;	}
							else{	cws[0][i][0] += cws[0][i][4];	}
						}
						if(cws[0][i][5] != 0){
							if(circDist(cws[0][i][1], cws[0][i][3], true) < Math.abs(cws[0][i][5])){	cws[0][i][1]=cws[0][i][3];	cws[0][i][5]=0;	}
							else{	cws[0][i][1] += cws[0][i][5];	}
						}
						if(cws[1][i][4] != 0){
							if(circDist(cws[1][i][0], cws[1][i][2], true) < Math.abs(cws[1][i][4])){	cws[1][i][0]=cws[1][i][2];	cws[1][i][4]=0;	}
							else{	cws[1][i][0] += cws[1][i][4];	}
						}
						if(cws[1][i][5] != 0){
							if(circDist(cws[1][i][1], cws[1][i][3], true) < Math.abs(cws[1][i][5])){	cws[1][i][1]=cws[1][i][3];	cws[1][i][5]=0;	}
							else{	cws[1][i][1] += cws[1][i][5];	}
						}
							
					}
				}
				if(clockMsec){
					//update millisecond
					if(clock.U == 2){t = clock.N[2][gtMS]} else {t = gtMS}
					if(t.toString().length == 1)		{	cwt[6]=0; cwt[7]=0;	cwt[8]=t.toString().charAt(0);	}
					else if(t.toString().length == 2)	{	cwt[6]=0; cwt[7]=t.toString().charAt(0);	cwt[8]=t.toString().charAt(1);	}
					else								{	cwt[6]=t.toString().charAt(0); cwt[7]=t.toString().charAt(1);	cwt[8]=t.toString().charAt(2);	}

					for(var i=0; i<24; i++){
						//update target direction
						cwms[0][i][2] = cwn[cwt[6]][0][i];
						cwms[0][i][3] = cwn[cwt[6]][1][i];
						cwms[1][i][2] = cwn[cwt[7]][0][i];
						cwms[1][i][3] = cwn[cwt[7]][1][i];
						cwms[2][i][2] = cwn[cwt[8]][0][i];
						cwms[2][i][3] = cwn[cwt[8]][1][i];
						
						//update curved velocity
						cD = circDist(cwms[0][i][0], cwms[0][i][2]);			cwms[0][i][4] = Math.round(cD/speed *5);
						cD = circDist(cwms[0][i][1], cwms[0][i][3]);			cwms[0][i][5] = Math.round(cD/speed *5);
						cD = circDist(cwms[1][i][0], cwms[1][i][2]);			cwms[1][i][4] = Math.round(cD/speed *5);
						cD = circDist(cwms[1][i][1], cwms[1][i][3]);			cwms[1][i][5] = Math.round(cD/speed *5);			
						cD = circDist(cwms[2][i][0], cwms[2][i][2]);			cwms[2][i][4] = Math.round(cD/speed *5);
						cD = circDist(cwms[2][i][1], cwms[2][i][3]);			cwms[2][i][5] = Math.round(cD/speed *5);			
					}	

					for(var i=0; i<24; i++){
						//update current direction if not too close
						if(cwms[0][i][4] != 0){
							if(circDist(cwms[0][i][0], cwms[0][i][2], true) < Math.abs(cwms[0][i][4])){	cwms[0][i][0]=cwms[0][i][2];	cwms[0][i][4]=0;	}
							else{	cwms[0][i][0] += cwms[0][i][4];	}
						}
						if(cwms[0][i][5] != 0){
							if(circDist(cwms[0][i][1], cwms[0][i][3], true) < Math.abs(cwms[0][i][5])){	cwms[0][i][1]=cwms[0][i][3];	cwms[0][i][5]=0;	}
							else{	cwms[0][i][1] += cwms[0][i][5];	}
						}
						if(cwms[1][i][4] != 0){
							if(circDist(cwms[1][i][0], cwms[1][i][2], true) < Math.abs(cwms[1][i][4])){	cwms[1][i][0]=cwms[1][i][2];	cwms[1][i][4]=0;	}
							else{	cwms[1][i][0] += cwms[1][i][4];	}
						}
						if(cwms[1][i][5] != 0){
							if(circDist(cwms[1][i][1], cwms[1][i][3], true) < Math.abs(cwms[1][i][5])){	cwms[1][i][1]=cwms[1][i][3];	cwms[1][i][5]=0;	}
							else{	cwms[1][i][1] += cwms[1][i][5];	}
						}
						if(cwms[2][i][4] != 0){
							if(circDist(cwms[2][i][0], cwms[2][i][2], true) < Math.abs(cwms[2][i][4])){	cwms[2][i][0]=cwms[2][i][2];	cwms[2][i][4]=0;	}
							else{	cwms[2][i][0] += cwms[2][i][4];	}
						}
						if(cwms[2][i][5] != 0){
							if(circDist(cwms[2][i][1], cwms[2][i][3], true) < Math.abs(cwms[2][i][5])){	cwms[2][i][1]=cwms[2][i][3];	cwms[2][i][5]=0;	}
							else{	cwms[2][i][1] += cwms[2][i][5];	}
						}
					}
				}
				
								


				// Draw BG
				if(bgu){
					if(clock.Back > 0) {
						setClockColor('cb', 'b', 0, clock.BOP, clock.bgGlow);	CTX.cb.shadowColor = clock.bggC[3];
						var bgS = Math.max(1, 10*clockSize +clock.bgS * ccW/2000);
					}
					if(clock.Back == 1){	drawS('cb', "box", "F", clockCX -bgS*11/10, clockCY-bgS*3/10, 0, clock.bgC, 0, 0, clockCX +bgS*11/10, clockCY+bgS*3/10 );	} // long rect
					if(clock.Back == 2){	drawS('cb', "box", "F", clockCX -bgS*7/10, clockCY-bgS*4/10, 0, clock.bgC, 0, 0, clockCX +bgS*7/10, clockCY+bgS*4/10 );		} // rect
					if(clock.Back == 3){	drawS('cb', "circle", "F", clockCX, clockCY, bgS*3/4, clock.bgC, 0, 2, 0, -90);	} // cir
					if(clock.Back == 4){	drawS('cb', "peanut", "F", clockCX, clockCY, bgS/2, clock.bgC, 0, 2, 0, -90); 	} // peanut
					if(clock.Back == 5){	drawS('cb', "star", "F", clockCX, clockCY, bgS*5/4, clock.bgC, 0, 0, 3, -90);		} // tri
					if(clock.Back == 6){	drawS('cb', "star", "F", clockCX, clockCY, bgS*7/8, clock.bgC, 0, 0, 4, -90);	} // diam
					if(clock.Back == 7){	drawS('cb', "poly", "F", clockCX, clockCY, bgS*7/8, clock.bgC, 0, 0, 5, -90);	} // 5
					if(clock.Back == 8){	drawS('cb', "poly", "F", clockCX, clockCY, bgS*13/16, clock.bgC, 0, 0, 6, -90);	} // 6
					if(clock.Back == 9){	drawS('cb', "poly", "F", clockCX, clockCY, bgS*13/16, clock.bgC, 0, 0, 7, -90);	} // 7
					if(clock.Back == 10){	drawS('cb', "poly", "F", clockCX, clockCY, bgS*3/4, clock.bgC, 0, 0, 8, -90);	} // 8
					if(clock.Back == 11){	drawS('cb', "poly", "F", clockCX, clockCY, bgS*3/4, clock.bgC, 0, 0, 10, -90);	} // 10
					if(clock.Back == 12){	drawS('cb', "poly", "F", clockCX, clockCY, bgS*3/4, clock.bgC, 0, 0, 12, -90);	} // 12
				}


				//=== draw Clockception ===
				var r = Math.max(1, 10+clock.fSize), nsp=r*10, vrt = -r*5, hz2 = (r-nsp)*2;
				if(clockSec) {hz2 += (-nsp)}
				if(clockMsec){hz2 += (-nsp) *1.5}
				
				//dots
				setClockColor('c', 'f', 0, clock.OP);	
				drawS('c', "circle", "F", clockCX +hz2+nsp*2-r*2, clockCY +r*2, r/2, CTX.c.strokeStyle, 0, 2, 0, -90);	
				drawS('c', "circle", "F", clockCX +hz2+nsp*2-r*2, clockCY -r*2, r/2, CTX.c.strokeStyle, 0, 2, 0, -90);	
				if(clockSec) {
					drawS('c', "circle", "F", clockCX +hz2+nsp*4-r*2, clockCY +r*2, r/2, CTX.c.strokeStyle, 0, 2, 0, -90);	
					drawS('c', "circle", "F", clockCX +hz2+nsp*4-r*2, clockCY -r*2, r/2, CTX.c.strokeStyle, 0, 2, 0, -90);	
				}
				if(clockMsec) {
					drawS('c', "circle", "F", clockCX +hz2+nsp*6-r*2, clockCY +r*3, r/2, CTX.c.strokeStyle, 0, 2, 0, -90);	
					drawS('c', "circle", "F", clockCX +hz2+nsp*6-r*2, clockCY, 		r/2, CTX.c.strokeStyle, 0, 2, 0, -90);	
					drawS('c', "circle", "F", clockCX +hz2+nsp*6-r*2, clockCY -r*3, r/2, CTX.c.strokeStyle, 0, 2, 0, -90);	
				}

				if(bgu){
					//Clock Faces (circles)
					if(clockSolid){	
						var vrt2 = 0+vrt;
						setClockColor('cb', 'b', 0, clock.BOP); //CTX.cb.shadowBlur = 0;
						for(var i=0; i<24; i++){
							var hz = (i%4) * (r*2);
							//H
							drawS('cb', "circle", "F", clockCX +hz+hz2, clockCY+vrt2, r, clock.bgC, 0, 2, 0, -90);	
							drawS('cb', "circle", "F", clockCX +hz+hz2+nsp, clockCY+vrt2, r, clock.bgC, 0, 2, 0, -90);	
							//M
							drawS('cb', "circle", "F", clockCX +hz+hz2+(nsp*2), clockCY+vrt2, r, clock.bgC, 0, 2, 0, -90);	
							drawS('cb', "circle", "F", clockCX +hz+hz2+(nsp*3), clockCY+vrt2, r, clock.bgC, 0, 2, 0, -90);	
							//S
							if(clockSec){	
								setClockColor('cb', 'b', 0, clock.BOP); CTX.c.shadowBlur = 0;
								drawS('cb', "circle", "F", clockCX +hz+hz2+(nsp*4), clockCY+vrt2, r, clock.bgC, 0, 2, 0, -90);	
								drawS('cb', "circle", "F", clockCX +hz+hz2+(nsp*5), clockCY+vrt2, r, clock.bgC, 0, 2, 0, -90);	
							}
							//MS
							if(clockMsec){	
								setClockColor('cb', 'b', 0, clock.BOP); CTX.c.shadowBlur = 0;
								drawS('cb', "circle", "F", clockCX +hz+hz2+(nsp*6), clockCY+vrt2, r, clock.bgC, 0, 2, 0, -90);	
								drawS('cb', "circle", "F", clockCX +hz+hz2+(nsp*7), clockCY+vrt2, r, clock.bgC, 0, 2, 0, -90);	
								drawS('cb', "circle", "F", clockCX +hz+hz2+(nsp*8), clockCY+vrt2, r, clock.bgC, 0, 2, 0, -90);	
							}
							if(i%4 == 3){vrt2 += r*2}	
						}
						CTX.c.shadowBlur = clock.Glow;			
					}
				}
				
				//Clock Hands
				CTX.c.lineCap= "round";
				//H
				//hands
				setClockColor('c', 'f', 1, clock.OP);	
				var vrt2 = 0+vrt;
				for(var i=0; i<24; i++){
					var hz = (i%4) * (r*2);
					cHands = circPoint(clockCX, clockCY, r, cwh[0][i][0], 360, -90);	drawLine('c', clockCX +hz+hz2, clockCY+vrt2, cHands[0]+hz+hz2, cHands[1]+vrt2, clw, clw)
					cHands = circPoint(clockCX, clockCY, r, cwh[0][i][1], 360, -90);	drawLine('c', clockCX +hz+hz2, clockCY+vrt2, cHands[0]+hz+hz2, cHands[1]+vrt2, clw, clw)
					cHands = circPoint(clockCX, clockCY, r, cwh[1][i][0], 360, -90);	drawLine('c', clockCX +hz+hz2+nsp, clockCY+vrt2, cHands[0]+hz+hz2+nsp, cHands[1]+vrt2, clw, clw)
					cHands = circPoint(clockCX, clockCY, r, cwh[1][i][1], 360, -90);	drawLine('c', clockCX +hz+hz2+nsp, clockCY+vrt2, cHands[0]+hz+hz2+nsp, cHands[1]+vrt2, clw, clw)		
					if(i%4 == 3){vrt2 += r*2}					
				}	
				//M
				setClockColor('c', 'f', 2, clock.OP);	
				var vrt2 = 0+vrt;
				for(var i=0; i<24; i++){
					var hz = (i%4) * (r*2);
					cHands = circPoint(clockCX, clockCY, r, cwm[0][i][0], 360, -90);	drawLine('c', clockCX +hz+hz2+(nsp*2), clockCY+vrt2, cHands[0]+hz+hz2+(nsp*2), cHands[1]+vrt2, clw, clw)
					cHands = circPoint(clockCX, clockCY, r, cwm[0][i][1], 360, -90);	drawLine('c', clockCX +hz+hz2+(nsp*2), clockCY+vrt2, cHands[0]+hz+hz2+(nsp*2), cHands[1]+vrt2, clw, clw)
					cHands = circPoint(clockCX, clockCY, r, cwm[1][i][0], 360, -90);	drawLine('c', clockCX +hz+hz2+(nsp*3), clockCY+vrt2, cHands[0]+hz+hz2+(nsp*3), cHands[1]+vrt2, clw, clw)
					cHands = circPoint(clockCX, clockCY, r, cwm[1][i][1], 360, -90);	drawLine('c', clockCX +hz+hz2+(nsp*3), clockCY+vrt2, cHands[0]+hz+hz2+(nsp*3), cHands[1]+vrt2, clw, clw)
					if(i%4 == 3){vrt2 += r*2}					
				}				
				//S
				setClockColor('c', 'f', 3, clock.OP);	
				var vrt2 = 0+vrt;
				for(var i=0; i<24; i++){
					var hz = (i%4) * (r*2);
					if(clockSec){	
						cHands = circPoint(clockCX, clockCY, r, cws[0][i][0], 360, -90);	drawLine('c', clockCX +hz+hz2+(nsp*4), clockCY+vrt2, cHands[0]+hz+hz2+(nsp*4), cHands[1]+vrt2, clw, clw)
						cHands = circPoint(clockCX, clockCY, r, cws[0][i][1], 360, -90);	drawLine('c', clockCX +hz+hz2+(nsp*4), clockCY+vrt2, cHands[0]+hz+hz2+(nsp*4), cHands[1]+vrt2, clw, clw)
						cHands = circPoint(clockCX, clockCY, r, cws[1][i][0], 360, -90);	drawLine('c', clockCX +hz+hz2+(nsp*5), clockCY+vrt2, cHands[0]+hz+hz2+(nsp*5), cHands[1]+vrt2, clw, clw)
						cHands = circPoint(clockCX, clockCY, r, cws[1][i][1], 360, -90);	drawLine('c', clockCX +hz+hz2+(nsp*5), clockCY+vrt2, cHands[0]+hz+hz2+(nsp*5), cHands[1]+vrt2, clw, clw)
					}
					if(i%4 == 3){vrt2 += r*2}					
				}						
				//MS
				setClockColor('c', 'f', 4, clock.OP);	
				var vrt2 = 0+vrt;
				for(var i=0; i<24; i++){
					var hz = (i%4) * (r*2);
					if(clockMsec){	
						cHands = circPoint(clockCX, clockCY, r, cwms[0][i][0], 360, -90);	drawLine('c', clockCX +hz+hz2+(nsp*6), clockCY+vrt2, cHands[0]+hz+hz2+(nsp*6), cHands[1]+vrt2, clw, clw)
						cHands = circPoint(clockCX, clockCY, r, cwms[0][i][1], 360, -90);	drawLine('c', clockCX +hz+hz2+(nsp*6), clockCY+vrt2, cHands[0]+hz+hz2+(nsp*6), cHands[1]+vrt2, clw, clw)
						cHands = circPoint(clockCX, clockCY, r, cwms[1][i][0], 360, -90);	drawLine('c', clockCX +hz+hz2+(nsp*7), clockCY+vrt2, cHands[0]+hz+hz2+(nsp*7), cHands[1]+vrt2, clw, clw)
						cHands = circPoint(clockCX, clockCY, r, cwms[1][i][1], 360, -90);	drawLine('c', clockCX +hz+hz2+(nsp*7), clockCY+vrt2, cHands[0]+hz+hz2+(nsp*7), cHands[1]+vrt2, clw, clw)
						cHands = circPoint(clockCX, clockCY, r, cwms[2][i][0], 360, -90);	drawLine('c', clockCX +hz+hz2+(nsp*8), clockCY+vrt2, cHands[0]+hz+hz2+(nsp*8), cHands[1]+vrt2, clw, clw)
						cHands = circPoint(clockCX, clockCY, r, cwms[2][i][1], 360, -90);	drawLine('c', clockCX +hz+hz2+(nsp*8), clockCY+vrt2, cHands[0]+hz+hz2+(nsp*8), cHands[1]+vrt2, clw, clw)
					}
					if(i%4 == 3){vrt2 += r*2}					
				}				
				//DebugDisplay2.textContent = 	cwh[0][1];					
				clockIsClear = false;
			}
		break;
		case 30: //Analog
			if(gtS != gtS2 || clockMsec == true){	//prevent unnecessary writes
				clear('c');
				if(bgu){	clear('cb');clock.bgupdate=false;	}				
				
				// Draw BG
				if(bgu){
					if(clock.Back > 0) {
						setClockColor('cb', 'b', 0, clock.BOP, clock.bgGlow);	CTX.cb.shadowColor = clock.bggC[3]; 
						var bgS = Math.max(1, 10*clockSize +clock.bgS * ccW/2000);
					}
					if(clock.Back == 1){	drawS('cb', "circle", "F", clockCX, clockCY, bgS, clock.bgC, 0, 2, 0, -90);		} // cir
					if(clock.Back == 2){	drawS('cb', "poly", "F", clockCX, clockCY, bgS *1.25, clock.bgC, 0, 0, 4, -45);	} // squa
					if(clock.Back == 3){	drawS('cb', "poly", "F", clockCX, clockCY, bgS*1.25, clock.bgC, 0, 0, 4, -90);	} // diam
					if(clock.Back == 4){	drawS('cb', "poly", "F", clockCX, clockCY, bgS*2, clock.bgC, 0, 0, 3, -90);		} // tri
					if(clock.Back == 5){	drawS('cb', "poly", "F", clockCX, clockCY, bgS*1.1, clock.bgC, 0, 0, 5, -90);	} // 5
					if(clock.Back == 6){	drawS('cb', "poly", "F", clockCX, clockCY, bgS*1.1, clock.bgC, 0, 0, 6, -90);	} // 6
					if(clock.Back == 7){	drawS('cb', "poly", "F", clockCX, clockCY, bgS*1.1, clock.bgC, 0, 0, 7, -90);	} // 7
					if(clock.Back == 8){	drawS('cb', "poly", "F", clockCX, clockCY, bgS*1.1, clock.bgC, 0, 0, 8, -90);	} // 8
					if(clock.Back == 9){	drawS('cb', "poly", "F", clockCX, clockCY, bgS*1.1, clock.bgC, 0, 0, 9, -90);	} // 9
					if(clock.Back == 10){	drawS('cb', "poly", "F", clockCX, clockCY, bgS*1.1, clock.bgC, 0, 0, 10, -90);	} // 10
					if(clock.Back == 11){	drawS('cb', "poly", "F", clockCX, clockCY, bgS*1.1, clock.bgC, 0, 0, 11, -90);	} // 11
					if(clock.Back == 12){	drawS('cb', "poly", "F", clockCX, clockCY, bgS*1.1, clock.bgC, 0, 0, 12, -90);	} // 12
				}
				
				CTX.c.font= fWeight +' '+ (clock.fSize +(clockSize)*25/10) +'px '+ clockFont +', algerian, serif';
				setClockColor('c', 'f', 0, clock.OP);	
				var fontHeight = (clockSize)*25/10+clockSpacing-50;
				
				CTX.c.textAlign="center"; CTX.c.textBaseline="middle"; 
				//create array of circle points
				var cPs = [];cPs['h']=[];
				for(c=1;c<numHours+1;c++){
					cPs['h'][c]=circPoint(clockCX, clockCY, fontHeight*Math.PI, c, numHours, -90);
					var nx = cPs['h'][c][0], ny = cPs['h'][c][1], nd = cPs['h'][c][2];
					if(clock.FT){
						CTX.c.save();	CTX.c.translate(nx, ny);		CTX.c.rotate(nd * Math.PI / 180);
						nx =0;	ny =0;
					}					
					if(clockSolid){CTX.c.fillText(clock.N[clock.U][c], nx, ny);}
					else		{CTX.c.strokeText(clock.N[clock.U][c], nx, ny);}
					if(clock.FT){	CTX.c.restore();		}	
				}
				CTX.c.textAlign="start"; 	CTX.c.textBaseline="alphabetic"; 				
				
				//create clock hands
				var clockHands = [];
				clockHands[0] = circPoint(clockCX, clockCY, fontHeight*(Math.PI-1.75), gtH, numHours, -90);
				clockHands[1] = circPoint(clockCX, clockCY, fontHeight*(Math.PI-1.25), gtM, 60, -90);					
				clockHands[2] = circPoint(clockCX, clockCY, fontHeight*(Math.PI-.5), gtS, 60, -90);
				clockHands[3] = circPoint(clockCX, clockCY, fontHeight*(Math.PI-.55), gtMS, 1000, -90);//Inner point
				clockHands[4] = circPoint(clockCX, clockCY, fontHeight*(Math.PI-.5), gtMS, 1000, -90);//Outer Point							
				CTX.c.lineCap= "round";
				
				//H
				setClockColor('c', 'f', 1, clock.OP);	
				CTX.c.lineWidth= 8*clockSize/40;	
				CTX.c.beginPath();
				CTX.c.moveTo(clockCX, clockCY);
				CTX.c.lineTo(clockHands[0][0],clockHands[0][1]);
				CTX.c.stroke();
				CTX.c.closePath();
				//M
				setClockColor('c', 'f', 2, clock.OP);	
				CTX.c.lineWidth= 4*clockSize/40;
				CTX.c.beginPath();
				CTX.c.moveTo(clockCX, clockCY);
				CTX.c.lineTo(clockHands[1][0],clockHands[1][1]);
				CTX.c.stroke();
				CTX.c.closePath();
				//S
				if(clockSec){	
					setClockColor('c', 'f', 3, clock.OP);	
					CTX.c.lineWidth= 2*clockSize/40;
					CTX.c.beginPath();
					CTX.c.moveTo(clockCX, clockCY);
					CTX.c.lineTo(clockHands[2][0],clockHands[2][1]);
					CTX.c.stroke();
					CTX.c.closePath();
				}
				//MS
				if(clockMsec){	
					setClockColor('c', 'f', 4, clock.OP);	
					CTX.c.lineWidth= 8*clockSize/40;
					CTX.c.beginPath();
					CTX.c.moveTo(clockHands[3][0],clockHands[3][1]);
					CTX.c.lineTo(clockHands[4][0],clockHands[4][1]);
					CTX.c.stroke();
					CTX.c.closePath();
				}
				
				//DebugDisplay2.textContent = 	CTX.c.font;					
				clockIsClear = false;
			}
		break;
		case 31: //Ptolemaic 
			if(gtS != gtS2 || clockMsec == true || (clock.Smooth && gtS == gtS2 && gtMS-gtMS2 > 1000/clock.Ups)){	//prevent unnecessary writes
				clear('c');
				if(bgu){	clear('cb');clock.bgupdate=false;	}				

				var radL = 1.5, sdwys = clock.Angle, cPs = []; cPs['ms']=[]; cPs['s']=[]; cPs['m']=[]; cPs['h']=[];
				var D = circPoint(clockCX, clockCY, 1, 12, 12, -90+sdwys);
				if(clock.Smooth){
					var UPS = 60;
					var adjS = UPS *Math.round(100*gtMS/1000)/100;
					var adjM = UPS *Math.round(100*gtS/60)/100 +adjS/UPS;
					var adjH = UPS *Math.round(100*gtM/60)/100 +adjM/UPS;
				} else {
					var UPS = 1;
					var adjH = 0;
					var adjM = 0;
					var adjS = 0;
				}
			
				// Draw BG
				if(bgu){
					if(clock.Back > 0) {
						setClockColor('cb', 'b', 0, clock.BOP, clock.bgGlow);	CTX.cb.shadowColor = clock.bggC[3];
						var bgS = Math.max(1, 10*clockSize +clock.bgS * ccW/2000);
						var rw=bgS*1/4, rg = bgS*1/100;
						if(clockSec && clockMsec)		{var rBoost = bgS *3/4 +rg*15;}
						else if(clockSec || clockMsec)	{var rBoost = bgS *2/4 +rg*5;}
						else							{var rBoost = 0;}
						
					}
					if([1, 2, 3].indexOf(clock.Back) > -1){
						setClockColor('cb', 'b', 0, clock.BOP, clock.bgGlow); CTX.cb.globalCompositeOperation="source-over";	
						if(clockSec && clockMsec){
							drawS('cb', "circle", "F", clockCX, clockCY, rw*6+rg*8, clock.bgC, 0, 2, 0, -90);
							setClockColor('cb', 'b', 0, 1, 0);			CTX.cb.globalCompositeOperation="destination-out";
							drawS('cb', "circle", "F", clockCX, clockCY, rw*5+rg*11, clock.bgC, 0, 2, 0, -90);	
							setClockColor('cb', 'b', 0, clock.BOP, clock.bgGlow);	CTX.cb.globalCompositeOperation="source-over";							
						}
						if(clockSec || clockMsec){
							drawS('cb', "circle", "F", clockCX, clockCY, rw*5+rg*5, clock.bgC, 0, 2, 0, -90);
							setClockColor('cb', 'b', 0, 1, 0);			CTX.cb.globalCompositeOperation="destination-out";
							drawS('cb', "circle", "F", clockCX, clockCY, rw*4+rg*6, clock.bgC, 0, 2, 0, -90);		
							setClockColor('cb', 'b', 0, clock.BOP, clock.bgGlow);	CTX.cb.globalCompositeOperation="source-over";								
						}
						drawS('cb', "circle", "F", clockCX, clockCY, rw*4, clock.bgC, 0, 2, 0, -90);
						setClockColor('cb', 'b', 0, 1, 0);			CTX.cb.globalCompositeOperation="destination-out";
						drawS('cb', "circle", "F", clockCX, clockCY, rw*3+rg, clock.bgC, 0, 2, 0, -90);
						setClockColor('cb', 'b', 0, clock.BOP, clock.bgGlow);	CTX.cb.globalCompositeOperation="source-over";	
						drawS('cb', "circle", "F", clockCX, clockCY, rw*3-rg*5, clock.bgC, 0, 2, 0, -90);
						setClockColor('cb', 'b', 0, 1, 0);			CTX.cb.globalCompositeOperation="destination-out";
						drawS('cb', "circle", "F", clockCX, clockCY, rw*2-rg, clock.bgC, 0, 2, 0, -90);
						setClockColor('cb', 'b', 0, clock.BOP, clock.bgGlow);	CTX.cb.globalCompositeOperation="source-over";	
					} // multi circles
					if(clock.Back == 2){	drawS('cb', "circle", "F", clockCX, clockCY, rw*1/2, clock.bgC, 0, 2, 0, -90);		} // small inner circle
					if(clock.Back == 3){	drawS('cb', "circle", "F", clockCX, clockCY, rw*2-rg*7, clock.bgC, 0, 2, 0, -90);	} // large inner circle
					if(clock.Back == 4){	drawS('cb', "circle", "F", clockCX, clockCY, bgS + rBoost *0.75, clock.bgC, 0, 2, 0, -90);		} // cir
					if(clock.Back == 5){	drawS('cb', "poly", "F", clockCX, clockCY, bgS *1.4 + rBoost, clock.bgC, 0, 0, 4, -45);	} // squa
					if(clock.Back == 6){	drawS('cb', "poly", "F", clockCX, clockCY, bgS *1.4 + rBoost, clock.bgC, 0, 0, 4, -90);	} // diam
					if(clock.Back == 7){	drawS('cb', "poly", "F", clockCX, clockCY, bgS *1.1 + rBoost, clock.bgC, 0, 0, 5, -90);	} // 5
					if(clock.Back == 8){	drawS('cb', "poly", "F", clockCX, clockCY, bgS *1.1 + rBoost, clock.bgC, 0, 0, 6, -90);	} // 6
					if(clock.Back == 9){	drawS('cb', "poly", "F", clockCX, clockCY, bgS *1.1 + rBoost, clock.bgC, 0, 0, 7, -90);	} // 7
					if(clock.Back == 10){	drawS('cb', "poly", "F", clockCX, clockCY, bgS *1.1 + rBoost, clock.bgC, 0, 0, 8, -90);	} // 8
					if(clock.Back == 11){	drawS('cb', "poly", "F", clockCX, clockCY, bgS *1.1 + rBoost, clock.bgC, 0, 0, 10, -90);	} // 10
					if(clock.Back == 12){	drawS('cb', "poly", "F", clockCX, clockCY, bgS *1.1 + rBoost, clock.bgC, 0, 0, 12, -90);	} // 12
				
					// Cut-out if split
					if(clock.Split > 2){
						CTX.cb.globalCompositeOperation="destination-out";	circDist(clock.Split, D[2])
						drawS('cb', "circle", "F", clockCX, clockCY, bgS + rBoost *0.75, "#aa0", 0, 0, (circDist(clock.Split, D[2])+sdwys+92)/180, (-circDist(clock.Split, D[2])+sdwys+88)/180, 'pac');
						CTX.cb.globalCompositeOperation="source-over";						
					}
				}

				CTX.c.textAlign="center"; CTX.c.textBaseline="middle"; 
				var fontHeight = (clockSize)*25/10/2+clockSpacing-50;
								
				// create arrays of rotating circle points
				//H
				setClockColor('c', 'f', 1, clock.OP);	
				CTX.c.font= fWeight +' '+ (clock.fSize +(clockSize)*25/20) +'px '+ clockFont +', algerian, serif';
				for(c=1;c<numHours+1;c++){
					cPs['h'][c]=circPoint(clockCX, clockCY, radL*fontHeight*Math.PI, (c-gtH)*UPS-adjH, numHours*UPS, -90+sdwys);
					var nx = cPs['h'][c][0], ny = cPs['h'][c][1], nd = cPs['h'][c][2];
					if(clock.Split == 0 || circDist(nd, D[2], true) <= 180-clock.Split){
						if(!clock.FT){nd=0}
						if(clock.FT){
							CTX.c.save();	CTX.c.translate(nx, ny);		CTX.c.rotate(nd * Math.PI / 180);
							nx =0;	ny =0;
						}						
						if(clockSolid || c==gtH){CTX.c.fillText(clock.N[clock.U][c], nx, ny);}
						else		{CTX.c.strokeText(clock.N[clock.U][c], nx, ny);}
						if(clock.FT){	CTX.c.restore();		}	
					}
				}
				radL += 0.75;
				//M				
				setClockColor('c', 'f', 2, clock.OP);	
				CTX.c.font= fWeight +' '+ (clock.fSize +(clockSize)*25/35) +'px '+ clockFont +', algerian, serif';
				for(c=1;c<60+1;c++){
					cPs['m'][c]=circPoint(clockCX, clockCY, radL*fontHeight*Math.PI, (c-gtM)*UPS-adjM, 60*UPS, -90+sdwys);
					var nx = cPs['m'][c][0], ny = cPs['m'][c][1], nd = cPs['m'][c][2];
					if(clock.Split == 0 || circDist(nd, D[2], true) <= 180-clock.Split){
						if(!clock.FT){nd=0}
						if(clock.FT){
							CTX.c.save();	CTX.c.translate(nx, ny);		CTX.c.rotate(nd * Math.PI / 180);
							nx =0;	ny =0;
						}						
						if(clockSolid || c==gtM){CTX.c.fillText(clock.N[clock.U][c], nx, ny);}
						else		{CTX.c.strokeText(clock.N[clock.U][c], nx, ny);}
						if(clock.FT){	CTX.c.restore();		}							
					}
				}
				radL += 0.75;
				//S
				setClockColor('c', 'f', 3, clock.OP);	
				CTX.c.font= fWeight +' '+ (clock.fSize +(clockSize)*25/35) +'px '+ clockFont +', algerian, serif';
				if(clockSec){	
					for(c=1;c<60+1;c++){
						cPs['s'][c]=circPoint(clockCX, clockCY, radL*fontHeight*Math.PI, (c-gtS)*UPS-adjS, 60*UPS, -90+sdwys);
						var nx = cPs['s'][c][0], ny = cPs['s'][c][1], nd = cPs['s'][c][2];
						if(clock.Split == 0 || circDist(nd, D[2], true) <= 180-clock.Split){
							if(!clock.FT){nd=0}
							if(clock.FT){
								CTX.c.save();	CTX.c.translate(nx, ny);		CTX.c.rotate(nd * Math.PI / 180);
								nx =0;	ny =0;
							}						
							if(clockSolid || c==gtS){CTX.c.fillText(clock.N[clock.U][c], nx, ny);}
							else		{CTX.c.strokeText(clock.N[clock.U][c], nx, ny);}
							if(clock.FT){	CTX.c.restore();		}	
						}
					}
					//DebugDisplay2.textContent =  cPs['s'][1][2] +":"+ D[2] +":"+ circDist(cPs['s'][1][2], D[2], true)	
					radL += 0.75;
				}
				//MS
				setClockColor('c', 'f', 4, clock.OP);	
				CTX.c.font= fWeight +' '+ (clock.fSize +(clockSize)*25/45) +'px '+ clockFont +', algerian, serif';
				if(clockMsec){	

					for(c=0;c<100;c++){
						cPs['ms'][c]=circPoint(clockCX, clockCY, radL*fontHeight*Math.PI, c-gtMS/10, 100, -90+sdwys);
						var nx = cPs['ms'][c][0], ny = cPs['ms'][c][1], nd = cPs['ms'][c][2];
						if(clock.Split == 0 || circDist(nd, D[2], true) <= 180-clock.Split){
							if(!clock.FT){nd=0}
							if(clock.FT){
								CTX.c.save();	CTX.c.translate(nx, ny);		CTX.c.rotate(nd * Math.PI / 180);
								nx =0;	ny =0;
							}						
							if(clockSolid || c==gtMS){CTX.c.fillText(clock.N[clock.U][c*10], nx, ny);}
							else		{CTX.c.strokeText(clock.N[clock.U][c*10], nx, ny);}
							if(clock.FT){	CTX.c.restore();		}	
						}
					}
				}
				//create static clock hand
				setClockColor('c', 'f', 0, clock.OP);	
				var clockHands = [];
				clockHands[0] = circPoint(clockCX, clockCY, fontHeight*(Math.PI-0.5), 0, 4, -90 +sdwys);
				clockHands[1] = circPoint(clockCX, clockCY, fontHeight*(Math.PI-0.55), 0, 4, -90 +sdwys);
				CTX.c.lineWidth= 8*clockSize/40;	
				CTX.c.lineCap= "round";
				CTX.c.beginPath();
				CTX.c.moveTo(clockCX, clockCY);	CTX.c.lineTo(clockHands[0][0],clockHands[0][1]);
				CTX.c.stroke();	CTX.c.closePath();
				drawS('c', "star", "F", clockHands[1][0],clockHands[1][1], fontHeight*0.07*(Math.PI), CTX.c.strokeStyle, 0, 0, 3, -90 +sdwys);
				
				//DebugDisplay2.textContent = 	CTX.c.font;					
				CTX.c.textAlign="start"; 	CTX.c.textBaseline="alphabetic"; 	
				clockIsClear = false;
			}
		break;
		case 32: //Square Clock
			if(gtS != gtS2 || clockMsec == true){	//prevent unnecessary writes
				clear('c');
				if(bgu){	clear('cb');clock.bgupdate=false;	}				
				
				// Draw BG
				if(bgu){
					if(clock.Back > 0) {
						setClockColor('cb', 'b', 0, clock.BOP, clock.bgGlow);	CTX.cb.shadowColor = clock.bggC[3]; 
						var bgS = Math.max(1, 10*clockSize +clock.bgS * ccW/2000)*0.6;
					}
					if(clock.Back == 1){	drawS('cb', "circle", "F", clockCX, clockCY, bgS, clock.bgC, 0, 2, 0, -90);		} // cir
					if(clock.Back == 2){	drawS('cb', "poly", "F", clockCX, clockCY, bgS *1.25, clock.bgC, 0, 0, 4, -45);	} // squa
					if(clock.Back == 3){	drawS('cb', "poly", "F", clockCX, clockCY, bgS*1.5, clock.bgC, 0, 0, 4, -90);	} // diam
					if(clock.Back == 4){	drawS('cb', "poly", "F", clockCX, clockCY, bgS*2, clock.bgC, 0, 0, 3, -90);		} // tri
					if(clock.Back == 5){	drawS('cb', "poly", "F", clockCX, clockCY, bgS*1.3, clock.bgC, 0, 0, 5, -90);	} // 5
					if(clock.Back == 6){	drawS('cb', "poly", "F", clockCX, clockCY, bgS*1.1, clock.bgC, 0, 0, 6, -90);	} // 6
					if(clock.Back == 7){	drawS('cb', "poly", "F", clockCX, clockCY, bgS*1.1, clock.bgC, 0, 0, 7, -90);	} // 7
					if(clock.Back == 8){	drawS('cb', "poly", "F", clockCX, clockCY, bgS*1.1, clock.bgC, 0, 0, 8, -90);	} // 8
					if(clock.Back == 9){	drawS('cb', "poly", "F", clockCX, clockCY, bgS*1.1, clock.bgC, 0, 0, 9, -90);	} // 9
					if(clock.Back == 10){	drawS('cb', "poly", "F", clockCX, clockCY, bgS*1.1, clock.bgC, 0, 0, 10, -90);	} // 10
					if(clock.Back == 11){	drawS('cb', "poly", "F", clockCX, clockCY, bgS*1.1, clock.bgC, 0, 0, 11, -90);	} // 11
					if(clock.Back == 12){	drawS('cb', "poly", "F", clockCX, clockCY, bgS*1.1, clock.bgC, 0, 0, 12, -90);	} // 12
				}
				
				setClockColor('c', 'f', 0, clock.OP);	
				var fontHeight = (clockSize)*25/10+clockSpacing-50;
				
				//create backdrop
				var sqR = fontHeight*0.07*(Math.PI), sqD = 2* sqR, sqcR = sqR*Math.SQRT2, shh=5/7, shm = 5/14, shs = 5/14, shms = 4/14;
				if(clock.Var == 2 || clock.Var == 3){		if(!clock.H24){	shm = 25/112, shs = 25/112, shms = 17.2/112;	} else {shm = 26.7/112, shs = 26.7/112, shms = 18.5/112;}		}
				if(clock.Var == 4 || clock.Var == 5){		if(!clock.H24){	shm = 17/112, shs = 17/112, shms = 9.5/112;		} else {shm = 20/112, shs = 20/112, shms = 11/112;}		}
				
				var sqcRm = sqcR*shm, sqcRs = sqcR*shs, sqcRms = sqcR*shms;
				if(clock.H24){sqcR *= 5/7}
				if(bgu){
					setClockColor('cb', 'f', 0, clock.OP, clock.Glow);	CTX.cb.shadowColor = clock.gC[0][3]; 
					clock.sqXY=[];clock.sqXY.h=[];clock.sqXY.m=[];clock.sqXY.s=[];clock.sqXY.ms=[];
					//H
					if(!clock.H24){		
						for(var i=-1; i<=1; i++){
							var sh = (sqD*i);
							if(clock.Var == 0 || clock.Var == 2 || clock.Var == 4){
								drawS('cb', "poly", "F", clockCX-sqD*2,		clockCY+sh,		sqcR, CTX.cb.strokeStyle, 0, 0, 4, -45);
								drawS('cb', "poly", "F", clockCX+sqD*2,		clockCY+sh,		sqcR, CTX.cb.strokeStyle, 0, 0, 4, -45);
								drawS('cb', "poly", "F", clockCX+sh,		clockCY+sqD*2,	sqcR, CTX.cb.strokeStyle, 0, 0, 4, -45);
								drawS('cb', "poly", "F", clockCX+sh,		clockCY-sqD*2,	sqcR, CTX.cb.strokeStyle, 0, 0, 4, -45);
							}
							else if(clock.Var == 1 || clock.Var == 3 || clock.Var == 5){
								drawS('cb', "circle", "F", clockCX-sqD*2,		clockCY+sh, 	sqcR/Math.SQRT2, CTX.cb.strokeStyle, 0, 2, 0, -90);
								drawS('cb', "circle", "F", clockCX+sqD*2,		clockCY-sh, 	sqcR/Math.SQRT2, CTX.cb.strokeStyle, 0, 2, 0, -90);
								drawS('cb', "circle", "F", clockCX+sh,			clockCY+sqD*2,	sqcR/Math.SQRT2, CTX.cb.strokeStyle, 0, 2, 0, -90);
								drawS('cb', "circle", "F", clockCX+sh,			clockCY-sqD*2,	sqcR/Math.SQRT2, CTX.cb.strokeStyle, 0, 2, 0, -90);
							}
						}
						for(var i=1; i<=12; i++){
							if(i<=1)				{	sqY= clockCY-sqD*2;	sqX= clockCX+(sqD*(i));		}
							else if(i>=2 && i<=4)	{	sqX= clockCX+sqD*2;	sqY= clockCY+(sqD*(i-3));	}
							else if(i>=5 && i<=7)	{	sqY= clockCY+sqD*2;	sqX= clockCX+(sqD*(6-i));	}
							else if(i>=8 && i<=10)	{	sqX= clockCX-sqD*2;	sqY= clockCY+(sqD*(9-i));	}
							else if(i>=11)			{	sqY= clockCY-sqD*2;	sqX= clockCX+(sqD*(i-12));	}
							
							clock.sqXY.h[i]=[sqX, sqY];
						}
					}
					else{
						for(var i=-2; i<=3; i++){
							var sh = (sqD*i*shh);
							if(clock.Var == 0 || clock.Var == 2 || clock.Var == 4){
								drawS('cb', "poly", "F", clockCX-sqD*3*shh,		clockCY+sh,			sqcR, CTX.cb.strokeStyle, 0, 0, 4, -45);
								drawS('cb', "poly", "F", clockCX+sqD*3*shh,		clockCY-sh,			sqcR, CTX.cb.strokeStyle, 0, 0, 4, -45);
								drawS('cb', "poly", "F", clockCX+sh,			clockCY+sqD*3*shh,	sqcR, CTX.cb.strokeStyle, 0, 0, 4, -45);
								drawS('cb', "poly", "F", clockCX-sh,			clockCY-sqD*3*shh,	sqcR, CTX.cb.strokeStyle, 0, 0, 4, -45);
							}
							else if(clock.Var == 1 || clock.Var == 3 || clock.Var == 5){
								drawS('cb', "circle", "F", clockCX-sqD*3*shh,	clockCY+sh, 		sqcR/Math.SQRT2, CTX.cb.strokeStyle, 0, 2, 0, -90);
								drawS('cb', "circle", "F", clockCX+sqD*3*shh,	clockCY-sh, 		sqcR/Math.SQRT2, CTX.cb.strokeStyle, 0, 2, 0, -90);
								drawS('cb', "circle", "F", clockCX+sh,			clockCY+sqD*3*shh,	sqcR/Math.SQRT2, CTX.cb.strokeStyle, 0, 2, 0, -90);
								drawS('cb', "circle", "F", clockCX-sh,			clockCY-sqD*3*shh,	sqcR/Math.SQRT2, CTX.cb.strokeStyle, 0, 2, 0, -90);
							}
						}
						for(var i=1; i<=24; i++){
							if(i<=3)		{	sqY= clockCY-sqD*3*shh;	sqX= clockCX+(sqD*(i)*shh);		}
							else if(i<=9)	{	sqX= clockCX+sqD*3*shh;	sqY= clockCY+(sqD*(i-6)*shh);	}
							else if(i<=15)	{	sqY= clockCY+sqD*3*shh;	sqX= clockCX+(sqD*(12-i)*shh);	}
							else if(i<=21)	{	sqX= clockCX-sqD*3*shh;	sqY= clockCY+(sqD*(18-i)*shh);	}
							else 			{	sqY= clockCY-sqD*3*shh;	sqX= clockCX+(sqD*(i-24)*shh);	}
							
							clock.sqXY.h[i]=[sqX, sqY];
						}
					}
					//M
					var dfm=8; if(clock.Var >= 2 && clock.Var <= 5){dfm++}
					for(var i=-7; i<=7; i++){
						var sh = (sqD*i*shm);
						if(clock.Var == 0 || clock.Var == 2 || clock.Var == 4){
							drawS('cb', "poly", "F", clockCX-sqD*dfm*shm,		clockCY+sh, sqcRm, CTX.cb.strokeStyle, 0, 0, 4, -45);
							drawS('cb', "poly", "F", clockCX+sqD*dfm*shm,		clockCY+sh, sqcRm, CTX.cb.strokeStyle, 0, 0, 4, -45);
							drawS('cb', "poly", "F", clockCX+sh,	clockCY+sqD*dfm*shm,	sqcRm, CTX.cb.strokeStyle, 0, 0, 4, -45);
							drawS('cb', "poly", "F", clockCX+sh,	clockCY-sqD*dfm*shm,	sqcRm, CTX.cb.strokeStyle, 0, 0, 4, -45);
						}
						else if(clock.Var == 1 || clock.Var == 3 || clock.Var == 5){
							drawS('cb', "circle", "F", clockCX-sqD*dfm*shm,		clockCY+sh, sqcRm/Math.SQRT2, CTX.cb.strokeStyle, 0, 2, 0, -90);
							drawS('cb', "circle", "F", clockCX+sqD*dfm*shm,		clockCY+sh, sqcRm/Math.SQRT2, CTX.cb.strokeStyle, 0, 2, 0, -90);
							drawS('cb', "circle", "F", clockCX+sh,	clockCY+sqD*dfm*shm,	sqcRm/Math.SQRT2, CTX.cb.strokeStyle, 0, 2, 0, -90);
							drawS('cb', "circle", "F", clockCX+sh,	clockCY-sqD*dfm*shm,	sqcRm/Math.SQRT2, CTX.cb.strokeStyle, 0, 2, 0, -90);
						}
					}
					for(var i=0; i<=59; i++){
						if(i<=7)		{	sqY= clockCY-sqD*dfm*shm;	sqX= clockCX+(sqD*(i)*shm);		}
						else if(i<=22)	{	sqX= clockCX+sqD*dfm*shm;	sqY= clockCY+(sqD*(i-15)*shm);	}
						else if(i<=37)	{	sqY= clockCY+sqD*dfm*shm;	sqX= clockCX+(sqD*(30-i)*shm);	}
						else if(i<=52)	{	sqX= clockCX-sqD*dfm*shm;	sqY= clockCY+(sqD*(45-i)*shm);	}
						else 			{	sqY= clockCY-sqD*dfm*shm;	sqX= clockCX+(sqD*(i-60)*shm);	}
						
						clock.sqXY.m[i]=[sqX, sqY];
					}
					//S
					if(clockSec){	
						var dfm=9; if(clock.Var == 4 || clock.Var == 5){dfm--}
						for(var i=-7; i<=7; i++){
							var sh = (sqD*i*shs);
							if(clock.Var == 0 || clock.Var == 2 || clock.Var == 4){
								drawS('cb', "poly", "F", clockCX-sqD*dfm*shs,		clockCY+sh, sqcRs, CTX.cb.strokeStyle, 0, 0, 4, -45);
								drawS('cb', "poly", "F", clockCX+sqD*dfm*shs,		clockCY+sh, sqcRs, CTX.cb.strokeStyle, 0, 0, 4, -45);
								drawS('cb', "poly", "F", clockCX+sh,	clockCY+sqD*dfm*shs,	sqcRs, CTX.cb.strokeStyle, 0, 0, 4, -45);
								drawS('cb', "poly", "F", clockCX+sh,	clockCY-sqD*dfm*shs,	sqcRs, CTX.cb.strokeStyle, 0, 0, 4, -45);
							}
							else if(clock.Var == 1 || clock.Var == 3 || clock.Var == 5){
								drawS('cb', "circle", "F", clockCX-sqD*dfm*shs,		clockCY+sh, sqcRs/Math.SQRT2, CTX.cb.strokeStyle, 0, 2, 0, -90);
								drawS('cb', "circle", "F", clockCX+sqD*dfm*shs,		clockCY+sh, sqcRs/Math.SQRT2, CTX.cb.strokeStyle, 0, 2, 0, -90);
								drawS('cb', "circle", "F", clockCX+sh,	clockCY+sqD*dfm*shs,	sqcRs/Math.SQRT2, CTX.cb.strokeStyle, 0, 2, 0, -90);
								drawS('cb', "circle", "F", clockCX+sh,	clockCY-sqD*dfm*shs,	sqcRs/Math.SQRT2, CTX.cb.strokeStyle, 0, 2, 0, -90);								
							}
						}
						for(var i=0; i<=59; i++){
							if(i<=7)		{	sqY= clockCY-sqD*dfm*shs;	sqX= clockCX+(sqD*(i)*shs);		}
							else if(i<=22)	{	sqX= clockCX+sqD*dfm*shs;	sqY= clockCY+(sqD*(i-15)*shs);	}
							else if(i<=37)	{	sqY= clockCY+sqD*dfm*shs;	sqX= clockCX+(sqD*(30-i)*shs);	}
							else if(i<=52)	{	sqX= clockCX-sqD*dfm*shs;	sqY= clockCY+(sqD*(45-i)*shs);	}
							else 			{	sqY= clockCY-sqD*dfm*shs;	sqX= clockCX+(sqD*(i-60)*shs);	}
							
							clock.sqXY.s[i]=[sqX, sqY];
						}
					}
					
					//MS
					if(clockMsec){	
						for(var i=-12; i<=12; i++){
							var sh = (sqD*i*shms);
							if(clock.Var == 0 || clock.Var == 2 || clock.Var == 4){
								drawS('cb', "poly", "F", clockCX-sqD*13*shms,		clockCY+sh, sqcRms, CTX.cb.strokeStyle, 0, 0, 4, -45);
								drawS('cb', "poly", "F", clockCX+sqD*13*shms,		clockCY+sh, sqcRms, CTX.cb.strokeStyle, 0, 0, 4, -45);
								drawS('cb', "poly", "F", clockCX+sh,	clockCY+sqD*13*shms,	sqcRms, CTX.cb.strokeStyle, 0, 0, 4, -45);
								drawS('cb', "poly", "F", clockCX+sh,	clockCY-sqD*13*shms,	sqcRms, CTX.cb.strokeStyle, 0, 0, 4, -45);
							}
							else if(clock.Var == 1 || clock.Var == 3 || clock.Var == 5){
								drawS('cb', "circle", "F", clockCX-sqD*13*shms,		clockCY+sh, sqcRms/Math.SQRT2, CTX.cb.strokeStyle, 0, 2, 0, -90);
								drawS('cb', "circle", "F", clockCX+sqD*13*shms,		clockCY+sh, sqcRms/Math.SQRT2, CTX.cb.strokeStyle, 0, 2, 0, -90);
								drawS('cb', "circle", "F", clockCX+sh,	clockCY+sqD*13*shms,	sqcRms/Math.SQRT2, CTX.cb.strokeStyle, 0, 2, 0, -90);
								drawS('cb', "circle", "F", clockCX+sh,	clockCY-sqD*13*shms,	sqcRms/Math.SQRT2, CTX.cb.strokeStyle, 0, 2, 0, -90);
							}
						}
						for(var i=0; i<=99; i++){
							if(i<=12)		{	sqY= clockCY-sqD*13*shms;	sqX= clockCX+(sqD*(i)*shms);	}
							else if(i<=37)	{	sqX= clockCX+sqD*13*shms;	sqY= clockCY+(sqD*(i-25)*shms);	}
							else if(i<=62)	{	sqY= clockCY+sqD*13*shms;	sqX= clockCX+(sqD*(50-i)*shms);	}
							else if(i<=87)	{	sqX= clockCX-sqD*13*shms;	sqY= clockCY+(sqD*(75-i)*shms);	}
							else 			{	sqY= clockCY-sqD*13*shms;	sqX= clockCX+(sqD*(i-100)*shms);	}
							
							clock.sqXY.ms[i]=[sqX, sqY];
						}
					}
					
					
				}
				
				//Show numbers
				//CTX.c.textAlign="center"; CTX.c.textBaseline="middle"; 
				//CTX.c.font= fWeight +' '+ (clock.fSize +(clockSize)*1/2) +'px '+ clockFont +', algerian, serif';
				//setClockColor('c', 'f', 1, clock.OP);	
				//for(c=1;c<=numHours;c++){	CTX.c.fillText(clock.N[clock.U][c], clock.sqXY.h[c][0], clock.sqXY.h[c][1]);				}
				//for(c=0;c<=59;c++){			CTX.c.fillText(clock.N[clock.U][c], clock.sqXY.m[c][0], clock.sqXY.m[c][1]);				}
				//for(c=0;c<=59;c++){			CTX.c.fillText(clock.N[clock.U][c], clock.sqXY.s[c][0], clock.sqXY.s[c][1]);				}
				//CTX.c.textAlign="start"; 	CTX.c.textBaseline="alphabetic"; 				
				
				// Highlight Time
				//H
				setClockColor('c', 'f', 1, clock.OP);	
				if(clock.Var == 0 || clock.Var == 2 || clock.Var == 4){
					drawS('c', "poly", "F", clock.sqXY.h[gtH][0], clock.sqXY.h[gtH][1], sqcR*9/10, CTX.c.strokeStyle, 0, 0, 4, -45);
				}
				else if(clock.Var == 1 || clock.Var == 3 || clock.Var == 5){
					drawS('c', "circle", "F", clock.sqXY.h[gtH][0], clock.sqXY.h[gtH][1], sqcR*9/10/Math.SQRT2, CTX.c.strokeStyle, 0, 2, 0, -90);
				}

				//M
				setClockColor('c', 'f', 2, clock.OP);	
				if(clock.Var == 2 || clock.Var == 3){sqcRm *= 2}
				if(clock.Var == 0 || clock.Var == 2 || clock.Var == 4){
					drawS('c', "poly", "F", clock.sqXY.m[gtM][0], clock.sqXY.m[gtM][1], sqcRm*9/10, CTX.c.strokeStyle, 0, 0, 4, -45);
				}
				else if(clock.Var == 1 || clock.Var == 3 || clock.Var == 5){
					drawS('c', "circle", "F", clock.sqXY.m[gtM][0], clock.sqXY.m[gtM][1], sqcRm*9/10/Math.SQRT2, CTX.c.strokeStyle, 0, 2, 0, -90);
				}

				//S
				if(clockSec){	
					setClockColor('c', 'f', 3, clock.OP);	
					if(clock.Var == 0 || clock.Var == 2 || clock.Var == 4){
						drawS('c', "poly", "F", clock.sqXY.s[gtS][0], clock.sqXY.s[gtS][1], sqcRs*9/10, CTX.c.strokeStyle, 0, 0, 4, -45);
					}
					else if(clock.Var == 1 || clock.Var == 3 || clock.Var == 5){
						drawS('c', "circle", "F", clock.sqXY.s[gtS][0], clock.sqXY.s[gtS][1], sqcRs*9/10/Math.SQRT2, CTX.c.strokeStyle, 0, 2, 0, -90);
					}
				}
				//MS
				if(clockMsec){	
					setClockColor('c', 'f', 4, clock.OP);	
					gtMSr = Math.floor(gtMS/10);
					if(clock.Var == 0 || clock.Var == 2 || clock.Var == 4){
						drawS('c', "poly", "F", clock.sqXY.ms[gtMSr][0], clock.sqXY.ms[gtMSr][1], sqcRms*9/10, CTX.c.strokeStyle, 0, 0, 4, -45);
					}
					else if(clock.Var == 1 || clock.Var == 3 || clock.Var == 5){
						drawS('c', "circle", "F", clock.sqXY.ms[gtMSr][0], clock.sqXY.ms[gtMSr][1], sqcRms*9/10/Math.SQRT2, CTX.c.strokeStyle, 0, 2, 0, -90);
					}
				}
				
				//DebugDisplay2.textContent = 	CTX.c.font;					
				clockIsClear = false;
			}
		break;
		case 50: //Binary - Number
			if(gtS != gtS2 || clockMsec){	//prevent unnecessary writes
				clear('c');
				if(bgu){	clear('cb');clock.bgupdate=false;	}				
				
				// Draw BG
				if(bgu){
					if(clock.Back > 0) {
						setClockColor('cb', 'b', 0, clock.BOP, clock.bgGlow);	CTX.cb.shadowColor = clock.bggC[3];
						var bgS = Math.max(1, 10*clockSize +clock.bgS * ccW/2000);
					}
					if(clock.Back == 1){	drawS('cb', "box", "F", clockCX -bgS*12/10, clockCY-bgS*5/10, 0, clock.bgC, 0, 0, clockCX +bgS*12/10, clockCY+bgS*5/10 );	} // long rect
					if(clock.Back == 2){	drawS('cb', "box", "F", clockCX -bgS*8/10, clockCY-bgS*5/10, 0, clock.bgC, 0, 0, clockCX +bgS*8/10, clockCY+bgS*5/10 );		} // rect
					if(clock.Back == 3){	drawS('cb', "circle", "F", clockCX, clockCY, bgS, clock.bgC, 0, 2, 0, -90);	} // cir
					if(clock.Back == 4){	drawS('cb', "peanut", "F", clockCX, clockCY, bgS, clock.bgC, 0, 2, 0, -90); 	} // peanut
					if(clock.Back == 5){	drawS('cb', "poly", "F", clockCX, clockCY, bgS*1.75, clock.bgC, 0, 0, 3, -90);	} // tri
					if(clock.Back == 6){	drawS('cb', "poly", "F", clockCX, clockCY, bgS*1.5, clock.bgC, 0, 0, 4, -90);	} // diam
					if(clock.Back == 7){	drawS('cb', "poly", "F", clockCX, clockCY, bgS*1.1, clock.bgC, 0, 0, 5, -90);	} // 5
					if(clock.Back == 8){	drawS('cb', "poly", "F", clockCX, clockCY, bgS*1.1, clock.bgC, 0, 0, 6, -90);	} // 6
					if(clock.Back == 9){	drawS('cb', "poly", "F", clockCX, clockCY, bgS*1.1, clock.bgC, 0, 0, 7, -90);	} // 7
					if(clock.Back == 10){	drawS('cb', "poly", "F", clockCX, clockCY, bgS*1.1, clock.bgC, 0, 0, 8, -90);	} // 8
					if(clock.Back == 11){	drawS('cb', "poly", "F", clockCX, clockCY, bgS*1.1, clock.bgC, 0, 0, 10, -90);	} // 10
					if(clock.Back == 12){	drawS('cb', "poly", "F", clockCX, clockCY, bgS*1.1, clock.bgC, 0, 0, 12, -90);	} // 12
				}
				
				CTX.c.font= fWeight +' '+ (clock.fSize +250*clockSize/100) +'px '+ clockFont +', algerian, serif';
				var fontHeight = 250*clockSize/100 //eval(CTX.c.font.split('px')[0]);
				var timeArray = [];	timeArray[0] = toBinary(gtMS, 1000).split('');timeArray[1] = toBinary(gtS, 60).split('');timeArray[2] = toBinary(gtM, 60).split('');timeArray[3] = toBinary(gtH, 60).split('');
				CTX.c.textAlign="center"; CTX.c.textBaseline="middle"; 
				
				var Ycentering = 0;		if(clockMsec){Ycentering = fontHeight} else if(clockSec){Ycentering = fontHeight/2}	// Correct for Y shift
				
				if(clockSolid){
					for(c=0; c<10; c++){ 
						if(clockMsec){	setClockColor('c', 'f', 4, clock.OP);	CTX.c.fillText(timeArray[0][c], clockCX +(c-4.5)*fontHeight, clockCY -fontHeight*2.5 + Ycentering);	}
					}
					for(c=0; c<6; c++){ 
						if(clockSec){
							setClockColor('c', 'f', 3, clock.OP);	CTX.c.fillText(timeArray[1][c], clockCX +(c-2.5)*fontHeight, clockCY -fontHeight*1.5 + Ycentering);	}
							setClockColor('c', 'f', 2, clock.OP);	CTX.c.fillText(timeArray[2][c], clockCX +(c-2.5)*fontHeight, clockCY -fontHeight/2 + Ycentering);
							setClockColor('c', 'f', 1, clock.OP);	CTX.c.fillText(timeArray[3][c], clockCX +(c-2.5)*fontHeight, clockCY +fontHeight/2 + Ycentering);
					}
				}
				else		{
					for(c=0; c<10; c++){ 
						if(clockMsec){	
							setClockColor('c', 'f', 4, clock.OP);							
							if(timeArray[0][c]==1){CTX.c.fillText(1, clockCX +(c-4.5)*fontHeight, clockCY -fontHeight*2.5 + Ycentering);		}
							else				{ CTX.c.strokeText(0, clockCX +(c-4.5)*fontHeight, clockCY -fontHeight*2.5 + Ycentering);	}
						}
					}

					for(c=0; c<6; c++){ 
						if(clockSec){				
							setClockColor('c', 'f', 3, clock.OP);							
							if(timeArray[1][c]==1){CTX.c.fillText(1, clockCX +(c-2.5)*fontHeight, clockCY -fontHeight*1.5 + Ycentering);		}
							else				{ CTX.c.strokeText(0, clockCX +(c-2.5)*fontHeight, clockCY -fontHeight*1.5 + Ycentering);	}
						}
			
						setClockColor('c', 'f', 2, clock.OP);							
						if(timeArray[2][c]==1){CTX.c.fillText(1, clockCX +(c-2.5)*fontHeight, clockCY -fontHeight/2 + Ycentering);	}
						else				{ CTX.c.strokeText(0, clockCX +(c-2.5)*fontHeight, clockCY -fontHeight/2 + Ycentering);	}

						setClockColor('c', 'f', 1, clock.OP);							
						if(timeArray[3][c]==1){CTX.c.fillText(1, clockCX +(c-2.5)*fontHeight, clockCY +fontHeight/2 + Ycentering);	}
						else				{ CTX.c.strokeText(0, clockCX +(c-2.5)*fontHeight, clockCY +fontHeight/2 + Ycentering);	}
					}
				}
				
				CTX.c.textAlign="start"; 	CTX.c.textBaseline="alphabetic"; 				
				clockIsClear = false;
			}
		break;
		case 51: //Binary - Lights
			if(gtS != gtS2 || clockMsec){	//prevent unnecessary writes
				clear('c');
				if(bgu){	clear('cb');clock.bgupdate=false;	}				
				
				// Draw BG
				if(bgu){
					if(clock.Back > 0) {
						setClockColor('cb', 'b', 0, clock.BOP, clock.bgGlow);	CTX.cb.shadowColor = clock.bggC[3];
						var bgS = Math.max(1, 10*clockSize +clock.bgS * ccW/2000);
					}
					if(clock.Back == 1){	drawS('cb', "box", "F", clockCX -bgS*8/10, clockCY-bgS*3/10, 0, clock.bgC, 0, 0, clockCX +bgS*8/10, clockCY+bgS*3/10 );	} // long rect
					if(clock.Back == 2){	drawS('cb', "box", "F", clockCX -bgS*5/10, clockCY-bgS*3/10, 0, clock.bgC, 0, 0, clockCX +bgS*5/10, clockCY+bgS*3/10 );	} // rect
					if(clock.Back == 3){	drawS('cb', "circle", "F", clockCX, clockCY, bgS *0.6, clock.bgC, 0, 2, 0, -90);	} // cir
					if(clock.Back == 4){	drawS('cb', "peanut", "F", clockCX, clockCY, bgS/2, clock.bgC, 0, 2, 0, -90); 	} // peanut
					if(clock.Back == 5){	drawS('cb', "poly", "F", clockCX, clockCY, bgS *1.1, clock.bgC, 0, 0, 3, -90);		} // tri
					if(clock.Back == 6){	drawS('cb', "poly", "F", clockCX, clockCY, bgS *0.7, clock.bgC, 0, 0, 4, -90);	} // diam
					if(clock.Back == 7){	drawS('cb', "poly", "F", clockCX, clockCY, bgS *0.6, clock.bgC, 0, 0, 5, -90);	} // 5
					if(clock.Back == 8){	drawS('cb', "poly", "F", clockCX, clockCY, bgS *0.6, clock.bgC, 0, 0, 6, -90);	} // 6
					if(clock.Back == 9){	drawS('cb', "poly", "F", clockCX, clockCY, bgS *0.6, clock.bgC, 0, 0, 7, -90);	} // 7
					if(clock.Back == 10){	drawS('cb', "poly", "F", clockCX, clockCY, bgS *0.6, clock.bgC, 0, 0, 8, -90);	} // 8
					if(clock.Back == 11){	drawS('cb', "poly", "F", clockCX, clockCY, bgS *0.6, clock.bgC, 0, 0, 10, -90);	} // 10
					if(clock.Back == 12){	drawS('cb', "poly", "F", clockCX, clockCY, bgS *0.6, clock.bgC, 0, 0, 12, -90);	} // 12
				}

				
				CTX.c.font= fWeight +' '+ (clock.fSize +250*clockSize/100) +'px '+ clockFont +', algerian, serif';
				var fontHeight = 250*clockSize/100 //eval(CTX.c.font.split('px')[0]);
				var timeArray = [];	timeArray[0] = toBinary(gtMS, 1000).split('');timeArray[1] = toBinary(gtS, 60).split('');timeArray[2] = toBinary(gtM, 60).split('');timeArray[3] = toBinary(gtH, 60).split('');
				
				var Ycentering = 0;		if(clockMsec){Ycentering = fontHeight/2} else if(clockSec){Ycentering = fontHeight/4}	// Correct for Y shift

				for(c=0; c<10; c++){ 
					if(clockMsec){	
						setClockColor('c', 'f', 4, clock.OP);
						CTX.c.beginPath();
						CTX.c.arc( clockCX +(c-4.5)*fontHeight/2, clockCY -fontHeight*1.25 + Ycentering, fontHeight/5, 0, 2*Math.PI);
						if(timeArray[0][c]==1){CTX.c.fill();}	else	{ CTX.c.stroke();	}
						CTX.c.closePath();
					}
				}
				for(c=0; c<6; c++){ 
					if(clockSec){	
						setClockColor('c', 'f', 3, clock.OP);
						CTX.c.beginPath();
						CTX.c.arc( clockCX +(c-2.5)*fontHeight/2, clockCY -fontHeight*0.75 + Ycentering, fontHeight/5, 0, 2*Math.PI);
						if(timeArray[1][c]==1){CTX.c.fill();}	else	{ CTX.c.stroke();	}
						CTX.c.closePath();
					}
					
					setClockColor('c', 'f', 2, clock.OP);
					CTX.c.beginPath();
					CTX.c.arc( clockCX +(c-2.5)*fontHeight/2, clockCY -fontHeight/4 + Ycentering, fontHeight/5, 0, 2*Math.PI);
					if(timeArray[2][c]==1){CTX.c.fill();}	else	{ CTX.c.stroke();	}
					CTX.c.closePath();
					
					setClockColor('c', 'f', 1, clock.OP);
					CTX.c.beginPath();
					CTX.c.arc( clockCX +(c-2.5)*fontHeight/2, clockCY +fontHeight/4+ Ycentering, fontHeight/5, 0, 2*Math.PI);
					if(timeArray[3][c]==1){CTX.c.fill();}	else	{ CTX.c.stroke();	}
					CTX.c.closePath();
				}
		
				clockIsClear = false;
			}	
		break;
	}

	gtH2 = gtH; gtM2 = gtM; gtS2 = gtS; gtMS2 = gtMS;
	// --------------- End Clock code

	//DebugDisplay2.textContent = timeArray[0];	
}

//============================================================ Background =====================================
function ChangeBgColorStyle(){
	bcH = CAN.b.offsetHeight
	bcW = CAN.b.offsetWidth
	var bgPos=[];
	bgPos.x = [	bgCX *bcW/2000 +0,	bgCX *bcW/2000 +bcW/2,	bgCX *bcW/2000 +bcW	];
	bgPos.y = [	bgCY *bcH/2000 +0,	bgCY *bcH/2000 +bcH/2,	bgCY *bcH/2000 +bcH	];
	var canvasDiameter = findDist(0, 0, bcW, bcH);
	
	if(bgGC > 0){
		bgcA = bgcM.x.length
		var bc = bgcM.x;
		bc.split=[];	for(var i = 0; i < bgcA; i++){	bc.split[i] = r10("floor", i/(bgcA-1), -4);} //color offset
	}
	else {
		bgcA = bgAmount
		var bc=[0, bgColor[1][3], bgColor[2][3], bgColor[3][3], bgColor[4][3], bgColor[5][3], bgColor[6][3], bgColor[7][3], bgColor[8][3], bgColor[9][3], bgColor[10][3]]; //colors
		bc.split=[];	for(var i = 0; i < bgcA; i++){	bc.split[i+1] = r10("floor", i/(bgcA-1), -4);} //color offset
	}	
	
			
	if(bgGC==0 && (bgGS==0 || bgAmount == 1)){ //Single Color
		CTX.b.fillStyle = bgColor[1][3];
	}
	else{
		var gradient2 = "#000";
		if(bgGS == 1)			{	gradient2=CTX.b.createLinearGradient(bgPos.x[0], bgPos.y[0], bgPos.x[2], bgPos.y[0]);	} //Gradient - Linear H
		else if(bgGS == 1.1)	{	gradient2=CTX.b.createLinearGradient(bgPos.x[0], bgPos.y[2], bgPos.x[0], bgPos.y[0]);	} //Gradient - Linear V
		else if(bgGS == 1.5)	{	gradient2=CTX.b.createLinearGradient(bgPos.x[0], bgPos.x[2], bgPos.x[2], bgPos.y[0]);	} //Gradient - Linear D
		else if(bgGS == 1.6)	{	gradient2=CTX.b.createLinearGradient(bgPos.x[0], bgPos.y[0], bgPos.x[2], bgPos.x[2]);	} //Gradient - Linear D2
		else if(bgGS == 2)		{	gradient2=CTX.b.createRadialGradient(bgPos.x[1], bgPos.y[1], bgR1, bgOX +bgPos.x[1], bgOY +bgPos.y[1], bgR1+bgR2);	}	//Gradient - Radial

		//Animate BG Gradient if desired
		if(bgGradAnim && bgGS > 0){
			if(bgGC==0)	{var adjA = 1, gSet=0}	else	{var adjA=0, gSet=bgIT} 
			if(!bgGradOffset[gSet][0]){ 		
				for(var i = 0; i < bgcA; i++){	bgGradOffset[gSet][i] = i/(bgcA);	}
				bgGradOffset[gSet]["First"] = 0;
			}

			for(var i=0; i < bgcA; i++){
				bgGradOffset[gSet][i]+= bgGradAnimSpeed/5000;
				bgGradOffset[gSet][i] = r10("floor", bgGradOffset[gSet][i], -4)
				if(bgGradOffset[gSet][i]>0.999){bgGradOffset[gSet][i]=0.001; bgGradOffset[gSet]["First"] = i;}
				if(bgGradOffset[gSet][i]<0.001){bgGradOffset[gSet][i]=0.999; bgGradOffset[gSet]["Last"] = i;}
				}
			if(bgGradAnimSpeed > 0){		bgGradOffset[gSet]["Last"] = bgGradOffset[gSet]["First"] - 1; if(bgGradOffset[gSet]["Last"] < 0){bgGradOffset[gSet]["Last"] = bgcA-1;}			}	
			else if(bgGradAnimSpeed < 0){	bgGradOffset[gSet]["First"] = bgGradOffset[gSet]["Last"] + 1; if(bgGradOffset[gSet]["First"] > bgcA-1){bgGradOffset[gSet]["First"] = 0;}		}	

			gradient2.addColorStop("0",bc[bgGradOffset[gSet]["Last"]+adjA]);
			gradient2.addColorStop("1",bc[bgGradOffset[gSet]["First"]+adjA]);
			
			for(var i = 0; i < bgcA; i++){	gradient2.addColorStop(""+bgGradOffset[gSet][i]+"",bc[i+adjA]);	}				
			CTX.b.fillStyle = gradient2;	
		}
		else { //No Animation
			for(var i = 0; i < bgcA; i++){
				if(bgGC==0)	{var ii = i+1}	else	{var ii = i}
				gradient2.addColorStop(""+bc.split[ii]+"", bc[ii]);
				}
			CTX.b.fillStyle = gradient2;	//	DebugDisplay2.textContent = ""+bc.split[bgcA]+","+ bc[bgcA];	
		}
	}
	

	//CTX.b.clearRect(bcW/2-canvasDiameter/2,bcH/2-canvasDiameter/2, canvasDiameter, canvasDiameter);  //Clear previous render
	CTX.b.fillRect(bcW/2-canvasDiameter/2,bcH/2-canvasDiameter/2, canvasDiameter, canvasDiameter);
	if(bgRain.on){mir();}

}

function updateBG(){
	if(bgType!=3){
		vidBox.style.visibility = "hidden";//tubeBox.innerHTML = "";
		vidBox.pause();
		vidBox.muted = true
	}
	
	if(bgType==0){	bgDisplay.style.backgroundImage = "";}
	if(bgType==1){//Pattern
		switch (bgPatNum) {
			case 00:	imageURL = patURL;			break;
			case 01:	imageURL = "UserPat1.png";	break;
			case 02:	imageURL = "UserPat2.png";	break;
			case 03:	imageURL = "UserPat3.png";	break;
			case 07:	imageURL = "SquareSpiralSmall.png";break;
			case 11:	imageURL = "Floral1.png";	break;
			case 12:	imageURL = "Floral2.png";	break;
			case 21:	imageURL = "Cubes1.png";	break;
			case 26:	imageURL = "Camo1.png";		break;
			case 28:	imageURL = "HoneyComb1.png";break;
			case 51:	imageURL = "Lattice1.png";	break;
			case 52:	imageURL = "Lattice2.png";	break;
			case 53:	imageURL = "Lattice3.png";	break;
			case 54:	imageURL = "Lattice4.png";	break;
			case 55:	imageURL = "Lattice5.png";	break;
			case 56:	imageURL = "Lattice6.png";	
		}				
		bgDisplay.style.backgroundSize = "auto";
		bgDisplay.style.backgroundImage = "url(images/"+imageURL+")";
	}
	if(bgType==2){//Image
		switch (bgImageNum) {
			case 00:	imageURL = imgURL;			break;
			case 01:	imageURL = "UserImage1.jpg";break;
			case 02:	imageURL = "UserImage2.jpg";break;
			case 03:	imageURL = "UserImage3.jpg";break;
			case 04:	imageURL = "UserImage4.png";break;
			case 05:	imageURL = "Bricks.png";	break;
			case 06:	imageURL = "Fractal.png";	break;
			case 07:	imageURL = "Swirl.png";		break;			
			case 08:	imageURL = "StainedSpiral.png";break;
			case 09:	imageURL = "Paint4K.png";	break;
			case 10:	imageURL = "Stripes2K.png";	break;
			case 12:	imageURL = "Hamburg.png";	break;
			case 13:	imageURL = "????.png";		break;
			case 15.1:	imageURL = "Space1.jpg";	break;
			case 15.2:	imageURL = "Space2.png";	break;
			case 15.3:	imageURL = "Space3.png";	break;
			case 15.4:	imageURL = "Space4.png";	break;
			case 16:	imageURL = "Aurora.png";	break;
			case 21:	imageURL = "SeaHorses.jpg";	break;
			case 33:	imageURL = "Audio.png";		break;
			case 35:	imageURL = "Tree1.png";		break;
			case 36:	imageURL = "Tree2.png";		break;
			case 37:	imageURL = "Birds.png";		break;
			case 38:	imageURL = "Flower.png";	break;
			case 40:	imageURL = "Gem.png";		break;
			case 41:	imageURL = "Bubbles2K.png";	break;		
			case 42:	imageURL = "Ball1.png";		break;
			case 43:	imageURL = "Ball2.png";		break;
			case 44:	imageURL = "Ball3.png";		break;
			case 45:	imageURL = "SquareSpiral.png";break;

		}
		bgDisplay.style.backgroundSize = "cover";
		bgDisplay.style.opacity = "1";
		bgDisplay.style.backgroundImage = "url(images/"+imageURL+")";
		
	}
	if(bgType==3){//Video  #Note: browser in engine is Chrome. Only webm & ogv supported.

		if(vidLoc<2){	//Local or URL
			//tubeBox.innerHTML = "";
			vidBox.style.visibility = "";
			vidBox.src = vidURL;
		}	
		/*if(vidLoc==2){	//Youtube... breaks viz for some reason...  and lacks any control
			vidBox.style.visibility = "hidden";
			vidBox.pause();
			vidBox.muted = true

			tubeBox.innerHTML = '<iframe width="100%"  height="100%" frameborder="0" src="https://www.youtube.com/embed/'+vidURL+'?autoplay=1&playlist='+vidURL+'&loop=1" style="position:absolute; z-index:-1; top:0; left:0; width:100%; height:99%;" ></iframe>'
		}*/	
		//DebugDisplay2.textContent = vidBox.src;
	}
	//DebugDisplay.textContent = bgType +' I: '+  bgImageNum +' P: '+ bgPatNum;
	//DebugDisplay2.textContent = bgType +':'+ imageURL;
	
	var bgpW = CAN.rp.width, bgpH = CAN.rp.height;
	bgImg.onload = function () {	CTX.rp.clearRect(0,0, bgpW, bgpH);	CTX.rp.drawImage(bgImg, 0, 0, bgpW, bgpH);  }; //copy image to canvas when loaded (data for rain effect)
	bgImg.src = "images/"+imageURL+"";
	
	if(bgRain.on){	mir();	}

}

// ================================ RAIN ================================
function mir(){ //Make it Rain
	var rW = CAN.r.width, rH = CAN.r.height;
	if(!bgRain.on){
		CTX.r.clearRect(0, 0, rW, rH); CTX.rd.clearRect(0,0, CAN.rd.width, CAN.rd.height);
		bgRain.n=[];	bgRain.counter=0;
		}
	else{
		//CTX.r.clearRect(0, 0, rW, rH);
		if(!bgRain.counter){bgRain.counter=0;	bgRain.n=[];}
		if(!bgRain.started){ // run once
					
			// start rain

			newDrop = setInterval(function(){ bgRain.n[bgRain.counter] = new rainDrop(	nr('x'), nr('y'), dropSize(), bgRain.counter); bgRain.counter++; }, 100/bgRain.int);
			bgRain.started = true;
		}
	}
	if(bgRain.int==0 || !bgRain.on){clearInterval(newDrop); bgRain.started = false; setTimeout(function(){CTX.r.clearRect(0, 0, rW, rH);}, 200);}

}

function nr(xy){
	var rW = CAN.r.width, rH = CAN.r.height;
	switch (xy) {
		case 'x':	return (rW+200) *Math.random() -100;	break;
		case 'y':	return (rH+200) *Math.random() -100;	break;
	}
}

function rainSteam(){//Steam window
	if(timer('rsteam', bgRain.steam, true)){ 
		var rW = CAN.r.width, rH = CAN.r.height;
		var fs = CTX.r.fillStyle;
		CTX.r.fillStyle= 'rgba('+bgRain.steamC[0]+', '+bgRain.steamC[1]+', '+bgRain.steamC[2]+', 0.00395)';	
		CTX.r.fillRect(0, 0, rW, rH); 
		CTX.r.fillStyle= fs;
	}
}

function dropSize(){
	var MR = Math.random();
	var dS = 1;
	if(MR >0.96)		{	dS = 1+ 50 *Math.random();	}
	else if(MR >0.92)	{	dS = 1+ 8  *Math.random();	}
	else if(MR >0.84)	{	dS = 1+ 5  *Math.random();	}
	else if(MR >0.70)	{	dS = 1+ 3  *Math.random();	}
	else 				{	dS = 1+ 2  *Math.random();	}

	dS = Math.min(dS, bgRain.dSize)
	
	return dS;
}

function rainDrop(x, y, r, n) {
    bgRain.x[n] = Math.round(x);
    bgRain.y[n] = Math.round(y);
    bgRain.r[n] = Math.round(r);
	bgRain.splat[n] = function(n) {
		drawDroplet(bgRain.x[n], bgRain.y[n], bgRain.r[n]*1.25); 

		setTimeout(function(n){	
			eraseDroplet(bgRain.x[n], bgRain.y[n], bgRain.r[n]*1.25); 
			drawDroplet(bgRain.x[n], bgRain.y[n], bgRain.r[n]); 
			setTimeout(function(n){ bgRain.move[n](n); }, 100, n);
		}, 75, n); };

	if(bgRain.r[n] > 7){
		bgRain.move[n] = function(n) {
			moveDroplet(n)

			//remove drops that have left the screen
			if(!bgRain.on || bgRain.x[n] < -100 || bgRain.y[n] < -100 || bgRain.x[n] > CAN.r.width+100 || bgRain.y[n] > CAN.r.height+100 ){} // self implosion when offscreen
			else{	setTimeout(function(n){ bgRain.move[n](n); }, 40, n);	}
		}
	} else {bgRain.move[n] = function(){};}
	bgRain.splat[n](n);
	//DebugDisplay.textContent = this.x;
}



function moveDroplet(n){
	if(bgRain.windS == 0 && bgRain.gravS == 0){}
	else{
		eraseDroplet(bgRain.x[n], bgRain.y[n], bgRain.r[n]+1); 
		
		// Gravity
		if(bgRain.gravT == 0)	{ 	bgRain.y[n] += bgRain.gravS/3;	}
		else	{
			if(!bgRain.v[n]){bgRain.v[n]=0.1}
			bgRain.y[n] += bgRain.v[n];
			bgRain.v[n] += bgRain.gravS *0.001;
		}
		
		//Wind
		if(bgRain.windT == 0)	{ 	bgRain.x[n] += bgRain.windS/3;	}
		else	{ 
			if(!bgRain.w){bgRain.w=0;bgRain.nw=0}
			bgRain.x[n] += bgRain.w;
			if(Math.round(bgRain.w*100)/100 == bgRain.nw){
				var WR = Math.random();
				if		(WR > 0.999){var newW = 80}
				else if	(WR > 0.99) {var newW = 60}
				else if	(WR > 0.98) {var newW = 50}
				else if	(WR > 0.97) {var newW = 44}
				else if	(WR > 0.96) {var newW = 40}
				else if	(WR > 0.95) {var newW = 34}
				else if	(WR > 0.90) {var newW = 30}
				else if	(WR > 0.85) {var newW = 20}
				else if	(WR > 0.75) {var newW = 10}
				else if	(WR > 0.70) {var newW = 8}
				else 				{var newW = 2}

				bgRain.nw = Math.round(Math.random()*newW -newW/2)
				}
			if(bgRain.nw > bgRain.w){bgRain.w += 0.002} else {bgRain.w -= 0.002}

			//DebugDisplay.textContent = bgRain.nw;
			//DebugDisplay2.textContent = Math.round(bgRain.w*100)/100;
		}
		
		drawDroplet(bgRain.x[n], bgRain.y[n], bgRain.r[n]);				
	}
}

function eraseDroplet(x, y, r){
	if(!bgRain.dSmear){
		CTX["r"].globalCompositeOperation="destination-out";
		CTX.r.fillStyle= "#000"
		CTX.r.beginPath();	CTX.r.arc(x, y, r, 0*Math.PI,2*Math.PI);		CTX.r.closePath();
		CTX.r.fill();		
		CTX["r"].globalCompositeOperation="source-over";	
	}
}

function drawDroplet(x1, y1, r1){
	var d1 = r1*2.5, d2 = r1*15;
	
	// Clear swatch of CAN.rd
	CAN.rd.width =	d1;
	CAN.rd.height =	d1;
	CTX.rd.clearRect(0,0, d1, d1);
	
	// Rotate CTX.rd 180°
	CTX.rd.translate(d1, d1);
	CTX.rd.rotate(180*Math.PI/180);
	
	// Sketch droplet shape
	CTX.rd.fillStyle= "#000"
	CTX.rd.beginPath();	CTX.rd.arc(d1/2,d1/2,d1/2,0*Math.PI,2*Math.PI);	CTX.rd.closePath();
	CTX.rd.fill();		
	CTX.rd.globalCompositeOperation="source-atop";
	
	// Draw section of CTX.b & CTX.rp to CTX.rd
	var x2 = Math.min(CAN.rp.width-d2, Math.max(0, x1-d2/2)); // set capture range
	var y2 = Math.min(CAN.rp.height-d2, Math.max(0, y1-d2/2)); // set capture range
	
	CTX.rd.drawImage(CTX.b.canvas, x2, y2, d2, d2, 0, 0, d1, d1); //copy bg color
	CTX.rd.drawImage(CTX.rp.canvas, x2, y2, d2, d2, 0, 0, d1, d1); // overlay bg image
	CTX.rd.globalCompositeOperation="source-over";

	// Reset rotation
	CTX.rd.translate(0, 0);
	
	// Add Steam
	if(bgRain.steam != 0){	rainSteam()	}

	// Copy Droplet to Rain Canvas
	CTX["r"].drawImage(CTX.rd.canvas, 0, 0, d1, d1, x1-r1, y1-r1, r1*2, r1*2); 

	
	//outline for visibility
	//CTX.r.strokeStyle= "#ff0000";	CTX.r.beginPath();	CTX.r.arc(x1,y1,r1/2,0*Math.PI,2*Math.PI);	CTX.r.closePath();	CTX.r.stroke();
}

//============================================================ Weather =====================================
function fetchWeather(loc){
	$(document).ready(function() {
	  $.simpleWeather({
		location: loc,
		woeid: '',
		unit: 'f',
		success: function(weather) {

			wData['city'] = weather.city;
			wData['region'] = weather.region;		//State,territory,region
			wData['country'] = weather.country;		//
			wData['updated'] = weather.updated;		//When last updated
			wData['title'] = weather.title;	

			wData['codeNow'] = weather.code;			// Condition code now
			wData['units.temp'] = weather.units.temp;// f or c
			wData['units.distance'] = weather.units.distance;
			wData['units.pressure'] = weather.units.pressure;
			wData['units.speed'] = weather.units.speed;
			wData['alt.unit'] = weather.alt.unit;	//If default is F, alt is C
			wData['currently'] = weather.currently; //Current Sky Condition
			wData['wind.chill'] = weather.wind.chill;
			wData['wind.direction'] = weather.wind.direction;
			wData['wind.speed'] = weather.wind.speed;
			wData['humidity'] = weather.humidity;
			wData['heatindex'] = weather.heatindex;
			wData['pressure'] = weather.pressure;
			wData['rising'] = weather.rising;
			wData['visibility'] = weather.visibility;
			wData['sunrise'] = weather.sunrise;
			wData['sunset'] = weather.sunset;
			
			wData['temp'] = [];		wData['high']=[];	wData['low']=[];
			wData['temp'][0]	= weather.temp;			//Current Temp in °F
			wData['temp'][1]	= weather.alt.temp;		//°C
			wData['temp'][2]	= FtoU(weather.temp, "K");					
			wData['temp'][3]	= FtoU(weather.temp, "R");					
			wData['temp'][4]	= FtoU(weather.temp, "De");					
			wData['temp'][5]	= FtoU(weather.temp, "N");					
			wData['temp'][6]	= FtoU(weather.temp, "Ré");					
			wData['temp'][7]	= FtoU(weather.temp, "Rø");					
			
			
			wData['high'][0]	= [weather.high, weather.forecast[1].high, weather.forecast[2].high, weather.forecast[3].high, weather.forecast[4].high];
			wData['high'][1]	= [weather.alt.high, weather.forecast[1].alt.high, weather.forecast[2].alt.high, weather.forecast[3].alt.high, weather.forecast[4].alt.high];
			wData['high'][2]	= [FtoU(weather.high, "K"), FtoU(weather.forecast[1].high, "K"), FtoU(weather.forecast[2].high, "K"), FtoU(weather.forecast[3].high, "K"), FtoU(weather.forecast[4].high, "K")];
			wData['high'][3]	= [FtoU(weather.high, "R"), FtoU(weather.forecast[1].high, "R"), FtoU(weather.forecast[2].high, "R"), FtoU(weather.forecast[3].high, "R"), FtoU(weather.forecast[4].high, "R")];
			wData['high'][4]	= [FtoU(weather.high, "De"), FtoU(weather.forecast[1].high, "De"), FtoU(weather.forecast[2].high, "De"), FtoU(weather.forecast[3].high, "De"), FtoU(weather.forecast[4].high, "De")];
			wData['high'][5]	= [FtoU(weather.high, "N"), FtoU(weather.forecast[1].high, "N"), FtoU(weather.forecast[2].high, "N"), FtoU(weather.forecast[3].high, "N"), FtoU(weather.forecast[4].high, "N")];
			wData['high'][6]	= [FtoU(weather.high, "Ré"), FtoU(weather.forecast[1].high, "Ré"), FtoU(weather.forecast[2].high, "Ré"), FtoU(weather.forecast[3].high, "Ré"), FtoU(weather.forecast[4].high, "Ré")];
			wData['high'][7]	= [FtoU(weather.high, "Rø"), FtoU(weather.forecast[1].high, "Rø"), FtoU(weather.forecast[2].high, "Rø"), FtoU(weather.forecast[3].high, "Rø"), FtoU(weather.forecast[4].high, "Rø")];


			wData['low'][0]		= [weather.low, weather.forecast[1].low, weather.forecast[2].low, weather.forecast[3].low, weather.forecast[4].low]	
			wData['low'][1]		= [weather.alt.low, weather.forecast[1].alt.low, weather.forecast[2].alt.low, weather.forecast[3].alt.low, weather.forecast[4].alt.low]	
			wData['low'][2]		= [FtoU(weather.low, "K"), FtoU(weather.forecast[1].low, "K"), FtoU(weather.forecast[2].low, "K"), FtoU(weather.forecast[3].low, "K"), FtoU(weather.forecast[4].low, "K")]	
			wData['low'][3]		= [FtoU(weather.low, "R"), FtoU(weather.forecast[1].low, "R"), FtoU(weather.forecast[2].low, "R"), FtoU(weather.forecast[3].low, "R"), FtoU(weather.forecast[4].low, "R")]	
			wData['low'][4]		= [FtoU(weather.low, "De"), FtoU(weather.forecast[1].low, "De"), FtoU(weather.forecast[2].low, "De"), FtoU(weather.forecast[3].low, "De"), FtoU(weather.forecast[4].low, "De")]	
			wData['low'][5]		= [FtoU(weather.low, "N"), FtoU(weather.forecast[1].low, "N"), FtoU(weather.forecast[2].low, "N"), FtoU(weather.forecast[3].low, "N"), FtoU(weather.forecast[4].low, "N")]	
			wData['low'][6]		= [FtoU(weather.low, "Ré"), FtoU(weather.forecast[1].low, "Ré"), FtoU(weather.forecast[2].low, "Ré"), FtoU(weather.forecast[3].low, "Ré"), FtoU(weather.forecast[4].low, "Ré")]	
			wData['low'][7]		= [FtoU(weather.low, "Rø"), FtoU(weather.forecast[1].low, "Rø"), FtoU(weather.forecast[2].low, "Rø"), FtoU(weather.forecast[3].low, "Rø"), FtoU(weather.forecast[4].low, "Rø")]	
			
			wData['code']		= [weather.todayCode, weather.forecast[1].code, weather.forecast[2].code, weather.forecast[3].code, weather.forecast[4].code];	// Condition code entire day
			wData['text']		= [weather.text, weather.forecast[1].text, weather.forecast[2].text, weather.forecast[3].text, weather.forecast[4].text];		//Code Text
			
			wData['thumbnail']	= [weather.thumbnail, weather.forecast[1].thumbnail, weather.forecast[2].thumbnail, weather.forecast[3].thumbnail, weather.forecast[4].thumbnail];
			wData['image']		= [weather.image, weather.forecast[1].image, weather.forecast[2].image, weather.forecast[3].image, weather.forecast[4].image];		
			
			wData['d2.date'] = weather.forecast[1].date;	wData['d3.date'] = weather.forecast[2].date;	wData['d4.date'] = weather.forecast[3].date;	wData['d5.date'] = weather.forecast[4].date;
			wData['d2.day'] = weather.forecast[1].day;		wData['d3.day'] = weather.forecast[2].day;		wData['d4.day'] = weather.forecast[3].day;		wData['d5.day'] = weather.forecast[4].day;	

			var d = new Date();
			var weekdayL = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
			var weekday = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; //weekday[d.getDay()]
			var weekdayS = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];		
			
			dayNames = ["TDY", wData['d2.day'], wData['d3.day'], wData['d4.day'], wData['d5.day']];
			dayTemps = [wData['temp'][wUnits], wData['high'][wUnits][1], wData['high'][wUnits][2], wData['high'][wUnits][3], wData['high'][wUnits][4]];
			
			//Calculate Brightest and Darkest hour
			midDay	 = eval(wData['sunrise'][0]) + (eval(wData['sunset'][0])+12-eval(wData['sunrise'][0]))/2;
			midNight = midDay-12; if(midNight < 0){midNight+=24}
			dawn = eval(wData['sunrise'][0])-0;
			dusk = eval(wData['sunset'][0])-0+12;	
			

			if(weatherOn){

				//Prefetch Icons
				if(wIconSet == 0){
					WeatherIcon0.src = wData['image'][0];
					WeatherIcon1.src = wData['image'][1];
					WeatherIcon2.src = wData['image'][2];
					WeatherIcon3.src = wData['image'][3];
					WeatherIcon4.src = wData['image'][4];			
				}
				else if(wIconSet > 0){
					WeatherIcon0.src = wIcons[wIconSet][wData['code'][0]];
					WeatherIcon1.src = wIcons[wIconSet][wData['code'][1]];
					WeatherIcon2.src = wIcons[wIconSet][wData['code'][2]];
					WeatherIcon3.src = wIcons[wIconSet][wData['code'][3]];
					WeatherIcon4.src = wIcons[wIconSet][wData['code'][4]];
				}
				if(wIconSet2 == 0){		WeatherIconNow.src = wData['image'][0];	}
				else if(wIconSet2 > 0){	WeatherIconNow.src = wIcons[wIconSet2][wData['codeNow']];	}				
				
				//Prefetch Backdrop
				var newbDrop = "WeatherWidget/Images/SkyViz/"+skyVis[wData['codeNow']]+"/Day.jpg"
				var theHour = new Date().getHours();
				if(theHour < dawn || theHour > dusk){newbDrop = "WeatherWidget/Images/SkyViz/"+skyVis[wData['codeNow']]+"/Night.jpg"}
				else if(theHour == dawn){newbDrop = "WeatherWidget/Images/SkyViz/"+skyVis[wData['codeNow']]+"/Dawn.jpg"}
				else if(theHour == dusk){newbDrop = "WeatherWidget/Images/SkyViz/"+skyVis[wData['codeNow']]+"/Dusk.jpg"}
				WeatherBackdrop.src = newbDrop;		
			}
		
		
		},
		error: function(error) {
		  //$("#weather").html('<p>'+error+'</p>');
		}
	  });
	});
	setTimeout(function(){displayWeather()}, 5000);
	//setTimeout(function(){ DebugDisplay2.textContent = midDay + " : " + midNight; }, 4000);	
}

function FtoU(F, To){ //Fahrenheit to other units
	var U = F;
	if(To == "K")	{U = Math.round((eval(F) + 459.67)* 5/9)}
	if(To == "R")	{U = Math.round((eval(F) + 459.67))}
	if(To == "De")	{U = Math.round((212 - eval(F))* 5/6)}
	if(To == "N")	{U = Math.round((eval(F) -32)* 11/60)}
	if(To == "Ré")	{U = Math.round((eval(F) -32)* 4/9)}
	if(To == "Rø")	{U = Math.round((eval(F) - 32)* 7/24+7.5)}
	return U
}

//=========== Display Weather ===========
function displayWeather(){
	CTX.w.restore(); //Remove any clipping that has been done.
	wcW = CAN.w.width;
	wcH = CAN.w.height;
	CTX.w.clearRect(0,0, wcW, wcH);
	CTX.w.lineWidth= 3;
	
	if(weatherOn){
		//prepare for ---{  Background  }---
		var SorF = "F";
		var wBgFill = wbgColor[3];
		var wAdjust = wbgwAdjust/5*wSize;
		CTX.w.shadowBlur= 0;
		CTX.w.shadowColor= wfsColor[3]; 	
		CTX.w.shadowOffsetX = 0;
		CTX.w.shadowOffsetY = 0;
		CTX.w.globalAlpha = wbgOpacity/100
		var newbDrop = "WeatherWidget/Images/SkyViz/"+skyVis[wData['codeNow']]+"/Day.jpg"
		var theHour = new Date().getHours();
		if(theHour < dawn || theHour > dusk){newbDrop = "WeatherWidget/Images/SkyViz/"+skyVis[wData['codeNow']]+"/Night.jpg"}
		else if(theHour == dawn){newbDrop = "WeatherWidget/Images/SkyViz/"+skyVis[wData['codeNow']]+"/Dawn.jpg"}
		else if(theHour == dusk){newbDrop = "WeatherWidget/Images/SkyViz/"+skyVis[wData['codeNow']]+"/Dusk.jpg"}
		WeatherBackdrop.src = newbDrop;		
		
		

		if(wBg == 1){SorF = "S"} //Border Only
		else if(wBg == 4 || wBg == 5){ //Fill BG color depending on hour of day (use sunset/sunrise)
			//DebugDisplay2.textContent = "wBg: " + wBg +", dawn: "+ dawn + ", now: " + theHour + ", dusk:" + dusk
			if(theHour < dawn || theHour > dusk){wBgFill="#334"}
			else if(theHour == dawn){wBgFill="#f82"}
			else if(theHour == dusk){wBgFill="#414"}
			else{wBgFill="#38d"}
		}
		
		//DebugDisplay2.textContent = "Code: " + wData['codeNow'] +", Currently: "+ wData['currently'] + ", LastWFetch: " + stamp["wFetch"]	
		var wTrims = [0, "box", "box0", "box12", "box14", "box23", "box34"];
		
		//Boundries
		var lBoundry = wcW*.05;
		var bBoundry = wcH*.95;

		if(wData['city'] == undefined){ // !!!ERROR HANDLING!!! Make sure there is weather info
			CTX.w.fillText('Error: Location{'+wData['city']+'}',lBoundry,bBoundry-wSize*5);
			CTX.w.fillText('Retrying...',lBoundry,bBoundry-wSize*2.5);
			CTX.w.fillText(''+stamp["time"]['wFetch']+'',lBoundry,bBoundry);
			}
		else {
			//Draw Widget Background
			if(wWidget == 1){
				var rBoundry = lBoundry+30*wSize+wAdjust;
				var tBoundry = bBoundry-19.5*wSize;
				var wBoundry = rBoundry-lBoundry;
				var hBoundry = bBoundry-tBoundry;
				
				//Create Canvas Boundries
				CTX.w.save(); //Save drawing area before clip
				CTX.w.globalAlpha = 0;//Make boundry box invisible
				if(wDays > 0){	weatherBox(wTrims[wTrim], "S", lBoundry, rBoundry, tBoundry, bBoundry, wBgFill, wSize)	}
				else		 {	weatherBox(wTrims[wTrim], "S", lBoundry, rBoundry, tBoundry, bBoundry-7.5*wSize, wBgFill, wSize)	}			
				CTX.w.clip(); //restrict drawing area to invisible boundry box
				
				//Create Picture Backdrop
				CTX.w.globalAlpha = wbgOpacity2/100;
				CTX.w.drawImage(WeatherBackdrop, lBoundry,	tBoundry,   wBoundry, hBoundry) //Backdrop
				//CTX.w.drawImage(WeatherCloudLayer, lBoundry,	tBoundry,   wBoundry, hBoundry) //Cloud Layer
				//drawBlur("w", eval("WeatherCloudLayer"), wbgOpacity/100, lBoundry,	tBoundry,   wBoundry, hBoundry, wAnim, 0.1) //Cloud layer

				//Create Text Background
				CTX.w.globalAlpha = wbgOpacity/100	//reset blur			
				weatherBox(wTrims[wTrim], SorF, lBoundry, rBoundry, bBoundry-7.3*wSize, bBoundry, wBgFill, wSize)
			}
			else if(wWidget == 2){
				weatherBox(wTrims[wTrim], SorF, lBoundry, lBoundry+wSize+ 10*wSize*2.3+wAdjust, bBoundry-(wDays+1.2)*wSize*2.3, bBoundry+wSize, wBgFill, wSize)
			}
			else if(wWidget == 3){
				var rBoundry = lBoundry+10*wSize+(3.5)*2*wSize*2.3+wAdjust;
				if(wDays < 4){			weatherBox(wTrims[wTrim], SorF, lBoundry, rBoundry, bBoundry-3.3*wSize*2.3, bBoundry+wSize, wBgFill, wSize)}
				else if(wDays == 4){	weatherBox(wTrims[wTrim], SorF, lBoundry, rBoundry, bBoundry-3.3*wSize*2.3, bBoundry+wSize, wBgFill, wSize)}
				else{					weatherBox(wTrims[wTrim], SorF, lBoundry, rBoundry, bBoundry-3.3*wSize*2.3, bBoundry+wSize, wBgFill, wSize)}
			}	
			else if(wWidget == 4){
				weatherBox(wTrims[wTrim], SorF, lBoundry, lBoundry+10*wSize+(5)*2*wSize*2.3+wAdjust, bBoundry-4.5*wSize*2.3, bBoundry+wSize, wBgFill, wSize)
			}						
			else if(wWidget == 5){

			}		

			//If SolidBG+Border
			if(wBg == 3 || wBg == 5){
			CTX.w.shadowBlur= wfsBlur;	
			CTX.w.shadowOffsetX = wfsOffset*wSize/20;
			CTX.w.shadowOffsetY = wfsOffset*wSize/20;		
			
				if(wWidget == 1){
					weatherBox(wTrims[wTrim], "S", lBoundry, rBoundry, bBoundry-7.3*wSize, bBoundry, wfColor2[3], wSize)				
				}
				
				
				
			}
					
			//Prepare for ---{  Icons  }---
			CTX.w.shadowBlur= wisBlur;
			CTX.w.shadowColor= wisColor[3];
			CTX.w.shadowOffsetX = wisOffset*wSize/20;
			CTX.w.shadowOffsetY = wisOffset*wSize/20;	
			CTX.w.globalAlpha = 1;
			if(wIconSet == 0){
				WeatherIcon0.src = wData['image'][0];
				WeatherIcon1.src = wData['image'][1];
				WeatherIcon2.src = wData['image'][2];
				WeatherIcon3.src = wData['image'][3];
				WeatherIcon4.src = wData['image'][4];	
				}
			else if(wIconSet > 0){
				WeatherIcon0.src = wIcons[wIconSet][wData['code'][0]];
				WeatherIcon1.src = wIcons[wIconSet][wData['code'][1]];
				WeatherIcon2.src = wIcons[wIconSet][wData['code'][2]];
				WeatherIcon3.src = wIcons[wIconSet][wData['code'][3]];
				WeatherIcon4.src = wIcons[wIconSet][wData['code'][4]];
				}
			if(wIconSet2 == 0){		WeatherIconNow.src = wData['image'][0];	}
			else if(wIconSet2 > 0){	WeatherIconNow.src = wIcons[wIconSet2][wData['codeNow']];	}
			
			
			//Draw Icons
			if(wWidget == 1){
				CTX.w.drawImage(WeatherIconNow,lBoundry + 2*wBoundry/10 - 1.5*wSize, bBoundry - 18.5*wSize, wSize*6, wSize*6); //Current Weather	
				for(var i = 0; i< wDays; i++){
					CTX.w.drawImage(eval("WeatherIcon"+i),lBoundry + (2*i+1)*wBoundry/(wDays*2) - wSize, bBoundry - 4.8*wSize, wSize*2, wSize*2)
				}
			}
			else if(wWidget == 2){
				for(var i = 0; i< wDays; i++){
					if(i==0){CTX.w.drawImage(eval("WeatherIconNow"), lBoundry + 6*wSize, wcH*.95-(wDays-i-0.3)*wSize*2.3, wSize*2, wSize*2);}
					else{CTX.w.drawImage(eval("WeatherIcon"+i), lBoundry + 6*wSize, wcH*.95-(wDays-i-0.3)*wSize*2.3, wSize*2, wSize*2);}
				}
			}
		}	
		

		//Prepare for ---{  Text  }---
		CTX.w.fillStyle = wfColor[3];		CTX.w.strokeStyle = wfColor[3];
		CTX.w.font = 225*wSize/100 +'px '+ weatherFont +', algerian, serif';
		CTX.w.textAlign="left";		
		CTX.w.shadowBlur= wfsBlur;
		CTX.w.shadowColor= wfsColor[3]; 	
		CTX.w.shadowOffsetX = wfsOffset*wSize/20;
		CTX.w.shadowOffsetY = wfsOffset*wSize/20;
	
		//Draw Widget Foreground
		if(wData['city'] == undefined){	}
		else {
			if(wWidget == 1){
				CTX.w.textAlign="center";
		
				CTX.w.font = 175*wSize/100 +'px '+ weatherFont +', algerian, serif';					
				 CTX.w.fillText(wData['city'], lBoundry + wBoundry/2, bBoundry - 9*wSize)
				CTX.w.font = 800*wSize/100 +'px '+ weatherFont +', algerian, serif';						
				 CTX.w.fillText(wData['temp'][wUnits] +"°", lBoundry + 7*wBoundry/10, bBoundry - 12*wSize)	
				CTX.w.font = 150*wSize/100 +'px '+ weatherFont +', algerian, serif';						
				 CTX.w.fillText(unitNames[wUnits], lBoundry + 9.5*wBoundry/10, bBoundry - 12*wSize)					
				 //CTX.w.fillText(stamp["time"]['wFetch'], lBoundry + 10*wBoundry/10, bBoundry - 18*wSize)	
				 
				CTX.w.fillStyle = wfColor2[3];		CTX.w.strokeStyle = wfColor2[3];				 
				CTX.w.shadowColor= wfsColor2[3]; 	
		
 				for(var i = 0; i< wDays; i++){
					CTX.w.font = 125*wSize/100 +'px '+ weatherFont +', algerian, serif';
					 CTX.w.fillText(dayNames[i], lBoundry + (2*i+1)*wBoundry/(wDays*2), bBoundry - 5.6*wSize)
					CTX.w.font = 100*wSize/100 +'px '+ weatherFont +', algerian, serif';
					 CTX.w.fillText("  "+ wData['low'][wUnits][i] +"°~"+ wData['high'][wUnits][i] +"° ", lBoundry + (2*i+1)*wBoundry/(wDays*2), bBoundry - wSize)
					if(i < wDays-1){
						drawLine("w", lBoundry + (i+1)*wBoundry/(wDays), bBoundry - 6.8*wSize, lBoundry + (i+1)*wBoundry/(wDays), bBoundry - wSize/2, 0.05*wSize, CTX.w.lineWidth)						
					}

				}			
			}
			else if(wWidget == 2){
				CTX.w.fillText(wData['city'] +", "+ wData['region'], lBoundry + wSize, wcH*.95-wDays*wSize*2.3)
				CTX.w.font = 150*wSize/100 +'px '+ weatherFont +', algerian, serif';
				for(var i = 0; i< wDays; i++){
					if(i==0){
						CTX.w.fillText("Now", lBoundry + wSize, wcH*.95-(wDays-i-1)*wSize*2.3)
						CTX.w.fillText(""+ wData['temp'][wUnits] +"° "+ unitNames[wUnits], lBoundry + 10*wSize, wcH*.95-(wDays-i-1)*wSize*2.3)						
					}
					else{
						CTX.w.fillText(dayNames[i], lBoundry + wSize, wcH*.95-(wDays-i-1)*wSize*2.3)
						CTX.w.fillText(""+ wData['high'][wUnits][i] +"° "+ unitNames[wUnits], lBoundry + 10*wSize, wcH*.95-(wDays-i-1)*wSize*2.3)
					}
				}	
			}
			else if(wWidget == 3){
				CTX.w.fillText(wData['city'] +", "+ wData['region'], wcW*.05,wcH*.95-2*wSize*2.3)
				CTX.w.font = 200*wSize/100 +'px '+ weatherFont +', algerian, serif';
				for(var i = 0; i< wDays; i++){
					CTX.w.fillText(dayNames[i], wcW*.05+(i)*wSize*8, wcH*.95-wSize*2.3)
					CTX.w.fillText(": "+ dayTemps[i] +"° "+ wData['units.temp'], wcW*.05+(i)*wSize*8, wcH*.95)
				}	
			}	
			else if(wWidget == 4){
				CTX.w.fillText(wData['city'] +", "+ wData['region'] +"     "+ wData['temp'] +"° "+ wData['units.temp'], wcW*.05,wcH*.95-3*wSize*2.3)
				CTX.w.font = 175*wSize/100 +'px '+ weatherFont +', algerian, serif';	
				CTX.w.fillText("H", wcW*.05,wcH*.95-1*wSize*2.3)
				CTX.w.fillText("L", wcW*.05,wcH*.95-0*wSize*2.3)
				CTX.w.font = 150*wSize/100 +'px '+ weatherFont +', algerian, serif';	
				CTX.w.textAlign="center";
 				for(var i = 0; i< wDays; i++){
					CTX.w.fillText(dayNames[i], wcW*.05+(i)*wSize*6+wSize*5, wcH*.95-2*wSize*2.3)
					CTX.w.fillText(""+ wData['high'][i] +"° "+ wData['units.temp'], wcW*.05+(i)*wSize*6+wSize*5, wcH*.95-1*wSize*2.3)
					CTX.w.fillText(""+ wData['low'][i] +"° "+ wData['units.temp'], wcW*.05+(i)*wSize*6+wSize*5, wcH*.95)
				}	
			}						
			else if(wWidget == 5){
	
			}		
			
			//CTX.w.fillText(wData['city'] +" : "+ wData['temp'] +" "+ wData['units.temp'],wcW*.05,wcH*.95)
			//DebugDisplay2.textContent = "" + ":" + wData['city'];
		}	
		
		
		
		
	}
	//DebugDisplay.textContent = weatherFont;

}


function weatherBox(boxShape, SorF, boxL, boxR, boxT, boxB, boxColor, cRadius){
	if(SorF=="S" || SorF=="F"){	drawS("w", boxShape, SorF, boxL, boxB, cRadius, boxColor, 0, 0, boxR, boxT, wSize)		}
}

function fetchZIP(){ //Doesn't seem to work with Wallpaper Engine (permissions pop-up doesn't appear)
	//http://stackoverflow.com/questions/6033561/geolocation-zip-code
	/*if(navigator.geolocation) {
		DebugDisplay2.textContent = "fetching geo";
        navigator.geolocation.getCurrentPosition(function(position) {
			var lat = position.coords.latitude;
			var long = position.coords.longitude;

			var point = new google.maps.LatLng(lat, long);
			new google.maps.Geocoder().geocode({'latLng': point}, function (res,    status) {
                    var zip = res[0].formatted_address.match(/,\s\w{2}\s(\d{5})/);
			DebugDisplay2.textContent = zip; 
			});
		}); 
     }
	 else{	DebugDisplay2.textContent = "nope";    }*/
}



//============================================================ Other Functions =====================================


function refreshCheck(tName, interval){ //interval is in milliseconds
	var t = Date.now();
	//DebugDisplay2.textContent = "Name: " + tName + ", Now: " + t +", LastFetch: " + stamp[tName]
	if(t > stamp[tName] + interval){stamp[tName] = Date.now();var nt = new Date(); stamp["time"][tName] = nt.toTimeString();	return true	}
	else{	return false	}
}

function findDist(x1, y1, x2, y2){
	var newD = Math.sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)) //A^2 + B^2 = C^2
	return newD
}

function MStoDate(MS){
	var minutes = 1000 * 60;
	var hours = minutes * 60;
	var days = hours * 24;
	var years = days * 365;
	var t = MS;

	var y = Math.round(t / years); t -= y;
	var m = Math.round(t / years)
}



function toRoman(num){ //Up to 9999. Too bad macrons don't automatically work in canvas (5000+)
	var digits = String(num).split("");
	var Rome = "";
	var digit = 0;
    var rKey = [];
	rKey[0] = ["","I","II","III","IV","V","VI","VII","VIII","IX"]
	rKey[1] = ["","X","XX","XXX","XL","L","LX","LXX","LXXX","XC"]
	rKey[2] = ["","C","CC","CCC","CD","D","DC","DCC","DCCC","CM"]
	rKey[3] = ["","M","MM","MMM","MMMI¯V¯","V¯","V¯I¯","V¯I¯I¯","V¯I¯I¯I¯","I¯X¯"]
	
	if(digits.length>3){	Rome += rKey[3][digits[digit]];	digit++}
	if(digits.length>2){	Rome += rKey[2][digits[digit]];	digit++}
	if(digits.length>1){	Rome += rKey[1][digits[digit]];	digit++}		
	if(digits.length>0){	Rome += rKey[0][digits[digit]];	digit++}	
	
	return Rome;
}


function hslToRgb(h, s, l) { //insert values between 0 & 1
	//Modified from: https://gist.github.com/mjackson/5311256
	if (isNaN(s)){s = parseFloat(s) / 100.0;} //if entered "100%" instead of 0-1 
	if (isNaN(l)){l = parseFloat(l) / 100.0;} //if entered "50%" instead of 0-1 
	if (h > 1){h /= 360} //if entered 0-360 num instead of 0-1
 	if (s > 1){s /= 100} //if entered 0-100 num instead of 0-1 
	if (l > 1){l /= 100} //if entered 0-100 num instead of 0-1 
		
	var r, g, b;

	if (s == 0) {
		r = g = b = l; // achromatic
	}
	else {
		function hue2rgb(p, q, t) {
			if (t < 0) t += 1;
			if (t > 1) t -= 1;
			if (t < 1/6) return p + (q - p) * 6 * t;
			if (t < 1/2) return q;
			if (t < 2/3) return p + (q - p) * (2/3 - t) * 6;
			return p;
		}

		var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
		var p = 2 * l - q;

		r = Math.round(255 * hue2rgb(p, q, h + 1/3));
		g = Math.round(255 * hue2rgb(p, q, h));
		b = Math.round(255 * hue2rgb(p, q, h - 1/3));
	}

  return [r, g, b];
}

function rgbToHsl(r, g, b) { //insert values between 0-255
	//Modified from: https://gist.github.com/mjackson/5311256
	r /= 255, g /= 255, b /= 255;

	var max = Math.max(r, g, b), min = Math.min(r, g, b);
	var h, s, l = (max + min) / 2;

	if (max == min) {
			h = s = 0; // achromatic
	}
	else {
		var d = max - min;
		s = l > 0.5 ? d / (2 - max - min) : d / (max + min);

		switch (max) {
			case r: h = (g - b) / d + (g < b ? 6 : 0); break;
			case g: h = (b - r) / d + 2; break;
			case b: h = (r - g) / d + 4; break;
		}

		h /= 6;
	}

	return [ h, s, l ]; //Outputs 0-1, 0-1, 0-1
}


function toHex(num){ 	var Hex = eval(num).toString(16);	return Hex;	}

function rgbToHex(R,G,B) {return "#" + toHex2(Math.round(R))+toHex2(Math.round(G))+toHex2(Math.round(B))}
function toHex2(n) {
 n = parseInt(n,10);
 if (isNaN(n)) return "00";
 n = Math.max(0,Math.min(n,255));
 return "0123456789ABCDEF".charAt((n-n%16)/16)
      + "0123456789ABCDEF".charAt(n%16);
}

function isOdd(num) { return num % 2;} //returns 1 if odd, 0 if even

function toBinary(num, max){
	var tempNum = num;	
	var numString = "";

	for(var i=10; i>=0; i--){
		var binary = Math.pow(2, i);
		if(binary <= max){
			if(tempNum >= binary){numString = "1" + numString; tempNum -= binary} else{numString = "0" + numString;}			
		}
	}

	return numString;
}

function minmax(Min, Max, n){	return Math.min(Max, Math.max(Min, n));	}

function r10(t, n, d){ //round to a decimal place
	var tempNum = n / Math.pow(10, d); //d=decimal place. 1= 10, -1=0.1
	if(t="ceil"){tempNum = Math.ceil(tempNum)}
	if(t="round"){tempNum = Math.round(tempNum)}
	if(t="floor"){tempNum = Math.floor(tempNum)}
	tempNum = tempNum * Math.pow(10, d); //shift back
	return tempNum
}

function pictureFill(canvas, imgSource, pW, pH, pS){
	//Picture Fill
	var tempCanvas = document.createElement("canvas"),	tCtx = tempCanvas.getContext("2d");
	tempCanvas.width = pW;
	tempCanvas.height = pH;
	//TempImage.src = imgSource //Fix this
	tCtx.drawImage(TempImage, 0, 0, TempImage.naturalWidth, TempImage.naturalHeight, 0, 0, pW, pH);
	CTX[canvas].fillstyle = CTX[canvas].createPattern(tempCanvas, 'repeat');			
}

function circPoint(cx, cy, radius, pointNum, totalPoints, adjust){
	var angle = 360/totalPoints * pointNum;
	var newPoint = [];
	newPoint[0] = cx + radius * Math.cos((angle+adjust) * Math.PI/180);
	newPoint[1] = cy + radius * Math.sin((angle+adjust) * Math.PI/180);
	newPoint[2] = angle;
	return newPoint;
}

function circDist(a1, a2, pstv){ //closest distance between 2 degrees around a circle
	if(a1 < 0){ a1 += 360}
	if(a2 < 0){ a2 += 360}
	if(a1 > a2)	{	var d = (a1-a2) *-1;	}
	else		{	var d = a2-a1;			}
	if(d > 180){	d = d-360}
	if(d <-180){	d = d+360}
	d=Math.round(d);
	if(pstv == true && d < 0){d *= -1}
	//DebugDisplay.textContent = a1 +":"+ a2 +":"+ pstv +":"+ d;		
	return d;
}

function drawBlur(canvas,img, opacity, x1, y1, w, h, motionBlur, blurAmount){	//creating a blur effect in a silly but effective manner
	var aB = 1;
	if(motionBlur){aB = Math.random()}
	if(blurAmount >= 0){aB = aB*blurAmount}
	
	CTX[canvas].globalAlpha = 0.09*opacity; 
	CTX[canvas].drawImage(img, x1,		y1,		w,	h);
	CTX[canvas].drawImage(img, x1,		y1,		w-1*aB,	h-1*aB);
	CTX[canvas].drawImage(img, x1,		y1,		w-3*aB,	h-3*aB);
	CTX[canvas].drawImage(img, x1,		y1,		w-6*aB,	h-6*aB);	
	CTX[canvas].drawImage(img, x1,		y1,		w-9*aB,	h-9*aB);	
	CTX[canvas].drawImage(img, x1,		y1,		w-12*aB,h-12*aB);	
	CTX[canvas].drawImage(img, x1+1*aB,	y1+1*aB,w-1*aB,	h-1*aB);
	CTX[canvas].drawImage(img, x1+3*aB,	y1+3*aB,w-3*aB,	h-3*aB);
	CTX[canvas].drawImage(img, x1+6*aB,	y1+6*aB,w-6*aB,	h-6*aB);	
	CTX[canvas].drawImage(img, x1+9*aB,	y1+9*aB,w-9*aB,	h-9*aB);		
	CTX[canvas].drawImage(img, x1+12*aB,y1+12*aB,w-12*aB,h-12*aB);
	CTX[canvas].drawImage(img, x1+1*aB,	y1, 	w-1*aB,	h);	
	CTX[canvas].drawImage(img, x1+3*aB,	y1, 	w-3*aB,	h);	
	CTX[canvas].drawImage(img, x1+6*aB,	y1, 	w-6*aB,	h);		
	CTX[canvas].drawImage(img, x1+9*aB,	y1, 	w-9*aB,	h);		
	CTX[canvas].drawImage(img, x1+12*aB,y1, 	w-12*aB,h);	
	CTX[canvas].drawImage(img, x1,		y1+1*aB,w,		h-1*aB);
	CTX[canvas].drawImage(img, x1,		y1+3*aB,w,		h-3*aB);
	CTX[canvas].drawImage(img, x1,		y1+6*aB,w,		h-6*aB);	
	CTX[canvas].drawImage(img, x1,		y1+9*aB,w,		h-9*aB);	
	CTX[canvas].drawImage(img, x1,		y1+12*aB,w,		h-12*aB);
}

function drawLine(canvas, x1, y1, x2, y2, width, restoreWidth){
	if(width>=0){CTX[canvas].lineWidth = width;}
	CTX[canvas].beginPath();
	CTX[canvas].moveTo(x1, y1); //x1=left boundry, y1=bottom, v1=right, v2=top
	CTX[canvas].lineTo(x2, y2);
	CTX[canvas].closePath();
	CTX[canvas].stroke();
	if(width>=0 && restoreWidth >= 0){CTX[canvas].lineWidth = restoreWidth;}
}

function drawS(canvas, shape, SorF, x1, y1, r1, c1, c2, c3, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10){
	if(SorF == "" || SorF == "N" ){}
	else{
		CTX[canvas].fillStyle = c1;	CTX[canvas].strokeStyle = c1;	
		if(shape=="box"){ //Rectangle
			CTX[canvas].beginPath();
			CTX[canvas].moveTo(x1, y1); //x1=left boundry, y1=bottom, v1=right, v2=top
			CTX[canvas].lineTo(x1, v2);
			CTX[canvas].lineTo(v1, v2);					
			CTX[canvas].lineTo(v1, y1);		
			CTX[canvas].closePath();
			if(SorF == "fill" || SorF == "F") {CTX[canvas].fill();} else{CTX[canvas].stroke();}
		}
		if(shape=="box0"){ //4 Round corners
			CTX[canvas].beginPath();
			CTX.w.moveTo(x1+v3*2, y1);//x1=left boundry, y1=bottom, v1=right, v2=top, v3=adjustsize, r1=corner radius
			CTX.w.arcTo( x1, y1, x1,	y1-v3*2, r1);
			CTX.w.lineTo(x1, v2+v3);
			CTX.w.arcTo( x1, v2, x1+v3*2, v2, r1);
			CTX.w.lineTo(v1-v3, v2);
			CTX.w.arcTo( v1, v2, v1, v2+v3,	r1);					
			CTX.w.lineTo(v1, y1-v3*2);
			CTX.w.arcTo( v1, y1, v1-v3, y1,	r1);
			CTX[canvas].closePath();
			if(SorF == "fill" || SorF == "F") {CTX[canvas].fill();} else{CTX[canvas].stroke();}
		}
		if(shape=="box12"){ //Corners 1 & 2 are Square
			CTX[canvas].beginPath();
			CTX.w.moveTo(x1+v3*2, y1);//x1=left boundry, y1=bottom, v1=right, v2=top, v3=adjustsize, r1=corner radius
			CTX.w.arcTo( x1, y1, x1,	y1-v3*2, r1);
			CTX.w.lineTo(x1, v2);
			CTX.w.lineTo(v1, v2);
			CTX.w.lineTo(v1, y1-v3*2);
			CTX.w.arcTo( v1, y1, v1-v3, y1,	r1);
			CTX[canvas].closePath();
			if(SorF == "fill" || SorF == "F") {CTX[canvas].fill();} else{CTX[canvas].stroke();}
		}
		if(shape=="box34"){ //Corners 3 & 4 are Square
			CTX[canvas].beginPath();
			CTX.w.moveTo(x1, y1);//x1=left boundry, y1=bottom, v1=right, v2=top, v3=adjustsize, r1=corner radius
			CTX.w.lineTo(x1, v2+v3);
			CTX.w.arcTo( x1, v2, x1+v3*2, v2, r1);
			CTX.w.lineTo(v1-v3, v2);
			CTX.w.arcTo( v1, v2, v1, v2+v3,	r1);					
			CTX.w.lineTo(v1, y1);
			CTX[canvas].closePath();
			if(SorF == "fill" || SorF == "F") {CTX[canvas].fill();} else{CTX[canvas].stroke();}
		}
		if(shape=="box14"){ //Corners 1 & 4 are Square
			CTX[canvas].beginPath();
			CTX.w.moveTo(x1+v3*2, y1);//x1=left boundry, y1=bottom, v1=right, v2=top, v3=adjustsize, r1=corner radius
			CTX.w.arcTo( x1, y1, x1,	y1-v3*2, r1);
			CTX.w.lineTo(x1, v2);
			CTX.w.lineTo(v1-v3, v2);
			CTX.w.arcTo( v1, v2, v1, v2+v3,	r1);					
			CTX.w.lineTo(v1, y1);
			CTX[canvas].closePath();
			if(SorF == "fill" || SorF == "F") {CTX[canvas].fill();} else{CTX[canvas].stroke();}
		}
		if(shape=="box23"){ //Corners 2 & 3 are Square
			CTX[canvas].beginPath();
			CTX.w.moveTo(x1, y1);//x1=left boundry, y1=bottom, v1=right, v2=top, v3=adjustsize, r1=corner radius
			CTX.w.lineTo(x1, v2+v3);
			CTX.w.arcTo( x1, v2, x1+v3*2, v2, r1);
			CTX.w.lineTo(v1, v2);
			CTX.w.lineTo(v1, y1-v3*2);
			CTX.w.arcTo( v1, y1, v1-v3, y1,	r1);
			CTX[canvas].closePath();
			if(SorF == "fill" || SorF == "F") {CTX[canvas].fill();} else{CTX[canvas].stroke();}
		}
		if(shape=="circle"){ //and semi circles
			CTX[canvas].beginPath();
			CTX[canvas].arc(x1,y1,r1,v1*Math.PI,v2*Math.PI);
			if(v3 == 'pac'){	CTX[canvas].lineTo(x1,y1);	}
			CTX[canvas].closePath();
			if(SorF == "fill" || SorF == "F") {CTX[canvas].fill();} else{CTX[canvas].stroke();}
		}
		if(shape=="peanut"){ // Peanut
			CTX[canvas].beginPath();
			CTX[canvas].arc(x1-r1/2,y1,r1,v1*Math.PI,v2*Math.PI);
			CTX[canvas].arc(x1+r1/2,y1,r1,v1*Math.PI,v2*Math.PI);
			CTX[canvas].closePath();
			if(SorF == "fill" || SorF == "F") {CTX[canvas].fill();} else{CTX[canvas].stroke();}
		}
		if(shape=="smiley"){ 
			CTX[canvas].beginPath();
			CTX[canvas].arc(x1,y1,r1,0*Math.PI,2*Math.PI);
			CTX[canvas].closePath();
			if(SorF == "fill" || SorF == "F") {CTX[canvas].fill();} else{CTX[canvas].stroke();}
			
			CTX[canvas].fillStyle = c2;	CTX[canvas].strokeStyle = c2;
			//left eye
			CTX[canvas].beginPath();
			CTX[canvas].arc(x1-r1*0.35,y1-r1*0.35,r1/4,0,2*Math.PI);
			CTX[canvas].closePath();
			if(SorF == "fill" || SorF == "F") {CTX[canvas].fill();} else{CTX[canvas].stroke();}
			//right eye
			CTX[canvas].beginPath();	
			CTX[canvas].arc(x1+r1*0.35,y1-r1*0.35,r1/4,0,2*Math.PI);
			CTX[canvas].closePath();
			if(SorF == "fill" || SorF == "F") {CTX[canvas].fill();} else{CTX[canvas].stroke();}
			//mouth
			CTX[canvas].beginPath();
			CTX[canvas].arc(x1,y1+r1/4,r1/2,0*Math.PI,1*Math.PI);
			CTX[canvas].closePath();
			if(SorF == "fill" || SorF == "F") {CTX[canvas].fill();} else{CTX[canvas].stroke();}
		}
		if(shape=="devil"){ 
			CTX[canvas].fillStyle = c2;	CTX[canvas].strokeStyle = c2;
			//tail
			CTX[canvas].beginPath();
			CTX[canvas].moveTo(x1+r1*1.5, y1+r1*0.75);
			CTX[canvas].lineTo(x1+r1*0.5, y1+r1*0.4);
			CTX[canvas].lineTo(x1+r1*0.75, y1+r1*0.25);
			CTX[canvas].closePath();
			if(SorF == "fill" || SorF == "F") {CTX[canvas].fill();} else{CTX[canvas].stroke();}
			CTX[canvas].beginPath();
			CTX[canvas].moveTo(x1+r1*1.5, y1+r1*0.75);
			CTX[canvas].lineTo(x1+r1*1, y1+r1*0.7);
			CTX[canvas].lineTo(x1+r1*1.25, y1+r1*0.35);
			CTX[canvas].closePath();
			if(SorF == "fill" || SorF == "F") {CTX[canvas].fill();} else{CTX[canvas].stroke();}
			
			CTX[canvas].fillStyle = c1;	CTX[canvas].strokeStyle = c1;
			//face circle
			CTX[canvas].beginPath();
			CTX[canvas].arc(x1,y1,r1,0*Math.PI,2*Math.PI);
			CTX[canvas].closePath();
			if(SorF == "fill" || SorF == "F") {CTX[canvas].fill();} else{CTX[canvas].stroke();}

			CTX[canvas].fillStyle = c2;	CTX[canvas].strokeStyle = c2;
			//left eye
			CTX[canvas].beginPath();
			CTX[canvas].arc(x1-r1*0.35,y1-r1*0.35,r1/4,0.1*Math.PI,1.3*Math.PI);
			CTX[canvas].closePath();
			if(SorF == "fill" || SorF == "F") {CTX[canvas].fill();} else{CTX[canvas].stroke();}
			//right eye
			CTX[canvas].beginPath();	
			CTX[canvas].arc(x1+r1*0.35,y1-r1*0.35,r1/4,-0.3*Math.PI,0.9*Math.PI);
			CTX[canvas].closePath();
			if(SorF == "fill" || SorF == "F") {CTX[canvas].fill();} else{CTX[canvas].stroke();}
			//mouth
			CTX[canvas].beginPath();
			CTX[canvas].arc(x1,y1+r1/4,r1/2,0*Math.PI,1*Math.PI);
			CTX[canvas].closePath();
			if(SorF == "fill" || SorF == "F") {CTX[canvas].fill();} else{CTX[canvas].stroke();}
			//left ear
			CTX[canvas].beginPath();
			CTX[canvas].moveTo(x1-r1, y1-r1);
			CTX[canvas].lineTo(x1-r1*0.5, y1-r1*0.75);
			CTX[canvas].lineTo(x1-r1*0.75, y1-r1*0.5);
			CTX[canvas].closePath();
			if(SorF == "fill" || SorF == "F") {CTX[canvas].fill();} else{CTX[canvas].stroke();}
			//right ear
			CTX[canvas].beginPath();
			CTX[canvas].moveTo(x1+r1, y1-r1);
			CTX[canvas].lineTo(x1+r1*0.5, y1-r1*0.75);
			CTX[canvas].lineTo(x1+r1*0.75, y1-r1*0.5);
			CTX[canvas].closePath();
			if(SorF == "fill" || SorF == "F") {CTX[canvas].fill();} else{CTX[canvas].stroke();}
		}
		if(shape=="bubble"){ 
			var returnLW = CTX[canvas].lineWidth;
			CTX[canvas].lineWidth = v1
			CTX[canvas].beginPath();	//Outer circle
			CTX[canvas].arc(x1,y1,r1,0*Math.PI,2*Math.PI);
			CTX[canvas].closePath();
			CTX[canvas].stroke();		
			CTX[canvas].beginPath();	//Inner mark
			CTX[canvas].arc(x1,y1,r1*16/24,0.9*Math.PI,1.6*Math.PI);
			CTX[canvas].arc(x1,y1,r1*13/24,1.5*Math.PI,0.9*Math.PI, true);
			CTX[canvas].closePath();
			if(SorF == "fill" || SorF == "F") {CTX[canvas].fill();} else{CTX[canvas].stroke();}
			CTX[canvas].beginPath();	//Inner mark 2
			CTX[canvas].arc(x1,y1,r1*16/24,0.7*Math.PI,0.8*Math.PI);
			CTX[canvas].arc(x1,y1,r1*13/24,0.79*Math.PI,0.77*Math.PI, true);
			CTX[canvas].closePath();			
			if(SorF == "fill" || SorF == "F") {CTX[canvas].fill();} else{CTX[canvas].stroke();}
			CTX[canvas].lineWidth = returnLW;
		}
		if(shape=="poly"){  //polygons
			var pPoints = [];
			for(var pp=1; pp<=v1; pp++){	pPoints[pp]=circPoint(x1, y1, r1, pp, v1, v2);	}
			
			CTX[canvas].beginPath();
			CTX[canvas].moveTo(pPoints[1][0],pPoints[1][1]);
			for(var pp=2; pp<=v1; pp++){	CTX[canvas].lineTo(pPoints[pp][0],pPoints[pp][1]);	}
			CTX[canvas].lineTo(pPoints[1][0],pPoints[1][1]);			
			CTX[canvas].closePath();
			
			if(SorF == "fill" || SorF == "F") {CTX[canvas].fill();} else{CTX[canvas].stroke();}
		}
		if(shape=="star"){ 
			var starPoints = [];
			for(var sp=1; sp<=v1; sp++){
				starPoints[sp]=circPoint(x1, y1, r1, sp, v1, v2);
			}
			
			CTX[canvas].beginPath();
			CTX[canvas].moveTo(starPoints[1][0],starPoints[1][1]);
			
			if(v3=="Real"){ //Realistic
				var returnLW = CTX[canvas].lineWidth;
				CTX[canvas].lineWidth = 0.5;				
				starPoints.In=[];
				for(var sp=1; sp<=v1; sp++){	starPoints.In[sp]=circPoint(x1, y1, r1*1/6, sp, v1, v2);	}	//sp must be even. 8 is default look

				CTX[canvas].moveTo(starPoints.In[1][0],starPoints.In[1][1]);// beams
				for(var i=1;i<=v1;i+=2){
					CTX[canvas].lineTo(starPoints.In[i][0],starPoints.In[i][1]);	
					CTX[canvas].lineTo(starPoints[i+1][0],starPoints[i+1][1]);					
				}

				CTX[canvas].closePath();
				if(SorF == "fill" || SorF == "F") {CTX[canvas].fill();} else{CTX[canvas].stroke();}
				CTX[canvas].beginPath();					
	
				CTX[canvas].arc(x1, y1,r1*8/40,0*Math.PI,2*Math.PI);				
				CTX[canvas].closePath();	CTX[canvas].fill();	CTX[canvas].beginPath();	
				CTX[canvas].arc(x1, y1,r1*9/40,0*Math.PI,2*Math.PI);				
				CTX[canvas].closePath();	CTX[canvas].stroke();	CTX[canvas].beginPath();		
				CTX[canvas].arc(x1, y1,r1*10/40,0*Math.PI,2*Math.PI);		
				CTX[canvas].closePath();	CTX[canvas].stroke();	CTX[canvas].beginPath();		
				CTX[canvas].arc(x1, y1,r1*12/40,0*Math.PI,2*Math.PI);		
				CTX[canvas].closePath();	CTX[canvas].stroke();	CTX[canvas].beginPath();		
				CTX[canvas].arc(x1, y1,r1*14/40,0*Math.PI,2*Math.PI);		
				CTX[canvas].closePath();	CTX[canvas].stroke();	CTX[canvas].beginPath();		
				CTX[canvas].arc(x1, y1,r1*17/40,0*Math.PI,2*Math.PI);				
				CTX[canvas].closePath();	CTX[canvas].stroke();	CTX[canvas].beginPath();		
				CTX[canvas].arc(x1, y1,r1*20/40,0*Math.PI,2*Math.PI);	
				CTX[canvas].closePath();	CTX[canvas].stroke();	CTX[canvas].beginPath();		
				CTX[canvas].lineWidth = returnLW;
			}
			else if(v1==3){ //Triangle
				CTX[canvas].lineTo(starPoints[2][0],starPoints[2][1]);			
				CTX[canvas].lineTo(starPoints[3][0],starPoints[3][1]);				
			}
			else if(v1==4){ //diamond
				CTX[canvas].lineTo(starPoints[2][0],starPoints[2][1]);			
				CTX[canvas].lineTo(starPoints[3][0],starPoints[3][1]);				
				CTX[canvas].lineTo(starPoints[4][0],starPoints[4][1]);
			}
			else if(v1==5){
				CTX[canvas].lineTo(starPoints[4][0],starPoints[4][1]);
				CTX[canvas].lineTo(starPoints[2][0],starPoints[2][1]);			
				CTX[canvas].lineTo(starPoints[5][0],starPoints[5][1]);
				CTX[canvas].lineTo(starPoints[3][0],starPoints[3][1]);		
			}
			else if(v1==7){
				CTX[canvas].lineTo(starPoints[5][0],starPoints[5][1]);
				CTX[canvas].lineTo(starPoints[2][0],starPoints[2][1]);	
				CTX[canvas].lineTo(starPoints[6][0],starPoints[6][1]);
				CTX[canvas].lineTo(starPoints[3][0],starPoints[3][1]);
				CTX[canvas].lineTo(starPoints[7][0],starPoints[7][1]);
				CTX[canvas].lineTo(starPoints[4][0],starPoints[4][1]);
			}
			else if(v1==9){
				CTX[canvas].lineTo(starPoints[6][0],starPoints[6][1]);
				CTX[canvas].lineTo(starPoints[2][0],starPoints[2][1]);	
				CTX[canvas].lineTo(starPoints[7][0],starPoints[7][1]);
				CTX[canvas].lineTo(starPoints[3][0],starPoints[3][1]);
				CTX[canvas].lineTo(starPoints[8][0],starPoints[8][1]);
				CTX[canvas].lineTo(starPoints[4][0],starPoints[4][1]);
				CTX[canvas].lineTo(starPoints[9][0],starPoints[9][1]);
				CTX[canvas].lineTo(starPoints[5][0],starPoints[5][1]);
			}
			CTX[canvas].closePath();		
			if(SorF == "fill" || SorF == "F") {CTX[canvas].fill();} else{CTX[canvas].stroke();}
		}
		if(shape=="snakehead"){ 
			//triangle head		
			var starPoints = [];
			starPoints[1]=circPoint(x1, y1, r1,		1, 5, v2); //cheek corner
			starPoints[2]=circPoint(x1, y1, r1*.65,	2, 5, v2); //back corner
			starPoints[3]=circPoint(x1, y1, r1*.65,	3, 5, v2); //back corner			
			starPoints[4]=circPoint(x1, y1, r1,		4, 5, v2); //cheek corner		
			starPoints[5]=circPoint(x1, y1, r1*1.75,5, 5, v2); //long nose	
			
			starPoints[10]=circPoint(x1, y1, r1,2, 5, v2-180); //eye		
			starPoints[11]=circPoint(x1, y1, r1,3, 5, v2-180); //eye				
			
			CTX[canvas].beginPath();
			CTX[canvas].moveTo(starPoints[1][0],starPoints[1][1]);
			CTX[canvas].lineTo(starPoints[2][0],starPoints[2][1]);		
			CTX[canvas].lineTo(starPoints[3][0],starPoints[3][1]);		
			CTX[canvas].lineTo(starPoints[4][0],starPoints[4][1]);				
			CTX[canvas].lineTo(starPoints[5][0],starPoints[5][1]);			
		
			CTX[canvas].closePath();
			CTX[canvas].fill();
			CTX[canvas].fillStyle = c2;	CTX[canvas].strokeStyle = c2;

			//eyes
			CTX[canvas].beginPath();
			CTX[canvas].arc(starPoints[10][0],starPoints[10][1],r1/9,0*Math.PI,2*Math.PI);
			CTX[canvas].closePath();
			CTX[canvas].fill();
			CTX[canvas].beginPath();
			CTX[canvas].arc(starPoints[11][0],starPoints[11][1],r1/9,0*Math.PI,2*Math.PI);
			CTX[canvas].closePath();		
			CTX[canvas].fill();
		}
		if(shape=="fish"){ 
			//drawS(canvas, shape, SorF, x1, 		y1, 		r1, 			c1,			c2,		 c3,		v1, 		v2, 			v3, 				v4, 		v5, 		v6, v7, v8, v9, v10)
			//drawS("a", "fish", fill, fish[i][0], fish[i][1], height/2, CTX.a.fillStyle, 0, vizStroke/3, fish.td[i], 180+fish.d[i], Math.round(fish.f[i]), fish.sh.b[i], fish.sh.f[i]);
			var returnLW = CTX[canvas].lineWidth;
			CTX[canvas].lineWidth = c3;	
			
			var leftC = circPoint(x1, y1, r1*2/3, 1, 4, v2); //center of left circle
			var rightC = circPoint(x1, y1, r1*2/3, 3, 4, v2); //center of right circle
			var fins=[];	
			fins.l = circPoint(x1, y1, r1*20/50, 6, 16, v2); //center of left fin
			fins.r = circPoint(x1, y1, r1*20/50, 10, 16, v2); //center of left fin
			//Side fin animation
			if(v1 < 0)	{	fins.l1 = circPoint(x1, y1, r1*18/30, 1, 4, v2); 	}
			else		{	fins.l1 = circPoint(x1, y1, r1*15/30, 1, 4, v2);	}
			if(v1 > 0)	{	fins.r2 = circPoint(x1, y1, r1*18/30, 3, 4, v2); 	}
			else		{	fins.r2 = circPoint(x1, y1, r1*15/30, 3, 4, v2); 	}
			
		
			
			//Body
			if(v4 == 0){
				CTX[canvas].beginPath();
				CTX[canvas].arc(leftC[0], leftC[1], r1,		(1.25+v2/180)*Math.PI, (1.75+v2/180)*Math.PI);
				CTX[canvas].arc(rightC[0], rightC[1], r1,	(0.25+v2/180)*Math.PI, (0.75+v2/180)*Math.PI);		
				CTX[canvas].closePath();		
				if(SorF == "fill" || SorF == "F") {CTX[canvas].fill();} else{CTX[canvas].stroke();}		
				
				//Fins
				CTX[canvas].beginPath();
				CTX[canvas].moveTo(fins.l1[0], fins.l1[1]);
				CTX[canvas].lineTo(fins.l[0], fins.l[1]);					
				CTX[canvas].closePath();	
				CTX[canvas].stroke();	
	
				CTX[canvas].beginPath();
				CTX[canvas].moveTo(fins.r2[0], fins.r2[1]);
				CTX[canvas].lineTo(fins.r[0], fins.r[1]);	
				CTX[canvas].closePath();					
				CTX[canvas].stroke();	

			}
			else {
				CTX[canvas].beginPath();
				CTX[canvas].arc(leftC[0], leftC[1], r1, 0*Math.PI, 2*Math.PI);
				CTX[canvas].arc(rightC[0], rightC[1], r1, 0*Math.PI, 2*Math.PI);		
				CTX[canvas].closePath();		
				if(SorF == "fill" || SorF == "F") {CTX[canvas].fill();} else{CTX[canvas].stroke();}				
			}
			
			//Tail
			var tail = circPoint(x1, y1, r1*2/3, 4, 4, v2); //where tail connects to body

			var tSp = 128, fFrames = Math.round(tSp/2.666);
			var fTP=[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]; //mid, left, right, 
		
			for(var i = 1; i <= fFrames; i++){
				if(i <= fFrames/2+1){	if(v3 == i){	fTP[0] = (tSp/4+tSp+1-i)%tSp+1;			fTP[1] = (tSp/6.5+tSp+1-i)%tSp+1;			fTP[2] = (tSp/8+tSp+1-i)%tSp+1;			fTP[3] = (fTP[2] - fFrames/10.5)%tSp+1;	fTP[4] = (fTP[2] - fFrames/6)%tSp+1;	fTP[5] = (fTP[2] - fFrames/4.5)%tSp+1;	fTP[6] = (fTP[2] - fFrames/2)%tSp+1;		}	}
				else 				{	if(v3 == i){	fTP[0] = (tSp/4+tSp+1-fFrames+i)%tSp+1;	fTP[1] = (tSp/6.5+tSp+1-fFrames+i)%tSp+1;	fTP[2] = (tSp/8+tSp+1-fFrames+i)%tSp+1;	fTP[3] = (fTP[2] - fFrames/10.5)%tSp+1;	fTP[4] = (fTP[2] - fFrames/6)%tSp+1;	fTP[5] = (fTP[2] - fFrames/4.5)%tSp+1;	fTP[6] = (fTP[2] - fFrames/2)%tSp+1;		}	}
			}	
			//Points on tail from body connection out [1/4, 2/4, 3/4, tip]
			var tailP = [];	
			tailP.l3 = [circPoint(tail[0], tail[1], r1*1/6, fTP[0], tSp, v2), circPoint(tail[0], tail[1], r1*2/6, fTP[0], tSp, v2), circPoint(tail[0], tail[1], r1*3/6, fTP[0], tSp, v2), circPoint(tail[0], tail[1], r1*4/6, fTP[0], tSp, v2)];			
			tailP.l2 = [circPoint(tail[0], tail[1], r1*1/6, fTP[1], tSp, v2), circPoint(tail[0], tail[1], r1*2/6, fTP[1], tSp, v2), circPoint(tail[0], tail[1], r1*3/6, fTP[1], tSp, v2), circPoint(tail[0], tail[1], r1*4/6, fTP[1], tSp, v2)];			
			tailP.l  = [circPoint(tail[0], tail[1], r1*1/6, fTP[2], tSp, v2), circPoint(tail[0], tail[1], r1*2/6, fTP[2], tSp, v2), circPoint(tail[0], tail[1], r1*3/6, fTP[2], tSp, v2), circPoint(tail[0], tail[1], r1*4/6, fTP[2], tSp, v2)];			
			tailP.m  = [circPoint(tail[0], tail[1], r1*1/6, fTP[3], tSp, v2), circPoint(tail[0], tail[1], r1*2/6, fTP[3], tSp, v2), circPoint(tail[0], tail[1], r1*3/6, fTP[3], tSp, v2), circPoint(tail[0], tail[1], r1*4/6, fTP[3], tSp, v2)];			
			tailP.r  = [circPoint(tail[0], tail[1], r1*1/6, fTP[4], tSp, v2), circPoint(tail[0], tail[1], r1*2/6, fTP[4], tSp, v2), circPoint(tail[0], tail[1], r1*3/6, fTP[4], tSp, v2), circPoint(tail[0], tail[1], r1*4/6, fTP[4], tSp, v2)];			
			tailP.r2 = [circPoint(tail[0], tail[1], r1*1/6, fTP[5], tSp, v2), circPoint(tail[0], tail[1], r1*2/6, fTP[5], tSp, v2), circPoint(tail[0], tail[1], r1*3/6, fTP[5], tSp, v2), circPoint(tail[0], tail[1], r1*4/6, fTP[5], tSp, v2)];			
			tailP.r3 = [circPoint(tail[0], tail[1], r1*1/6, fTP[6], tSp, v2), circPoint(tail[0], tail[1], r1*2/6, fTP[6], tSp, v2), circPoint(tail[0], tail[1], r1*3/6, fTP[6], tSp, v2), circPoint(tail[0], tail[1], r1*4/6, fTP[6], tSp, v2)];			
			
			/*if(v3 == 1)				{	ftp1 = 8;	ftp2 = 4;	} //Nonloop antiquated version. This is what the above loops create
			else if(v3 == 2  || v3 == 24){	ftp1 = 7;	ftp2 = 3;	}
			else if(v3 == 3  || v3 == 23){	ftp1 = 6;	ftp2 = 2;	}
			else if(v3 == 4  || v3 == 22){	ftp1 = 5;	ftp2 = 1;	}
			else if(v3 == 5  || v3 == 21){	ftp1 = 4;	ftp2 = 64;	}
			else if(v3 == 6  || v3 == 20){	ftp1 = 3;	ftp2 = 63;	}
			else if(v3 == 7  || v3 == 19){	ftp1 = 2;	ftp2 = 62;	}
			else if(v3 == 8  || v3 == 18){	ftp1 = 1;	ftp2 = 61;	}
			else if(v3 == 9  || v3 == 17){	ftp1 = 64;	ftp2 = 60;	}
			else if(v3 == 10 || v3 == 16){	ftp1 = 63;	ftp2 = 59;	}
			else if(v3 == 11 || v3 == 15){	ftp1 = 62;	ftp2 = 58;	}
			else if(v3 == 12 || v3 == 14){	ftp1 = 61;	ftp2 = 57;	}
			else if(v3 == 13)			{	ftp1 = 60;	ftp2 = 56;	}*/
			
			CTX[canvas].beginPath();		
			if(v5 == 0){	//long wedge			
				CTX[canvas].moveTo(tailP.l[3][0], tailP.l[3][1]);	
				CTX[canvas].lineTo(tail[0], tail[1]);
				CTX[canvas].lineTo(tailP.r[3][0], tailP.r[3][1]);
			}
			else if(v5 == 1){ //mid wedge
				CTX[canvas].moveTo(tail[0], tail[1]);
				CTX[canvas].lineTo(tailP.m[1][0], tailP.m[1][1]);
				CTX[canvas].lineTo(tailP.r[3][0], tailP.r[3][1]);
				CTX[canvas].lineTo(tailP.l[3][0], tailP.l[3][1]);	
				CTX[canvas].lineTo(tailP.m[1][0], tailP.m[1][1]);
			} 
			else if(v5 == 2){//notched tailfin
				CTX[canvas].moveTo(tailP.l[3][0], tailP.l[3][1]);	
				CTX[canvas].lineTo(tail[0], tail[1]);
				CTX[canvas].lineTo(tailP.r[3][0], tailP.r[3][1]);
				CTX[canvas].lineTo(tailP.m[2][0], tailP.m[2][1]);
			} 
			else if(v5 == 3){ //Two Tip
				CTX[canvas].moveTo(tail[0], tail[1]);
				CTX[canvas].lineTo(tailP.r2[2][0], tailP.r2[2][1]);
				CTX[canvas].lineTo(tailP.r[1][0], tailP.r[1][1]);
				CTX[canvas].lineTo(tailP.m[1][0], tailP.m[1][1]);
				CTX[canvas].lineTo(tailP.l[1][0], tailP.l[1][1]);
				CTX[canvas].lineTo(tailP.l2[2][0], tailP.l2[2][1]);
			} 
			else if(v5 == 4){ //Tritip
				CTX[canvas].moveTo(tailP.l2[3][0], tailP.l2[3][1]);	
				CTX[canvas].lineTo(tail[0], tail[1]);
				CTX[canvas].lineTo(tailP.r2[3][0], tailP.r2[3][1]);
				CTX[canvas].lineTo(tailP.r[2][0], tailP.r[2][1]);
				CTX[canvas].lineTo(tailP.m[3][0], tailP.m[3][1]);
				CTX[canvas].lineTo(tailP.l[2][0], tailP.l[2][1]);
			} 
			else if(v5 == 5){ //Fan Tail
				CTX[canvas].moveTo(tailP.l3[2][0], tailP.l3[2][1]);	
				CTX[canvas].lineTo(tail[0], tail[1]);
				CTX[canvas].lineTo(tailP.r3[2][0], tailP.r3[2][1]);
				CTX[canvas].lineTo(tailP.r2[2][0], tailP.r2[2][1]);
				CTX[canvas].lineTo(tailP.r[2][0], tailP.r[2][1]);
				CTX[canvas].lineTo(tailP.m[2][0], tailP.m[2][1]);
				CTX[canvas].lineTo(tailP.l[2][0], tailP.l[2][1]);
				CTX[canvas].lineTo(tailP.l2[2][0], tailP.l2[2][1]);
			} 
			else if(v5 == 6){ //Sideways Double Fin
				CTX[canvas].moveTo(tailP.l3[2][0], tailP.l3[2][1]);	
				CTX[canvas].lineTo(tail[0], tail[1]);
				CTX[canvas].lineTo(tailP.r3[2][0], tailP.r3[2][1]);
				CTX[canvas].lineTo(tailP.r2[0][0], tailP.r2[0][1]);
				CTX[canvas].lineTo(tailP.r[0][0], tailP.r[0][1]);
				CTX[canvas].lineTo(tailP.m[0][0], tailP.m[0][1]);
				CTX[canvas].lineTo(tailP.l[0][0], tailP.l[0][1]);
				CTX[canvas].lineTo(tailP.l2[0][0], tailP.l2[0][1]);
			}
			CTX[canvas].closePath();		
			CTX[canvas].stroke();	

			CTX[canvas].lineWidth = returnLW;
		}
		if(shape=="ghost"){ 
			//drawS(canvas, shape, SorF, x1, 		y1, 		r1, 			c1,			c2,		 c3,		v1, 		v2, 			v3, 				v4, 		v5, 		v6, v7, v8, v9, v10)
			//drawS("a", "ghost", fill, fish[i][0], fish[i][1], height/2, CTX.a.fillStyle, 0, vizStroke/3, fish.td[i], 180+fish.d[i], Math.round(fish.f[i]), fish.sh.b[i], fish.sh.f[i]);
			var returnLW = CTX[canvas].lineWidth;
			CTX[canvas].lineWidth = c3;	
			var tSp = 128, fFrames = Math.round(tSp/2.666);
			var bl=2/3;	//  body length
			var fl=1/3;	//  fin length
			fl +=bl;
			
			if(c3 > 0 || SorF == "fill" || SorF == "F"){ // Can't set stroke width to 0, so don't draw lines instead when 0
				//Body
				CTX[canvas].beginPath();
				CTX[canvas].moveTo(x1-r1, y1+r1*bl);	
				CTX[canvas].lineTo(x1-r1, y1);	
				CTX[canvas].arc(x1,y1,r1,1*Math.PI,2*Math.PI);
				CTX[canvas].lineTo(x1+r1, y1+r1*bl);

				//Bottom Fins
				if(v3 < fFrames *1/8 || (v3 > fFrames *2/8 && v3 < fFrames *3/8 ) || (v3 > fFrames *4/8 && v3 < fFrames *5/8 ) || (v3 > fFrames *6/8 && v3 < fFrames *7/8 )  ){		//Frame 1
					CTX[canvas].lineTo(x1+r1, y1+r1*fl);
					CTX[canvas].lineTo(x1+r1*2/3, y1+r1*bl);
					CTX[canvas].lineTo(x1+r1*1/3, y1+r1*fl);
					CTX[canvas].lineTo(x1+r1*1/6, y1+r1*fl);	
					CTX[canvas].lineTo(x1+r1*1/6, y1+r1*bl);	
					CTX[canvas].lineTo(x1-r1*1/6, y1+r1*bl);	
					CTX[canvas].lineTo(x1-r1*1/6, y1+r1*fl);				
					CTX[canvas].lineTo(x1-r1*1/3, y1+r1*fl);			
					CTX[canvas].lineTo(x1-r1*2/3, y1+r1*bl);			
					CTX[canvas].lineTo(x1-r1, y1+r1*fl);
				}
				else			{		//Frame 2
					CTX[canvas].lineTo(x1+r1*2/3, y1+r1*fl);
					CTX[canvas].lineTo(x1+r1*1/3, y1+r1*bl);
					CTX[canvas].lineTo(x1, y1+r1*fl);				
					CTX[canvas].lineTo(x1-r1*1/3, y1+r1*bl);			
					CTX[canvas].lineTo(x1-r1*2/3, y1+r1*fl);			
				}
				CTX[canvas].closePath();
				if(SorF == "fill" || SorF == "F") {CTX[canvas].fill();} else{CTX[canvas].stroke();}
			}
			CTX[canvas].lineWidth = returnLW;
			
			
			//  Eyes - Whites
			CTX[canvas].fillStyle = "#fff";	CTX[canvas].strokeStyle = "#fff";	
			var eye=[];
			eye.l = circPoint(x1-r1/3, y1-r1/3, r1*1/6, 155, 360, v2);
			eye.r = circPoint(x1+r1/3, y1-r1/3, r1*1/6, 155, 360, v2);
			eye.lp = circPoint(eye.l[0], eye.l[1], r1*1/8, 155, 360, v2);
			eye.rp = circPoint(eye.r[0], eye.r[1], r1*1/8, 155, 360, v2);
			CTX[canvas].beginPath();	CTX[canvas].arc(eye.l[0], eye.l[1], r1/4, 0*Math.PI, 2*Math.PI);	CTX[canvas].closePath();	CTX[canvas].fill();			
			CTX[canvas].beginPath();	CTX[canvas].arc(eye.r[0], eye.r[1], r1/4, 0*Math.PI, 2*Math.PI);	CTX[canvas].closePath();	CTX[canvas].fill();		
			//  Eyes - Pupils
			CTX[canvas].fillStyle = "#00f";	CTX[canvas].strokeStyle = "#00f";	
			CTX[canvas].beginPath();	CTX[canvas].arc(eye.lp[0], eye.lp[1], r1/8, 0*Math.PI, 2*Math.PI);	CTX[canvas].closePath();	CTX[canvas].fill();			
			CTX[canvas].beginPath();	CTX[canvas].arc(eye.rp[0], eye.rp[1], r1/8, 0*Math.PI, 2*Math.PI);	CTX[canvas].closePath();	CTX[canvas].fill();		
		}
		//DebugDisplay2.textContent = c1;		
	}
}


window.onload = function() {
    parent = document.getElementById('AudioCanvasParent');
	
    CAN.a	= document.getElementById('AudioCanvas');		CTX.a	= CAN.a.getContext('2d');
	CAN.agl	= document.getElementById('AudioCanvasGL');		gl = CTX['agl'] = CAN.agl.getContext('webgl', {premultipliedAlpha: false});	
    CAN.vu	= document.getElementById('VuCanvas');			CTX.vu	= CAN.vu.getContext('2d');
	CAN.b	= document.getElementById('BgCanvas');			CTX.b	= CAN.b.getContext('2d');
	CAN.rp	= document.getElementById('RPatCanvas');		CTX.rp	= CAN.rp.getContext('2d');
	CAN.rd	= document.getElementById('RDropCanvas');		CTX.rd	= CAN.rd.getContext('2d'); 
	CAN.r	= document.getElementById('RainCanvas');		CTX.r	= CAN.r.getContext('2d');
	CAN.c	= document.getElementById('ClockCanvas');		CTX.c	= CAN.c.getContext('2d');
	CAN.cb	= document.getElementById('ClockBgCanvas');		CTX.cb	= CAN.cb.getContext('2d');
	CAN.w	= document.getElementById('WeatherCanvas');		CTX.w	= CAN.w.getContext('2d');
	
	bgDisplay	= document.getElementById('MGdiv');
	bgImg		= document.getElementById('bgIMG');
	vidBox		= document.getElementById('VideoBox');
	//tubeBox	= document.getElementById('YoutubeDiv');
	

    window.wallpaperRegisterAudioListener(wallpaperAudioListener);
	
    window.requestAnimationFrame(run);
    onWindowResized();
};

window.onresize = onWindowResized;
