Firemonkey TTimer はざっくりしすぎているので、TStopWatch を使って正確な時間を測る。
これでずいぶん正確になった。
unit untTaskIndicater;
interface
uses
untViewer,
untWordDic,
untWaveFilePlayer,
untClientManager,
System.Diagnostics,
MMsystem,
FMX.Filter.Effects,
FMX.Objects,
FMX.Types,
FMX.Dialogs,
System.Types,
System.UITypes,
SysUtils;
const
CLOCK_INTERVAL = 5;
type
TTaskIndicator = class
private
FWordRecord: TWordRecord;
FRoughTimer: TTimer;
FIndicatingIndex: Integer;
FIsVoiceOnly: Boolean;
FStopwatch :TStopwatch;
procedure OnRoughTimer(Sender: TObject);
public
constructor Create();
destructor Destroy(); override;
procedure Reset();
procedure Indicate(aWordRecord: TWordRecord; aIsVoiceOnly: Boolean);
end;
implementation
uses
untModel,
untMainForm;
constructor TTaskIndicator.Create;
begin
FStopwatch.Create;
FRoughTimer := TTimer.Create(nil);
FRoughTimer.OnTimer := OnRoughTimer;
FRoughTimer.Enabled := False;
FRoughTimer.Interval := CLOCK_INTERVAL;
end;
destructor TTaskIndicator.Destroy;
begin
FRoughTimer.Free;
inherited;
end;
procedure TTaskIndicator.Indicate(aWordRecord: TWordRecord; aIsVoiceOnly: Boolean);
var
i: Integer;
begin
FIsVoiceOnly := aIsVoiceOnly;
FWordRecord := aWordRecord;
Viewer.DispAllPlanes();
// タイマーが動く前に再生開始が望ましい
WaveFilePlayer.Play(FWordRecord.VoiceStream);
FRoughTimer.Enabled := True;
FStopwatch.Reset;
FStopwatch.Start;
FIndicatingIndex := -1;
end;
procedure TTaskIndicator.OnRoughTimer(Sender: TObject);
var
tmpTime: Integer;
begin
// For Pause
if Model.IsPausing then Exit;
tmpTime := FStopwatch.ElapsedMilliseconds;
// 終了条件
if FWordRecord.IndicateScheduleArray[Length(FWordRecord.IndicateScheduleArray)-1].EndTime <= tmpTime then
begin
Viewer.DeAccentPlane(Length(FWordRecord.IndicateScheduleArray)-1);
if not FIsVoiceOnly then Viewer.DispAllPlanes();
FRoughTimer.Enabled := False;
FStopwatch.Stop;
Model.onIndicaterFinished(); // 終わりを知らせる
end;
if not FIsVoiceOnly then
begin
if FWordRecord.IndicateScheduleArray[FIndicatingIndex+1].StartTime <= tmpTime then
begin
FIndicatingIndex := FIndicatingIndex + 1;
if FIndicatingIndex <> 0 then Viewer.DeAccentPlane(FIndicatingIndex-1);
Viewer.AccentPlane(FIndicatingIndex);
end;
end;
end;
procedure TTaskIndicator.Reset;
begin
FRoughTimer.Enabled := False;
end;
end.
正確なタイマーを無理やり作る
コメントをどうぞ