zoukankan      html  css  js  c++  java
  • 在 Delphi 下使用 DirectSound (8): IDirectSound8.DuplicateSoundBuffer() 与 IDirectSoundBuffer.GetStatus()


    IDirectSoundBuffer.GetStatus() 用于获取缓冲区的当前状态, 譬如是否正在播放、是否指定为循环播放等等.

    IDirectSound8.DuplicateSoundBuffer() 是通过根据已存在的缓冲区建立缓冲区副本, 这类似引用; 通过它可以让同一个声音交叉播放.
    复制缓冲区不能复制主缓冲区.

    示例:
    unit Unit1;
    
    interface
    
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls;
    
    type
      TForm1 = class(TForm)
        Button1: TButton;     //播放 buf
        Button2: TButton;     //播放 bufs[0]
        Button3: TButton;     //播放 bufs[1]
        Button4: TButton;     //全部停止
        CheckBox1: TCheckBox; //控制是否循环播放
        procedure FormCreate(Sender: TObject);
        procedure FormDestroy(Sender: TObject);
        procedure Button1Click(Sender: TObject);
        procedure Button3Click(Sender: TObject);
        procedure Button2Click(Sender: TObject);
        procedure Button4Click(Sender: TObject);
        procedure CheckBox1Click(Sender: TObject);
      end;
    
    var
      Form1: TForm1;
    
    implementation
    
    {$R *.dfm}
    
    uses DirectSound, MMSystem, ReadWave; //ReadWave 是前面(7)自定义的单元
    
    var
      myDSound: IDirectSound8;
      buf: IDirectSoundBuffer; //准备用这个缓冲区载入波形
      bufs: array[0..1] of IDirectSoundBuffer; //这个缓冲区数组都将复制上面的 buf
      loop: DWORD = 0; //是否循环播放; 0:不循环; 1(DSBPLAY_LOOPING):循环
    
    {判断缓冲区是否正在播放的函数}
    function IsPlay(b: IDirectSoundBuffer): Boolean;
    var
      dStatus: DWORD;
    begin
      Result := b <> nil;
      if Succeeded(b.GetStatus(dStatus)) then
        Result := dStatus and DSBSTATUS_PLAYING = DSBSTATUS_PLAYING;
    end;
    
    {初始化设备}
    procedure TForm1.FormCreate(Sender: TObject);
    var
      wavFormat: TWaveFormatEx;
      bufDesc: TDSBufferDesc;
      wavPath: string;
      wav: TReadWave;
      p1: Pointer;
      n1: DWORD;
      i: Integer;
    begin
      with TOpenDialog.Create(nil) do begin
        Filter := 'Wave File(*.wav)|*.wav';
        if Execute then wavPath := FileName;
        Free;
      end;
    
      wav := TReadWave.Create;
      if not wav.Open(wavPath) then
      begin
        ShowMessage('打开失败');
        wav.Free;
        Application.Terminate;
      end;
    
      DirectSoundCreate8(nil, myDSound, nil);
      myDSound.SetCooperativeLevel(Handle, DSSCL_NORMAL);
    
      ZeroMemory(@bufDesc, SizeOf(TDSBufferDesc));
      bufDesc.dwSize := SizeOf(TDSBufferDesc);
      bufDesc.dwFlags := DSBCAPS_STATIC;
      bufDesc.dwBufferBytes := wav.Size;
      bufDesc.lpwfxFormat := @wav.Format;
    
      {建立 buf 并载入波形}
      myDSound.CreateSoundBuffer(bufDesc, buf, nil);
      buf.Lock(0, 0, @p1, @n1, nil, nil, DSBLOCK_ENTIREBUFFER);
      wav.Read(p1, n1);
      wav.Free;
      buf.Unlock(p1, n1, nil, 0);
    
      {根据 buf 复制几个缓冲区}
      for i := Low(bufs) to High(bufs) do
      begin
        myDSound.DuplicateSoundBuffer(buf, bufs[i]);
      end;
    end;
    
    {播放或暂停 buf}
    procedure TForm1.Button1Click(Sender: TObject);
    begin
      if IsPlay(buf) then buf.Stop else buf.Play(0, 0, loop);
    end;
    
    {播放或暂停 buf[0]}
    procedure TForm1.Button2Click(Sender: TObject);
    begin
      if IsPlay(bufs[0]) then buf.Stop else bufs[0].Play(0, 0, loop);
    end;
    
    {播放或暂停 buf[1]}
    procedure TForm1.Button3Click(Sender: TObject);
    begin
      if IsPlay(bufs[1]) then buf.Stop else bufs[1].Play(0, 0, loop);
    end;
    
    {全部停止}
    procedure TForm1.Button4Click(Sender: TObject);
    var
      i: Integer;
    begin
      if buf <> nil then buf.Stop;
      for i := Low(bufs) to High(bufs) do if bufs[i] <> nil then bufs[i].Stop;
    end;
    
    {切换是否循环播放, 没有对正在播放的缓冲区进行控制}
    procedure TForm1.CheckBox1Click(Sender: TObject);
    begin
      loop := DWORD(CheckBox1.Checked);
    end;
    
    procedure TForm1.FormDestroy(Sender: TObject);
    var
      i: Integer;
    begin
      buf := nil;
      for i := Low(bufs) to High(bufs) do bufs[i] := nil;
      myDSound := nil;
    end;
    
    end.
    

  • 相关阅读:
    Adodb.recorset中Field字段的属性及意义
    郁闷的新一篇
    最近身体越来越差了。。。
    成事在天,谋事在人
    我要带我老婆去看看机场...
    Javascript 时间比较
    同步异步传输
    使用WSPBuilder 生成wsp文件,部署,激活,使用
    动态添加SqlParameter
    C#几种排序方法
  • 原文地址:https://www.cnblogs.com/del/p/1939944.html
Copyright © 2011-2022 走看看