在 Delphi 下使用 DirectSound (18): 3D 特效


DirectSound 3D 特效相关接口: IDirectSound3DBuffer8、IDirectSound3DListener8.

IDirectSound3DBuffer8 是声源, 它可以有一个或多个; IDirectSound3DListener8 是听者, 它只能有一个.

IDirectSound3DBuffer8 通过 QueryInterface() 从次缓冲获取, 要求该次缓冲建立时必须指定 DSBCAPS_CTRL3D;
IDirectSound3DListener8 通过 QueryInterface() 从主缓冲区获取, 该主缓冲区建立时也必须指定 DSBCAPS_CTRL3D.

"声源" 和 "听者" 可以交互变换, 也可独立变换; 只变换 "听者" 时, 提供声音的缓冲区建立时也应该指定 DSBCAPS_CTRL3D.
IDirectSound3DBuffer8 其实只负责 3D 效果变换, 真正提供声音和播放控制的还是它之前的 IDirectSound3DBuffer 或 IDirectSound3DBuffer8.

IDirectSound3DBuffer8 相关方法:
{3D 音效处理模式}
GetMode()、SetMode()
  DS3DMODE_NORMAL       = $00000000; //普通
  DS3DMODE_HEADRELATIVE = $00000001; //声源的参数是相对于听者的
  DS3DMODE_DISABLE      = $00000002; //禁用 3D 特效

{最大、最小距离}
GetMaxDistance()、SetMaxDistance()
GetMinDistance()、SetMinDistance()

{位置、速度、方向}
GetPosition()、SetPosition()
GetVelocity()、SetVelocity()
GetConeOrientation()、SetConeOrientation()

{声源椎参数}
GetConeAngles()、SetConeAngles()
GetConeOutsideVolume()、SetConeOutsideVolume()

{一起获取或设置参数}
GetAllParameters()、SetAllParameters()


IDirectSound3DListener8 相关方法:
{位置、速度、方向}
GetPosition()、SetPosition()
GetVelocity()、SetVelocity()
GetOrientation()、SetOrientation()

{距离因子、多普勒因子、滚降因子}
GetDistanceFactor()、SetDistanceFactor() 
GetDopplerFactor()、SetDopplerFactor()
GetRolloffFactor()、SetRolloffFactor()

{一起获取或设置参数}
GetAllParameters()、SetAllParameters()

{延迟设置}
CommitDeferredSettings() //在使用系列 Set... 方法时, 如果指定了 DS3D_DEFERRED 参数, 则需用该方法提交参数设置;
                         //和 DS3D_DEFERRED = 1 对应的是 DS3D_IMMEDIATE = 0, 表示立即生效; 使用延迟设置更节省资源.


测试代码(测试文件须是单声道的 Wave):
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    RadioGroup1: TRadioGroup;
    RadioGroup2: TRadioGroup;
    GroupBox1: TGroupBox;
    LabeledEdit1: TLabeledEdit;
    LabeledEdit2: TLabeledEdit;
    LabeledEdit3: TLabeledEdit;
    LabeledEdit4: TLabeledEdit;
    LabeledEdit5: TLabeledEdit;
    LabeledEdit6: TLabeledEdit;
    LabeledEdit7: TLabeledEdit;
    LabeledEdit8: TLabeledEdit;
    LabeledEdit9: TLabeledEdit;
    LabeledEdit10: TLabeledEdit;
    LabeledEdit11: TLabeledEdit;
    LabeledEdit12: TLabeledEdit;
    LabeledEdit13: TLabeledEdit;
    LabeledEdit14: TLabeledEdit;
    GroupBox2: TGroupBox;
    LabeledEdit15: TLabeledEdit;
    LabeledEdit16: TLabeledEdit;
    LabeledEdit17: TLabeledEdit;
    LabeledEdit18: TLabeledEdit;
    LabeledEdit19: TLabeledEdit;
    LabeledEdit20: TLabeledEdit;
    LabeledEdit21: TLabeledEdit;
    LabeledEdit22: TLabeledEdit;
    LabeledEdit23: TLabeledEdit;
    LabeledEdit24: TLabeledEdit;
    LabeledEdit25: TLabeledEdit;
    LabeledEdit26: TLabeledEdit;
    LabeledEdit27: TLabeledEdit;
    LabeledEdit28: TLabeledEdit;
    LabeledEdit29: TLabeledEdit;
    procedure FormCreate(Sender: TObject);
    procedure FormShow(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure LabeledEdit1KeyPress(Sender: TObject; var Key: Char);
    procedure LabeledEdit1Change(Sender: TObject);
    procedure LabeledEdit15Change(Sender: TObject);
    procedure RadioGroup1Click(Sender: TObject);
    procedure RadioGroup2Click(Sender: TObject);
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

uses DirectSound, ReadWave2; //ReadWave2 是前面(9)自定义的单元

var
  myDSound: IDirectSound8;
  buf: IDirectSoundBuffer;
  buf3D: IDirectSound3DBuffer8;      //3D声源
  Listener: IDirectSound3DListener8;
  dwApply: DWORD = DS3D_IMMEDIATE;   //0

{建立 IDirectSound8、IDirectSound3DListener8}
procedure TForm1.FormCreate(Sender: TObject);
var
  bufDesc: TDSBufferDesc;
  bufPrimary: IDirectSoundBuffer; //这里的主缓冲区只是个临时的桥
begin
  System.ReportMemoryLeaksOnShutdown := true;
  DirectSoundCreate8(nil, myDSound, nil);
  myDSound.SetCooperativeLevel(Handle, DSSCL_PRIORITY); //要用到主缓冲区, 所以使用 DSSCL_PRIORITY 级别

  ZeroMemory(@bufDesc, SizeOf(TDSBufferDesc));
  bufDesc.dwSize := SizeOf(TDSBufferDesc);
  bufDesc.dwFlags := DSBCAPS_PRIMARYBUFFER or DSBCAPS_CTRL3D; //标识是主缓冲区、同时准备使用 3D 特效
  bufDesc.dwBufferBytes := 0;
  bufDesc.lpwfxFormat := nil;
  bufDesc.guid3DAlgorithm := DS3DALG_DEFAULT; //主缓冲区在 DSBCAPS_CTRL3D 模式下可以启用这个选项

  myDSound.CreateSoundBuffer(bufDesc, bufPrimary, nil);
  bufPrimary.QueryInterface(IID_IDirectSound3DListener8, Listener);
  //bufPrimary := nil;
end;

{建立 IDirectSoundBuffer、IDirectSound3DBuffer8, 并载入播放资源}
procedure TForm1.Button1Click(Sender: TObject);
var
  wav: TReadWave;
  bufDesc: TDSBufferDesc;
  p1: Pointer;
  n1: DWORD;
begin
  Self.OnShow(nil);
  wav := TReadWave.Create;
  {如果打开失败或不是单声道则退出}
  if not wav.OpenDialog or (wav.Format.nChannels <> 1) then
  begin
    wav.Free;
    Exit;
  end;

  ZeroMemory(@bufDesc, SizeOf(bufDesc));
  bufDesc.dwSize := SizeOf(bufDesc);
  bufDesc.dwFlags := DSBCAPS_STATIC or DSBCAPS_CTRL3D;
  bufDesc.dwBufferBytes := wav.Size;
  bufdesc.lpwfxFormat := @wav.Format;

  myDSound.CreateSoundBuffer(bufDesc, buf, nil);
  buf.QueryInterface(IID_IDirectSound3DBuffer8, buf3D);

  buf.Lock(0, 0, @p1, @n1, nil, nil, DSBLOCK_ENTIREBUFFER);
  wav.Read(p1, wav.Size);
  wav.Free;
  buf.Unlock(p1, n1, nil, 0);

  buf.Play(0, 0, DSBPLAY_LOOPING);
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  if buf <> nil then buf.Stop;
end;

{初始化控件及默认值}
procedure TForm1.FormShow(Sender: TObject);
var
  i: Integer;
begin
  Button1.Caption := '打开并播放';
  Button2.Caption := '停止播放';

  RadioGroup1.Caption := 'Mode:';
  RadioGroup1.Items.CommaText := 'DS3DMODE_NORMAL, DS3DMODE_HEADRELATIVE, DS3DMODE_DISABLE';
  RadioGroup1.ItemIndex := 0;

  RadioGroup2.Caption := 'Apply:';
  RadioGroup2.Items.CommaText := 'DS3D_IMMEDIATE, DS3D_DEFERRED';
  RadioGroup2.ItemIndex := dwApply;

  GroupBox1.Caption := '声源控制:';
  LabeledEdit1.EditLabel.Caption := 'Position-X:';
  LabeledEdit2.EditLabel.Caption := 'Position-Y:';
  LabeledEdit3.EditLabel.Caption := 'Position-Z:';
  LabeledEdit1.Text := '0.0';
  LabeledEdit2.Text := '0.0';
  LabeledEdit3.Text := '0.0';

  LabeledEdit4.EditLabel.Caption := 'Velocity-X:';
  LabeledEdit5.EditLabel.Caption := 'Velocity-Y:';
  LabeledEdit6.EditLabel.Caption := 'Velocity-Z:';
  LabeledEdit4.Text := '0.0';
  LabeledEdit5.Text := '0.0';
  LabeledEdit6.Text := '0.0';

  LabeledEdit7.EditLabel.Caption := 'Orientation-X:';
  LabeledEdit8.EditLabel.Caption := 'Orientation-Y:';
  LabeledEdit9.EditLabel.Caption := 'Orientation-Z:';
  LabeledEdit7.Text := '0.0';
  LabeledEdit8.Text := '0.0';
  LabeledEdit9.Text := '1.0';

  LabeledEdit10.EditLabel.Caption := 'Min:';
  LabeledEdit11.EditLabel.Caption := 'Max:';
  LabeledEdit10.Text := '0.0';
  LabeledEdit11.Text := '1000000000.0';

  LabeledEdit12.EditLabel.Caption := 'Volume:';
  LabeledEdit12.Text := '0';

  LabeledEdit13.EditLabel.Caption := 'InsideConeAngle:';
  LabeledEdit14.EditLabel.Caption := 'OutsideConeAngle:';
  LabeledEdit13.Text := '360';
  LabeledEdit14.Text := '360';

  //
  GroupBox2.Caption := '听者控制:';
  LabeledEdit15.EditLabel.Caption := 'Position-X:';
  LabeledEdit16.EditLabel.Caption := 'Position-Y:';
  LabeledEdit17.EditLabel.Caption := 'Position-Z:';
  LabeledEdit15.Text := '0.0';
  LabeledEdit16.Text := '0.0';
  LabeledEdit17.Text := '0.0';

  LabeledEdit18.EditLabel.Caption := 'Velocity-X:';
  LabeledEdit19.EditLabel.Caption := 'Velocity-Y:';
  LabeledEdit20.EditLabel.Caption := 'Velocity-Z:';
  LabeledEdit18.Text := '0.0';
  LabeledEdit19.Text := '0.0';
  LabeledEdit20.Text := '0.0';

  LabeledEdit21.EditLabel.Caption := 'Orientation-xFront:';
  LabeledEdit22.EditLabel.Caption := 'Orientation-yFront:';
  LabeledEdit23.EditLabel.Caption := 'Orientation-zFront:';
  LabeledEdit21.Text := '0.0';
  LabeledEdit22.Text := '0.0';
  LabeledEdit23.Text := '1.0';

  LabeledEdit24.EditLabel.Caption := 'Orientation-xTop:';
  LabeledEdit25.EditLabel.Caption := 'Orientation-yTop:';
  LabeledEdit26.EditLabel.Caption := 'Orientation-zTop:';
  LabeledEdit24.Text := '0.0';
  LabeledEdit25.Text := '1.0';
  LabeledEdit26.Text := '0.0';

  LabeledEdit27.EditLabel.Caption := 'DistanceFactor:';
  LabeledEdit28.EditLabel.Caption := 'DopplerFactor:';
  LabeledEdit29.EditLabel.Caption := 'RolloffFactor:';
  LabeledEdit27.Text := '1.0';
  LabeledEdit28.Text := '1.0';
  LabeledEdit29.Text := '1.0';

  for i := 0 to self.ComponentCount - 1 do
  begin
    if Components[i].ClassNameIs('TLabeledEdit') then
    begin
      TLabeledEdit(Components[i]).OnKeyPress := LabeledEdit1.OnKeyPress;
      if TLabeledEdit(Components[i]).Parent = GroupBox1 then TLabeledEdit(Components[i]).OnChange := LabeledEdit1.OnChange;
      if TLabeledEdit(Components[i]).Parent = GroupBox2 then TLabeledEdit(Components[i]).OnChange := LabeledEdit15.OnChange;
    end;
  end;
end;

{限制测试数据}
procedure TForm1.LabeledEdit1KeyPress(Sender: TObject; var Key: Char);
begin
  Self.Caption := TLabeledEdit(Sender).Name;
  if not CharInSet(Key, ['-', '.', '0'..'9', #8]) then Key := #0;
end;

{声源变换时}
procedure TForm1.LabeledEdit1Change(Sender: TObject);
var
  str: string;
begin
  if buf3D = nil then Exit;
  str := TLabeledEdit(Sender).Text;
  if (str = '-') or (str = '.') or (str = '') then Exit;

  buf3D.SetPosition(StrToFloat(LabeledEdit1.Text),
                    StrToFloat(LabeledEdit2.Text),
                    StrToFloat(LabeledEdit3.Text), dwApply);

  buf3D.SetVelocity(StrToFloat(LabeledEdit4.Text),
                    StrToFloat(LabeledEdit5.Text),
                    StrToFloat(LabeledEdit6.Text), dwApply);

  buf3D.SetConeOrientation(StrToFloat(LabeledEdit7.Text),
                           StrToFloat(LabeledEdit8.Text),
                           StrToFloat(LabeledEdit9.Text), dwApply);

  buf3D.SetMinDistance(StrToFloat(LabeledEdit10.Text), dwApply);
  buf3D.SetMaxDistance(StrToFloat(LabeledEdit11.Text), dwApply);

  buf3D.SetConeOutsideVolume(StrToInt(LabeledEdit12.Text), dwApply);

  buf3D.SetConeAngles(StrToInt(LabeledEdit13.Text), StrToInt(LabeledEdit14.Text), dwApply);

  if (dwApply = DS3D_DEFERRED) and Assigned(Listener) then Listener.CommitDeferredSettings;
end;

{听者变换时}
procedure TForm1.LabeledEdit15Change(Sender: TObject);
var
  str: string;
  rVector: TD3DVector;
begin
  if (buf = nil) or (Listener = nil) then Exit;
  str := TLabeledEdit(Sender).Text;
  if (str = '-') or (str = '.') or (str = '') then Exit;

  Listener.SetPosition(StrToFloat(LabeledEdit15.Text),
                       StrToFloat(LabeledEdit16.Text),
                       StrToFloat(LabeledEdit17.Text), dwApply);

  Listener.SetVelocity(StrToFloat(LabeledEdit18.Text),
                       StrToFloat(LabeledEdit19.Text),
                       StrToFloat(LabeledEdit20.Text), dwApply);

  Listener.SetOrientation(StrToFloat(LabeledEdit21.Text),
                          StrToFloat(LabeledEdit22.Text),
                          StrToFloat(LabeledEdit23.Text),
                          StrToFloat(LabeledEdit24.Text),
                          StrToFloat(LabeledEdit25.Text),
                          StrToFloat(LabeledEdit26.Text), dwApply);

  Listener.SetDistanceFactor(StrToFloat(LabeledEdit27.Text), dwApply);
  Listener.SetDopplerFactor(StrToFloat(LabeledEdit28.Text), dwApply);
  Listener.SetRolloffFactor(StrToFloat(LabeledEdit29.Text), dwApply);

  if dwApply = DS3D_DEFERRED then Listener.CommitDeferredSettings;
end;

{3D 音效模式}
procedure TForm1.RadioGroup1Click(Sender: TObject);
begin
  if Assigned(buf3D) then buf3D.SetMode(RadioGroup1.ItemIndex, dwApply);
  if (dwApply = DS3D_DEFERRED) and Assigned(Listener) then Listener.CommitDeferredSettings;
end;

{是否延迟设置; 此变化内在的, 应该不会被觉察}
procedure TForm1.RadioGroup2Click(Sender: TObject);
var
  i: Integer;
begin
  if buf3D = nil then Exit;
  dwApply := TRadioGroup(Sender).ItemIndex;
  for i := 0 to self.ComponentCount - 1 do if Components[i].ClassNameIs('TLabeledEdit') then
    TLabeledEdit(Components[i]).OnChange(TLabeledEdit(Components[i]));
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  buf := nil;
  buf3D := nil;
  Listener := nil;
  myDSound := nil;
end;

end.


窗体设计:
object Form1: TForm1
  Left = 0
  Top = 0
  Caption = 'Form1'
  ClientHeight = 459
  ClientWidth = 759
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  OnCreate = FormCreate
  OnDestroy = FormDestroy
  OnShow = FormShow
  PixelsPerInch = 96
  TextHeight = 13
  object Button1: TButton
    Left = 23
    Top = 40
    Width = 75
    Height = 49
    Caption = 'Button1'
    TabOrder = 0
    OnClick = Button1Click
  end
  object Button2: TButton
    Left = 104
    Top = 40
    Width = 75
    Height = 49
    Caption = 'Button2'
    TabOrder = 1
    OnClick = Button2Click
  end
  object GroupBox1: TGroupBox
    Left = 8
    Top = 134
    Width = 353
    Height = 317
    Caption = 'GroupBox1'
    TabOrder = 2
    object LabeledEdit1: TLabeledEdit
      Left = 16
      Top = 42
      Width = 97
      Height = 21
      EditLabel.Width = 61
      EditLabel.Height = 13
      EditLabel.Caption = 'LabeledEdit1'
      TabOrder = 0
      OnChange = LabeledEdit1Change
      OnKeyPress = LabeledEdit1KeyPress
    end
    object LabeledEdit2: TLabeledEdit
      Left = 128
      Top = 42
      Width = 97
      Height = 21
      EditLabel.Width = 61
      EditLabel.Height = 13
      EditLabel.Caption = 'LabeledEdit2'
      TabOrder = 1
    end
    object LabeledEdit3: TLabeledEdit
      Left = 240
      Top = 42
      Width = 97
      Height = 21
      EditLabel.Width = 61
      EditLabel.Height = 13
      EditLabel.Caption = 'LabeledEdit3'
      TabOrder = 2
    end
    object LabeledEdit4: TLabeledEdit
      Left = 16
      Top = 90
      Width = 97
      Height = 21
      EditLabel.Width = 61
      EditLabel.Height = 13
      EditLabel.Caption = 'LabeledEdit4'
      TabOrder = 3
    end
    object LabeledEdit5: TLabeledEdit
      Left = 128
      Top = 90
      Width = 97
      Height = 21
      EditLabel.Width = 61
      EditLabel.Height = 13
      EditLabel.Caption = 'LabeledEdit5'
      TabOrder = 4
    end
    object LabeledEdit6: TLabeledEdit
      Left = 240
      Top = 90
      Width = 97
      Height = 21
      EditLabel.Width = 61
      EditLabel.Height = 13
      EditLabel.Caption = 'LabeledEdit6'
      TabOrder = 5
    end
    object LabeledEdit7: TLabeledEdit
      Left = 16
      Top = 138
      Width = 97
      Height = 21
      EditLabel.Width = 61
      EditLabel.Height = 13
      EditLabel.Caption = 'LabeledEdit7'
      TabOrder = 6
    end
    object LabeledEdit8: TLabeledEdit
      Left = 128
      Top = 138
      Width = 97
      Height = 21
      EditLabel.Width = 61
      EditLabel.Height = 13
      EditLabel.Caption = 'LabeledEdit8'
      TabOrder = 7
    end
    object LabeledEdit9: TLabeledEdit
      Left = 240
      Top = 138
      Width = 97
      Height = 21
      EditLabel.Width = 61
      EditLabel.Height = 13
      EditLabel.Caption = 'LabeledEdit9'
      TabOrder = 8
    end
    object LabeledEdit10: TLabeledEdit
      Left = 16
      Top = 186
      Width = 97
      Height = 21
      EditLabel.Width = 67
      EditLabel.Height = 13
      EditLabel.Caption = 'LabeledEdit10'
      TabOrder = 9
    end
    object LabeledEdit11: TLabeledEdit
      Left = 128
      Top = 186
      Width = 97
      Height = 21
      EditLabel.Width = 67
      EditLabel.Height = 13
      EditLabel.Caption = 'LabeledEdit11'
      TabOrder = 10
    end
    object LabeledEdit12: TLabeledEdit
      Left = 16
      Top = 234
      Width = 97
      Height = 21
      EditLabel.Width = 67
      EditLabel.Height = 13
      EditLabel.Caption = 'LabeledEdit12'
      TabOrder = 11
    end
    object LabeledEdit13: TLabeledEdit
      Left = 16
      Top = 282
      Width = 97
      Height = 21
      EditLabel.Width = 67
      EditLabel.Height = 13
      EditLabel.Caption = 'LabeledEdit13'
      TabOrder = 12
    end
    object LabeledEdit14: TLabeledEdit
      Left = 128
      Top = 285
      Width = 97
      Height = 21
      EditLabel.Width = 67
      EditLabel.Height = 13
      EditLabel.Caption = 'LabeledEdit14'
      TabOrder = 13
    end
  end
  object GroupBox2: TGroupBox
    Left = 390
    Top = 136
    Width = 355
    Height = 315
    Caption = 'GroupBox2'
    TabOrder = 3
    object LabeledEdit15: TLabeledEdit
      Left = 16
      Top = 42
      Width = 97
      Height = 21
      EditLabel.Width = 67
      EditLabel.Height = 13
      EditLabel.Caption = 'LabeledEdit15'
      TabOrder = 0
      OnChange = LabeledEdit15Change
    end
    object LabeledEdit16: TLabeledEdit
      Left = 127
      Top = 42
      Width = 97
      Height = 21
      EditLabel.Width = 67
      EditLabel.Height = 13
      EditLabel.Caption = 'LabeledEdit16'
      TabOrder = 1
    end
    object LabeledEdit17: TLabeledEdit
      Left = 240
      Top = 42
      Width = 97
      Height = 21
      EditLabel.Width = 67
      EditLabel.Height = 13
      EditLabel.Caption = 'LabeledEdit17'
      TabOrder = 2
    end
    object LabeledEdit18: TLabeledEdit
      Left = 16
      Top = 106
      Width = 97
      Height = 21
      EditLabel.Width = 67
      EditLabel.Height = 13
      EditLabel.Caption = 'LabeledEdit18'
      TabOrder = 3
    end
    object LabeledEdit19: TLabeledEdit
      Left = 128
      Top = 106
      Width = 97
      Height = 21
      EditLabel.Width = 67
      EditLabel.Height = 13
      EditLabel.Caption = 'LabeledEdit19'
      TabOrder = 4
    end
    object LabeledEdit20: TLabeledEdit
      Left = 240
      Top = 106
      Width = 97
      Height = 21
      EditLabel.Width = 67
      EditLabel.Height = 13
      EditLabel.Caption = 'LabeledEdit20'
      TabOrder = 5
    end
    object LabeledEdit21: TLabeledEdit
      Left = 16
      Top = 170
      Width = 97
      Height = 21
      EditLabel.Width = 67
      EditLabel.Height = 13
      EditLabel.Caption = 'LabeledEdit21'
      TabOrder = 6
    end
    object LabeledEdit22: TLabeledEdit
      Left = 128
      Top = 170
      Width = 97
      Height = 21
      EditLabel.Width = 67
      EditLabel.Height = 13
      EditLabel.Caption = 'LabeledEdit22'
      TabOrder = 7
    end
    object LabeledEdit23: TLabeledEdit
      Left = 240
      Top = 170
      Width = 97
      Height = 21
      EditLabel.Width = 67
      EditLabel.Height = 13
      EditLabel.Caption = 'LabeledEdit23'
      TabOrder = 8
    end
    object LabeledEdit24: TLabeledEdit
      Left = 16
      Top = 218
      Width = 97
      Height = 21
      EditLabel.Width = 67
      EditLabel.Height = 13
      EditLabel.Caption = 'LabeledEdit24'
      TabOrder = 9
    end
    object LabeledEdit25: TLabeledEdit
      Left = 128
      Top = 218
      Width = 97
      Height = 21
      EditLabel.Width = 67
      EditLabel.Height = 13
      EditLabel.Caption = 'LabeledEdit25'
      TabOrder = 10
    end
    object LabeledEdit26: TLabeledEdit
      Left = 240
      Top = 218
      Width = 97
      Height = 21
      EditLabel.Width = 67
      EditLabel.Height = 13
      EditLabel.Caption = 'LabeledEdit26'
      TabOrder = 11
    end
    object LabeledEdit27: TLabeledEdit
      Left = 16
      Top = 282
      Width = 97
      Height = 21
      EditLabel.Width = 67
      EditLabel.Height = 13
      EditLabel.Caption = 'LabeledEdit27'
      TabOrder = 12
    end
    object LabeledEdit28: TLabeledEdit
      Left = 128
      Top = 282
      Width = 97
      Height = 21
      EditLabel.Width = 67
      EditLabel.Height = 13
      EditLabel.Caption = 'LabeledEdit28'
      TabOrder = 13
    end
    object LabeledEdit29: TLabeledEdit
      Left = 240
      Top = 282
      Width = 97
      Height = 21
      EditLabel.Width = 67
      EditLabel.Height = 13
      EditLabel.Caption = 'LabeledEdit29'
      TabOrder = 14
    end
  end
  object RadioGroup1: TRadioGroup
    Left = 200
    Top = 17
    Width = 281
    Height = 98
    Caption = 'RadioGroup1'
    TabOrder = 4
    OnClick = RadioGroup1Click
  end
  object RadioGroup2: TRadioGroup
    Left = 504
    Top = 17
    Width = 241
    Height = 96
    Caption = 'RadioGroup2'
    TabOrder = 5
    OnClick = RadioGroup2Click
  end
end


运行效果图:

在 Delphi 下使用 DirectSound (18): 3D 特效_第1张图片

你可能感兴趣的:(Delphi)