Reduce CPU time spent in VCL

∥☆過路亽.° 提交于 2019-12-05 21:24:39

You won't be able to change the world, nor VCL nor Windows. I suspect you are asking to much to those...

IMHO you should better change a little bit your architecture:

  • Sound processing shall be in one (or more) separated thread(s), and should not be at all linked to the UI (e.g. do not send GDI messages from it);
  • UI refresh shall be made using a timer with a 500 ms resolution (half a second refresh sounds reactive enough), not every time there is a change.

That is, the sequencer won't refresh the UI, but the UI will ask periodically the sequencer what is its current status. This will be IMHO much smoother.

To answer your exact questions:

  • "Moving a bevel" is in fact sending several GDI messages, and the rendering will be made by the GDI stack (gdi32.dll) using a temporary bitmap;
  • Try to use a smaller bitmap, or try using a Direct X buffer mapping;
  • Try DoubleBuffered := true on your TForm.OnCreate event, or use a dedicated component (TPaintBox) with a global bitmap for the whole component content, with something like that for the message WM_ERASEBKGND.

Some code:

   procedure TMyPaintBox.WMEraseBkgnd(var Message: TWmEraseBkgnd);
   begin
     Message.Result := 1; // no erasing is necessary after this method call
   end;

I have the feeling that your bitmap buffering is wrong. When you move your clip it shouldn't have to be redrawn at all. you could try with This clip component structure:

TMidiClip = Class(TControl)
Private
 FBuffer: TBitmap;
 FGridPos: TPoint;
 FHasToRepaint: Boolean;
Public
  Procedure Paint; Override; // you only draw the bitmap on the control canvas
  Procedure Refresh; // you recompute the FBuffer.canvas
End;

When you change some properties such as "clip tick length" you set "FHasToRepaint" to true but not when changing "FGridPos" (position on the grid). So most of the time, in your Paint event, you only have a copy of your FBuffer.

Actually, this is very dependent on the design of your grid and its children (clips). I might be wrong but it seems that your design is not enough decomposed in Controls: the master grid should be a TControl, a clip should be a TControl, even the events on a clip should be some TControls...You can only define a strongly optimized bitmap-buffering system by this way (aka "double-buffering").

About the Timer: you should use a musical clock which processes per audio sample otherwise you can't have a good enough resolution. Such a clock can be implemented using the "Windows Audio driver" (mmsystem.pas) or an "Asio" driver (you have an interface in BASS, The Delphi Asio Vst project, for example).

By far the best way to tackle this is to stop the GUI message queue interfering with your MIDI player. Put the MIDI player on a background thread so that it can do its work without interruption from the main thread. Naturally this relies on you running on a machine with more than a single processor but it's not unreasonable to take that for granted nowadays.

Judging from your comments it looks like your audio processing is being blocked by the UI thread. Don't let that happen and your audio problems will disappear. If you are using something like TThread.Synchronize to fire VCL events from the audio thread then that will block on the UI thread. Use an asynchronous communication method instead.

Your proposed alternative of speeding up the VCL is not really viable. You can't modify the VCL and even if you could, the bottleneck could easily be the underlying Windows code.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!