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)