package com.domemusictechnologies.mrmemory;


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.round;    // Round double to nearest integer value
import static java.lang.Math.floor;    // Trunc double to lower integer value
import static java.lang.Math.floorMod; // Modulus which works with negative numbers

//[/user-imports]


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

public MrMemory( long moduleID, VoltageObjects voltageObjects )
{
   super( moduleID, voltageObjects, "Mister Memory", ModuleType.ModuleType_Effect, 1.0 );

   InitializeControls();


   canBeBypassed = true;
   SetSkin( "a7a62de4ddee477c853dcadce5fdc5d7" );
}

void InitializeControls()
{

   millisecondsKnob = new VoltageKnob( "Milliseconds", "Milliseconds", this, 0.0, 2500, 250 );
   AddComponent( millisecondsKnob );
   millisecondsKnob.SetWantsMouseNotifications( false );
   millisecondsKnob.SetPosition( 16, 240 );
   millisecondsKnob.SetSize( 41, 41 );
   millisecondsKnob.SetSkin( "Dial Blue" );
   millisecondsKnob.SetRange( 0.0, 2500, 250, false, 0 );
   millisecondsKnob.SetKnobParams( 215, 145 );
   millisecondsKnob.DisplayValueInPercent( false );
   millisecondsKnob.SetKnobAdjustsRing( true );

   inputCV = new VoltageAudioJack( "CV Input", "CV Input", this, JackType.JackType_AudioInput );
   AddComponent( inputCV );
   inputCV.SetWantsMouseNotifications( false );
   inputCV.SetPosition( 4, 305 );
   inputCV.SetSize( 25, 25 );
   inputCV.SetSkin( "Jack Round Sky Ring" );

   attenKnobCV = new VoltageKnob( "CV Attenuator", "CV Attenuator", this, 0, 1250, 10 );
   AddComponent( attenKnobCV );
   attenKnobCV.SetWantsMouseNotifications( false );
   attenKnobCV.SetPosition( 32, 300 );
   attenKnobCV.SetSize( 37, 37 );
   attenKnobCV.SetSkin( "Plastic Blue" );
   attenKnobCV.SetRingSkin( "Ramp Teal/Mist" );
   attenKnobCV.SetRange( 0, 1250, 10, false, 0 );
   attenKnobCV.SetKnobParams( 215, 145 );
   attenKnobCV.DisplayValueInPercent( false );
   attenKnobCV.SetKnobAdjustsRing( false );
   attenKnobCV.SetMidpointValue( 10.0 );

   inputAudio = new VoltageAudioJack( "Audio Input", "Audio Input", this, JackType.JackType_AudioInput );
   AddComponent( inputAudio );
   inputAudio.SetWantsMouseNotifications( false );
   inputAudio.SetPosition( 6, 53 );
   inputAudio.SetSize( 25, 25 );
   inputAudio.SetSkin( "Jack Round Sky Ring" );

   knobDryWetMix = new VoltageKnob( "Wet / Dry Mix", "Wet / Dry Mix", this, 0.0, 1.0, 0.5 );
   AddComponent( knobDryWetMix );
   knobDryWetMix.SetWantsMouseNotifications( false );
   knobDryWetMix.SetPosition( 18, 96 );
   knobDryWetMix.SetSize( 37, 37 );
   knobDryWetMix.SetSkin( "Plastic Blue" );
   knobDryWetMix.SetRingSkin( "Ramp Teal/Mist" );
   knobDryWetMix.SetRange( 0.0, 1.0, 0.5, false, 0 );
   knobDryWetMix.SetKnobParams( 215, 145 );
   knobDryWetMix.DisplayValueInPercent( true );
   knobDryWetMix.SetKnobAdjustsRing( true );

   outputAudio = new VoltageAudioJack( "Audio Output", "Audio Output", this, JackType.JackType_AudioOutput );
   AddComponent( outputAudio );
   outputAudio.SetWantsMouseNotifications( false );
   outputAudio.SetPosition( 41, 53 );
   outputAudio.SetSize( 25, 25 );
   outputAudio.SetSkin( "Jack Round Sky Ring" );

   textLabel8 = new VoltageLabel( "textLabel8", "textLabel8", this, "In" );
   AddComponent( textLabel8 );
   textLabel8.SetWantsMouseNotifications( false );
   textLabel8.SetPosition( 13, 39 );
   textLabel8.SetSize( 16, 12 );
   textLabel8.SetEditable( false, false );
   textLabel8.SetJustificationFlags( VoltageLabel.Justification.Left );
   textLabel8.SetJustificationFlags( VoltageLabel.Justification.VertCentered );
   textLabel8.SetColor( new Color( 255, 255, 255, 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 );

   textLabel9 = new VoltageLabel( "textLabel9", "textLabel9", this, "Mix" );
   AddComponent( textLabel9 );
   textLabel9.SetWantsMouseNotifications( false );
   textLabel9.SetPosition( 29, 81 );
   textLabel9.SetSize( 20, 17 );
   textLabel9.SetEditable( false, false );
   textLabel9.SetJustificationFlags( VoltageLabel.Justification.Left );
   textLabel9.SetJustificationFlags( VoltageLabel.Justification.VertCentered );
   textLabel9.SetColor( new Color( 255, 255, 255, 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", 10, false, false );

   textLabel15 = new VoltageLabel( "textLabel15", "textLabel15", this, "Dry" );
   AddComponent( textLabel15 );
   textLabel15.SetWantsMouseNotifications( false );
   textLabel15.SetPosition( 15, 125 );
   textLabel15.SetSize( 19, 18 );
   textLabel15.SetEditable( false, false );
   textLabel15.SetJustificationFlags( VoltageLabel.Justification.Left );
   textLabel15.SetJustificationFlags( VoltageLabel.Justification.VertCentered );
   textLabel15.SetColor( new Color( 255, 255, 255, 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", 10, false, false );

   textLabel19 = new VoltageLabel( "textLabel19", "textLabel19", this, "-ve" );
   AddComponent( textLabel19 );
   textLabel19.SetWantsMouseNotifications( false );
   textLabel19.SetPosition( 15, 195 );
   textLabel19.SetSize( 19, 21 );
   textLabel19.SetEditable( false, false );
   textLabel19.SetJustificationFlags( VoltageLabel.Justification.Left );
   textLabel19.SetJustificationFlags( VoltageLabel.Justification.VertCentered );
   textLabel19.SetColor( new Color( 255, 255, 255, 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 );

   textLabel20 = new VoltageLabel( "textLabel20", "textLabel20", this, "+ve" );
   AddComponent( textLabel20 );
   textLabel20.SetWantsMouseNotifications( false );
   textLabel20.SetPosition( 36, 194 );
   textLabel20.SetSize( 19, 23 );
   textLabel20.SetEditable( false, false );
   textLabel20.SetJustificationFlags( VoltageLabel.Justification.Left );
   textLabel20.SetJustificationFlags( VoltageLabel.Justification.VertCentered );
   textLabel20.SetColor( new Color( 255, 255, 255, 255 ) );
   textLabel20.SetBkColor( new Color( 65, 65, 65, 0 ) );
   textLabel20.SetBorderColor( new Color( 0, 0, 0, 0 ) );
   textLabel20.SetBorderSize( 1 );
   textLabel20.SetMultiLineEdit( false );
   textLabel20.SetIsNumberEditor( false );
   textLabel20.SetNumberEditorRange( 0, 100 );
   textLabel20.SetNumberEditorInterval( 1 );
   textLabel20.SetNumberEditorUsesMouseWheel( false );
   textLabel20.SetHasCustomTextHoverColor( false );
   textLabel20.SetTextHoverColor( new Color( 0, 0, 0, 255 ) );
   textLabel20.SetFont( "Verdana", 10, false, false );

   textLabel16 = new VoltageLabel( "textLabel16", "textLabel16", this, "Wet" );
   AddComponent( textLabel16 );
   textLabel16.SetWantsMouseNotifications( false );
   textLabel16.SetPosition( 39, 124 );
   textLabel16.SetSize( 19, 20 );
   textLabel16.SetEditable( false, false );
   textLabel16.SetJustificationFlags( VoltageLabel.Justification.Left );
   textLabel16.SetJustificationFlags( VoltageLabel.Justification.VertCentered );
   textLabel16.SetColor( new Color( 255, 255, 255, 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", 10, false, false );

   feedbackKnob = new VoltageKnob( "Feedback", "Feedback", this, -1.0, 1.0, 0 );
   AddComponent( feedbackKnob );
   feedbackKnob.SetWantsMouseNotifications( false );
   feedbackKnob.SetPosition( 18, 170 );
   feedbackKnob.SetSize( 37, 37 );
   feedbackKnob.SetSkin( "Plastic Dark Blue" );
   feedbackKnob.SetRingSkin( "Crescent Teal/Mist" );
   feedbackKnob.SetRange( -1.0, 1.0, 0, false, 0 );
   feedbackKnob.SetKnobParams( 215, 145 );
   feedbackKnob.DisplayValueInPercent( true );
   feedbackKnob.SetKnobAdjustsRing( true );

   textLabel17 = new VoltageLabel( "textLabel17", "textLabel17", this, "Feedback" );
   AddComponent( textLabel17 );
   textLabel17.SetWantsMouseNotifications( false );
   textLabel17.SetPosition( 1, 153 );
   textLabel17.SetSize( 70, 18 );
   textLabel17.SetEditable( false, false );
   textLabel17.SetJustificationFlags( VoltageLabel.Justification.HorizCentered );
   textLabel17.SetJustificationFlags( VoltageLabel.Justification.VertCentered );
   textLabel17.SetColor( new Color( 255, 255, 255, 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 );

   textLabel21 = new VoltageLabel( "textLabel21", "textLabel21", this, "CV In" );
   AddComponent( textLabel21 );
   textLabel21.SetWantsMouseNotifications( false );
   textLabel21.SetPosition( 4, 286 );
   textLabel21.SetSize( 29, 22 );
   textLabel21.SetEditable( false, false );
   textLabel21.SetJustificationFlags( VoltageLabel.Justification.Left );
   textLabel21.SetJustificationFlags( VoltageLabel.Justification.VertCentered );
   textLabel21.SetColor( new Color( 255, 255, 255, 255 ) );
   textLabel21.SetBkColor( new Color( 65, 65, 65, 0 ) );
   textLabel21.SetBorderColor( new Color( 0, 0, 0, 0 ) );
   textLabel21.SetBorderSize( 1 );
   textLabel21.SetMultiLineEdit( false );
   textLabel21.SetIsNumberEditor( false );
   textLabel21.SetNumberEditorRange( 0, 100 );
   textLabel21.SetNumberEditorInterval( 1 );
   textLabel21.SetNumberEditorUsesMouseWheel( false );
   textLabel21.SetHasCustomTextHoverColor( false );
   textLabel21.SetTextHoverColor( new Color( 0, 0, 0, 255 ) );
   textLabel21.SetFont( "Verdana", 10, false, false );

   textLabel10 = new VoltageLabel( "textLabel10", "textLabel10", this, "Out" );
   AddComponent( textLabel10 );
   textLabel10.SetWantsMouseNotifications( false );
   textLabel10.SetPosition( 42, 39 );
   textLabel10.SetSize( 23, 12 );
   textLabel10.SetEditable( false, false );
   textLabel10.SetJustificationFlags( VoltageLabel.Justification.HorizCentered );
   textLabel10.SetJustificationFlags( VoltageLabel.Justification.VertCentered );
   textLabel10.SetColor( new Color( 255, 255, 255, 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 );

   textLabel18 = new VoltageLabel( "textLabel18", "textLabel18", this, "Delay Time" );
   AddComponent( textLabel18 );
   textLabel18.SetWantsMouseNotifications( false );
   textLabel18.SetPosition( 1, 223 );
   textLabel18.SetSize( 70, 18 );
   textLabel18.SetEditable( false, false );
   textLabel18.SetJustificationFlags( VoltageLabel.Justification.HorizCentered );
   textLabel18.SetJustificationFlags( VoltageLabel.Justification.VertCentered );
   textLabel18.SetColor( new Color( 255, 255, 255, 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 );

   textLabel33 = new VoltageLabel( "textLabel33", "textLabel33", this, "Mister Memory" );
   AddComponent( textLabel33 );
   textLabel33.SetWantsMouseNotifications( false );
   textLabel33.SetPosition( 8, 0 );
   textLabel33.SetSize( 56, 30 );
   textLabel33.SetEditable( false, false );
   textLabel33.SetJustificationFlags( VoltageLabel.Justification.HorizCentered );
   textLabel33.SetJustificationFlags( VoltageLabel.Justification.VertCentered );
   textLabel33.SetColor( new Color( 255, 255, 255, 255 ) );
   textLabel33.SetBkColor( new Color( 65, 65, 65, 0 ) );
   textLabel33.SetBorderColor( new Color( 0, 0, 0, 0 ) );
   textLabel33.SetBorderSize( 1 );
   textLabel33.SetMultiLineEdit( true );
   textLabel33.SetIsNumberEditor( false );
   textLabel33.SetNumberEditorRange( 0, 100 );
   textLabel33.SetNumberEditorInterval( 1 );
   textLabel33.SetNumberEditorUsesMouseWheel( false );
   textLabel33.SetHasCustomTextHoverColor( false );
   textLabel33.SetTextHoverColor( new Color( 0, 0, 0, 255 ) );
   textLabel33.SetFont( "Verdana", 14, false, false );

   textLabel34 = new VoltageLabel( "textLabel34", "textLabel34", this, "Dome Music Technologies" );
   AddComponent( textLabel34 );
   textLabel34.SetWantsMouseNotifications( false );
   textLabel34.SetPosition( 7, 340 );
   textLabel34.SetSize( 59, 20 );
   textLabel34.SetEditable( false, false );
   textLabel34.SetJustificationFlags( VoltageLabel.Justification.HorizCentered );
   textLabel34.SetJustificationFlags( VoltageLabel.Justification.VertCentered );
   textLabel34.SetColor( new Color( 255, 255, 255, 255 ) );
   textLabel34.SetBkColor( new Color( 65, 65, 65, 0 ) );
   textLabel34.SetBorderColor( new Color( 0, 0, 0, 0 ) );
   textLabel34.SetBorderSize( 1 );
   textLabel34.SetMultiLineEdit( true );
   textLabel34.SetIsNumberEditor( false );
   textLabel34.SetNumberEditorRange( 0, 100 );
   textLabel34.SetNumberEditorInterval( 1 );
   textLabel34.SetNumberEditorUsesMouseWheel( false );
   textLabel34.SetHasCustomTextHoverColor( false );
   textLabel34.SetTextHoverColor( new Color( 0, 0, 0, 255 ) );
   textLabel34.SetFont( "Verdana", 7, false, false );
}



//-------------------------------------------------------------------------------
//  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

   currentWritePos = 0;
   previousFeedbackValue = 0.0;

   // Read all knobs at startup - don't wait for Notify.
   
   smoothMix.SetValue (knobDryWetMix.GetValue());
   smoothFeedback.SetValue (feedbackKnob.GetValue());
   smoothCVDepth.SetValue (attenKnobCV.GetValue());

   CheckConnections();

   //[/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

   int roundedValue;

   switch( notification )
   {
      case Knob_Changed:   // doubleValue is the new VoltageKnob value
      {
         if (component == millisecondsKnob)
         {
            doubleDelayInSamples = doubleValue * Values.SamplesPerMs;
         }
         else if (component == knobDryWetMix)
         {
            smoothMix.SetValue (doubleValue);
         }
         else if (component == feedbackKnob)
         {
            smoothFeedback.SetValue (doubleValue);
         }
         else if (component == attenKnobCV)
         {
            smoothCVDepth.SetValue (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
      {
      }
      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
      {
      }
      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

   double currentInputAudio;
   double currentWriteValue;
   double delayedValueN;
   double delayedValueNPlus1;
   int tempIndex;
   double mixOutput;
   double intIndex;
   double outputAudioValue;
   double currentFeedbackSetting;
   double currentMixSetting;
   double currentDrySignal;
   double currentWetSignal;
   double currentCVAttenSetting;
   double currentCVInputValue;
   double antiAliasedDelayedValue;
   double CVdelay;
   double fractionalDelayCV;
   double integerDelayCV;
   int tempInt;   
   double tempDbl;
   
   currentInputAudio = inputAudio.GetValue();
   currentCVInputValue = inputCV.GetValue();
      
   currentFeedbackSetting = smoothFeedback.GetSmoothValue();
   currentCVAttenSetting = smoothCVDepth.GetSmoothValue();
   currentMixSetting = smoothMix.GetSmoothValue();
   
   // Write current input signal and feedback signal to head of delay line
   
   currentWriteValue = currentInputAudio + previousFeedbackValue;
   delayLine[currentWritePos] = currentWriteValue;
   
   // Calculate slewed delay value from knob
   
   tempDbl = doubleDelayInSamples - slewedDelayInSamples;
   slewedDelayInSamples = doubleDelayInSamples - (tempDbl * INITIAL_DELAY_SLEW_FACTOR);
   
   // Calculate total delay time from slewed knob setting and CV input
   
   CVdelay = currentCVInputValue *
             currentCVAttenSetting *
             CV_RANGE_MULTIPLIER;
   
   // Add slewed knob setting and CV delay time
   tempDbl = slewedDelayInSamples + CVdelay;
   
   // Limit total delay time to the range 0.0 to 2500.0 ms
   
   if (tempDbl < 0.0)
   {
      tempDbl = 0.0;
   }
   else if (tempDbl > MAX_DELAY_IN_SAMPLES)
   {
      tempDbl = MAX_DELAY_IN_SAMPLES;
   }
   
   integerDelayCV = floor(tempDbl);
   fractionalDelayCV = tempDbl - integerDelayCV;
   
   tempInt = currentWritePos - (int)integerDelayCV;
   
   tempInt = floorMod(tempInt, DELAY_LINE_LENGTH_IN_SAMPLES);
   
   delayedValueN = delayLine[tempInt];
   
   tempInt--;
   if (tempInt < 0)
   {
      tempInt = DELAY_LINE_LENGTH_IN_SAMPLES - 1;
   }
   
   delayedValueNPlus1 = delayLine[tempInt];
   
   antiAliasedDelayedValue = (1.0 - fractionalDelayCV) * delayedValueN +
                             fractionalDelayCV * delayedValueNPlus1;
                             
   // Now we have the anti-aliased delay value, we can perform mixing
   // and feedback calculations;
   
   currentDrySignal = currentInputAudio * (1.0 - currentMixSetting);
   currentWetSignal = antiAliasedDelayedValue * currentMixSetting;

   // Invert wet signal if Mix Polarity switch is in negative position
   
   outputAudioValue = currentDrySignal + currentWetSignal;
   outputAudio.SetValue (outputAudioValue);
   
   // Calculate feedback value to add to next iteration's input
   
   previousFeedbackValue = currentFeedbackSetting * antiAliasedDelayedValue;
   
   // Limit feedback value to +/- 10.0V
   
   if (previousFeedbackValue > 10.0)
   {
      previousFeedbackValue = 10.0;
   }
   else if (previousFeedbackValue < -10.0)
   {
      previousFeedbackValue = -10.0;
   }
   
   // Increment write position by one sample
   
   currentWritePos++;
   if (currentWritePos >= DELAY_LINE_LENGTH_IN_SAMPLES)
   {
      currentWritePos = 0;
   }

   //[/user-ProcessSample]
}


//-------------------------------------------------------------------------------
//  public void ProcessBypassedSample()

//  ProcessBypassedSample gets called instead of ProcessSample when you've checked the "Can Be Bypassed" box
//  and a user has bypassed your module. If your module processes data from input jacks and then sends it to
//  output jack(s), make ProcessBypassedSample just send the data from the input jacks to the output jacks without
//  processing it.
//-------------------------------------------------------------------------------
@Override
public void ProcessBypassedSample()
{
   //[user-ProcessBypassedSample]   Add your own code here

   outputAudio.SetValue(inputAudio.GetValue());

   //[/user-ProcessBypassedSample]
}


//-------------------------------------------------------------------------------
//  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 VoltageLabel textLabel34;
private VoltageLabel textLabel33;
private VoltageLabel textLabel18;
private VoltageLabel textLabel10;
private VoltageLabel textLabel21;
private VoltageLabel textLabel17;
private VoltageKnob feedbackKnob;
private VoltageLabel textLabel16;
private VoltageLabel textLabel20;
private VoltageLabel textLabel19;
private VoltageLabel textLabel15;
private VoltageLabel textLabel9;
private VoltageLabel textLabel8;
private VoltageAudioJack outputAudio;
private VoltageKnob knobDryWetMix;
private VoltageAudioJack inputAudio;
private VoltageKnob attenKnobCV;
private VoltageAudioJack inputCV;
private VoltageKnob millisecondsKnob;


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


// Constants

private final int DELAY_LINE_LENGTH = 2510;
private final int SAMPLES_PER_MS = (int)Values.SamplesPerMs;
private final int MAX_DELAY_IN_MS = 2500;
private final int MAX_DELAY_IN_SAMPLES = MAX_DELAY_IN_MS * SAMPLES_PER_MS;
private final int DELAY_LINE_LENGTH_IN_SAMPLES = DELAY_LINE_LENGTH * SAMPLES_PER_MS;


private final double CV_RANGE_LOW  = 10.0;                     // 10 samples per volt
private final double CV_RANGE_HIGH = 10.0 * SAMPLES_PER_MS;    // 10 milliseconds per volt
private final double CV_RANGE_FULL = 250.0 * SAMPLES_PER_MS;   // 250 milliseconds per volt
private final double INITIAL_DELAY_SLEW_FACTOR = 0.99995;      // Roughly 10 seconds RC factor
private final double CV_RANGE_MULTIPLIER = 9.6;                // 48 (samples) / 5 (volts)

// Variables

private int basicDelayMsCount;      // As read from knob
private int basicDelaySampleCount;  // As read from knob
private int intDelayInSamples;
private double doubleDelayInSamples;   // Actual calculated basic delay
private double slewedDelayInSamples;   // Basic delay knob slewed
private double doubleDelayInMS;        // Basic delay for display.
private double previousDelayInMS;      // Check changed delay for display.
private String delayDisplayedValue;

private double[] delayLine = new double[DELAY_LINE_LENGTH_IN_SAMPLES];

private int currentWritePos;
private double previousFeedbackValue;  // Used for feedback in next iteration.

private boolean audioInConnected;
private boolean audioOutConnected;
private boolean extCVInConnected;

// Objects

private SmoothValue smoothFeedback = new SmoothValue();
private SmoothValue smoothCVDepth = new SmoothValue();
private SmoothValue smoothMix = new SmoothValue();

// Functions

private void CheckConnections()
{
   audioInConnected = inputAudio.IsConnected();
   audioOutConnected = outputAudio.IsConnected();
}


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

 