减少音频文件播放前的延迟
Reduce delay before audio file plays
我有一个包含三个按钮组件的 delphi VCL 窗体。单击按钮后,将播放与该特定按钮关联的 4 秒短音频文件 .wav(在资源文件中)。
程序打开后第一次单击按钮时,播放开始前会出现大约 1/2 秒的恼人延迟。在文件播放后 5 秒左右的时间内单击按钮不会发生此类延迟,但间隔较长时会再次出现延迟。在当前播放文件完成之前单击按钮中断播放也不会产生延迟。
我怎样才能摆脱这些延迟,或者至少大大减少它们?声音文件本身没有无声导入。这是代码(Delphi 社区版):
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.
您实际上是在要求 Windows 每次播放 .EXE 文件时重新加载 .WAV 数据。这将需要一些时间,除非数据仍在缓存中(这就是为什么如果您等待足够长的时间让数据成为缓存的 "thrown out" - Windows 然后必须重新- 从 .EXE 文件加载数据)。
因此,您应该在启动时 (FormCreate) 将数据缓存在您自己的应用程序中,然后在播放声音时使用缓存的数据。
使用此函数将资源读入 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;
然后以这个函数为基础播放声音:
FUNCTION PlayWAV(CONST Data : TBytes ; Flags : UINT = SND_ASYNC) : BOOLEAN;
BEGIN
Result:=sndPlaySound(PChar(Data),Flags OR SND_MEMORY)
END;
我有一个包含三个按钮组件的 delphi VCL 窗体。单击按钮后,将播放与该特定按钮关联的 4 秒短音频文件 .wav(在资源文件中)。
程序打开后第一次单击按钮时,播放开始前会出现大约 1/2 秒的恼人延迟。在文件播放后 5 秒左右的时间内单击按钮不会发生此类延迟,但间隔较长时会再次出现延迟。在当前播放文件完成之前单击按钮中断播放也不会产生延迟。
我怎样才能摆脱这些延迟,或者至少大大减少它们?声音文件本身没有无声导入。这是代码(Delphi 社区版):
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.
您实际上是在要求 Windows 每次播放 .EXE 文件时重新加载 .WAV 数据。这将需要一些时间,除非数据仍在缓存中(这就是为什么如果您等待足够长的时间让数据成为缓存的 "thrown out" - Windows 然后必须重新- 从 .EXE 文件加载数据)。
因此,您应该在启动时 (FormCreate) 将数据缓存在您自己的应用程序中,然后在播放声音时使用缓存的数据。
使用此函数将资源读入 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;
然后以这个函数为基础播放声音:
FUNCTION PlayWAV(CONST Data : TBytes ; Flags : UINT = SND_ASYNC) : BOOLEAN;
BEGIN
Result:=sndPlaySound(PChar(Data),Flags OR SND_MEMORY)
END;