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;