package com.domemusictechnologies.microstringer;


import voltage.controllers.*;
import voltage.core.*;
import voltage.core.Jack.JackType;
import voltage.sources.*;
import voltage.utility.*;
import voltage.processors.*;
import voltage.effects.*;
import java.awt.*;

//[user-imports]   Add your own imports here

import static java.lang.Math.floor;

//[/user-imports]


public class MicroStringer extends VoltageModule
//[user-inheritance]
//[/user-inheritance]
{

public MicroStringer( long moduleID, VoltageObjects voltageObjects )
{
   super( moduleID, voltageObjects, "Micro Stringer", ModuleType.ModuleType_Instruments, 1.0 );

   InitializeControls();


   canBeBypassed = false;
   SetSkin( "25b972dca7d9413f8cd4891e52b3ef0d" );
}

void InitializeControls()
{

   line4 = new VoltageLine( "line4", "line4", this );
   AddComponent( line4 );
   line4.SetWantsMouseNotifications( false );
   line4.SetLineColor( new Color( 255, 237, 0, 255 ) );
   line4.SetLineWidth( (float)0.5 );
   line4.SetStartPosition( 61, 235 );
   line4.SetEndPosition( 56, 235 );
   line4.SetHasArrow( false );
   line4.SetArrowWidth( (float)8 );
   line4.SetArrowLength( (float)12 );

   line3 = new VoltageLine( "line3", "line3", this );
   AddComponent( line3 );
   line3.SetWantsMouseNotifications( false );
   line3.SetLineColor( new Color( 255, 237, 0, 255 ) );
   line3.SetLineWidth( (float)0.5 );
   line3.SetStartPosition( 67, 246 );
   line3.SetEndPosition( 61, 235 );
   line3.SetHasArrow( false );
   line3.SetArrowWidth( (float)8 );
   line3.SetArrowLength( (float)12 );

   line2 = new VoltageLine( "line2", "line2", this );
   AddComponent( line2 );
   line2.SetWantsMouseNotifications( false );
   line2.SetLineColor( new Color( 255, 237, 0, 255 ) );
   line2.SetLineWidth( (float)0.5 );
   line2.SetStartPosition( 51, 246 );
   line2.SetEndPosition( 56, 235 );
   line2.SetHasArrow( false );
   line2.SetArrowWidth( (float)8 );
   line2.SetArrowLength( (float)12 );

   line1 = new VoltageLine( "line1", "line1", this );
   AddComponent( line1 );
   line1.SetWantsMouseNotifications( false );
   line1.SetLineColor( new Color( 255, 237, 0, 255 ) );
   line1.SetLineWidth( (float)0.5 );
   line1.SetStartPosition( 10, 235 );
   line1.SetEndPosition( 19, 246 );
   line1.SetHasArrow( false );
   line1.SetArrowWidth( (float)8 );
   line1.SetArrowLength( (float)12 );

   line0 = new VoltageLine( "line0", "line0", this );
   AddComponent( line0 );
   line0.SetWantsMouseNotifications( false );
   line0.SetLineColor( new Color( 255, 237, 0, 255 ) );
   line0.SetLineWidth( (float)0.5 );
   line0.SetStartPosition( 6, 246 );
   line0.SetEndPosition( 10, 235 );
   line0.SetHasArrow( false );
   line0.SetArrowWidth( (float)8 );
   line0.SetArrowLength( (float)12 );

   polyInputJackPitch = new VoltagePolyJack( "Poly Pitch Input", "Poly Pitch Input", this, JackType.JackType_PolyInput );
   AddComponent( polyInputJackPitch );
   polyInputJackPitch.SetWantsMouseNotifications( false );
   polyInputJackPitch.SetPosition( 5, 48 );
   polyInputJackPitch.SetSize( 25, 25 );
   polyInputJackPitch.SetSkin( "Poly Jack Straight" );

   polyInputJackGate = new VoltagePolyJack( "Poly Gate Input", "Poly Gate Input", this, JackType.JackType_PolyInput );
   AddComponent( polyInputJackGate );
   polyInputJackGate.SetWantsMouseNotifications( false );
   polyInputJackGate.SetPosition( 41, 48 );
   polyInputJackGate.SetSize( 25, 25 );
   polyInputJackGate.SetSkin( "Poly Jack Straight" );

   outputJack = new VoltageAudioJack( "Output", "Output", this, JackType.JackType_AudioOutput );
   AddComponent( outputJack );
   outputJack.SetWantsMouseNotifications( false );
   outputJack.SetPosition( 42, 302 );
   outputJack.SetSize( 25, 25 );
   outputJack.SetSkin( "Jack Round Cherry Ring" );

   knobSemitone = new VoltageKnob( "Pitch Semitone", "Pitch Semitone", this, -12, 12, 0 );
   AddComponent( knobSemitone );
   knobSemitone.SetWantsMouseNotifications( false );
   knobSemitone.SetPosition( 4, 138 );
   knobSemitone.SetSize( 27, 27 );
   knobSemitone.SetSkin( "Plastic Yellow" );
   knobSemitone.SetRange( -12, 12, 0, false, 25 );
   knobSemitone.SetKnobParams( 215, 145 );
   knobSemitone.DisplayValueInPercent( false );
   knobSemitone.SetKnobAdjustsRing( true );

   textLabel1 = new VoltageLabel( "textLabel1", "textLabel1", this, "Poly Inputs" );
   AddComponent( textLabel1 );
   textLabel1.SetWantsMouseNotifications( false );
   textLabel1.SetPosition( 0, 29 );
   textLabel1.SetSize( 71, 20 );
   textLabel1.SetEditable( false, false );
   textLabel1.SetJustificationFlags( VoltageLabel.Justification.HorizCentered );
   textLabel1.SetJustificationFlags( VoltageLabel.Justification.VertCentered );
   textLabel1.SetColor( new Color( 149, 81, 0, 255 ) );
   textLabel1.SetBkColor( new Color( 65, 65, 65, 0 ) );
   textLabel1.SetBorderColor( new Color( 0, 0, 0, 0 ) );
   textLabel1.SetBorderSize( 1 );
   textLabel1.SetMultiLineEdit( false );
   textLabel1.SetIsNumberEditor( false );
   textLabel1.SetNumberEditorRange( 0, 100 );
   textLabel1.SetNumberEditorInterval( 1 );
   textLabel1.SetNumberEditorUsesMouseWheel( false );
   textLabel1.SetHasCustomTextHoverColor( false );
   textLabel1.SetTextHoverColor( new Color( 0, 0, 0, 255 ) );
   textLabel1.SetFont( "Verdana", 12, false, false );

   textLabel2 = new VoltageLabel( "textLabel2", "textLabel2", this, "Pitch" );
   AddComponent( textLabel2 );
   textLabel2.SetWantsMouseNotifications( false );
   textLabel2.SetPosition( 0, 71 );
   textLabel2.SetSize( 34, 17 );
   textLabel2.SetEditable( false, false );
   textLabel2.SetJustificationFlags( VoltageLabel.Justification.HorizCentered );
   textLabel2.SetJustificationFlags( VoltageLabel.Justification.VertCentered );
   textLabel2.SetColor( new Color( 110, 60, 0, 255 ) );
   textLabel2.SetBkColor( new Color( 65, 65, 65, 0 ) );
   textLabel2.SetBorderColor( new Color( 0, 0, 0, 0 ) );
   textLabel2.SetBorderSize( 1 );
   textLabel2.SetMultiLineEdit( false );
   textLabel2.SetIsNumberEditor( false );
   textLabel2.SetNumberEditorRange( 0, 100 );
   textLabel2.SetNumberEditorInterval( 1 );
   textLabel2.SetNumberEditorUsesMouseWheel( false );
   textLabel2.SetHasCustomTextHoverColor( false );
   textLabel2.SetTextHoverColor( new Color( 0, 0, 0, 255 ) );
   textLabel2.SetFont( "Verdana", 12, false, false );

   textLabel3 = new VoltageLabel( "textLabel3", "textLabel3", this, "Gate" );
   AddComponent( textLabel3 );
   textLabel3.SetWantsMouseNotifications( false );
   textLabel3.SetPosition( 37, 71 );
   textLabel3.SetSize( 33, 17 );
   textLabel3.SetEditable( false, false );
   textLabel3.SetJustificationFlags( VoltageLabel.Justification.HorizCentered );
   textLabel3.SetJustificationFlags( VoltageLabel.Justification.VertCentered );
   textLabel3.SetColor( new Color( 110, 60, 0, 255 ) );
   textLabel3.SetBkColor( new Color( 65, 65, 65, 0 ) );
   textLabel3.SetBorderColor( new Color( 0, 0, 0, 0 ) );
   textLabel3.SetBorderSize( 1 );
   textLabel3.SetMultiLineEdit( false );
   textLabel3.SetIsNumberEditor( false );
   textLabel3.SetNumberEditorRange( 0, 100 );
   textLabel3.SetNumberEditorInterval( 1 );
   textLabel3.SetNumberEditorUsesMouseWheel( false );
   textLabel3.SetHasCustomTextHoverColor( false );
   textLabel3.SetTextHoverColor( new Color( 0, 0, 0, 255 ) );
   textLabel3.SetFont( "Verdana", 12, false, false );

   textLabel4 = new VoltageLabel( "textLabel4", "textLabel4", this, "Micro Stringer" );
   AddComponent( textLabel4 );
   textLabel4.SetWantsMouseNotifications( false );
   textLabel4.SetPosition( 4, 0 );
   textLabel4.SetSize( 64, 30 );
   textLabel4.SetEditable( false, false );
   textLabel4.SetJustificationFlags( VoltageLabel.Justification.HorizCentered );
   textLabel4.SetJustificationFlags( VoltageLabel.Justification.VertCentered );
   textLabel4.SetColor( new Color( 145, 49, 0, 255 ) );
   textLabel4.SetBkColor( new Color( 65, 65, 65, 0 ) );
   textLabel4.SetBorderColor( new Color( 0, 0, 0, 0 ) );
   textLabel4.SetBorderSize( 1 );
   textLabel4.SetMultiLineEdit( true );
   textLabel4.SetIsNumberEditor( false );
   textLabel4.SetNumberEditorRange( 0, 100 );
   textLabel4.SetNumberEditorInterval( 1 );
   textLabel4.SetNumberEditorUsesMouseWheel( false );
   textLabel4.SetHasCustomTextHoverColor( false );
   textLabel4.SetTextHoverColor( new Color( 0, 0, 0, 255 ) );
   textLabel4.SetFont( "Verdana", 14, true, false );

   switchOctave = new VoltageSwitch( "Octave Switch", "Octave Switch", this, 0 );
   AddComponent( switchOctave );
   switchOctave.SetWantsMouseNotifications( false );
   switchOctave.SetPosition( 28, 93 );
   switchOctave.SetSize( 35, 35 );
   switchOctave.SetSkin( "3-State Bar Vertical" );

   textLabel5 = new VoltageLabel( "textLabel5", "textLabel5", this, "8'" );
   AddComponent( textLabel5 );
   textLabel5.SetWantsMouseNotifications( false );
   textLabel5.SetPosition( 54, 89 );
   textLabel5.SetSize( 18, 16 );
   textLabel5.SetEditable( false, false );
   textLabel5.SetJustificationFlags( VoltageLabel.Justification.HorizCentered );
   textLabel5.SetJustificationFlags( VoltageLabel.Justification.VertCentered );
   textLabel5.SetColor( new Color( 93, 51, 0, 255 ) );
   textLabel5.SetBkColor( new Color( 65, 65, 65, 0 ) );
   textLabel5.SetBorderColor( new Color( 0, 0, 0, 0 ) );
   textLabel5.SetBorderSize( 1 );
   textLabel5.SetMultiLineEdit( false );
   textLabel5.SetIsNumberEditor( false );
   textLabel5.SetNumberEditorRange( 0, 100 );
   textLabel5.SetNumberEditorInterval( 1 );
   textLabel5.SetNumberEditorUsesMouseWheel( false );
   textLabel5.SetHasCustomTextHoverColor( false );
   textLabel5.SetTextHoverColor( new Color( 0, 0, 0, 255 ) );
   textLabel5.SetFont( "Verdana", 10, false, false );

   textLabel6 = new VoltageLabel( "textLabel6", "textLabel6", this, "16'" );
   AddComponent( textLabel6 );
   textLabel6.SetWantsMouseNotifications( false );
   textLabel6.SetPosition( 53, 102 );
   textLabel6.SetSize( 18, 17 );
   textLabel6.SetEditable( false, false );
   textLabel6.SetJustificationFlags( VoltageLabel.Justification.HorizCentered );
   textLabel6.SetJustificationFlags( VoltageLabel.Justification.VertCentered );
   textLabel6.SetColor( new Color( 93, 51, 0, 255 ) );
   textLabel6.SetBkColor( new Color( 65, 65, 65, 0 ) );
   textLabel6.SetBorderColor( new Color( 0, 0, 0, 0 ) );
   textLabel6.SetBorderSize( 1 );
   textLabel6.SetMultiLineEdit( false );
   textLabel6.SetIsNumberEditor( false );
   textLabel6.SetNumberEditorRange( 0, 100 );
   textLabel6.SetNumberEditorInterval( 1 );
   textLabel6.SetNumberEditorUsesMouseWheel( false );
   textLabel6.SetHasCustomTextHoverColor( false );
   textLabel6.SetTextHoverColor( new Color( 0, 0, 0, 255 ) );
   textLabel6.SetFont( "Verdana", 10, false, false );

   textLabel7 = new VoltageLabel( "textLabel7", "textLabel7", this, "32'" );
   AddComponent( textLabel7 );
   textLabel7.SetWantsMouseNotifications( false );
   textLabel7.SetPosition( 52, 115 );
   textLabel7.SetSize( 20, 18 );
   textLabel7.SetEditable( false, false );
   textLabel7.SetJustificationFlags( VoltageLabel.Justification.HorizCentered );
   textLabel7.SetJustificationFlags( VoltageLabel.Justification.VertCentered );
   textLabel7.SetColor( new Color( 93, 51, 0, 255 ) );
   textLabel7.SetBkColor( new Color( 65, 65, 65, 0 ) );
   textLabel7.SetBorderColor( new Color( 0, 0, 0, 0 ) );
   textLabel7.SetBorderSize( 1 );
   textLabel7.SetMultiLineEdit( false );
   textLabel7.SetIsNumberEditor( false );
   textLabel7.SetNumberEditorRange( 0, 100 );
   textLabel7.SetNumberEditorInterval( 1 );
   textLabel7.SetNumberEditorUsesMouseWheel( false );
   textLabel7.SetHasCustomTextHoverColor( false );
   textLabel7.SetTextHoverColor( new Color( 0, 0, 0, 255 ) );
   textLabel7.SetFont( "Verdana", 10, false, false );

   textLabel17 = new VoltageLabel( "textLabel17", "textLabel17", this, "Off" );
   AddComponent( textLabel17 );
   textLabel17.SetWantsMouseNotifications( false );
   textLabel17.SetPosition( 15, 114 );
   textLabel17.SetSize( 19, 18 );
   textLabel17.SetEditable( false, false );
   textLabel17.SetJustificationFlags( VoltageLabel.Justification.HorizCentered );
   textLabel17.SetJustificationFlags( VoltageLabel.Justification.VertCentered );
   textLabel17.SetColor( new Color( 93, 51, 0, 255 ) );
   textLabel17.SetBkColor( new Color( 65, 65, 65, 0 ) );
   textLabel17.SetBorderColor( new Color( 0, 0, 0, 0 ) );
   textLabel17.SetBorderSize( 1 );
   textLabel17.SetMultiLineEdit( false );
   textLabel17.SetIsNumberEditor( false );
   textLabel17.SetNumberEditorRange( 0, 100 );
   textLabel17.SetNumberEditorInterval( 1 );
   textLabel17.SetNumberEditorUsesMouseWheel( false );
   textLabel17.SetHasCustomTextHoverColor( false );
   textLabel17.SetTextHoverColor( new Color( 0, 0, 0, 255 ) );
   textLabel17.SetFont( "Verdana", 10, false, false );

   textLabel18 = new VoltageLabel( "textLabel18", "textLabel18", this, "Chr" );
   AddComponent( textLabel18 );
   textLabel18.SetWantsMouseNotifications( false );
   textLabel18.SetPosition( 17, 101 );
   textLabel18.SetSize( 17, 18 );
   textLabel18.SetEditable( false, false );
   textLabel18.SetJustificationFlags( VoltageLabel.Justification.HorizCentered );
   textLabel18.SetJustificationFlags( VoltageLabel.Justification.VertCentered );
   textLabel18.SetColor( new Color( 93, 51, 0, 255 ) );
   textLabel18.SetBkColor( new Color( 65, 65, 65, 0 ) );
   textLabel18.SetBorderColor( new Color( 0, 0, 0, 0 ) );
   textLabel18.SetBorderSize( 1 );
   textLabel18.SetMultiLineEdit( false );
   textLabel18.SetIsNumberEditor( false );
   textLabel18.SetNumberEditorRange( 0, 100 );
   textLabel18.SetNumberEditorInterval( 1 );
   textLabel18.SetNumberEditorUsesMouseWheel( false );
   textLabel18.SetHasCustomTextHoverColor( false );
   textLabel18.SetTextHoverColor( new Color( 0, 0, 0, 255 ) );
   textLabel18.SetFont( "Verdana", 10, false, false );

   textLabel19 = new VoltageLabel( "textLabel19", "textLabel19", this, "Ens" );
   AddComponent( textLabel19 );
   textLabel19.SetWantsMouseNotifications( false );
   textLabel19.SetPosition( 17, 89 );
   textLabel19.SetSize( 17, 18 );
   textLabel19.SetEditable( false, false );
   textLabel19.SetJustificationFlags( VoltageLabel.Justification.HorizCentered );
   textLabel19.SetJustificationFlags( VoltageLabel.Justification.VertCentered );
   textLabel19.SetColor( new Color( 93, 51, 0, 255 ) );
   textLabel19.SetBkColor( new Color( 65, 65, 65, 0 ) );
   textLabel19.SetBorderColor( new Color( 0, 0, 0, 0 ) );
   textLabel19.SetBorderSize( 1 );
   textLabel19.SetMultiLineEdit( false );
   textLabel19.SetIsNumberEditor( false );
   textLabel19.SetNumberEditorRange( 0, 100 );
   textLabel19.SetNumberEditorInterval( 1 );
   textLabel19.SetNumberEditorUsesMouseWheel( false );
   textLabel19.SetHasCustomTextHoverColor( false );
   textLabel19.SetTextHoverColor( new Color( 0, 0, 0, 255 ) );
   textLabel19.SetFont( "Verdana", 10, false, false );

   textLabel8 = new VoltageLabel( "textLabel8", "textLabel8", this, "Semi" );
   AddComponent( textLabel8 );
   textLabel8.SetWantsMouseNotifications( false );
   textLabel8.SetPosition( 1, 162 );
   textLabel8.SetSize( 34, 17 );
   textLabel8.SetEditable( false, false );
   textLabel8.SetJustificationFlags( VoltageLabel.Justification.HorizCentered );
   textLabel8.SetJustificationFlags( VoltageLabel.Justification.VertCentered );
   textLabel8.SetColor( new Color( 102, 56, 0, 255 ) );
   textLabel8.SetBkColor( new Color( 65, 65, 65, 0 ) );
   textLabel8.SetBorderColor( new Color( 0, 0, 0, 0 ) );
   textLabel8.SetBorderSize( 1 );
   textLabel8.SetMultiLineEdit( false );
   textLabel8.SetIsNumberEditor( false );
   textLabel8.SetNumberEditorRange( 0, 100 );
   textLabel8.SetNumberEditorInterval( 1 );
   textLabel8.SetNumberEditorUsesMouseWheel( false );
   textLabel8.SetHasCustomTextHoverColor( false );
   textLabel8.SetTextHoverColor( new Color( 0, 0, 0, 255 ) );
   textLabel8.SetFont( "Verdana", 12, false, false );

   knobFine = new VoltageKnob( "Fine Tune", "Fine Tune", this, -1, 1.0, 0 );
   AddComponent( knobFine );
   knobFine.SetWantsMouseNotifications( false );
   knobFine.SetPosition( 41, 138 );
   knobFine.SetSize( 27, 27 );
   knobFine.SetSkin( "Plastic Yellow" );
   knobFine.SetRange( -1, 1.0, 0, false, 0 );
   knobFine.SetKnobParams( 215, 145 );
   knobFine.DisplayValueInPercent( false );
   knobFine.SetKnobAdjustsRing( true );

   textLabel9 = new VoltageLabel( "textLabel9", "textLabel9", this, "Fine" );
   AddComponent( textLabel9 );
   textLabel9.SetWantsMouseNotifications( false );
   textLabel9.SetPosition( 39, 162 );
   textLabel9.SetSize( 32, 17 );
   textLabel9.SetEditable( false, false );
   textLabel9.SetJustificationFlags( VoltageLabel.Justification.HorizCentered );
   textLabel9.SetJustificationFlags( VoltageLabel.Justification.VertCentered );
   textLabel9.SetColor( new Color( 102, 56, 0, 255 ) );
   textLabel9.SetBkColor( new Color( 65, 65, 65, 0 ) );
   textLabel9.SetBorderColor( new Color( 0, 0, 0, 0 ) );
   textLabel9.SetBorderSize( 1 );
   textLabel9.SetMultiLineEdit( false );
   textLabel9.SetIsNumberEditor( false );
   textLabel9.SetNumberEditorRange( 0, 100 );
   textLabel9.SetNumberEditorInterval( 1 );
   textLabel9.SetNumberEditorUsesMouseWheel( false );
   textLabel9.SetHasCustomTextHoverColor( false );
   textLabel9.SetTextHoverColor( new Color( 0, 0, 0, 255 ) );
   textLabel9.SetFont( "Verdana", 12, false, false );

   knobVolume = new VoltageKnob( "Volume", "Volume", this, 0.0, 2.0, 1.0 );
   AddComponent( knobVolume );
   knobVolume.SetWantsMouseNotifications( false );
   knobVolume.SetPosition( 4, 301 );
   knobVolume.SetSize( 27, 27 );
   knobVolume.SetSkin( "Plastic Maroon" );
   knobVolume.SetRange( 0.0, 2.0, 1.0, false, 0 );
   knobVolume.SetKnobParams( 215, 145 );
   knobVolume.DisplayValueInPercent( true );
   knobVolume.SetKnobAdjustsRing( true );

   textLabel10 = new VoltageLabel( "textLabel10", "textLabel10", this, "Vol" );
   AddComponent( textLabel10 );
   textLabel10.SetWantsMouseNotifications( false );
   textLabel10.SetPosition( 1, 325 );
   textLabel10.SetSize( 31, 17 );
   textLabel10.SetEditable( false, false );
   textLabel10.SetJustificationFlags( VoltageLabel.Justification.HorizCentered );
   textLabel10.SetJustificationFlags( VoltageLabel.Justification.VertCentered );
   textLabel10.SetColor( new Color( 122, 0, 0, 255 ) );
   textLabel10.SetBkColor( new Color( 65, 65, 65, 0 ) );
   textLabel10.SetBorderColor( new Color( 0, 0, 0, 0 ) );
   textLabel10.SetBorderSize( 1 );
   textLabel10.SetMultiLineEdit( false );
   textLabel10.SetIsNumberEditor( false );
   textLabel10.SetNumberEditorRange( 0, 100 );
   textLabel10.SetNumberEditorInterval( 1 );
   textLabel10.SetNumberEditorUsesMouseWheel( false );
   textLabel10.SetHasCustomTextHoverColor( false );
   textLabel10.SetTextHoverColor( new Color( 0, 0, 0, 255 ) );
   textLabel10.SetFont( "Verdana", 12, false, false );

   textLabel11 = new VoltageLabel( "textLabel11", "textLabel11", this, "Out" );
   AddComponent( textLabel11 );
   textLabel11.SetWantsMouseNotifications( false );
   textLabel11.SetPosition( 38, 325 );
   textLabel11.SetSize( 30, 17 );
   textLabel11.SetEditable( false, false );
   textLabel11.SetJustificationFlags( VoltageLabel.Justification.HorizCentered );
   textLabel11.SetJustificationFlags( VoltageLabel.Justification.VertCentered );
   textLabel11.SetColor( new Color( 255, 183, 0, 255 ) );
   textLabel11.SetBkColor( new Color( 65, 65, 65, 0 ) );
   textLabel11.SetBorderColor( new Color( 0, 0, 0, 0 ) );
   textLabel11.SetBorderSize( 1 );
   textLabel11.SetMultiLineEdit( false );
   textLabel11.SetIsNumberEditor( false );
   textLabel11.SetNumberEditorRange( 0, 100 );
   textLabel11.SetNumberEditorInterval( 1 );
   textLabel11.SetNumberEditorUsesMouseWheel( false );
   textLabel11.SetHasCustomTextHoverColor( false );
   textLabel11.SetTextHoverColor( new Color( 0, 0, 0, 255 ) );
   textLabel11.SetFont( "Verdana", 12, false, false );

   knobAttack = new VoltageKnob( "Attack Time", "Attack Time", this, 0.0, 20, 0.02 );
   AddComponent( knobAttack );
   knobAttack.SetWantsMouseNotifications( false );
   knobAttack.SetPosition( 4, 252 );
   knobAttack.SetSize( 27, 27 );
   knobAttack.SetSkin( "Plastic Red" );
   knobAttack.SetRange( 0.0, 20, 0.02, false, 0 );
   knobAttack.SetKnobParams( 215, 145 );
   knobAttack.DisplayValueInPercent( false );
   knobAttack.SetKnobAdjustsRing( true );
   knobAttack.SetMidpointValue( 1 );

   textLabel12 = new VoltageLabel( "textLabel12", "textLabel12", this, "Attack" );
   AddComponent( textLabel12 );
   textLabel12.SetWantsMouseNotifications( false );
   textLabel12.SetPosition( 1, 276 );
   textLabel12.SetSize( 35, 17 );
   textLabel12.SetEditable( false, false );
   textLabel12.SetJustificationFlags( VoltageLabel.Justification.HorizCentered );
   textLabel12.SetJustificationFlags( VoltageLabel.Justification.VertCentered );
   textLabel12.SetColor( new Color( 255, 183, 0, 255 ) );
   textLabel12.SetBkColor( new Color( 65, 65, 65, 0 ) );
   textLabel12.SetBorderColor( new Color( 0, 0, 0, 0 ) );
   textLabel12.SetBorderSize( 1 );
   textLabel12.SetMultiLineEdit( false );
   textLabel12.SetIsNumberEditor( false );
   textLabel12.SetNumberEditorRange( 0, 100 );
   textLabel12.SetNumberEditorInterval( 1 );
   textLabel12.SetNumberEditorUsesMouseWheel( false );
   textLabel12.SetHasCustomTextHoverColor( false );
   textLabel12.SetTextHoverColor( new Color( 0, 0, 0, 255 ) );
   textLabel12.SetFont( "Verdana", 12, false, false );

   knobDecay = new VoltageKnob( "Decay Time", "Decay Time", this, 0.0, 20, 3 );
   AddComponent( knobDecay );
   knobDecay.SetWantsMouseNotifications( false );
   knobDecay.SetPosition( 41, 252 );
   knobDecay.SetSize( 27, 27 );
   knobDecay.SetSkin( "Plastic Red" );
   knobDecay.SetRange( 0.0, 20, 3, false, 0 );
   knobDecay.SetKnobParams( 215, 145 );
   knobDecay.DisplayValueInPercent( false );
   knobDecay.SetKnobAdjustsRing( true );
   knobDecay.SetMidpointValue( 1 );

   textLabel13 = new VoltageLabel( "textLabel13", "textLabel13", this, "Decay" );
   AddComponent( textLabel13 );
   textLabel13.SetWantsMouseNotifications( false );
   textLabel13.SetPosition( 35, 276 );
   textLabel13.SetSize( 36, 17 );
   textLabel13.SetEditable( false, false );
   textLabel13.SetJustificationFlags( VoltageLabel.Justification.HorizCentered );
   textLabel13.SetJustificationFlags( VoltageLabel.Justification.VertCentered );
   textLabel13.SetColor( new Color( 255, 183, 0, 255 ) );
   textLabel13.SetBkColor( new Color( 65, 65, 65, 0 ) );
   textLabel13.SetBorderColor( new Color( 0, 0, 0, 0 ) );
   textLabel13.SetBorderSize( 1 );
   textLabel13.SetMultiLineEdit( false );
   textLabel13.SetIsNumberEditor( false );
   textLabel13.SetNumberEditorRange( 0, 100 );
   textLabel13.SetNumberEditorInterval( 1 );
   textLabel13.SetNumberEditorUsesMouseWheel( false );
   textLabel13.SetHasCustomTextHoverColor( false );
   textLabel13.SetTextHoverColor( new Color( 0, 0, 0, 255 ) );
   textLabel13.SetFont( "Verdana", 12, false, false );

   textLabel14 = new VoltageLabel( "textLabel14", "textLabel14", this, "Dome Music Technologies" );
   AddComponent( textLabel14 );
   textLabel14.SetWantsMouseNotifications( false );
   textLabel14.SetPosition( 12, 342 );
   textLabel14.SetSize( 48, 18 );
   textLabel14.SetEditable( false, false );
   textLabel14.SetJustificationFlags( VoltageLabel.Justification.HorizCentered );
   textLabel14.SetJustificationFlags( VoltageLabel.Justification.VertCentered );
   textLabel14.SetColor( new Color( 251, 173, 78, 255 ) );
   textLabel14.SetBkColor( new Color( 65, 65, 65, 0 ) );
   textLabel14.SetBorderColor( new Color( 0, 0, 0, 0 ) );
   textLabel14.SetBorderSize( 1 );
   textLabel14.SetMultiLineEdit( true );
   textLabel14.SetIsNumberEditor( false );
   textLabel14.SetNumberEditorRange( 0, 100 );
   textLabel14.SetNumberEditorInterval( 1 );
   textLabel14.SetNumberEditorUsesMouseWheel( false );
   textLabel14.SetHasCustomTextHoverColor( false );
   textLabel14.SetTextHoverColor( new Color( 0, 0, 0, 255 ) );
   textLabel14.SetFont( "Verdana", 7, false, false );

   textLabel15 = new VoltageLabel( "textLabel15", "textLabel15", this, "CV In" );
   AddComponent( textLabel15 );
   textLabel15.SetWantsMouseNotifications( false );
   textLabel15.SetPosition( 0, 207 );
   textLabel15.SetSize( 35, 17 );
   textLabel15.SetEditable( false, false );
   textLabel15.SetJustificationFlags( VoltageLabel.Justification.HorizCentered );
   textLabel15.SetJustificationFlags( VoltageLabel.Justification.VertCentered );
   textLabel15.SetColor( new Color( 255, 237, 0, 255 ) );
   textLabel15.SetBkColor( new Color( 65, 65, 65, 0 ) );
   textLabel15.SetBorderColor( new Color( 0, 0, 0, 0 ) );
   textLabel15.SetBorderSize( 1 );
   textLabel15.SetMultiLineEdit( false );
   textLabel15.SetIsNumberEditor( false );
   textLabel15.SetNumberEditorRange( 0, 100 );
   textLabel15.SetNumberEditorInterval( 1 );
   textLabel15.SetNumberEditorUsesMouseWheel( false );
   textLabel15.SetHasCustomTextHoverColor( false );
   textLabel15.SetTextHoverColor( new Color( 0, 0, 0, 255 ) );
   textLabel15.SetFont( "Verdana", 12, false, false );

   knobPitchMod = new VoltageKnob( "Pitch Mod Depth", "Pitch Mod Depth", this, 0.0, 12, 0 );
   AddComponent( knobPitchMod );
   knobPitchMod.SetWantsMouseNotifications( false );
   knobPitchMod.SetPosition( 41, 183 );
   knobPitchMod.SetSize( 27, 27 );
   knobPitchMod.SetSkin( "Plastic Orange" );
   knobPitchMod.SetRange( 0.0, 12, 0, false, 0 );
   knobPitchMod.SetKnobParams( 215, 145 );
   knobPitchMod.DisplayValueInPercent( false );
   knobPitchMod.SetKnobAdjustsRing( true );
   knobPitchMod.SetMidpointValue( 2 );

   textLabel16 = new VoltageLabel( "textLabel16", "textLabel16", this, "Depth" );
   AddComponent( textLabel16 );
   textLabel16.SetWantsMouseNotifications( false );
   textLabel16.SetPosition( 36, 207 );
   textLabel16.SetSize( 36, 17 );
   textLabel16.SetEditable( false, false );
   textLabel16.SetJustificationFlags( VoltageLabel.Justification.HorizCentered );
   textLabel16.SetJustificationFlags( VoltageLabel.Justification.VertCentered );
   textLabel16.SetColor( new Color( 255, 237, 0, 255 ) );
   textLabel16.SetBkColor( new Color( 65, 65, 65, 0 ) );
   textLabel16.SetBorderColor( new Color( 0, 0, 0, 0 ) );
   textLabel16.SetBorderSize( 1 );
   textLabel16.SetMultiLineEdit( false );
   textLabel16.SetIsNumberEditor( false );
   textLabel16.SetNumberEditorRange( 0, 100 );
   textLabel16.SetNumberEditorInterval( 1 );
   textLabel16.SetNumberEditorUsesMouseWheel( false );
   textLabel16.SetHasCustomTextHoverColor( false );
   textLabel16.SetTextHoverColor( new Color( 0, 0, 0, 255 ) );
   textLabel16.SetFont( "Verdana", 12, false, false );

   switchSustain = new VoltageSwitch( "Sustain Switch", "Sustain Switch", this, 1 );
   AddComponent( switchSustain );
   switchSustain.SetWantsMouseNotifications( false );
   switchSustain.SetPosition( 22, 233 );
   switchSustain.SetSize( 27, 15 );
   switchSustain.SetSkin( "2-State Slide Horizontal" );

   inputJackCV = new VoltageAudioJack( "Pitch CV Input", "Pitch CV Input", this, JackType.JackType_AudioInput );
   AddComponent( inputJackCV );
   inputJackCV.SetWantsMouseNotifications( false );
   inputJackCV.SetPosition( 5, 184 );
   inputJackCV.SetSize( 25, 25 );
   inputJackCV.SetSkin( "Jack Round Orange Ring" );

   switchEnsemble = new VoltageSwitch( "Chorus / Ensemble", "Chorus / Ensemble", this, 2 );
   AddComponent( switchEnsemble );
   switchEnsemble.SetWantsMouseNotifications( false );
   switchEnsemble.SetPosition( 3, 91 );
   switchEnsemble.SetSize( 15, 39 );
   switchEnsemble.SetSkin( "3-State Slide Vertical" );
}



//-------------------------------------------------------------------------------
//  public void Initialize()

//  Initialize will get called shortly after your module's constructor runs. You can use it to
//  do any initialization that the auto-generated code doesn't handle.
//-------------------------------------------------------------------------------
@Override
public void Initialize()
{
   //[user-Initialize]   Add your own initialization code here

   int i;
   
   for (i = 0; i < MAX_POLY_VOICES; i++)
   {
      channelOscillator[i] = new AnalogOscillator();
      channelEnvelope[i] = new ADSREnvelope();
      channelPitch[i] = -5.001f;
   }   
   
   pitchOffset = 0.0f;
   pitchMultiplier = 1.0f;
   ensembleSetting = EnsembleSetting.ENSEMBLE;

   ResetEnvelopesFrom (0);
   
   CheckConnections();
   
   // Set all variables to knob and switch values
   
   // Tuning / Transposition
   ReadOctaveSwitch(switchOctave.GetValue());
   ReadEnsembleSwitch(switchEnsemble.GetValue());
   ReadSemitoneKnob(knobSemitone.GetValue());
   ReadFineTuneKnob(knobFine.GetValue());
   
   // Envelope
   SetAttackTime(knobAttack.GetValue());
   SetDecayTime(knobDecay.GetValue());
   SetSustainLevel(switchSustain.GetValue());
   SetReleaseTime(knobDecay.GetValue());
   
   // Volume
   smoothLevel.SetValue(knobVolume.GetValue());
      
   SetPolyphony(GetNumberOfPolyVoices());
   
   // Ensemble
   
   RestartLFOs();
   
   delayWritePos = 0;   

   //[/user-Initialize]
}


//-------------------------------------------------------------------------------
//  public void Destroy()

//  Destroy will get called just before your module gets deleted. You can use it to perform any
//  cleanup that's not handled automatically by Java.
//-------------------------------------------------------------------------------
@Override
public void Destroy()
{
   super.Destroy();
   //[user-Destroy]   Add your own module-getting-deleted code here



   //[/user-Destroy]
}


//-------------------------------------------------------------------------------
//  public boolean Notify( VoltageComponent component, ModuleNotifications notification, double doubleValue, long longValue, int x, int y, Object object )

//  Notify will get called when various events occur - control values changing, timers firing, etc.
//-------------------------------------------------------------------------------
@Override
public boolean Notify( VoltageComponent component, ModuleNotifications notification, double doubleValue, long longValue, int x, int y, Object object )
{
   //[user-Notify]   Add your own notification handling code between this line and the notify-close comment
   switch( notification )
   {
      case Knob_Changed:   // doubleValue is the new VoltageKnob value
      {
         if (component == knobVolume)
         {
            smoothLevel.SetValue(doubleValue);
         }
         else if (component == knobAttack)
         {
            SetAttackTime(doubleValue);
         }
         else if (component == knobDecay)
         {
            SetDecayTime(doubleValue);
            SetReleaseTime(doubleValue);
         }
         else if (component == knobFine)
         {
            ReadFineTuneKnob (doubleValue);
         }
         else if (component == knobSemitone)
         {
            ReadSemitoneKnob (doubleValue);
         }
            
      }
      break;
   
      case Slider_Changed:   // doubleValue is the new slider value
      {
      }
      break;
   
      case Button_Changed:   // doubleValue is the new button/toggle button value
      {
      }
      break;
   
      case Switch_Changed:   // doubleValue is the new switch value
      {
         if (component == switchOctave)
         {
            ReadOctaveSwitch (doubleValue);
         }
         else if (component == switchSustain)
         {
            SetSustainLevel (doubleValue);
         }
         else if (component == switchEnsemble)
         {
            ReadEnsembleSwitch (doubleValue);
            RestartLFOs();
         }         
      }
      break;
   
      case Jack_Connected:   // longValue is the new cable ID
      {
         CheckConnections();
      }
      break;
   
      case Jack_Disconnected:   // All cables have been disconnected from this jack
      {
         CheckConnections();
      }
      break;
   
      case GUI_Update_Timer:   // Called every 50ms (by default) if turned on
      {
      }
      break;
   
      case Object_MouseMove:   // called when mouse is over an object that receives mouse notifications. 'object' parameter is a VoltageMouseKeyFlags object.
      {
      }
      break;
   
      case Object_MouseLeave:  // called when mouse leaves an object that receives mouse notifications. 'object' parameter is a VoltageMouseKeyFlags object.
      {
      }
      break;
   
      case Object_LeftButtonDown:   // called when user left-clicks on an object that receives mouse notifications. 'object' parameter is a VoltageMouseKeyFlags object.
      {
      }
      break;
   
      case Object_LeftButtonUp:   // called when user releases left mouse button on an object that receives mouse notifications. 'object' parameter is a VoltageMouseKeyFlags object.
      {
      }
      break;
   
      case Object_RightButtonDown:   // called when user releases right mouse button on an object that receives mouse notifications. 'object' parameter is a VoltageMouseKeyFlags object.
      {
      }
      break;
   
      case Object_RightButtonUp:   // called when user right-clicks on an object that receives mouse notifications
      {
      }
      break;
   
      case Object_LeftButtonDoubleClick: // called when user left-button double-clicks on an object that receives mouse notifications
      {
      }
      break;
   
      // Less common notifications:
   
      case Named_Timer:   // object contains a String with the name of the timer that has fired
      {
      }
      break;
   
      case Canvas_Painting:   // About to paint canvas.  object is a java.awt.Rectangle with painting boundaries
      {
      }
      break;
   
      case Canvas_Painted:   // Canvas painting is complete
      {
      }
      break;
   
      case Control_DragStart:    // A user has started dragging on a control that has been marked as draggable
      {
      }
      break;
   
      case Control_DragOn:       // This control has been dragged over during a drag operation. object contains the dragged object
      {
      }
      break;
   
      case Control_DragOff:      // This control has been dragged over during a drag operation. object contains the dragged object
      {
      }
      break;
   
      case Control_DragEnd:      // A user has ended their drag on a control that has been marked as draggable
      {
      }
      break;
   
      case Label_Changed:        // The text of an editable text control has changed
      {
      }
      break;
   
      case SoundPlayback_Start:   // A sound has begun playback
      {
      }
      break;
   
      case SoundPlayback_End:     // A sound has ended playback
      {
      }
      break;
   
      case Scrollbar_Position:    // longValue is the new scrollbar position
      {
      }
      break;
   
      case PolyVoices_Changed:    // longValue is the new number of poly voices
      {
         SetPolyphony((int)longValue);
      }
      break;
   
      case File_Dropped:     // 'object' is a String containing the file path
      {
      }
      break;
   
      case Preset_Loading_Start:   // called when preset loading begins
      {
      }
      break;
   
      case Preset_Loading_Finish:  // called when preset loading finishes
      {
      }
      break;
   
      case Variation_Loading_Start:    // sent when a variation is about to load
      {
      }
      break;
   
      case Variation_Loading_Finish:   // sent when a variation has just finished loading
      {
      }
      break;
   
      case Tempo_Changed:     // doubleValue is the new tempo
      {
      }
      break;
   
      case Randomized:     // called when the module's controls get randomized
      {
      }
      break;
   
      case VariationListChanged:   // sent when a variation gets added, deleted, or renamed, or the variations list gets reordered
      {
      }
      break;
   
      case Key_Press:     // sent when module has keyboard focus and a key is pressed; object is a VoltageKeyPressInfo object
      {
      }
      break;
   
      case Reset:    // sent when the module has been reset to default settings
      {
      }
      break;
   
      case Keyboard_NoteOn:   // sent when a note has been pressed on a VoltageKeyboard object. longValue is the note value ( 0-127 )
      {
      }
      break;
   
      case Keyboard_NoteOff:   // sent when a note has been released on a VoltageKeyboard object. longValue is the note value ( 0-127 )
      {
      }
      break;
   
      case Curve_Changed:   // sent when user has edited a curve's value. 'object' will be a VoltageCurve.CurveChangeNotification object.
      {
      }
      break;
   }



   return false;
   //[/user-Notify]
}


//-------------------------------------------------------------------------------
//  public void ProcessSample()

//  ProcessSample is called once per sample. Usually it's where you read
//  from input jacks, process audio, and write it to your output jacks.
//  Since ProcesssSample gets called 48,000 times per second, offload CPU-intensive operations
//  to other threads when possible and avoid calling native functions.
//-------------------------------------------------------------------------------
@Override
public void ProcessSample()
{
   //[user-ProcessSample]   Add your own process-sampling code here

   int i;
   float tempFloat;
   double tempDbl;
   double totalMix;
   double oscillatorOutput;
   
   double temp;
   int tempIndex;
   double intIndex;
   double fractIndex;
   double valuePosN;
   double valuePosNplus1;
   double out1;
   double out2;
   double out3;   
   
   totalMix = 0.0;
   
   // Calculate pitch offset
   tempFloat = octaveVolts + semitoneVolts + fineVolts;
   
   if (pitchModConnected)
   {
      tempDbl = inputJackCV.GetValue() *
                knobPitchMod.GetValue() *
                VOLTS_PER_SEMITONE *
                FIVE_VOLTS_ATTEN;
      
      tempFloat += (float)tempDbl;
   }
   
   if (tempFloat != pitchOffset)
   {
      // Calculate new pitch multiplier value
      pitchOffset = tempFloat;
      pitchMultiplier = Values.FastTwoToTheX(pitchOffset);
   }
   
   for (i=0; i < currentPolyphony; i++)
   {
      if (polyGateConnected)
      {
         tempDbl = polyInputJackGate.GetPolyValue(i);
      }
      else
      {
         tempDbl = GetIOPanelPolyValue(IOPanelPolyValues.IOPanel_PolyGate, i);
      }
      if (tempDbl != channelGate[i])
      {
         // Change in gate voltage
         channelGate[i] = tempDbl;
         channelEnvelope[i].SetGate(tempDbl > 2.5);
      }
      
      channelEnvelope[i].AdvanceSample();
      
      if (channelEnvelope[i].GetStage() != ADSREnvelope.ENV_STAGE.ADSR_Stage_Off)
      {
         // Only process this channel if audible
         
         if (polyPitchConnected)
         {
            tempDbl = polyInputJackPitch.GetPolyValue(i);
         }
         else
         {
            tempDbl = GetIOPanelPolyValue(IOPanelPolyValues.IOPanel_PolyPitch, i);
         }
         tempFloat = (float)tempDbl;
         if (tempFloat != channelPitch[i])
         {
            channelPitch[i] = tempFloat;
            // Change in pitch voltage
            tempFloat = LOWEST_C_FREQ * 
                        Values.FastTwoToTheX(tempFloat);
            channelFrequency[i] = tempFloat;
         }
         
         tempFloat = channelFrequency[i] * pitchMultiplier;
         channelOscillator[i].SetFrequency(tempFloat);
         
         channelOscillator[i].AdvanceSample();
      
         oscillatorOutput = channelOscillator[i].GetSawtoothValue();
         
         totalMix += oscillatorOutput *
                     channelEnvelope[i].GetValue() * FIVE_VOLTS_ATTEN;
      }
      
    }
    
    totalMix *= polyphonyCompensationAtten;
    
    tempDbl = smoothLevel.GetSmoothValue();

    totalMix *= tempDbl;
    
    // Send audio input to delay line
   
    delayLine[delayWritePos] = totalMix;
    delayWritePos++;
    if (delayWritePos >= DELAY_LINE_LENGTH)
    {
       delayWritePos = 0;
    }
   
    // Check for rising edge on Sync input
   
    // Advance LFOs
    SlowLFO1.AdvanceSample();
    SlowLFO2.AdvanceSample();
    SlowLFO3.AdvanceSample();

    FastLFO1.AdvanceSample();
    FastLFO2.AdvanceSample();
    FastLFO3.AdvanceSample();
   
    // ----------------------------- Calculate channel 1 output
   
    temp = SlowLFO1.GetSineValue() * SLOW_LFO_DEPTH;
    temp += FastLFO1.GetSineValue() * FAST_LFO_DEPTH;
   
    intIndex = floor(temp);
    fractIndex = temp - intIndex;
   
    tempIndex = (int)(intIndex);
   
    tempIndex += delayWritePos + DELAY_LINE_MIDPOINT;
    if (tempIndex >= DELAY_LINE_LENGTH)
    {
       tempIndex -= DELAY_LINE_LENGTH;
    }   
    valuePosN = delayLine[tempIndex];
   
    tempIndex++;
    if (tempIndex >= DELAY_LINE_LENGTH)
    {
       tempIndex -= DELAY_LINE_LENGTH;
    }
    valuePosNplus1 = delayLine[tempIndex];
   
    // Linear interpolation between successive values
   
    temp = valuePosN * (1.0 - fractIndex) +
           valuePosNplus1 * fractIndex;

    out1 = temp;

    // ----------------------------- Calculate channel 2 output
   
    temp = SlowLFO2.GetSineValue() * SLOW_LFO_DEPTH;
    temp += FastLFO2.GetSineValue() * FAST_LFO_DEPTH;
   
    intIndex = floor(temp);
    fractIndex = temp - intIndex;
   
    tempIndex = (int)(intIndex);
   
    tempIndex += delayWritePos + DELAY_LINE_MIDPOINT;
    if (tempIndex >= DELAY_LINE_LENGTH)
    {
       tempIndex -= DELAY_LINE_LENGTH;
    }   
    valuePosN = delayLine[tempIndex];
   
    tempIndex++;
    if (tempIndex >= DELAY_LINE_LENGTH)
    {
       tempIndex -= DELAY_LINE_LENGTH;
    }
    valuePosNplus1 = delayLine[tempIndex];
   
    // Linear interpolation between successive values
   
    temp = valuePosN * (1.0 - fractIndex) +
           valuePosNplus1 * fractIndex;

    out2 = temp;

    // ----------------------------- Calculate channel 3 output
   
    temp = SlowLFO3.GetSineValue() * SLOW_LFO_DEPTH;
    temp += FastLFO3.GetSineValue() * FAST_LFO_DEPTH;
   
    intIndex = floor(temp);
    fractIndex = temp - intIndex;
   
    tempIndex = (int)(intIndex);
   
    tempIndex += delayWritePos + DELAY_LINE_MIDPOINT;
    if (tempIndex >= DELAY_LINE_LENGTH)
    {
       tempIndex -= DELAY_LINE_LENGTH;
    }   
    valuePosN = delayLine[tempIndex];
   
    tempIndex++;
    if (tempIndex >= DELAY_LINE_LENGTH)
    {
       tempIndex -= DELAY_LINE_LENGTH;
    }
    valuePosNplus1 = delayLine[tempIndex];
   
    // Linear interpolation between successive values
   
    temp = valuePosN * (1.0 - fractIndex) +
           valuePosNplus1 * fractIndex;

    out3 = temp;
   
    // ----------------------------- Calculate Chorus / Ensemble Output
    
    switch (ensembleSetting)
    {
      case OFF:
      {
         temp = totalMix;
      }
      break;
      
      case CHORUS:
      {
         temp = 0.5 * (out1 + totalMix);          
      }
      break;
      
      case ENSEMBLE:
      {
         temp = 0.333 * (out1 + out2 + out3);          
      }
      break;
      
    }   
    
    outputJack.SetValue(temp);

   //[/user-ProcessSample]
}


//-------------------------------------------------------------------------------
//  public String GetTooltipText( VoltageComponent component )

//  Gets called when a tooltip is about to display for a control. Override it if
//  you want to change what the tooltip displays - if you want a knob to work in logarithmic fashion,
//  for instance, you can translate the knob's current value to a log-based string and display it here.
//-------------------------------------------------------------------------------
@Override
public String GetTooltipText( VoltageComponent component )
{
   //[user-GetTooltipText]   Add your own code here



   return super.GetTooltipText( component );
   //[/user-GetTooltipText]
}


//-------------------------------------------------------------------------------
//  public void EditComponentValue( VoltageComponent component, double newValue, String newText )

//  Gets called after a user clicks on a tooltip and types in a new value for a control. Override this if
//  you've changed the default tooltip display (translating a linear value to logarithmic, for instance)
//  in GetTooltipText().
//-------------------------------------------------------------------------------
@Override
public void EditComponentValue( VoltageComponent component, double newValue, String newText )
{
   //[user-EditComponentValue]   Add your own code here



   //[/user-EditComponentValue]
   super.EditComponentValue( component, newValue, newText );
}


//-------------------------------------------------------------------------------
//  public void OnUndoRedo( String undoType, double newValue, Object optionalObject )

//  If you've created custom undo events via calls to CreateUndoEvent, you'll need to
//  process them in this function when they get triggered by undo/redo actions.
//-------------------------------------------------------------------------------
@Override
public void OnUndoRedo( String undoType, double newValue, Object optionalObject )
{
   //[user-OnUndoRedo]   Add your own code here



   //[/user-OnUndoRedo]
}


//-------------------------------------------------------------------------------
//  public byte[] GetStateInformation()

//  Gets called when the module's state gets saved, typically when the user saves a preset with
//  this module in it. Voltage Modular will automatically save the states of knobs, sliders, etc.,
//  but if you have any custom state information you need to save, return it from this function.
//-------------------------------------------------------------------------------
@Override
public byte[] GetStateInformation()
{
   //[user-GetStateInformation]   Add your own code here



   return null;
   //[/user-GetStateInformation]
}


//-------------------------------------------------------------------------------
//  public void SetStateInformation(byte[] stateInfo)

//  Gets called when this module's state is getting restored, typically when a user opens a preset with
//  this module in it. The stateInfo parameter will contain whatever custom data you stored in GetStateInformation().
//-------------------------------------------------------------------------------
@Override
public void SetStateInformation(byte[] stateInfo)
{
   //[user-SetStateInformation]   Add your own code here



   //[/user-SetStateInformation]
}


//-------------------------------------------------------------------------------
//  public byte[] GetStateInformationForVariations()

//  Gets called when a user saves a variation with this module in it.
//  Voltage Modular will automatically save the states of knobs, sliders, etc.,
//  but if you have any custom state information you need to save, return it from this function.
//-------------------------------------------------------------------------------
@Override
public byte[] GetStateInformationForVariations()
{
   //[user-GetStateInformationForVariations]   Add your own code here



   return GetStateInformation();
   //[/user-GetStateInformationForVariations]
}


//-------------------------------------------------------------------------------
//  public void SetStateInformationForVariations(byte[] stateInfo)

//  Gets called when a user loads a variation with this module in it.
//  The stateInfo parameter will contain whatever custom data you stored in GetStateInformationForVariations().
//-------------------------------------------------------------------------------
@Override
public void SetStateInformationForVariations(byte[] stateInfo)
{
   //[user-SetStateInformationForVariations]   Add your own code here
   SetStateInformation(stateInfo);



   //[/user-SetStateInformationForVariations]
}


// Auto-generated variables
private VoltageSwitch switchEnsemble;
private VoltageAudioJack inputJackCV;
private VoltageSwitch switchSustain;
private VoltageLabel textLabel16;
private VoltageKnob knobPitchMod;
private VoltageLabel textLabel15;
private VoltageLabel textLabel14;
private VoltageLabel textLabel13;
private VoltageKnob knobDecay;
private VoltageLabel textLabel12;
private VoltageKnob knobAttack;
private VoltageLabel textLabel11;
private VoltageLabel textLabel10;
private VoltageKnob knobVolume;
private VoltageLabel textLabel9;
private VoltageKnob knobFine;
private VoltageLabel textLabel8;
private VoltageLabel textLabel19;
private VoltageLabel textLabel18;
private VoltageLabel textLabel17;
private VoltageLabel textLabel7;
private VoltageLabel textLabel6;
private VoltageLabel textLabel5;
private VoltageSwitch switchOctave;
private VoltageLabel textLabel4;
private VoltageLabel textLabel3;
private VoltageLabel textLabel2;
private VoltageLabel textLabel1;
private VoltageKnob knobSemitone;
private VoltageAudioJack outputJack;
private VoltagePolyJack polyInputJackGate;
private VoltagePolyJack polyInputJackPitch;
private VoltageLine line0;
private VoltageLine line1;
private VoltageLine line2;
private VoltageLine line3;
private VoltageLine line4;


//[user-code-and-variables]    Add your own variables and functions here

// Types

private enum EnsembleSetting
{
   OFF,
   CHORUS,
   ENSEMBLE
}

// Constants

// Stringer Constants

private final int MAX_POLY_VOICES = 16;
private final double FIVE_VOLTS_ATTEN = 0.2;
private final float LOWEST_C_FREQ = 65.406f;
private final float SEMITONES_PER_OCTAVE = 12.0f;
private final float VOLTS_PER_SEMITONE = 1.0f / SEMITONES_PER_OCTAVE;

// Ensemble Constants

private final double DEGREES_000 = 0.0;
private final double DEGREES_360 = 1.0;
private final double DEGREES_120 = DEGREES_360 / 3.0;
private final double DEGREES_240 = DEGREES_120 * 2.0;

private final double SLOW_LFO_RATE = 1.21;
private final double FAST_LFO_RATE = 5.82;

private final double SLOW_LFO_DEPTH = 20.0 / 5.0;
private final double FAST_LFO_DEPTH = 13.0 / 5.0;

private final int DELAY_LINE_LENGTH = 100;
private final int DELAY_LINE_MIDPOINT = DELAY_LINE_LENGTH / 2;



// Variables

// Stringer Variables

private int currentPolyphony;
private double polyphonyCompensationAtten;

private float pitchOffset;
private float pitchMultiplier;
private float octaveVolts;
private float semitoneVolts;
private float fineVolts;

private boolean pitchModConnected;
private boolean outputConnected;
private boolean polyPitchConnected;
private boolean polyGateConnected;

private EnsembleSetting ensembleSetting;

// Ensemble Variables

private double[] delayLine = new double[DELAY_LINE_LENGTH];
private int delayWritePos;

private double currentLFO1Rate;
private double currentLFO1Depth;
private double currentLFO2Rate;
private double currentLFO2Depth;

private double previousLFO1Rate;
private double previousLFO1Depth;
private double previousLFO2Rate;
private double previousLFO2Depth;



// Objects

// Stringer Objects

protected AnalogOscillator[] channelOscillator = new AnalogOscillator[MAX_POLY_VOICES];
protected ADSREnvelope[] channelEnvelope = new ADSREnvelope[MAX_POLY_VOICES];
private float[] channelPitch = new float[MAX_POLY_VOICES];
private float[] channelFrequency = new float[MAX_POLY_VOICES];
private double[] channelGate = new double[MAX_POLY_VOICES];
private double[] channelVelocity = new double[MAX_POLY_VOICES];
private SmoothValue smoothLevel = new SmoothValue();

// Ensemble Objects

protected DigitalOscillator SlowLFO1 = new DigitalOscillator();
protected DigitalOscillator SlowLFO2 = new DigitalOscillator();
protected DigitalOscillator SlowLFO3 = new DigitalOscillator();

protected DigitalOscillator FastLFO1 = new DigitalOscillator();
protected DigitalOscillator FastLFO2 = new DigitalOscillator();
protected DigitalOscillator FastLFO3 = new DigitalOscillator();



// Functions

private void SetAttackTime (double attackSeconds)
{
   int i;
   double attackMilliseconds;
   
   attackMilliseconds = attackSeconds * 1000.0;
   
   for (i=0; i < MAX_POLY_VOICES; i++)
   {
      channelEnvelope[i].SetAttackTime(attackMilliseconds);
   }
}

private void SetDecayTime (double decaySeconds)
{
   int i;
   double decayMilliseconds;
   
   decayMilliseconds = decaySeconds * 1000.0;
   
   for (i=0; i < MAX_POLY_VOICES; i++)
   {
      channelEnvelope[i].SetDecayTime(decayMilliseconds);
   }
}

private void SetSustainLevel (double sustainLevelPercent)
{
   int i;
   double sustainVolts;
   
   sustainVolts = sustainLevelPercent * 5.0;
   
   for (i=0; i < MAX_POLY_VOICES; i++)
   {
      channelEnvelope[i].SetSustainLevel(sustainVolts);
   }
}

private void SetReleaseTime (double releaseSeconds)
{
   int i;
   double releaseMilliseconds;
   
   releaseMilliseconds = releaseSeconds * 1000.0;
   
   for (i=0; i < MAX_POLY_VOICES; i++)
   {
      channelEnvelope[i].SetReleaseTime(releaseMilliseconds);
   }
}

private void SetPolyphony (int numberOfVoices)
{
   if (numberOfVoices < 1)
   {
      currentPolyphony = 1;
   }
   else if (numberOfVoices > 16)
   {
      currentPolyphony = 16;
   }
   else
   {
      currentPolyphony = numberOfVoices;
   }
   
   polyphonyCompensationAtten = 1.0 / (double)currentPolyphony;
}

private void ResetEnvelopesFrom (int firstUnusedChannel)
{
   int i;
   
   for (i = firstUnusedChannel; i < MAX_POLY_VOICES; i++)
   {
      channelEnvelope[i].Reset();
   }
}

private void CheckConnections ()
{
   pitchModConnected = inputJackCV.IsConnected();
   outputConnected = outputJack.IsConnected();
   polyPitchConnected = polyInputJackPitch.IsConnected();
   polyGateConnected = polyInputJackGate.IsConnected();
}

private void ReadOctaveSwitch (double octaveValue)
{
   if (octaveValue < 0.5)
   {
      octaveVolts = -1.0f;
   }
   else if (octaveValue < 1.5)
   {
      octaveVolts = -0.0f;
   }
   else
   {
      octaveVolts = 1.0f;
   }
}

private void ReadEnsembleSwitch (double ensembleValue)
{
   if (ensembleValue < 0.5)
   {
      ensembleSetting = EnsembleSetting.OFF;
   }
   else if (ensembleValue < 1.5)
   {
      ensembleSetting = EnsembleSetting.CHORUS;
   }
   else
   {
      ensembleSetting = EnsembleSetting.ENSEMBLE;
   }
}

private void ReadSemitoneKnob (double semitoneValue)
{
   semitoneVolts = VOLTS_PER_SEMITONE *
                   (float)semitoneValue;
}

private void ReadFineTuneKnob (double fineValue)
{
   fineVolts = VOLTS_PER_SEMITONE *
               (float)fineValue;
}

private void RestartLFOs()
{
   SlowLFO1.SetFrequency(SLOW_LFO_RATE);
   SlowLFO2.SetFrequency(SLOW_LFO_RATE);
   SlowLFO3.SetFrequency(SLOW_LFO_RATE);

   SlowLFO1.SetCycle(DEGREES_000);
   SlowLFO2.SetCycle(DEGREES_120);
   SlowLFO3.SetCycle(DEGREES_240);

   FastLFO1.SetFrequency(FAST_LFO_RATE);
   FastLFO2.SetFrequency(FAST_LFO_RATE);
   FastLFO3.SetFrequency(FAST_LFO_RATE);
      
   FastLFO1.SetCycle(DEGREES_000);
   FastLFO2.SetCycle(DEGREES_120);
   FastLFO3.SetCycle(DEGREES_240);
   
}



//[/user-code-and-variables]
}

 