Einzelnen Beitrag anzeigen

Medium

Registriert seit: 23. Jan 2008
3.686 Beiträge
 
Delphi 2007 Enterprise
 
#13

AW: Zwei unabhängige Zeitschleifen D7

  Alt 29. Aug 2014, 10:20
Sieh den gesamten zeitlichen Ablauf mal durch nur einen einzigen Taktgeber bestimmt, und sowohl deine Szene als auch einzelne Fades als Arrays, deren Index in Zeit angegeben wird (mal so hypothetisch). Die eigentliche Hauptaufgabe ist es dann zu jedem Timer Event einfach nur die Werte der einzelnen Arrays zum DMX Interface zu schicken. Ein Array mit 4 Elementen würde bei 250ms Takt einer Sekunde entsprechen. Ich versuche mal Pseudocode. (Skizze in Pascal-Art, kein C&P fähiger Code.)

Delphi-Quellcode:
type
  TFadeBlock = class
  private
    FValues: array of Byte;
    FStartTime: Integer;
  public
    property StartTime: Integer;
    property Values[index: Integer]: Byte;
    constructor Create(aStartTime, aLengthInSec: Integer);
    function GetValueAtTime(aTime: Integer): Byte;
  end;

  TMyForm = class(TForm)
  private
    Channels: array[1..479] of TFadeBlock;
    Scene: array of TSceneEvent;
    CurrentTime: Integer;
  end;

implementation

constructor TFadeBlock.Create(aStartTime, aLengthInSec: Integer);
begin
  SetLength(FValues, aLengthInSec*(1/TimerInterval));
  FStartTime := aStartTime;
end;

function GetValueAtTime(aTime: Integer): Byte;
var
  i: Integer;
begin
  i := Max(Low(FValues), Min(aTime-FStartTime, High(FValues)));
  result := FValues[i];
end;

//--------------

procedure TMyForm.OnTimerEvent;
begin
  // Channel-Liste anhand von Szenenanweisungen mit Fade-Blöcken versehen
  if Assigned(SceneEvents[CurrentTime]) then
  begin
    Event := SceneEvents[CurrentTime];
    Channel := Event.Channel;
    Channels[Channel] := TFadeBlock.Create(CurrentTime, Event.LengthInSec);
    for i := 0 to High(Channels[Channel].Values) do // Internes Value-Array des Blocks mit den interpolierten Werten beschreiben, schöner wäre es noch wenn die Fade-Klasse dies selber täte
      Channels[Channel].Values[i] := Interpolate(Event.StartValue, Event.EndValue, i);
  end;
  
  // Nun einfach alle Kanäle "fragen" welchen Wert sie denn gerade haben, und den ausgeben
  for i := Low(Channels) to High(Channels) do
  begin
    if Assigned(Channels[i]) then
      OutputDMX(Channels[i].GetValueAtTime(CurrentTime), i);
  end;
  
  Inc(CurrentTime);
end;
Da das Szenen-Array ggf. etwas lang würde wenn man das Intervall kleiner macht (was sinnvoll wäre, da Fades mit 250ms nicht so toll aussehen), sollte man dafür vielleicht eher eine Liste nehmen, deren Index nicht der Zeit entspricht, sondern wo jeder Eintrag seine Startzeit als Feld bekommt. Dann muss man zwar pro Timer-Event alle Szenenanweisungen durchgehen, und schauen ob jetzt eine davon ansteht, aber das sollte selbst bei ein paar Tausend keine merkbare Performance kosten.

Und ja, das ist mit Delphi geschrieben. Da ich dafür TurboPower AsyncPro (COM-Port) nutze und dies nur für Delphi 7 parat hatte, ist es sogar noch Delphi 7.
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)

Geändert von Medium (29. Aug 2014 um 10:23 Uhr)
  Mit Zitat antworten Zitat