hi
ich arbeite mal wieder an meinen Bass(.dll) komponenten, die komponenten sind mittlerweile so kompliziert geworden
dass es immer schwieriger wird die zu managen! zum beispiel die Sound-Recorder komponente, die hat vier haupt threads(feeder)
und wenn einer der threads zu schnell oder zu langsam ist bricht das ganze zusammen.
und hier komme ich auch gleich zu meiner frage. was ist die eleganteste lösung um threads oder das innenleben
perfect zu takten?
zur zeit benutze ich zwei verschieden methoden Sleep(x) und TSimpleEvent. vielleicht hat einer von euch noch einen dritten vorschlag
für den unteren code, das timing muss 100% präzise sein damit der buffer nicht lehr läuft.
Delphi-Quellcode:
procedure TBassRecorder.RecThreadWorkerCallback(Thread: TMultiThreadThread;
Parameters : TObject; var Data, Results : TObject);
var
FBuff : array [0..50000] of Byte;
FData : DWORD;
WorkMessage: TWorkMessage;
WorkResult: TWorkResult;
begin
WorkMessage := TWorkMessage.Create;
WorkMessage.ID := TWork(Data).ID;
WorkMessage.Text := 'Starting';
WorkMessage.Status:= thStarting;
Thread.SendMessage(WorkMessage, nil);
repeat
Sleep(TWork(Data).TimeToWait); //TimeToWait = 1
if not ThreadPause[THREAD_REC] then
begin
FData:= BASS_ChannelGetData(Channel[CHANN_REC_MIXER], @FBuff, SizeOf(FBuff));
if FData = DW_ERROR then
begin
Break;
// Error
end;
end;
until
Thread.Terminated or (Channel[CHANN_REC_MIXER] = 0);
if Thread.Terminated then
begin
WorkMessage := TWorkMessage.Create;
WorkMessage.ID := TWork(Data).ID;
WorkMessage.Text := 'Terminated';
WorkMessage.Status:= thTerminated;
Thread.SendMessage(WorkMessage, nil);
end;
WorkResult := TWorkResult.Create;
WorkResult.ID := TWork(Data).ID;
WorkResult.Text := 'Finished'; //finished successfuly.
WorkResult.Status:= thFinished;
Results := WorkResult;
end;
Delphi-Quellcode:
procedure TBassRecorder.VasThreadWorkerCallback(Thread: TMultiThreadThread; Parameters: TObject; var Data, Results: TObject);
var
Time : QWORD;
Level : DWORD;
Active : Boolean;
Timer: TWaitResult;
WorkMessage : TWorkMessage;
WorkResult : TWorkResult;
begin
WorkMessage := TWorkMessage.Create;
WorkMessage.ID := TWork(Data).ID;
WorkMessage.Text := 'Starting';
WorkMessage.Status:= thStarting;
Thread.SendMessage(WorkMessage, nil);
repeat
if not ThreadPause[THREAD_VAS] then
begin
Level:= BASS_Mixer_ChannelGetLevel(Channel[CHANN_VIS_SPLIT]);
Active:= (LOWORD(Level) >= FVAS_Threshold) or
(HIWORD(Level) >= FVAS_Threshold);
(* sound is coming through *)
if Active then
begin
(* continue recording when the sound starts up again. *)
...
(* start a new recording ehen the sound starts up again. *)
...
end;
Timer:= TWork(Data).TimeEvent.WaitFor(TWork(Data).TimeToWait); // 1000 = 1 Sec.
if Timer = wrTimeout then
begin
(* sound is not coming through *)
if not Active then
begin
(* Pause Recording after X Sec. of silence *)
...
(* Pause Recording after X Sec. of silence *)
...
(* Stop Recording after X Sec. of silence *)
...
end;
end;
end;
until
(FVAS_ForceStop) or
(Timer <> wrTimeout) or
(Thread.Terminated) or
(Application.Terminated);
if Thread.Terminated then
begin
WorkMessage := TWorkMessage.Create;
WorkMessage.ID := TWork(Data).ID;
WorkMessage.Text := 'Terminated';
WorkMessage.Status:= thTerminated;
if Assigned(TWork(Data).TimeEvent) then
TWork(Data).TimeEvent.SetEvent;
Thread.SendMessage(WorkMessage, nil);
end;
WorkResult := TWorkResult.Create;
WorkResult.ID := TWork(Data).ID;
WorkResult.Text := 'Finished'; //finished successfuly.
WorkResult.Status:= thFinished;
if Assigned(TWork(Data).TimeEvent) then
TWork(Data).TimeEvent.SetEvent;
Results := WorkResult;
end;