Reputation: 81
I have a delphi VCL form with three button components. Having clicked a button a short 4 second audio file .wav (in a resource file) associated with that particular button then plays.
When clicking a button for the first time after the program opens an annoying delay of about 1/2 second occurs before playing starts. No such delay occurs from clicking a button within 5 seconds or so of a file having played, though with longer intervals the delay recurs. Nor does a delay arise from interrupting playing by clicking a button before the currently playing file has finished.
How can I get rid of these delays, or at least reduce them substantially? The sound files themselves have no silent lead ins. Here's the code (Delphi community edition):
unit Unit8;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
type
TForm8 = class(TForm)
Button1: TButton;
Button2: TButton;
Button3: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
private
public
end;
var
Form8: TForm8;
implementation
{$R *.dfm}
procedure TForm8.Button1Click(Sender: TObject);
begin
PlaySound('Resource_1', HInstance, SND_RESOURCE or SND_NODEFAULT or SND_ASYNC or SND_SENTRY);
end;
procedure TForm8.Button2Click(Sender: TObject);
begin
PlaySound('Resource_2', HInstance, SND_RESOURCE or SND_NODEFAULT or SND_ASYNC or SND_SENTRY);
end;
procedure TForm8.Button3Click(Sender: TObject);
begin
PlaySound('Resource_3', HInstance, SND_RESOURCE or SND_NODEFAULT or SND_ASYNC or SND_SENTRY);
end;
end.
Upvotes: 1
Views: 483
Reputation: 8261
You are effectively asking Windows to re-load the .WAV data from the .EXE file each and every time you play it. This will take a little while, unless the data is still in the cache (which is why it takes longer if you wait long enough for the data to be "thrown out" of the cache - Windows then has to re-load the data from the .EXE file).
You should therefore cache the data in your own application once at startup (FormCreate) and then use the cached data when playing back the sound.
Use this function to read a resource into a TBytes
:
FUNCTION LoadResource(CONST ResourceName : STRING) : TBytes;
VAR
S : TStream;
SZ : Int64;
BEGIN
S:=TResourceStream.Create(HInstance,ResourceName,RT_RCDATA);
TRY
SZ:=S.Size;
SetLength(Result,SZ);
S.Read(Result,0,SZ)
FINALLY
FreeAndNIL(S)
END
END;
Then use this function as the basis to play the sound:
FUNCTION PlayWAV(CONST Data : TBytes ; Flags : UINT = SND_ASYNC) : BOOLEAN;
BEGIN
Result:=sndPlaySound(PChar(Data),Flags OR SND_MEMORY)
END;
Upvotes: 4