代码之家  ›  专栏  ›  技术社区  ›  Mariner

减少音频文件播放前的延迟

  •  1
  • Mariner  · 技术社区  · 6 年前

    我有一个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.
    
    1 回复  |  直到 6 年前
        1
  •  4
  •   HeartWare    6 年前

    实际上,每次播放时都会要求Windows从.EXE文件重新加载.WAV数据。这将需要一段时间,除非数据仍在缓存中(这就是为什么如果等待足够长的时间才能将数据“抛出”缓存,则需要更长的时间-然后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;