Registriert seit: 29. Mär 2009
439 Beiträge
|
AW: Zeitcode
27. Jul 2018, 08:49
Um Rundungsfehler zu vermeiden, würde ich mit Sekunden und Frames rechnen. Wenn die maximale Anzahl der FPS überschritten wird, muss der Übertrag berücksichtigt werden.
Diese Lösung sollte mit allen Timecodes funktionieren die ganzzahlige fps haben (also z.B. nicht 23.976fps). Man muss lediglich die Konstante fps anpassen.
Delphi-Quellcode:
program Project1;
{$APPTYPE CONSOLE}
{$R *.res}
uses
Types, SysUtils, Math, StrUtils;
type
TCDTimecode = record
h, m, s, f: Word;
neg: Boolean;
function GetSeconds: Integer; // h, m, s => seconds
procedure SetSeconds(Seconds: Integer);
procedure Add( const t: TCDTimecode);
function GetAsString: String;
procedure SetAsString( const tc: String);
end;
{ TCDTimecode }
procedure TCDTimecode.Add( const t: TCDTimecode);
const
fps = 75;
var
s: Integer;
f: Integer;
begin
s := Self.GetSeconds + t.GetSeconds;
f := Self.f;
if Self.neg
then
f := -f;
if t.neg
then
dec(f, t.f)
else
inc(f, t.f);
if f<0
then begin
inc(f, fps);
dec(s); // Carry
end
else
if f>=fps
then begin
dec(f, fps);
inc(s); // Carry
end;
SetSeconds(s);
Self.f := Word(f);
end;
function TCDTimecode.GetAsString: String;
const
sign: array [Boolean] of String = (' +', ' -');
begin
Result := Format(' %s%.2d:%.2d:%.2d:%.2d', [sign[neg], h, m, s, f])
end;
function TCDTimecode.GetSeconds: Integer;
begin
Result := h * SecsPerHour + m * SecsPerMin + s;
if neg
then
Result := -Result;
end;
procedure TCDTimecode.SetAsString( const tc: String);
var
List: TStringDynArray;
t: Integer;
begin
List := SplitString(tc, ' :');
if length(List) = 4
then begin
t := StrToInt(List[0]);
neg := t<0;
h := abs(t);
m := StrToInt(List[1]);
s := StrToInt(List[2]);
f := StrToInt(List[3]);
end
else
raise Exception.CreateFmt(' invalid timecode "%s"', [tc]);
end;
procedure TCDTimecode.SetSeconds(Seconds: Integer);
begin
neg := Seconds<0;
divmod(Cardinal(abs(Seconds)), SecsPerHour, h, m);
divmod(Cardinal(m), SecsPerMin, m, s);
end;
var
t1, t2: TCDTimecode;
begin
try
t1.SetAsString(' 03:00:00:12');
t2.SetAsString(' -01:00:00:12');
t1.Add(t2);
writeln(t1.GetAsString);
t1.SetAsString(' 03:00:00:12');
t2.SetAsString(' -01:00:00:13');
t1.Add(t2);
writeln(t1.GetAsString);
readln;
except
on E: Exception do
Writeln(E.ClassName, ' : ', E. Message);
end;
end.
Ausgabe
+02:00:00:00
+01:59:59:74
Geändert von samso (27. Jul 2018 um 09:03 Uhr)
Grund: Einschränkung auf ganzzahlige Frameraten
|
|
Zitat
|