Swing

In the image below (also see the patch further down):

  TModClockGen = class( TMod)
  strict private
  const
    i_reset   = 0;
    i_tempo   = 1;
    i_swing   = 2;
    i_mute    = 3;
    i_div     = 4;
  const
    o_16      = 0;
    o_96      = 1;
    o_sync    = 2;
    o_phase16 = 3;
    o_phase96 = 4;
  private
    FPhase16     : TSignal; // Phase acuumulator for * 16 output
    FPhase96     : TSignal; // Phase acuumulator for * 96 output
    FOldRes      : Boolean; // Old reset value
    FOldMute     : Boolean; // Old mute state
    FEven        : Boolean; // Even / Odd cycle for * 16 output
    FState       : Boolean; // * 96 state
    FSwing       : TSignal; // Current Swing value
    FDividerSync : Integer; // Divider for sync output
    FResCount    : Integer; // Reset LED counter
  public
    constructor Create( aParent: TSynthPatch; const aName: string);                              override;
    procedure   DoSlowTick;                                                                      override;
    procedure   GatherLights( const aPrefix: string; const aCallback: TLightsHandler);           override;
    function    InputName ( anIndex: Integer): string;                                           override;
    function    OutputName( anIndex: Integer): string;                                           override;
  end;


    procedure   TModClockGen.DoSlowTick; // override;
    var
      Delta96 : TSignal;
      Delta16 : TSignal;
      DidWrap : Boolean;
      Muted   : Boolean;
      Reset   : Boolean;
      SyncDiv : Integer;
    begin
      Reset   := SignalToLogic( FInputs[ i_reset]);
      Muted   := SignalToMute ( FInputs[ i_mute ]) < 0.5;
      SyncDiv := Round( FInputs[ i_div]);

      if ResetFlag or ( not FOldRes and Reset) or ( FOldMute and not Muted)
      then begin
        FPhase96     := 0.0;
        FPhase16     := 0.0;
        FEven        := True;
        FState       := True;
        FDividerSync := 0;
        FResCount    := Round( SlowTimeToSampleCount( 125e-3));
        FSwing       := 0.5;
      end;

      ResetFlag := False;
      FOldRes   := Reset;
      FOldMute  := Muted;
      Delta96   := LookupLfoBPMPhaseDelta( FInputs[ i_tempo]) * 24;
      Delta16   := LookupLfoBPMPhaseDelta( FInputs[ i_tempo]) *  4;
      FPhase96  := FPhase96 + Delta96;
      FPhase16  := FPhase16 + Delta16;
      DidWrap   := False;

      while FPhase96 > 1.0
      do begin
        if not DidWrap
        then begin
          DidWrap := True;
          FState  := True;
          Inc( FDividerSync);

          if FDividerSync > 24 * SyncDiv - 1
          then FDividerSync := 0;
        end;

        FPhase96 := FPhase96 - 1.0;
      end;

      if FState
      then begin
        if FPhase96 > 0.5
        then FState := False;
      end;

      DidWrap   := False;

      while FPhase16 > 1.0
      do begin
        if not DidWrap
        then begin
          DidWrap := True;
          FEven   := not FEven;

          if FEven
          then FSwing := 0.5
          else FSwing := FInputs[ i_swing];
        end;

        FPhase16 := FPhase16 - 1.0;
      end;

      if FResCount > 0
      then Dec( FResCount);

      if Muted
      then begin
        FOutputs[ o_16     ] := LogicToSignal( False);
        FOutputs[ o_96     ] := LogicToSignal( False);
        FOutputs[ o_sync   ] := LogicToSignal( False);
        FOutputs[ o_phase16] := 0;
        FOutputs[ o_phase96] := 0;
      end
      else begin
        FOutputs[ o_16     ] := LogicToSignal( FPhase16 > FSwing);
        FOutputs[ o_96     ] := LogicToSignal( FState           );
        FOutputs[ o_sync   ] := LogicToSignal( FDividerSync = 0 );
        FOutputs[ o_phase16] := FPhase16;
        FOutputs[ o_phase96] := FPhase96;
      end;
    end;