MMDSMix.pas
上传用户:hylc_2004
上传日期:2014-01-23
资源大小:46800k
文件大小:92k
源码类别:

Delphi控件源码

开发平台:

Delphi

  1. {========================================================================}
  2. {=                (c) 1995-98 SwiftSoft Ronald Dittrich                 =}
  3. {========================================================================}
  4. {=                          All Rights Reserved                         =}
  5. {========================================================================}
  6. {=  D 01099 Dresden             = Fax.: +49(0)351-8037944               =}
  7. {=  Loewenstr.7a                = info@swiftsoft.de                     =}
  8. {========================================================================}
  9. {=  Actual versions on http://www.swiftsoft.de/index.html               =}
  10. {========================================================================}
  11. {=  This code is for reference purposes only and may not be copied or   =}
  12. {=  distributed in any format electronic or otherwise except one copy   =}
  13. {=  for backup purposes.                                                =}
  14. {=                                                                      =}
  15. {=  No Delphi Component Kit or Component individually or in a collection=}
  16. {=  subclassed or otherwise from the code in this unit, or associated   =}
  17. {=  .pas, .dfm, .dcu, .asm or .obj files may be sold or distributed     =}
  18. {=  without express permission from SwiftSoft.                          =}
  19. {=                                                                      =}
  20. {=  For more licence informations please refer to the associated        =}
  21. {=  HelpFile.                                                           =}
  22. {========================================================================}
  23. {=  $Date: 17.11.98 - 16:26:10 $                                        =}
  24. {========================================================================}
  25. unit MMDSMix;
  26. {$I COMPILER.INC}
  27. interface
  28. uses
  29.   Windows,
  30.   Messages,
  31.   SysUtils,
  32.   Classes,
  33.   Graphics,
  34.   Controls,
  35.   Dialogs,
  36.   Forms,
  37.   MMOLE2,
  38.   MMSystem,
  39.   MMObj,
  40.   MMUtils,
  41.   MMDSound,
  42.   MMD3DTyp,
  43.   MM3D,
  44.   MMRegs,
  45.   MMWave,
  46.   MMPCMSup,
  47.   MMACMSup,
  48.   MMADPCM,
  49.   MMMulDiv,
  50.   MMWaveIO,
  51.   MMCCon;
  52. type
  53.   EMMDSWaveMixError     = class(Exception);
  54.   TMMDSSpeakerConfig    = (scHeadphone,scMono,scQuad,scStereo,scSurround);
  55.   TMMDSLevel            = (prNormal, prPriority, prExclusive);
  56.   TMMDS3DBufferMode     = (bmNormal,bmHeadRelative,bmNo3D);
  57. const
  58.   {$IFDEF CBUILDER3} {$EXTERNALSYM defMaxDistance} {$ENDIF}
  59.   defMaxDistance        = 1e+09; {? Should be inf}
  60.   {$IFDEF CBUILDER3} {$EXTERNALSYM defMinDistance} {$ENDIF}
  61.   defMinDistance        = 1.0;
  62.   {$IFDEF CBUILDER3} {$EXTERNALSYM defMode} {$ENDIF}
  63.   defMode               = bmNormal;
  64.   {$IFDEF CBUILDER3} {$EXTERNALSYM defPosX} {$ENDIF}
  65.   defPosX               = 0; {?}
  66.   {$IFDEF CBUILDER3} {$EXTERNALSYM defPosY} {$ENDIF}
  67.   defPosY               = 0; {?}
  68.   {$IFDEF CBUILDER3} {$EXTERNALSYM defPosZ} {$ENDIF}
  69.   defPosZ               = 0; {?}
  70.   {$IFDEF CBUILDER3} {$EXTERNALSYM defInsideConeAngle} {$ENDIF}
  71.   defInsideConeAngle    = 360;
  72.   {$IFDEF CBUILDER3} {$EXTERNALSYM defOutsideConeAngle} {$ENDIF}
  73.   defOutsideConeAngle   = 360;
  74.   {$IFDEF CBUILDER3} {$EXTERNALSYM defConeOrientX} {$ENDIF}
  75.   defConeOrientX        = 0;
  76.   {$IFDEF CBUILDER3} {$EXTERNALSYM defConeOrientY} {$ENDIF}
  77.   defConeOrientY        = 0;
  78.   {$IFDEF CBUILDER3} {$EXTERNALSYM defConeOrientZ} {$ENDIF}
  79.   defConeOrientZ        = 1;
  80.   {$IFDEF CBUILDER3} {$EXTERNALSYM defConeOutsideVolume} {$ENDIF}
  81.   defConeOutsideVolume  = 0; {?}
  82.   {$IFDEF CBUILDER3} {$EXTERNALSYM defVelX} {$ENDIF}
  83.   defVelX               = 0; {?}
  84.   {$IFDEF CBUILDER3} {$EXTERNALSYM defVelY} {$ENDIF}
  85.   defVelY               = 0; {?}
  86.   {$IFDEF CBUILDER3} {$EXTERNALSYM defVelZ} {$ENDIF}
  87.   defVelZ               = 0; {?}
  88.   {$IFDEF CBUILDER3} {$EXTERNALSYM defDistanceFactor} {$ENDIF}
  89.   defDistanceFactor     = DS3D_DEFAULTDISTANCEFACTOR;
  90.   {$IFDEF CBUILDER3} {$EXTERNALSYM defDopplerFactor} {$ENDIF}
  91.   defDopplerFactor      = DS3D_DEFAULTDOPPLERFACTOR;
  92.   {$IFDEF CBUILDER3} {$EXTERNALSYM defOrientFrontX} {$ENDIF}
  93.   defOrientFrontX       = 0;
  94.   {$IFDEF CBUILDER3} {$EXTERNALSYM defOrientFrontY} {$ENDIF}
  95.   defOrientFrontY       = 0;
  96.   {$IFDEF CBUILDER3} {$EXTERNALSYM defOrientFrontZ} {$ENDIF}
  97.   defOrientFrontZ       = 1;
  98.   {$IFDEF CBUILDER3} {$EXTERNALSYM defOrientTopX} {$ENDIF}
  99.   defOrientTopX         = 0;
  100.   {$IFDEF CBUILDER3} {$EXTERNALSYM defOrientTopY} {$ENDIF}
  101.   defOrientTopY         = 1;
  102.   {$IFDEF CBUILDER3} {$EXTERNALSYM defOrientTopZ} {$ENDIF}
  103.   defOrientTopZ         = 0;
  104.   {$IFDEF CBUILDER3} {$EXTERNALSYM defPositionX} {$ENDIF}
  105.   defPositionX          = 0; {?}
  106.   {$IFDEF CBUILDER3} {$EXTERNALSYM defPositionY} {$ENDIF}
  107.   defPositionY          = 0; {?}
  108.   {$IFDEF CBUILDER3} {$EXTERNALSYM defPositionZ} {$ENDIF}
  109.   defPositionZ          = 0; {?}
  110.   {$IFDEF CBUILDER3} {$EXTERNALSYM defRollOffFactor} {$ENDIF}
  111.   defRollOffFactor      = DS3D_DEFAULTROLLOFFFACTOR;
  112.   {$IFDEF CBUILDER3} {$EXTERNALSYM defVelocityX} {$ENDIF}
  113.   defVelocityX          = 0; {?}
  114.   {$IFDEF CBUILDER3} {$EXTERNALSYM defVelocityY} {$ENDIF}
  115.   defVelocityY          = 0; {?}
  116.   {$IFDEF CBUILDER3} {$EXTERNALSYM defVelocityZ} {$ENDIF}
  117.   defVelocityZ          = 0; {?}
  118. type
  119.   {-- TMMDS3DControl -----------------------------------------------------}
  120.   TMMDS3DControl = class(TMMObject)
  121.   private
  122.     FDeferred   : Boolean;
  123.     FUpdate     : Integer;
  124.     FInApply    : Boolean;
  125.   protected
  126.     function    SetDirect: Boolean;
  127.     function    GetDirect: Boolean;
  128.     function    ApplyFlags: DWORD;
  129.     procedure   SetDeferred(Value: Boolean);
  130.     destructor  Destroy; override;
  131.     procedure   CreateBuffer(DSBuffer: IDirectSoundBuffer);
  132.     procedure   FreeBuffer;
  133.     procedure   ApplySettings;
  134.     procedure   ObtainControl(DSBuffer: IDirectSoundBuffer); virtual; abstract;
  135.     procedure   FreeControl; virtual; abstract;
  136.     procedure   DoApplySettings; virtual; abstract;
  137.     function    ControlAllocated: Boolean; virtual; abstract;
  138.   public
  139.     procedure   BeginUpdate;
  140.     procedure   EndUpdate;
  141.   published
  142.     property    Deferred: Boolean read FDeferred write SetDeferred;
  143.   end;
  144.   {-- TMMDS3DBuffer ------------------------------------------------------}
  145.   TMMDS3DBuffer         = class(TMMDS3DControl)
  146.   private
  147.     FDS3DBuffer         : IDirectSound3DBuffer;
  148.     FMaxDistance        : D3DVALUE;
  149.     FMinDistance        : D3DVALUE;
  150.     FMode               : TMMDS3DBufferMode;
  151.     FPosition           : TMMVector3D;
  152.     FInsideConeAngle    : LongInt;
  153.     FOutsideConeAngle   : LongInt;
  154.     FConeOrientation    : TMMVector3D;
  155.     FConeOutsideVolume  : LongInt;
  156.     FVelocity           : TMMVector3D;
  157.     procedure   SetMaxDistance(Value: D3DVALUE);
  158.     procedure   SetMinDistance(Value: D3DVALUE);
  159.     procedure   SetMode(Value: TMMDS3DBufferMode);
  160.     procedure   SetPosition(Value: TMMVector3D);
  161.     procedure   SetInsideConeAngle(Value: LongInt);
  162.     procedure   SetOutsideConeAngle(Value: LongInt);
  163.     procedure   SetConeOrientation(Value: TMMVector3D);
  164.     procedure   SetConeOutsideVolume(Value: LongInt);
  165.     procedure   SetVelocity(Value: TMMVector3D);
  166.     function    GetMaxDistance: D3DVALUE;
  167.     function    GetMinDistance: D3DVALUE;
  168.     function    GetMode: TMMDS3DBufferMode;
  169.     function    GetPosition: TMMVector3D;
  170.     function    GetInsideConeAngle: LongInt;
  171.     function    GetOutsideConeAngle: LongInt;
  172.     function    GetConeOrientation: TMMVector3D;
  173.     function    GetConeOutsideVolume: LongInt;
  174.     function    GetVelocity: TMMVector3D;
  175.     procedure   VectorChanged(Sender: TObject);
  176.   protected
  177.     procedure   ObtainControl(DSBuffer: IDirectSoundBuffer); override;
  178.     procedure   FreeControl; override;
  179.     procedure   DoApplySettings; override;
  180.     function    ControlAllocated: Boolean; override;
  181.   public
  182.     constructor Create(Loading: Boolean);
  183.     destructor  Destroy; override;
  184.     procedure   Assign(Source: TPersistent); override;
  185.   published
  186.     property    MaxDistance: D3DVALUE read GetMaxDistance write SetMaxDistance;
  187.     property    MinDistance: D3DVALUE read GetMinDistance write SetMinDistance;
  188.     property    Mode: TMMDS3DBufferMode read GetMode write SetMode default defMode;
  189.     property    Position: TMMVector3D read GetPosition write SetPosition;
  190.     property    InsideConeAngle: LongInt read GetInsideConeAngle write SetInsideConeAngle default defInsideConeAngle;
  191.     property    OutsideConeAngle: LongInt read GetOutsideConeAngle write SetOutsideConeAngle default defOutsideConeAngle;
  192.     property    ConeOrientation: TMMVector3D read GetConeOrientation write SetConeOrientation;
  193.     property    ConeOutsideVolume: LongInt read GetConeOutsideVolume write SetConeOutsideVolume default defConeOutsideVolume;
  194.     property    Velocity: TMMVector3D read GetVelocity write SetVelocity;
  195.   end;
  196.   {-- TMMDS3DListener ----------------------------------------------------}
  197.   TMMDS3DListener       = class(TMMDS3DControl)
  198.   private
  199.     FDS3DListener       : IDirectSound3DListener;
  200.     FDistanceFactor     : D3DVALUE;
  201.     FDopplerFactor      : D3DVALUE;
  202.     FOrientFront        : TMMVector3D;
  203.     FOrientTop          : TMMVector3D;
  204.     FPosition           : TMMVector3D;
  205.     FRollOffFactor      : D3DVALUE;
  206.     FVelocity           : TMMVector3D;
  207.     function    GetDistanceFactor: D3DVALUE;
  208.     function    GetDopplerFactor: D3DVALUE;
  209.     function    GetOrientFront: TMMVector3D;
  210.     function    GetOrientTop: TMMVector3D;
  211.     function    GetPosition: TMMVector3D;
  212.     function    GetRollOffFactor: D3DVALUE;
  213.     function    GetVelocity: TMMVector3D;
  214.     procedure   SetDistanceFactor(Value: D3DVALUE);
  215.     procedure   SetDopplerFactor(Value: D3DVALUE);
  216.     procedure   SetOrientFront(Value: TMMVector3D);
  217.     procedure   SetOrientTop(Value: TMMVector3D);
  218.     procedure   SetPosition(Value: TMMVector3D);
  219.     procedure   SetRollOffFactor(Value: D3DVALUE);
  220.     procedure   SetVelocity(Value: TMMVector3D);
  221.     procedure   VectorChanged(Sender: TObject);
  222.   protected
  223.     procedure   ObtainControl(DSBuffer: IDirectSoundBuffer); override;
  224.     procedure   FreeControl; override;
  225.     procedure   DoApplySettings; override;
  226.     function    ControlAllocated: Boolean; override;
  227.   public
  228.     constructor Create(Loading: Boolean);
  229.     destructor  Destroy; override;
  230.     procedure   Assign(Source: TPersistent); override;
  231.     procedure   Commit;
  232.   published
  233.     property    DistanceFactor: D3DVALUE read GetDistanceFactor write SetDistanceFactor;
  234.     property    DopplerFactor: D3DVALUE read GetDopplerFactor write SetDopplerFactor;
  235.     property    OrientFront: TMMVector3D read GetOrientFront write SetOrientFront;
  236.     property    OrientTop: TMMVector3D read GetOrientTop write SetOrientTop;
  237.     property    Position: TMMVector3D read GetPosition write SetPosition;
  238.     property    RollOffFactor: D3DVALUE read GetRollOffFactor write SetRollOffFactor;
  239.     property    Velocity: TMMVector3D read GetVelocity write SetVelocity;
  240.   end;
  241.   {-- TMMDSSoundBuffer ---------------------------------------------------}
  242.   TMMDSSoundBuffer = class(TMMObject)
  243.   private
  244.      DirectSoundBuffer: IDirectSoundBuffer;
  245.      FName       : string;
  246.      FWave       : TMMWave;
  247.      FVolume     : Longint;
  248.      FPanning    : Longint;
  249.      FFrequency  : Longint;
  250.      FPosition   : Longint;
  251.      FMuted      : Boolean;
  252.      FPlaying    : Boolean;
  253.      FPaused     : Boolean;
  254.      FLooping    : Boolean;
  255.      FOnBufferEnd: TNotifyEvent;
  256.      FOnRelease  : TNotifyEvent;
  257.      procedure SetMuted(aValue: Boolean);
  258.      procedure SetVolume(aValue: Longint);
  259.      function  GetVolume: Longint;
  260.      procedure SetPanning(aValue: Longint);
  261.      function  GetPanning: Longint;
  262.      procedure SetFrequency(aValue: Longint);
  263.      function  GetFrequency: Longint;
  264.      procedure SetPosition(aValue: Longint);
  265.      function  GetPosition: Longint;
  266.      procedure SetLooping(aValue: Boolean);
  267.      function  GetLooping: Boolean;
  268.      function  GetPlaying: Boolean;
  269.      function  GetBufferLength: Longint;
  270.      function  GetCaps: TDSBCAPS;
  271.   protected
  272.      procedure Play;
  273.      procedure Pause;
  274.      procedure Stop;
  275.      procedure ReleaseBuffer;
  276.      procedure FreeBuffer;
  277.   public
  278.      FOwned      : Boolean;
  279.      constructor Create; virtual;
  280.      property SoundBuffer: IDirectSoundBuffer read DirectSoundBuffer;
  281.      property Caps: TDSBCAPS read GetCaps;
  282.      property Wave: TMMWave read FWave;
  283.      property Name: string read FName;
  284.      property BufferLength: Longint read GetBufferLength;
  285.      property Playing: Boolean read GetPlaying;
  286.      property Paused: Boolean read FPaused;
  287.      property Muted: Boolean read FMuted write SetMuted default False;
  288.      property Volume: Longint read GetVolume write SetVolume default 0;
  289.      property Panning: Longint read GetPanning write SetPanning default 0;
  290.      property Frequency: Longint read GetFrequency write SetFrequency default 0;
  291.      property Position: Longint read GetPosition write SetPosition default 0;
  292.      property Looping: Boolean read GetLooping write SetLooping default False;
  293.   end;
  294.   {-- TMMDSSoundCaps ----------------------------------------------------}
  295.   TMMDSSoundCaps = class(TMMObject)
  296.   private
  297.      FBDummy: Boolean;
  298.      FLDummy: DWORD;
  299.      FContinuousRate: Boolean;
  300.      FEmulDriver: Boolean;
  301.      FCertified: Boolean;
  302.      FPrimary16Bit: Boolean;
  303.      FPrimary8Bit: Boolean;
  304.      FPrimaryMono: Boolean;
  305.      FPrimaryStereo: Boolean;
  306.      FSecondary16Bit: Boolean;
  307.      FSecondary8Bit: Boolean;
  308.      FSecondaryMono: Boolean;
  309.      FSecondaryStero: Boolean;
  310.      FMin2Sample: DWORD;
  311.      FMax2Sample: DWORD;
  312.      FPrimaryBuffers: DWORD;
  313.      FMaxHWAll: DWORD;
  314.      FMaxHWStatic: DWORD;
  315.      FMaxHWStream: DWORD;
  316.      FFreeHWAlls: DWORD;
  317.      FFreeHWStatic: DWORD;
  318.      FFreeHWStream: DWORD;
  319.      FMaxHW3All: DWORD;
  320.      FMaxHW3Static: DWORD;
  321.      FMaxHW3Stream: DWORD;
  322.      FFreeHW3Alls: DWORD;
  323.      FFreeHW3Static: DWORD;
  324.      FFreeHW3Stream: DWORD;
  325.      FTotalHWMemBytes: DWORD;
  326.      FFreeHWMemBytes: DWORD;
  327.      FMaxContigFree: DWORD;
  328.      FUnlockRate: DWORD;
  329.      FPlayCPU: DWORD;
  330.   published
  331.      property ContinuousRate: Boolean read FContinuousRate write FBDummy stored False;
  332.      property EmulDriver: Boolean read FEmulDriver write FBDummy stored False;
  333.      property Certified: Boolean read FCertified write FBDummy stored False;
  334.      property Primary16Bit: Boolean read FPrimary16Bit write FBDummy stored False;
  335.      property Primary8Bit: Boolean read FPrimary8Bit write FBDummy stored False;
  336.      property PrimaryMono: Boolean read FPrimaryMono write FBDummy stored False;
  337.      property PrimaryStereo: Boolean read FPrimaryStereo write FBDummy stored False;
  338.      property Secondary16Bit: Boolean read FSecondary16Bit write FBDummy stored False;
  339.      property Secondary8Bit: Boolean read FSecondary8Bit write FBDummy stored False;
  340.      property SecondaryMono: Boolean read FSecondaryMono write FBDummy stored False;
  341.      property SecondaryStereo: Boolean read FSecondaryStero write FBDummy stored False;
  342.      property MinSecondarySampleRate: DWORD read FMin2Sample write FLDummy stored False;
  343.      property MaxSecondarySampleRate: DWORD read FMax2Sample write FLDummy stored False;
  344.      property PrimaryBuffers: DWORD read FPrimaryBuffers write FLDummy stored False;
  345.      property MaxHWMixingAllBuffers: DWORD read FMaxHWAll write FLDummy stored False;
  346.      property MaxHWMixingStaticBuffers: DWORD read FMaxHWStatic write FLDummy stored False;
  347.      property MaxHWMixingStreamingBuffers: DWORD read FMaxHWStream write FLDummy stored False;
  348.      property FreeHWMixingAllBuffers: DWORD read FFreeHWAlls write FLDummy stored False;
  349.      property FreeHWMixingStaticBuffers: DWORD read FFreeHWStatic write FLDummy stored False;
  350.      property FreeHWMixingStreamingBuffers: DWORD read FFreeHWStream write FLDummy stored False;
  351.      property MaxHW3DAllBuffers: DWORD read FMaxHW3All write FLDummy stored False;
  352.      property MaxHW3DStaticBuffers: DWORD read FMaxHW3Static write FLDummy stored False;
  353.      property MaxHW3DStreamingBuffers: DWORD read FMaxHW3Stream write FLDummy stored False;
  354.      property FreeHW3DAllBuffers: DWORD read FFreeHW3Alls write FLDummy stored False;
  355.      property FreeHW3DStaticBuffers: DWORD read FFreeHW3Static write FLDummy stored False;
  356.      property FreeHW3DStreamingBuffers: DWORD read FFreeHW3Stream write FLDummy stored False;
  357.      property TotalHWMemBytes: DWORD read FTotalHWMemBytes write FLDummy stored False;
  358.      property FreeHWMemBytes: DWORD read FFreeHWMemBytes write FLDummy stored False;
  359.      property MaxContigFreeHWMemBytes: DWORD read FMaxContigFree write FLDummy stored False;
  360.      property UnlockTransferRateHWBuffers: DWORD read FUnlockRate write FLDummy stored False;
  361.      property PlayCPUOverheadSWBuffers: DWORD read FPlayCPU write FLDummy stored False;
  362.   end;
  363.   TMMDSBufferLostEvent = procedure(Sender: TObject; Buffer: TMMDSSoundBuffer; var Abort: Boolean) of object;
  364.   TMMDSBufferEndEvent  = procedure(Sender: TObject; Buffer: TMMDSSoundBuffer) of object;
  365.   {-- TMMDSWaveMixer ----------------------------------------------------}
  366.   TMMDSWaveMixer = class(TMMNonVisualComponent)
  367.   private
  368.      DirectSoundObject: IDirectSound;
  369.      FDevices         : TList;
  370.      FDeviceID        : TMMDeviceID;
  371.      FSampleRate      : Longint;        { sampling rate               }
  372.      FBits            : TMMBits;        { bit8 or bit16               }
  373.      FMode            : TMMMode;        { mMono, mStereo              }
  374.      FProductName     : String;
  375.      FPrimaryBuffer   : IDirectSoundBuffer;
  376.      FBuffers         : TList;
  377.      FLevel           : TMMDSLevel;
  378.      FCaps            : TMMDSSoundCaps;
  379.      FSpeakerConfig   : TMMDSSpeakerConfig;
  380.      FVolume          : Longint;
  381.      FPanning         : Longint;
  382.      FMuted           : Boolean;
  383.      FHandle          : THandle;
  384.      FTimerInit       : integer;
  385.      FUse3D           : Boolean;
  386.      F3DListener      : TMMDS3DListener;
  387.      FWorkInDesign    : Boolean;
  388.      FCoopHandle      : THandle;
  389.      FOnBufferLost    : TMMDSBufferLostEvent;
  390.      FOnBufferEnd     : TMMDSBufferEndEvent;
  391.      procedure SetPrimaryWaveFormat;
  392.      procedure SetPCMWaveFormat(wf: TPCMWaveFormat);
  393.      function  GetPCMWaveFormat: TPCMWaveFormat;
  394.      procedure SetBits(aValue: TMMBits);
  395.      procedure SetMode(aValue: TMMMode);
  396.      procedure SetSampleRate(aValue: Longint);
  397.      procedure SetCaps(aValue: TMMDSSoundCaps);
  398.      function  GetCaps: TMMDSSoundCaps;
  399.      procedure SetLevel(aValue: TMMDSLevel);
  400.      function  GetNumDevs: integer;
  401.      function  GetDevices(Index: integer): PDSDRIVERDESC;
  402.      procedure SetDeviceID(DeviceID: TMMDeviceID);
  403.      procedure SetProductName(aValue: String);
  404.      function  GetBuffer(Index: integer): TMMDSSoundBuffer;
  405.      function  GetBufferName(aName: string): TMMDSSoundBuffer;
  406.      function  GetBufferCount: integer;
  407.      function  GetSpeaker: TMMDSSpeakerConfig;
  408.      procedure SetSpeaker(aValue: TMMDSSpeakerConfig);
  409.      procedure SetMuted(aValue: Boolean);
  410.      procedure SetVolume(aValue: Longint);
  411.      function  GetVolume: Longint;
  412.      procedure SetPanning(aValue: Longint);
  413.      function  GetPanning: Longint;
  414.      procedure CopyData(Buffer: TMMDSSoundBuffer);
  415.      procedure UpdateTimer(Enable: Boolean);
  416.      function  FindFreeName(aName: String): String;
  417.      procedure SetUse3D(Value: Boolean);
  418.      procedure Set3DListener(Value: TMMDS3DListener);
  419.      function  GetOpened: Boolean;
  420.   protected
  421.      procedure WndProc(var Msg: TMessage); virtual;
  422.      procedure BufferLost(Buffer: TMMDSSoundBuffer; Abort: Boolean); dynamic;
  423.      procedure BufferEnd(Buffer: TMMDSSoundBuffer); dynamic;
  424.      procedure Loaded; override;
  425.   public
  426.      constructor Create(AOwner: TComponent); override;
  427.      destructor  Destroy; override;
  428.      procedure Open;
  429.      procedure Close;
  430.      procedure CooperateWith(Handle: THandle);
  431.      procedure CreateSoundBuffer(pwfx: PWaveFormatEx; dwLength: Longint; Buffer: TMMDSSoundBuffer; Static: Boolean);
  432.      function  AddBuffer(var aName: string; aWave: TMMWave): TMMDSSoundBuffer;
  433.      procedure SetupBuffer(var aName: string; aWave: TMMWave; Buffer: TMMDSSoundBuffer);
  434.      function  DuplicateBuffer(var aName: string; Buffer: TMMDSSoundBuffer): TMMDSSoundBuffer;
  435.      procedure ClearBuffer(Buffer: TMMDSSoundBuffer);
  436.      procedure RemoveBuffer(Buffer: TMMDSSoundBuffer);
  437.      procedure PlayBuffer(Buffer: TMMDSSoundBuffer);
  438.      procedure PauseBuffer(Buffer: TMMDSSoundBuffer);
  439.      procedure StopBuffer(Buffer: TMMDSSoundBuffer);
  440.      procedure FreeBuffers;
  441.      procedure OpenInDesignTime;
  442.      procedure CloseInDesignTime;
  443.      property  PCMWaveFormat: TPCMWaveFormat read GetPCMWaveFormat write SetPCMWaveFormat;
  444.      property  Buffer[Index: integer]: TMMDSSoundBuffer read GetBuffer;
  445.      property  BufferByName[aName: string]: TMMDSSoundBuffer read GetBufferName;
  446.      property  BufferCount: integer read GetBufferCount;
  447.      property  NumDevs: integer read GetNumDevs;
  448.      property  Devices[Index: integer]: PDSDRIVERDESC read GetDevices;
  449.      property  DirectSound: IDirectSound read DirectSoundObject;
  450.      property  PrimaryBuffer: IDirectSoundBuffer read FPrimaryBuffer;
  451.      property  Muted: Boolean read FMuted write SetMuted default False;
  452.      property  Volume: Longint read GetVolume write SetVolume default 0;
  453.      property  Panning: Longint read GetPanning write SetPanning default 0;
  454.      property  Opened: Boolean read GetOpened;
  455.   published
  456.      property  OnBufferLost: TMMDSBufferLostEvent read FOnBufferLost write FOnBufferLost;
  457.      property  OnBufferEnd: TMMDSBufferEndEvent read FOnBufferEnd write FOnBufferEnd;
  458.      property  Level: TMMDSLevel read FLevel write SetLevel default prPriority;
  459.      property  SoundCaps: TMMDSSoundCaps read GetCaps write SetCaps;
  460.      property  SpeakerConfiguration: TMMDSSpeakerConfig read GetSpeaker write SetSpeaker default scStereo;
  461.      property  DeviceID: TMMDeviceID read FDeviceID write SetDeviceID default 0;
  462.      property  ProductName: String read FProductName write SetProductName stored False;
  463.      property  BitLength: TMMBits read FBits write SetBits default b8bit;
  464.      property  SampleRate: Longint read FSampleRate write SetSampleRate default 11025;
  465.      property  Mode: TMMMode read FMode write SetMode default mMono;
  466.      property  Use3D: Boolean read FUse3D write SetUse3D default False;
  467.      property  Sound3D: TMMDS3DListener read F3DListener write Set3DListener;
  468.   end;
  469.   {-- TMMDSMixChannel ---------------------------------------------------}
  470.   TMMDSMixChannel = class(TMMCustomMemoryWave)
  471.   private
  472.      FSoundBuffer   : TMMDSSoundBuffer;
  473.      F3DBuffer      : TMMDS3DBuffer;
  474.      FMixer         : TMMDSWaveMixer;
  475.      FOnPlayEnd     : TNotifyEvent;
  476.      procedure WaveChanged(Sender: TObject);
  477.      procedure SetMuted(aValue: Boolean);
  478.      function  GetMuted: Boolean;
  479.      procedure SetVolume(aValue: Longint);
  480.      function  GetVolume: Longint;
  481.      procedure SetPanning(aValue: Longint);
  482.      function  GetPanning: Longint;
  483.      procedure SetFrequency(aValue: Longint);
  484.      function  GetFrequency: Longint;
  485.      procedure SetPosition(aValue: Longint);
  486.      function  GetPosition: Longint;
  487.      procedure SetLooping(aValue: Boolean);
  488.      function  GetLooping: Boolean;
  489.      function  GetPlaying: Boolean;
  490.      function  GetPaused: Boolean;
  491.      function  GetBufferLength: Longint;
  492.      procedure BufferEnd(Sender: TObject);
  493.      procedure BufferRelease(Sender: TObject);
  494.      procedure Set3DBuffer(Value: TMMDS3DBuffer);
  495.   protected
  496.      procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  497.      procedure Loaded; override;
  498.   public
  499.      constructor Create(aOwner: TComponent); override;
  500.      destructor  Destroy; override;
  501.      procedure GetVUMeter(var LeftValue, RightValue, BothValue: integer; Interval: integer);
  502.      procedure Init;
  503.      procedure Play;
  504.      procedure Pause;
  505.      procedure Stop;
  506.      property SoundBuffer: TMMDSSoundBuffer read FSoundBuffer;
  507.      property BufferLength: Longint read GetBufferLength;
  508.      property Position: Longint read GetPosition write SetPosition;
  509.      property Playing: Boolean read GetPlaying;
  510.      property Paused: Boolean read GetPaused;
  511.      
  512.   published
  513.      property OnPlayEnd: TNotifyEvent read FOnPlayEnd write FOnPlayEnd;
  514.      property Mixer: TMMDSWaveMixer read FMixer write FMixer;
  515.      property Muted: Boolean read GetMuted write SetMuted default False;
  516.      property Volume: Longint read GetVolume write SetVolume default 0;
  517.      property Panning: Longint read GetPanning write SetPanning default 0;
  518.      property Frequency: Longint read GetFrequency write SetFrequency default 0;
  519.      property Looping: Boolean read GetLooping write SetLooping default False;
  520.      property Sound3D: TMMDS3DBuffer read F3DBuffer write Set3DBuffer;
  521.   end;
  522.   {-- EDSMixError -------------------------------------------------------}
  523.   EDSMixError       = class(Exception)
  524.   end;
  525.   {-- EDirectSoundError -------------------------------------------------}
  526.   EDirectSoundError = class(EDSMixError)
  527.   private
  528.     FResult : HResult;
  529.   public
  530.     constructor CreateRes(Code: HResult);
  531.     property Result: HResult read FResult;
  532.   end;
  533. procedure DSCheck(Res: HRESULT);
  534. function  DSCheckExcl(Res: HRESULT; const Excl: array of HRESULT): HRESULT;
  535. implementation
  536. uses consts;
  537. {------------------------------------------------------------------------}
  538. function MM3DVectorToD3DVector(vec: TMM3DVector): TD3DVector;
  539. begin
  540.    with Result do
  541.    begin
  542.       X := vec.X;
  543.       Y := vec.Y;
  544.       Z := vec.Z;
  545.    end;
  546. end;
  547. {------------------------------------------------------------------------}
  548. function D3DVectorToMM3DVector(vec: TD3DVector): TMM3DVector;
  549. begin
  550.    with Result do
  551.    begin
  552.       X := vec.X;
  553.       Y := vec.Y;
  554.       Z := vec.Z;
  555.    end;
  556. end;
  557. {== TMMDSSoundBuffer ====================================================}
  558. constructor TMMDSSoundBuffer.Create;
  559. begin
  560.    inherited Create;
  561.    DirectSoundBuffer := nil;
  562.    FPlaying := False;
  563.    FPaused := False;
  564.    FLooping := False;
  565.    FMuted := False;
  566.    FVolume := 0;
  567.    FPanning := 0;
  568.    FFrequency := 0;
  569.    FOnBufferEnd := nil;
  570. end;
  571. {-- TMMDSSoundBuffer ----------------------------------------------------}
  572. function TMMDSSoundBuffer.GetCaps: TDSBCaps;
  573. begin
  574.    FillChar(Result, SizeOf(TDSBCAPS), 0);
  575.    Result.dwSize := SizeOf(TDSBCAPS);
  576.    if (DirectSoundBuffer <> nil) then DirectSoundBuffer.GetCaps(Result);
  577. end;
  578. {-- TMMDSSoundBuffer ----------------------------------------------------}
  579. procedure TMMDSSoundBuffer.SetLooping(aValue: Boolean);
  580. const
  581.   LoopFlags: array[Boolean] of Integer = (0, DSBPLAY_LOOPING);
  582. begin
  583.    if (aValue <> FLooping) then
  584.    begin
  585.       FLooping := aValue;
  586.       if Playing then
  587.       begin
  588.          DirectSoundBuffer.Play(0, 0, LoopFlags[FLooping]);
  589.       end;
  590.    end;
  591. end;
  592. {-- TMMDSSoundBuffer ----------------------------------------------------}
  593. function TMMDSSoundBuffer.GetLooping: Boolean;
  594. var
  595.    aValue: DWORD;
  596. begin
  597.    if not Playing then Result := FLooping
  598.    else
  599.    begin
  600.       DirectSoundBuffer.GetStatus(aValue);
  601.       Result := (aValue and DSBSTATUS_LOOPING) > 0;
  602.    end;
  603. end;
  604. {-- TMMDSSoundBuffer ----------------------------------------------------}
  605. function TMMDSSoundBuffer.GetPlaying: Boolean;
  606. var
  607.   aResult: DWORD;
  608. begin
  609.    if (DirectSoundBuffer <> nil) then
  610.    begin
  611.       DirectSoundBuffer.GetStatus(aResult);
  612.       Result := (aResult and DSBSTATUS_PLAYING) > 0;
  613.    end
  614.    else Result := False;
  615. end;
  616. {-- TMMDSSoundBuffer ----------------------------------------------------}
  617. procedure TMMDSSoundBuffer.Play;
  618. const
  619.   LoopFlags: array[Boolean] of Integer = (0, DSBPLAY_LOOPING);
  620. begin
  621.    if Playing then Position := 0
  622.    else if (DirectSoundBuffer <> nil) then
  623.    begin
  624.       DirectSoundBuffer.Play(0, 0, LoopFlags[FLooping]);
  625.       FPlaying := True;
  626.       FPaused := False;
  627.    end;
  628. end;
  629. {-- TMMDSSoundBuffer ----------------------------------------------------}
  630. procedure TMMDSSoundBuffer.Pause;
  631. begin
  632.    if (DirectSoundBuffer <> nil) then
  633.    begin
  634.       FPaused := True;
  635.       DirectSoundBuffer.Stop;
  636.    end;
  637. end;
  638. {-- TMMDSSoundBuffer ----------------------------------------------------}
  639. procedure TMMDSSoundBuffer.Stop;
  640. begin
  641.    if (DirectSoundBuffer <> nil) then
  642.    begin
  643.       FPlaying := False;
  644.       FPaused := False;
  645.       DirectSoundBuffer.Stop;
  646.       Position := 0;
  647.    end;
  648. end;
  649. {-- TMMDSSoundBuffer ----------------------------------------------------}
  650. procedure TMMDSSoundBuffer.ReleaseBuffer;
  651. begin
  652.     if DirectSoundBuffer <> nil then
  653.     begin
  654.         DirectSoundBuffer.Release;
  655.         DirectSoundBuffer := nil;
  656.         if Assigned(FOnRelease) then FOnRelease(Self);
  657.     end;
  658. end;
  659. {-- TMMDSSoundBuffer ----------------------------------------------------}
  660. procedure TMMDSSoundBuffer.FreeBuffer;
  661. begin
  662.     if DirectSoundBuffer <> nil then
  663.         ReleaseBuffer;
  664.     if not FOwned then Free;
  665. end;
  666. {-- TMMDSSoundBuffer ----------------------------------------------------}
  667. procedure TMMDSSoundBuffer.SetMuted(aValue: Boolean);
  668. var
  669.    m: integer;
  670. begin
  671.    if (aValue <> FMuted) then
  672.    begin
  673.       if aValue then
  674.       begin
  675.          if (DirectSoundBuffer <> nil) then
  676.          begin
  677.             m := -10000;
  678.             DirectSoundBuffer.SetVolume(m);
  679.          end;
  680.          FMuted := True;
  681.       end
  682.       else
  683.       begin
  684.          { restore the volume setting }
  685.          if (DirectSoundBuffer <> nil) then
  686.             DirectSoundBuffer.SetVolume(FVolume);
  687.          FMuted := False;
  688.       end;
  689.    end;
  690. end;
  691. {-- TMMDSSoundBuffer ----------------------------------------------------}
  692. procedure TMMDSSoundBuffer.SetVolume(aValue: Longint);
  693. begin
  694.    if (aValue <> FVolume) then
  695.    begin
  696.       FVolume := MinMax(aValue,-10000,0);
  697.       if (DirectSoundBuffer <> nil) and not FMuted then
  698.          DirectSoundBuffer.SetVolume(FVolume);
  699.    end;
  700. end;
  701. {-- TMMDSSoundBuffer ----------------------------------------------------}
  702. function TMMDSSoundBuffer.GetVolume: Longint;
  703. var
  704.    aResult: DWORD;
  705. begin
  706.    if (DirectSoundBuffer <> nil) and not FMuted then
  707.    begin
  708.       DirectSoundBuffer.GetVolume(aResult);
  709.       FVolume := aResult;
  710.    end;
  711.    Result := FVolume;
  712. end;
  713. {-- TMMDSSoundBuffer ----------------------------------------------------}
  714. procedure TMMDSSoundBuffer.SetPanning(aValue: Longint);
  715. begin
  716.    if (aValue <> FPanning) then
  717.    begin
  718.       FPanning := MinMax(aValue,-10000,10000);
  719.       if (DirectSoundBuffer <> nil) then DirectSoundBuffer.SetPan(FPanning);
  720.    end;
  721. end;
  722. {-- TMMDSSoundBuffer ----------------------------------------------------}
  723. function TMMDSSoundBuffer.GetPanning: Longint;
  724. var
  725.    aResult: DWORD;
  726. begin
  727.    if (DirectSoundBuffer <> nil) then
  728.    begin
  729.       DirectSoundBuffer.GetPan(aResult);
  730.       FPanning := aResult;
  731.    end;
  732.    Result := FPanning;
  733. end;
  734. {-- TMMDSSoundBuffer ----------------------------------------------------}
  735. procedure TMMDSSoundBuffer.SetFrequency(aValue: Longint);
  736. begin
  737.    if (aValue <> FFrequency) then
  738.    begin
  739.       FFrequency := min(aValue,100000);
  740.       if (DirectSoundBuffer <> nil) then DirectSoundBuffer.SetFrequency(FFrequency);
  741.    end;
  742. end;
  743. {-- TMMDSSoundBuffer ----------------------------------------------------}
  744. function TMMDSSoundBuffer.GetFrequency: Longint;
  745. var
  746.    aResult: DWORD;
  747. begin
  748.    if (DirectSoundBuffer <> nil) then
  749.    begin
  750.       DirectSoundBuffer.GetFrequency(aResult);
  751.       FFrequency := aResult;
  752.    end;
  753.    Result := FFrequency;
  754. end;
  755. {-- TMMDSSoundBuffer ----------------------------------------------------}
  756. procedure TMMDSSoundBuffer.SetPosition(aValue: Longint);
  757. begin
  758.    FPosition := aValue;
  759.    if (DirectSoundBuffer <> nil) then
  760.       DirectSoundBuffer.SetCurrentPosition(aValue);
  761. end;
  762. {-- TMMDSSoundBuffer ----------------------------------------------------}
  763. function TMMDSSoundBuffer.GetPosition: Longint;
  764. var
  765.    aResult,dummy: DWORD;
  766. begin
  767.    if (DirectSoundBuffer <> nil) then
  768.    begin
  769.       DirectSoundBuffer.GetCurrentPosition(aResult, dummy);
  770.       FPosition := aResult;
  771.    end;
  772.    Result := FPosition;
  773. end;
  774. {-- TMMDSSoundBuffer ----------------------------------------------------}
  775. function TMMDSSoundBuffer.GetBufferLength: Longint;
  776. begin
  777.    Result := 0;
  778.    if (DirectSoundBuffer <> nil) then
  779.    begin
  780.       Result := Caps.dwBufferBytes;
  781.    end;
  782. end;
  783. {== TMMDSWaveMixer ======================================================}
  784. constructor TMMDSWaveMixer.Create(AOwner: TComponent);
  785. begin
  786.    inherited Create(AOwner);
  787.    FLevel := prPriority;
  788.    FBuffers := TList.Create;
  789.    FCaps := TMMDSSoundCaps.Create;
  790.    FSpeakerConfig := scStereo;
  791.    FProductName := '';
  792.    FMuted := False;
  793.    FVolume := 0;
  794.    FPanning := 0;
  795.    FTimerInit := 0;
  796.    DirectSoundObject := nil;
  797.    FPrimaryBuffer := nil;
  798.    FBits := b8Bit;
  799.    FMode := mMono;
  800.    FSampleRate := 11025;
  801.    if _WinNT3_ then
  802.       raise EMMDSWaveMixError.Create(LoadResStr(IDS_DSNOTSUPPORTED));
  803.    if not LoadDSoundDLL then
  804.       raise EMMDSWaveMixError.Create(LoadResStr(IDS_DLLERROR)+' DSOUND.DLL...');
  805.    FDevices := TList.Create;
  806.    DirectSoundEnumerate(DriverEnumerate, FDevices);
  807.    SetDeviceID(0);
  808.    FHandle := AllocateHWnd(WndProc);
  809.    FCoopHandle := 0;
  810.    F3DListener := TMMDS3DListener.Create((AOwner <> nil) and (csLoading in AOwner.ComponentState));
  811.    ErrorCode := ComponentRegistered(InitCode, Self, ClassName);
  812.    if (ErrorCode <> 0) then RegisterFailed(InitCode, Self , ClassName);
  813. end;
  814. {-- TMMDSWaveMixer ------------------------------------------------------}
  815. destructor TMMDSWaveMixer.Destroy;
  816. begin
  817.    UpdateTimer(False);
  818.    DeallocateHWnd(FHandle);
  819.    { finally close the dsound device and free memory }
  820.    Close;
  821.    if (FCaps <> nil) then FCaps.Free;
  822.    if (FBuffers <> nil) then FBuffers.Free;
  823.    { free the device list }
  824.    FreeDriverList(FDevices);
  825.    FDevices.Free;
  826.    F3DListener.Free;
  827.    inherited Destroy;
  828. end;
  829. {-- TMMDSWaveMixer ------------------------------------------------------}
  830. procedure   TMMDSWaveMixer.Loaded;
  831. begin
  832.     inherited Loaded;
  833.     with Sound3D do
  834.     begin
  835.         if MM3DVectorEqual(OrientFront.AsVector,ZeroVector) then
  836.             OrientFront.AsVector := MM3DVector(defOrientFrontX,defOrientFrontY,defOrientFrontZ);
  837.         if MM3DVectorEqual(OrientTop.AsVector,ZeroVector) then
  838.             OrientTop.AsVector := MM3DVector(defOrientTopX,defOrientTopY,defOrientTopZ);
  839.     end;
  840. end;
  841. {-- TMMDSWaveMixer ------------------------------------------------------}
  842. procedure TMMDSWaveMixer.UpdateTimer(Enable: Boolean);
  843. begin
  844.    KillTimer(FHandle, 1);
  845.    if Enable then
  846.       if SetTimer(FHandle, 1, 50, nil) = 0 then
  847.          raise EOutOfResources.Create({$IFDEF DELPHI3}SNoTimers{$ELSE}LoadStr(SNoTimers){$ENDIF});
  848. end;
  849. {-- TMMDSWaveMixer ------------------------------------------------------}
  850. procedure TMMDSWaveMixer.WndProc(var Msg: TMessage);
  851. var
  852.    i: integer;
  853. begin
  854.    if (Msg.Msg = WM_TIMER) and (Msg.wParam = 1) then
  855.    begin
  856.       for i := 0 to BufferCount-1 do
  857.       with Buffer[i] do
  858.       begin
  859.          if FPlaying and not Playing and not Paused then
  860.          begin
  861.             FPlaying := False;
  862.             dec(FTimerInit);
  863.             if (FTimerInit = 0) then UpdateTimer(False);
  864.             BufferEnd(Buffer[i]);
  865.          end;
  866.       end;
  867.    end
  868.    else with Msg do Result := DefWindowProc(FHandle, Msg, wParam, lParam);
  869. end;
  870. {-- TMMDSWaveMixer ------------------------------------------------------}
  871. procedure TMMDSWaveMixer.BufferLost(Buffer: TMMDSSoundBuffer; Abort: Boolean);
  872. begin
  873.    if assigned(FOnBufferLost) then
  874.       FOnBufferLost(Self, Buffer, Abort)
  875.    else Abort := True;
  876. end;
  877. {-- TMMDSWaveMixer ------------------------------------------------------}
  878. procedure TMMDSWaveMixer.BufferEnd(Buffer: TMMDSSoundBuffer);
  879. begin
  880.    if not assigned(Buffer) or (csDestroying in ComponentState) then exit;
  881.    if assigned(FOnBufferEnd) then FOnBufferEnd(Self, Buffer);
  882.    if assigned(Buffer.FOnBufferEnd) then Buffer.FOnBufferEnd(Buffer);
  883. end;
  884. {-- TMMDSWaveMixer ------------------------------------------------------}
  885. function TMMDSWaveMixer.GetDevices(Index: integer): PDSDRIVERDESC;
  886. begin
  887.    if Index < NumDevs then
  888.       Result := PDSDRIVERDESC(FDevices.Items[Index])
  889.    else Result := nil;
  890. end;
  891. {-- TMMDSWaveMixer ------------------------------------------------------}
  892. procedure TMMDSWaveMixer.SetProductName(aValue: String);
  893. begin
  894.    { dummy }
  895. end;
  896. {-- TMMDSWaveMixer ------------------------------------------------------}
  897. Procedure TMMDSWaveMixer.SetLevel(aValue: TMMDSLevel);
  898. begin
  899.      if (DirectSoundObject <> nil) then
  900.         raise EMMDSWaveMixError.Create(LoadResStr(IDS_PROPERTYOPEN));
  901.      if (FLevel <> aValue) then
  902.      begin
  903.         FLevel := aValue;
  904.      end;
  905. end;
  906. {-- TMMDSWaveMixer ------------------------------------------------------}
  907. function TMMDSWaveMixer.GetNumDevs: integer;
  908. begin
  909.    Result := FDevices.Count;
  910. end;
  911. {-- TMMDSWaveMixer ------------------------------------------------------}
  912. Procedure TMMDSWaveMixer.SetDeviceID(DeviceID: TMMDeviceID);
  913. begin
  914.      if (DirectSoundObject <> nil) then
  915.         raise EMMDSWaveMixError.Create(LoadResStr(IDS_PROPERTYOPEN));
  916.      FProductName := LoadResStr(IDS_DSNODEVICE);
  917.      if (NumDevs > 1) and (DeviceID >= 0) and (DeviceID < NumDevs) then
  918.      begin
  919.         GetCaps;
  920.         FProductName := Devices[DeviceID]^.Description;
  921.      end;
  922.    { set the new device }
  923.    FDeviceID := DeviceID;
  924.    if (FDeviceID >= NumDevs) or (FDeviceID < 0) or (NumDevs < 2) then
  925.       FDeviceID := InvalidID;
  926. end;
  927. {-- TMMDSWaveMixer ------------------------------------------------------}
  928. procedure TMMDSWaveMixer.SetUse3D(Value: Boolean);
  929. begin
  930.      if (DirectSoundObject <> nil) then
  931.         raise EMMDSWaveMixError.Create(LoadResStr(IDS_PROPERTYOPEN));
  932.      FUse3D := Value;
  933. end;
  934. {-- TMMDSWaveMixer ------------------------------------------------------}
  935. procedure TMMDSWaveMixer.Set3DListener(Value: TMMDS3DListener);
  936. begin
  937.     F3DListener.Assign(Value);
  938. end;
  939. {-- TMMDSWaveMixer ------------------------------------------------------}
  940. Procedure TMMDSWaveMixer.SetPrimaryWaveFormat;
  941. var
  942.    wf: TPCMWaveFormat;
  943. begin
  944.    if not (csDesigning in ComponentState) or FWorkInDesign then
  945.    begin
  946.       wf := PCMWaveFormat;
  947.       if (FLevel <> prNormal) and (FPrimaryBuffer <> nil) then
  948.       begin
  949.          if FPrimaryBuffer.SetFormat(@wf) <> DS_OK then
  950.             raise EMMDSWaveMixError.Create('DirectSound PrimaryBuffer SetFormat failed');
  951.       end;
  952.    end;
  953. end;
  954. {-- TMMDSWaveMixer ------------------------------------------------------}
  955. Procedure TMMDSWaveMixer.SetPCMWaveFormat(wf: TPCMWaveFormat);
  956. var
  957.    pwfx: PWaveFormatEx;
  958. begin
  959.    pwfx := @wf;
  960.    if not pcmIsValidFormat(pwfx) then
  961.       raise EMMDSWaveMixError.Create(LoadResStr(IDS_INVALIDFORMAT));
  962.    SampleRate := pwfx^.nSamplesPerSec;
  963.    BitLength := TMMBits(pwfx^.wBitsPerSample div 8 - 1);
  964.    Mode := TMMMode(pwfx^.nChannels-1);
  965. end;
  966. {-- TMMDSWaveMixer ------------------------------------------------------}
  967. function TMMDSWaveMixer.GetPCMWaveFormat: TPCMWaveFormat;
  968. var
  969.    wfx: TWaveFormatEx;
  970. begin
  971.    pcmBuildWaveHeader(@wfx, (Ord(FBits)+1)*8, Ord(FMode)+1, SampleRate);
  972.    Result := PPCMWaveFormat(@wfx)^;
  973. end;
  974. {-- TMMDSWaveMixer ------------------------------------------------------}
  975. Procedure TMMDSWaveMixer.SetBits(aValue: TMMBits);
  976. begin
  977.    if (aValue <> FBits) then
  978.    begin
  979.       FBits := aValue;
  980.       SetPrimaryWaveFormat;
  981.    end;
  982. end;
  983. {-- TMMDSWaveMixer ------------------------------------------------------}
  984. Procedure TMMDSWaveMixer.SetMode(aValue: TMMMode);
  985. begin
  986.    if (aValue <> FMode) then
  987.    begin
  988.       FMode := aValue;
  989.       SetPrimaryWaveFormat;
  990.    end;
  991. end;
  992. {-- TMMDSWaveMixer ------------------------------------------------------}
  993. procedure TMMDSWaveMixer.SetSampleRate(aValue: Longint);
  994. begin
  995.    if (aValue <> FSampleRate) then
  996.    begin
  997.       FSampleRate := MinMax(aValue, 8000, 100000);
  998.       SetPrimaryWaveFormat;
  999.    end;
  1000. end;
  1001. {-- TMMDSWaveMixer ------------------------------------------------------}
  1002. procedure TMMDSWaveMixer.Open;
  1003. var
  1004.   aResult: DWORD;
  1005.   BufferDesc: TDSBUFFERDESC;
  1006.   H: THandle;
  1007. begin
  1008.    if LoadDSoundDLL and (DirectSoundObject = nil) then
  1009.    begin
  1010.       if (NumDevs < 2) then
  1011.           raise EMMDSWaveMixError.Create(LoadResStr(IDS_DSNODEVICE));
  1012.       if (DeviceID = InvalidID) then
  1013.           raise EMMDSWaveMixError.Create(LoadResStr(IDS_INVALIDDEVICEID));
  1014.       try
  1015.          DSCheck(DirectSoundCreate(Devices[FDeviceID]^.lpGUID, DirectSoundObject, nil));
  1016.          if (FCoopHandle = 0) then
  1017.          begin
  1018.             H := 0;
  1019.             if (Owner <> nil) and (Owner is TForm) then
  1020.                 H := TForm(Owner).Handle
  1021.             {$IFDEF BUILD_ACTIVEX}
  1022.             else
  1023.                 H := ParentWindow
  1024.             {$ENDIF}
  1025.             ;
  1026.             if (H <> 0) then
  1027.                 CooperateWith(H);
  1028.          end
  1029.          else
  1030.              CooperateWith(FCoopHandle);
  1031.          FillChar(BufferDesc, SizeOf(TDSBUFFERDESC), 0);
  1032.          with BufferDesc do
  1033.          begin
  1034.             dwSize := SizeOf(TDSBUFFERDESC);
  1035.             dwFlags := DSBCAPS_CTRLVOLUME or DSBCAPS_CTRLPAN or DSBCAPS_PRIMARYBUFFER;
  1036.             if Use3D then
  1037.                 dwFlags := (dwFlags or DSBCAPS_CTRL3D) and not DSBCAPS_CTRLPAN;
  1038.          end;
  1039.          aResult := DirectSoundObject.CreateSoundBuffer(BufferDesc, FPrimaryBuffer, nil);
  1040.          if Use3D then
  1041.          begin
  1042.             if aResult <> DS_OK then
  1043.                if (csDesigning in ComponentState) and not FWorkInDesign then
  1044.                begin
  1045.                   with BufferDesc do
  1046.                        dwFlags := (dwFlags and not DSBCAPS_CTRL3D) or DSBCAPS_CTRLPAN;
  1047.                   DSCheck(DirectSoundObject.CreateSoundBuffer(BufferDesc, FPrimaryBuffer, nil));
  1048.                end
  1049.                else
  1050.                   { TODO: Should be resource id }
  1051.                   raise EDSMixError.Create('3D sound not available')
  1052.             else
  1053.                 F3DListener.CreateBuffer(FPrimaryBuffer);
  1054.          end
  1055.          else
  1056.          begin
  1057.             if (aResult = DSERR_CONTROLUNAVAIL) then
  1058.             begin
  1059.                with BufferDesc do dwFlags := dwFlags and not DSBCAPS_CTRLVOLUME and not DSBCAPS_CTRLPAN;
  1060.                aResult := DirectSoundObject.CreateSoundBuffer(BufferDesc, FPrimaryBuffer, nil);
  1061.             end;
  1062.             DSCheck(aResult);
  1063.          end;
  1064.          SetPrimaryWaveFormat;
  1065.          SetSpeaker(FSpeakerConfig);
  1066.          FPrimaryBuffer.Play(0,0,DSBPLAY_LOOPING);
  1067.          
  1068.       except
  1069.          Close;
  1070.          raise;
  1071.       end;
  1072.    end;
  1073. end;
  1074. {-- TMMDSWaveMixer ------------------------------------------------------}
  1075. function  TMMDSWaveMixer.GetOpened: Boolean;
  1076. begin
  1077.     Result := FPrimaryBuffer <> nil;
  1078. end;
  1079. {-- TMMDSWaveMixer ------------------------------------------------------}
  1080. procedure TMMDSWaveMixer.CooperateWith(Handle: THandle);
  1081. var
  1082.     dwLevel: Longint;
  1083. begin
  1084.     FCoopHandle := Handle;
  1085.     if (DirectSoundObject <> nil) then
  1086.     begin
  1087.         case FLevel of
  1088.            prPriority : dwLevel := DSSCL_PRIORITY;
  1089.            prExclusive: dwLevel := DSSCL_EXCLUSIVE;
  1090.            else dwLevel := DSSCL_NORMAL;
  1091.         end;
  1092.         DSCheck(DirectSoundObject.SetCooperativeLevel(FCoopHandle, dwLevel));
  1093.     end;
  1094. end;
  1095. {-- TMMDSWaveMixer ------------------------------------------------------}
  1096. procedure TMMDSWaveMixer.Close;
  1097. begin
  1098.    FreeBuffers;
  1099.    if (DirectSoundObject <> nil) then
  1100.    begin
  1101.       if Use3D then
  1102.         F3DListener.FreeBuffer;
  1103.       if (FPrimaryBuffer <> nil) then
  1104.       begin
  1105.          FPrimaryBuffer.Release;
  1106.          FPrimaryBuffer := nil;
  1107.       end;
  1108.       DirectSoundObject.Release;
  1109.       DirectSoundObject := nil;
  1110.    end;
  1111. end;
  1112. {-- TMMDSWaveMixer ------------------------------------------------------}
  1113. procedure TMMDSWaveMixer.SetCaps(aValue: TMMDSSoundCaps);
  1114. begin
  1115.    { dummy }
  1116. end;
  1117. {-- TMMDSWaveMixer ------------------------------------------------------}
  1118. function TMMDSWaveMixer.GetCaps: TMMDSSoundCaps;
  1119. var
  1120.    aCaps: TDSCAPS;
  1121.    wasClosed: Boolean;
  1122. begin
  1123.    wasClosed := False;
  1124.    FillChar(aCaps, SizeOf(TDSCAPS), 0);
  1125.    if (DeviceID <> InvalidID) and (NumDevs > 1) then
  1126.    try
  1127.        { open the device if not open }
  1128.        if DirectSoundObject = nil then
  1129.        begin
  1130.           wasClosed := True;
  1131.           Open;
  1132.        end;
  1133.        try
  1134.           aCaps.dwSize := SizeOf(TDSCAPS);
  1135.           DirectSoundObject.GetCaps(aCaps);
  1136.           with FCaps do
  1137.           begin
  1138.              FContinuousRate := (aCaps.dwFlags and DSCAPS_CONTINUOUSRATE) > 0;
  1139.              FEmulDriver := (aCaps.dwFlags and DSCAPS_EMULDRIVER) > 0;
  1140.              FCertified := (aCaps.dwFlags and DSCAPS_CERTIFIED) > 0;
  1141.              FPrimary16Bit := (aCaps.dwFlags and DSCAPS_PRIMARY16BIT) > 0;
  1142.              FPrimary8Bit := (aCaps.dwFlags and DSCAPS_PRIMARY8BIT) > 0;
  1143.              FPrimaryMono := (aCaps.dwFlags and DSCAPS_PRIMARYMONO) > 0;
  1144.              FPrimaryStereo := (aCaps.dwFlags and DSCAPS_PRIMARYSTEREO) > 0;
  1145.              FSecondary16Bit := (aCaps.dwFlags and DSCAPS_SECONDARY16BIT) > 0;
  1146.              FSecondary8Bit := (aCaps.dwFlags and DSCAPS_SECONDARY8BIT) > 0;
  1147.              FSecondaryMono := (aCaps.dwFlags and DSCAPS_SECONDARYMONO) > 0;
  1148.              FSecondaryStero := (aCaps.dwFlags and DSCAPS_SECONDARYSTEREO) > 0;
  1149.              FMin2Sample := aCaps.dwMinSecondarySampleRate;
  1150.              FMax2Sample := aCaps.dwMaxSecondarySampleRate;
  1151.              FPrimaryBuffers := aCaps.dwPrimaryBuffers;
  1152.              FMaxHWAll := aCaps.dwMaxHWMixingAllBuffers;
  1153.              FMaxHWStatic := aCaps.dwMaxHWMixingStaticBuffers;
  1154.              FMaxHWStream := aCaps.dwMaxHWMixingStreamingBuffers;
  1155.              FFreeHWAlls := aCaps.dwFreeHWMixingAllBuffers;
  1156.              FFreeHWStatic := aCaps.dwFreeHWMixingStaticBuffers;
  1157.              FFreeHWStream := aCaps.dwFreeHWMixingStreamingBuffers;
  1158.              FMaxHW3All := aCaps.dwMaxHw3DAllBuffers;
  1159.              FMaxHW3Static := aCaps.dwMaxHw3DStaticBuffers;
  1160.              FMaxHW3Stream := aCaps.dwMaxHw3DStreamingBuffers;
  1161.              FFreeHW3Alls := aCaps.dwFreeHw3DAllBuffers;
  1162.              FFreeHW3Static := aCaps.dwFreeHw3DStaticBuffers;
  1163.              FFreeHW3Stream := aCaps.dwFreeHw3DStreamingBuffers;
  1164.              FTotalHWMemBytes := aCaps.dwTotalHwMemBytes;
  1165.              FFreeHWMemBytes := aCaps.dwFreeHwMemBytes;
  1166.              FMaxContigFree := aCaps.dwMaxContigFreeHwMemBytes;
  1167.              FUnlockRate := aCaps.dwUnlockTransferRateHwBuffers;
  1168.              FPlayCPU := aCaps.dwPlayCpuOverheadSwBuffers;
  1169.           end;
  1170.        finally
  1171.           { close the device if it was closed }
  1172.           if wasClosed then Close;
  1173.        end;
  1174.    except
  1175.        on E: Exception do
  1176.         if (csDesigning in ComponentState) then
  1177.             MessageDlg(E.Message,mtError,[mbOk],0)
  1178.         else
  1179.             raise;
  1180.    end;
  1181.    Result := FCaps;
  1182. end;
  1183. {-- TMMDSWaveMixer ------------------------------------------------------}
  1184. procedure TMMDSWaveMixer.SetMuted(aValue: Boolean);
  1185. var
  1186.    m: integer;
  1187. begin
  1188.    if (aValue <> FMuted) then
  1189.    begin
  1190.       if aValue then
  1191.       begin
  1192.          if (FPrimaryBuffer <> nil) then
  1193.          begin
  1194.             m := -10000;
  1195.             FPrimaryBuffer.SetVolume(m);
  1196.          end;
  1197.          FMuted := True;
  1198.       end
  1199.       else
  1200.       begin
  1201.          { restore the volume setting }
  1202.          if (FPrimaryBuffer <> nil) then
  1203.             FPrimaryBuffer.SetVolume(FVolume);
  1204.          FMuted := False;
  1205.       end;
  1206.    end;
  1207. end;
  1208. {-- TMMDSWaveMixer ------------------------------------------------------}
  1209. procedure TMMDSWaveMixer.SetVolume(aValue: Longint);
  1210. begin
  1211.    if (aValue <> FVolume) then
  1212.    begin
  1213.       FVolume := MinMax(aValue,-10000,0);
  1214.       if (FPrimaryBuffer <> nil) and not FMuted then
  1215.          FPrimaryBuffer.SetVolume(FVolume);
  1216.    end;
  1217. end;
  1218. {-- TMMDSWaveMixer ------------------------------------------------------}
  1219. function TMMDSWaveMixer.GetVolume: Longint;
  1220. var
  1221.    aResult: DWORD;
  1222. begin
  1223.    if (FPrimaryBuffer <> nil) and not FMuted then
  1224.    begin
  1225.       FPrimaryBuffer.GetVolume(aResult);
  1226.       FVolume := aResult;
  1227.    end;
  1228.    Result := FVolume;
  1229. end;
  1230. {-- TMMDSWaveMixer ------------------------------------------------------}
  1231. procedure TMMDSWaveMixer.SetPanning(aValue: Longint);
  1232. begin
  1233.    if (aValue <> FPanning) then
  1234.    begin
  1235.       FPanning := MinMax(aValue,-10000,10000);
  1236.       if (FPrimaryBuffer <> nil) then FPrimaryBuffer.SetPan(aValue);
  1237.    end;
  1238. end;
  1239. {-- TMMDSWaveMixer ------------------------------------------------------}
  1240. function TMMDSWaveMixer.GetPanning: Longint;
  1241. var
  1242.    aResult: DWORD;
  1243. begin
  1244.    if (FPrimaryBuffer <> nil) then
  1245.    begin
  1246.       FPrimaryBuffer.GetPan(aResult);
  1247.       FPanning := aResult;
  1248.    end;
  1249.    Result := FPanning;
  1250. end;
  1251. {-- TMMDSWaveMixer ------------------------------------------------------}
  1252. function TMMDSWaveMixer.GetBuffer(Index: integer): TMMDSSoundBuffer;
  1253. begin
  1254.    Result := TMMDSSoundBuffer(FBuffers[Index]);
  1255. end;
  1256. {-- TMMDSWaveMixer ------------------------------------------------------}
  1257. function TMMDSWaveMixer.GetBufferName(aName: string): TMMDSSoundBuffer;
  1258. var
  1259.   i: integer;
  1260. begin
  1261.    Result := nil;
  1262.    for i := 0 to FBuffers.Count-1 do
  1263.    if TMMDSSoundBuffer(FBuffers[i]).Name = aName then
  1264.    begin
  1265.       Result := TMMDSSoundBuffer(FBuffers[i]);
  1266.       break;
  1267.    end;
  1268. end;
  1269. {-- TMMDSWaveMixer ------------------------------------------------------}
  1270. function TMMDSWaveMixer.FindFreeName(aName: String): String;
  1271. var
  1272.    i: integer;
  1273. begin
  1274.    Result := aName;
  1275.    if (BufferByName[aName] <> nil) or (aName = '') then
  1276.    begin
  1277.       i := 1;
  1278.       while BufferByName[aName+IntToStr(i)] <> nil do inc(i);
  1279.       Result := aName + IntToStr(i);
  1280.    end;
  1281. end;
  1282. {-- TMMDSWaveMixer ------------------------------------------------------}
  1283. function TMMDSWaveMixer.GetBufferCount: integer;
  1284. begin
  1285.    Result := FBuffers.Count;
  1286. end;
  1287. {-- TMMDSWaveMixer ------------------------------------------------------}
  1288. procedure TMMDSWaveMixer.CopyData(Buffer: TMMDSSoundBuffer);
  1289. Label Ready;
  1290. var
  1291.   p, pDummy: PChar;
  1292.   Length, Dummy: DWORD;
  1293.   BufSize: DWORD;
  1294.   wfx: TWaveFormatEx;
  1295.   pwfxSrc: PWaveFormatEx;
  1296.   lpACMConvert: PACMConvert;
  1297. begin
  1298.    if Buffer.DirectSoundBuffer = nil then exit;
  1299.    BufSize := Buffer.Caps.dwBufferBytes;
  1300.    if Buffer.DirectSoundBuffer.Lock(0, BufSize, p, Length, pDummy, Dummy, 0) <> DS_OK then
  1301.    begin
  1302.       Buffer.ReleaseBuffer;
  1303.       raise EMMDSWaveMixError.Create('DirectSoundBuffer Lock failed');
  1304.    end;
  1305.    try
  1306.       if (Buffer.Wave.FormatTag <> WAVE_FORMAT_PCM) then
  1307.       begin
  1308.          if (Buffer.Wave.FormatTag = WAVE_FORMAT_ADPCM) then
  1309.          begin
  1310.             pwfxSrc := Buffer.Wave.PWaveFormat;
  1311.             if adpcmBuildFormatHeader(pwfxSrc, @wfx, 16, 0, 0) then
  1312.             begin
  1313.                adpcmDecode4Bit(Pointer(pwfxSrc), @wfx, Buffer.Wave.PWaveData, p,
  1314.                                Buffer.Wave.PWaveIOInfo^.dwDataBytes);
  1315.                goto Ready;
  1316.             end;
  1317.          end;
  1318.          wfx := acmSuggestPCMFormat(Buffer.Wave.PWaveFormat);
  1319.          lpACMConvert := acmBeginConvert(Buffer.Wave.PWaveFormat,@wfx,
  1320.                                          Buffer.Wave.PWaveData,
  1321.                                          Buffer.Wave.PWaveIOInfo^.dwDataBytes,
  1322.                                          False);
  1323.          if (lpACMConvert <> nil) then
  1324.          begin
  1325.             acmDoConvert(lpACMConvert, Buffer.Wave.PWaveIOInfo^.dwDataBytes);
  1326.             Move(lpACMConvert^.lpDstBuffer^, p^, lpACMConvert^.dwBytesConverted);
  1327.             acmDoneConvert(lpACMConvert);
  1328.          end
  1329.          else raise EMMDSWaveMixError.Create('Unable to convert sound data');
  1330.       end
  1331.       else
  1332.       begin
  1333.          Move(Buffer.Wave.PWaveData^, p^, Buffer.Wave.PWaveIOInfo^.dwDataBytes);
  1334.       end;
  1335. Ready:
  1336.    finally
  1337.       Buffer.DirectSoundBuffer.Unlock(p, BufSize, nil, 0);
  1338.    end;
  1339. end;
  1340. {-- TMMDSWaveMixer ------------------------------------------------------}
  1341. procedure TMMDSWaveMixer.CreateSoundBuffer(pwfx: PWaveFormatEx; dwLength: Longint; Buffer: TMMDSSoundBuffer; Static: Boolean);
  1342. var
  1343.   BufferDesc: TDSBUFFERDESC;
  1344.   m: integer;
  1345. begin
  1346.    FillChar(BufferDesc, SizeOf(TDSBUFFERDESC), 0);
  1347.    with BufferDesc do
  1348.    begin
  1349.       dwSize := SizeOf(TDSBUFFERDESC);
  1350.       dwFlags := DSBCAPS_CTRLDEFAULT or DSBCAPS_STICKYFOCUS or DSBCAPS_GLOBALFOCUS or DSBCAPS_GETCURRENTPOSITION2;
  1351.       if Static then
  1352.          dwFlags := dwFlags or DSBCAPS_STATIC;
  1353.       if Use3D then
  1354.         dwFlags := (dwFlags or DSBCAPS_CTRL3D) and not DSBCAPS_CTRLPAN;
  1355.       dwBufferBytes := dwLength;
  1356.       lpwfxFormat   := pwfx;
  1357.    end;
  1358.    Buffer.DirectSoundBuffer := nil;
  1359.    if DirectSoundObject.CreateSoundBuffer(BufferDesc, Buffer.DirectSoundBuffer, nil) <> DS_OK then
  1360.    begin
  1361.       { May be we've no 3D sound? }
  1362.       if Use3D then
  1363.         if (csDesigning in ComponentState) and not FWorkInDesign then
  1364.         begin
  1365.             with BufferDesc do
  1366.                  dwFlags := (dwFlags and not DSBCAPS_CTRL3D) or DSBCAPS_CTRLPAN;
  1367.             DSCheck(DirectSoundObject.CreateSoundBuffer(BufferDesc, Buffer.DirectSoundBuffer, nil));
  1368.         end
  1369.         else
  1370.             { TODO: should be resource id }
  1371.             raise EDSMixError.Create('3D sound not available')
  1372.       else
  1373.       begin
  1374.           { ev. older DSound version which doesn't support DSBCAPS_STICKYFOCUS }
  1375.           BufferDesc.dwFlags := DSBCAPS_CTRLDEFAULT;
  1376.           if Static then
  1377.              BufferDesc.dwFlags := BufferDesc.dwFlags or DSBCAPS_STATIC;
  1378.           DSCheck(DirectSoundObject.CreateSoundBuffer(BufferDesc, Buffer.DirectSoundBuffer, nil));
  1379.       end;
  1380.    end;
  1381.    if Buffer.Muted then
  1382.    begin
  1383.       m := -10000;
  1384.       Buffer.DirectSoundBuffer.SetVolume(m);
  1385.    end
  1386.    else Buffer.DirectSoundBuffer.SetVolume(Buffer.FVolume);
  1387.    Buffer.DirectSoundBuffer.SetPan(Buffer.FPanning);
  1388.    Buffer.DirectSoundBuffer.SetFrequency(Buffer.FFrequency);
  1389.    FBuffers.Add(Buffer);
  1390. end;
  1391. {-- TMMDSWaveMixer ------------------------------------------------------}
  1392. procedure TMMDSWaveMixer.SetupBuffer(var aName: string; aWave: TMMWave; Buffer: TMMDSSoundBuffer);
  1393. Label Ready;
  1394. var
  1395.   pwfxSrc: PWaveFormatEx;
  1396.   wfx: TWaveFormatEx;
  1397.   BufSize: Longint;
  1398. begin
  1399.    if (Buffer = nil) then exit;
  1400.    if not aWave.IsMemWave then
  1401.       raise EMMDSWaveMixError.Create(LoadResStr(IDS_NOMEMWAVE));
  1402.    if (aWave.FormatTag <> WAVE_FORMAT_PCM) then
  1403.    begin
  1404.       if (aWave.FormatTag = WAVE_FORMAT_ADPCM) then
  1405.       begin
  1406.          pwfxSrc := aWave.PWaveFormat;
  1407.          if adpcmBuildFormatHeader(pwfxSrc, @wfx, 16, 0, 0) then
  1408.          begin
  1409.             BufSize := PADPCMWaveFormat(pwfxSrc)^.wSamplesPerBlock * Longint(wfx.nBlockAlign);
  1410.             BufSize := BufSize*(aWave.PWaveIOInfo^.dwDataBytes div pwfxSrc^.nBlockAlign);
  1411.             goto Ready;
  1412.          end;
  1413.       end;
  1414.       wfx := acmSuggestPCMFormat(aWave.PWaveFormat);
  1415.       if not acmQueryConvert(aWave.PWaveFormat,@wfx,False) then
  1416.          raise EMMDSWaveMixError.Create(LoadResStr(IDS_INVALIDFORMAT));
  1417.       BufSize := acmSizeOutputData(aWave.PWaveFormat,@wfx,aWave.PWaveIOInfo^.dwDataBytes);
  1418.    end
  1419.    else
  1420.    begin
  1421.       wfx     := aWave.PWaveFormat^;
  1422.       BufSize := aWave.PWaveIOInfo^.dwDataBytes;
  1423.    end;
  1424. Ready:
  1425.    with Buffer do
  1426.    begin
  1427.       aName := FindFreeName(aName);
  1428.       FName := aName;
  1429.       FWave := aWave;
  1430.    end;
  1431.    CreateSoundBuffer(@wfx, BufSize, Buffer, True);
  1432.    try
  1433.       CopyData(Buffer);
  1434.    except
  1435.       RemoveBuffer(Buffer);
  1436.    end;
  1437. end;
  1438. {-- TMMDSWaveMixer ------------------------------------------------------}
  1439. function TMMDSWaveMixer.AddBuffer(var aName: string; aWave: TMMWave): TMMDSSoundBuffer;
  1440. var
  1441.   Buffer: TMMDSSoundBuffer;
  1442. begin
  1443.    Buffer := TMMDSSoundBuffer.Create;
  1444.    try
  1445.       SetupBuffer(aName,aWave,Buffer);
  1446.    except
  1447.       Buffer.Free;
  1448.       raise;
  1449.    end;
  1450.    Result := Buffer;
  1451. end;
  1452. {-- TMMDSWaveMixer ------------------------------------------------------}
  1453. procedure TMMDSWaveMixer.FreeBuffers;
  1454. begin
  1455.    while BufferCount > 0 do RemoveBuffer(Buffer[0]);
  1456. end;
  1457. {-- TMMDSWaveMixer ------------------------------------------------------}
  1458. procedure TMMDSWaveMixer.ClearBuffer(Buffer: TMMDSSoundBuffer);
  1459. var
  1460.   i: integer;
  1461. begin
  1462.    i := FBuffers.IndexOf(Buffer);
  1463.    if i >= 0 then
  1464.    begin
  1465.       StopBuffer(Buffer);
  1466.       Buffer.ReleaseBuffer;
  1467.       FBuffers.Delete(i);
  1468.       FBuffers.Pack;
  1469.    end;
  1470. end;
  1471. {-- TMMDSWaveMixer ------------------------------------------------------}
  1472. procedure TMMDSWaveMixer.RemoveBuffer(Buffer: TMMDSSoundBuffer);
  1473. begin
  1474.    ClearBuffer(Buffer);
  1475.    Buffer.FreeBuffer;
  1476. end;
  1477. {-- TMMDSWaveMixer ------------------------------------------------------}
  1478. function TMMDSWaveMixer.DuplicateBuffer(var aName: string; Buffer: TMMDSSoundBuffer): TMMDSSoundBuffer;
  1479. var
  1480.   NewBuffer: TMMDSSoundBuffer;
  1481. begin
  1482.    Result := nil;
  1483.    if (Buffer = nil) or (Buffer.DirectSoundBuffer = nil) then exit;
  1484.    NewBuffer := TMMDSSoundBuffer.Create;
  1485.    aName := FindFreeName(aName);
  1486.    NewBuffer.FName := aName;
  1487.    NewBuffer.FWave := Buffer.Wave;
  1488.    if DirectSoundObject.DuplicateSoundBuffer(Buffer.DirectSoundBuffer, NewBuffer.DirectSoundBuffer) <> DS_OK then
  1489.    begin
  1490.       NewBuffer.Free;
  1491.       raise EMMDSWaveMixError.Create('DirectSound DuplicateSoundBuffer failed');
  1492.    end;
  1493.    if Buffer.Muted then
  1494.    begin
  1495.       NewBuffer.Volume := Buffer.FVolume;
  1496.       NewBuffer.Muted := Buffer.Muted;
  1497.    end
  1498.    else NewBuffer.Volume := Buffer.Volume;
  1499.    NewBuffer.Panning := Buffer.Panning;
  1500.    NewBuffer.Frequency := Buffer.Frequency;
  1501.    NewBuffer.Position := Buffer.Position;
  1502.    NewBuffer.Looping := Buffer.Looping;
  1503.    FBuffers.Add(NewBuffer);
  1504.    Result := NewBuffer;
  1505. end;
  1506. {-- TMMDSWaveMixer ------------------------------------------------------}
  1507. procedure TMMDSWaveMixer.SetSpeaker(aValue: TMMDSSpeakerConfig);
  1508. begin
  1509.    FSpeakerConfig := aValue;
  1510.    if (DirectSoundObject <> nil) then
  1511.          DirectSoundObject.SetSpeakerConfig(Ord(aValue)+1);
  1512. end;
  1513. {-- TMMDSWaveMixer ------------------------------------------------------}
  1514. function TMMDSWaveMixer.GetSpeaker: TMMDSSpeakerConfig;
  1515. var
  1516.   aResult: DWORD;
  1517. begin
  1518.    if (DirectSoundObject <> nil) then
  1519.    begin
  1520.       DirectSoundObject.GetSpeakerConfig(aResult);
  1521.       Result := TMMDSSpeakerConfig(aResult-1);
  1522.    end
  1523.    else Result := FSpeakerConfig;
  1524. end;
  1525. {-- TMMDSWaveMixer ------------------------------------------------------}
  1526. procedure TMMDSWaveMixer.PlayBuffer(Buffer: TMMDSSoundBuffer);
  1527. var
  1528.   Status: DWORD;
  1529.   Abort : Boolean;
  1530. begin
  1531.    if (Buffer = nil) or (Buffer.DirectSoundBuffer = nil) then exit;
  1532.    Buffer.DirectSoundBuffer.GetStatus(Status);
  1533.    if (Status and DSBSTATUS_BUFFERLOST) > 0 then
  1534.    begin
  1535.       { Restore the buffer, rewrite data, and play }
  1536.       if Buffer.DirectSoundBuffer.Restore <> DS_OK then
  1537.          raise EMMDSWaveMixError.Create('DirectSoundBuffer restore failed');
  1538.       Abort := False;
  1539.       BufferLost(Buffer, Abort);
  1540.       if Abort then
  1541.       begin
  1542.          RemoveBuffer(Buffer);
  1543.          exit;
  1544.       end;
  1545.       CopyData(Buffer);
  1546.    end;
  1547.    if not Buffer.Playing and not Buffer.Paused then
  1548.    begin
  1549.       inc(FTimerInit);
  1550.       if (FTimerInit = 1) then UpdateTimer(True);
  1551.    end;
  1552.    Buffer.Play;
  1553. end;
  1554. {-- TMMDSWaveMixer ------------------------------------------------------}
  1555. procedure TMMDSWaveMixer.PauseBuffer(Buffer: TMMDSSoundBuffer);
  1556. begin
  1557.    if (Buffer = nil) or (Buffer.DirectSoundBuffer = nil) then exit;
  1558.    Buffer.Pause;
  1559. end;
  1560. {-- TMMDSWaveMixer ------------------------------------------------------}
  1561. procedure TMMDSWaveMixer.StopBuffer(Buffer: TMMDSSoundBuffer);
  1562. begin
  1563.    if (Buffer = nil) or (Buffer.DirectSoundBuffer = nil) then exit;
  1564.    if Buffer.Playing or Buffer.Paused then
  1565.    begin
  1566.       dec(FTimerInit);
  1567.       if (FTimerInit = 0) then UpdateTimer(False);
  1568.       Buffer.Stop;
  1569.       BufferEnd(Buffer);
  1570.    end
  1571.    else Buffer.Stop;
  1572. end;
  1573. {-- TMMDSWaveMixer ------------------------------------------------------}
  1574. procedure TMMDSWaveMixer.OpenInDesignTime;
  1575. begin
  1576.     if not (csDesigning in ComponentState) then
  1577.         raise EMMDSWaveMixError.Create('OpenInDesignTime called in run-time');
  1578.     FWorkInDesign := True;
  1579.     Open;
  1580.     SetPrimaryWaveFormat;
  1581. end;
  1582. {-- TMMDSWaveMixer ------------------------------------------------------}
  1583. procedure TMMDSWaveMixer.CloseInDesignTime;
  1584. begin
  1585.     if not (csDesigning in ComponentState) then
  1586.         raise EMMDSWaveMixError.Create('CloseInDesignTime called in run-time');
  1587.     Close;
  1588.     FWorkInDesign := False;
  1589. end;
  1590. {== TMMDSMixChannel =====================================================}
  1591. constructor TMMDSMixChannel.Create(aOwner: TComponent);
  1592. begin
  1593.    inherited Create(aOwner);
  1594.    FMixer := nil;
  1595.    if _WinNT3_ then
  1596.       raise EMMDSWaveMixError.Create(LoadResStr(IDS_DSNOTSUPPORTED));
  1597.    if not LoadDSoundDLL then
  1598.       raise EMMDSWaveMixError.Create(LoadResStr(IDS_DLLERROR)+' DSOUND.DLL...');
  1599.    FSoundBuffer := TMMDSSoundBuffer.Create;
  1600.    FSoundBuffer.FOnBufferEnd := BufferEnd;
  1601.    FSoundBuffer.FOnRelease   := BufferRelease;
  1602.    FSoundBuffer.FOwned       := True;
  1603.    Wave.OnChange := WaveChanged;
  1604.    F3DBuffer    := TMMDS3DBuffer.Create((aOwner <> nil) and (csLoading in aOwner.ComponentState));
  1605.    ErrorCode := ComponentRegistered(InitCode, Self, ClassName);
  1606.    if (ErrorCode <> 0) then RegisterFailed(InitCode, Self , ClassName);
  1607. end;
  1608. {-- TMMDSMixChannel -----------------------------------------------------}
  1609. destructor TMMDSMixChannel.Destroy;
  1610. begin
  1611.    if FMixer <> nil then FMixer.Close;
  1612.    F3DBuffer.Free;
  1613.    inherited Destroy;
  1614. end;
  1615. {-- TMMDSMixChannel -----------------------------------------------------}
  1616. procedure   TMMDSMixChannel.Loaded;
  1617. begin
  1618.     inherited Loaded;
  1619.     with Sound3D do
  1620.         if MM3DVectorEqual(ConeOrientation.AsVector,ZeroVector) then
  1621.             ConeOrientation.AsVector := MM3DVector(defConeOrientX,defConeOrientY,defConeOrientZ);
  1622. end;
  1623. {-- TMMDSMixChannel -----------------------------------------------------}
  1624. procedure TMMDSMixChannel.Notification(AComponent: TComponent; Operation: TOperation);
  1625. begin
  1626.    inherited Notification(AComponent, Operation);
  1627.    if (Operation = opRemove) and (AComponent = FMixer) then FMixer := Nil;
  1628. end;
  1629. {-- TMMDSMixChannel -----------------------------------------------------}
  1630. procedure TMMDSMixChannel.WaveChanged(Sender: TObject);
  1631. begin
  1632.    if (FMixer <> nil) and (FSoundBuffer <> nil) then
  1633.    begin
  1634.       FMixer.ClearBuffer(FSoundBuffer);
  1635.    end;
  1636. end;
  1637. {-- TMMDSMixChannel -----------------------------------------------------}
  1638. procedure TMMDSMixChannel.Set3DBuffer(Value: TMMDS3DBuffer);
  1639. begin
  1640.     F3DBuffer.Assign(Value);
  1641. end;
  1642. {-- TMMDSMixChannel -----------------------------------------------------}
  1643. procedure TMMDSMixChannel.BufferEnd(Sender: TObject);
  1644. begin
  1645.    if (Sender = FSoundBuffer) then
  1646.    begin
  1647.       if assigned(FOnPlayEnd) then FOnPlayEnd(Self);
  1648.    end;
  1649. end;
  1650. {-- TMMDSMixChannel -----------------------------------------------------}
  1651. procedure TMMDSMixChannel.BufferRelease(Sender: TObject);
  1652. begin
  1653.     F3DBuffer.FreeBuffer;
  1654. end;
  1655. {-- TMMDSMixChannel -----------------------------------------------------}
  1656. procedure TMMDSMixChannel.Init;
  1657. var
  1658.    aName: String;
  1659. begin
  1660.    if (FMixer <> nil) and not Wave.Empty then
  1661.    with FMixer do
  1662.    begin
  1663.       if (FSoundBuffer.DirectSoundBuffer = nil) then
  1664.       begin
  1665.          FMixer.Open;
  1666.          aName := Wave.FileName;
  1667.          SetupBuffer(aName,Wave,FSoundBuffer);
  1668.          if Use3D then
  1669.             F3DBuffer.CreateBuffer(FSoundBuffer.DirectSoundBuffer);
  1670.       end;
  1671.    end;
  1672. end;
  1673. {-- TMMDSMixChannel -----------------------------------------------------}
  1674. procedure TMMDSMixChannel.Play;
  1675. begin
  1676.    Init;
  1677.    if (FMixer <> nil) then FMixer.PlayBuffer(FSoundBuffer);
  1678. end;
  1679. {-- TMMDSMixChannel -----------------------------------------------------}
  1680. procedure TMMDSMixChannel.Pause;
  1681. begin
  1682.    if (FMixer <> nil) then FMixer.PauseBuffer(FSoundBuffer);
  1683. end;
  1684. {-- TMMDSMixChannel -----------------------------------------------------}
  1685. procedure TMMDSMixChannel.Stop;
  1686. begin
  1687.    if (FMixer <> nil) then FMixer.StopBuffer(FSoundBuffer);
  1688. end;
  1689. {-- TMMDSMixChannel -----------------------------------------------------}
  1690. procedure TMMDSMixChannel.SetPosition(aValue: Longint);
  1691. begin
  1692.    FSoundBuffer.Position := aValue;
  1693. end;
  1694. {-- TMMDSMixChannel -----------------------------------------------------}
  1695. function TMMDSMixChannel.GetPosition: Longint;
  1696. begin
  1697.    Result := FSoundBuffer.Position;
  1698. end;
  1699. {-- TMMDSMixChannel -----------------------------------------------------}
  1700. function TMMDSMixChannel.GetBufferLength: Longint;
  1701. var
  1702.    wfx: TWaveFormatEx;
  1703.    pwfxSrc: PWaveFormatEx;
  1704.    
  1705. begin
  1706.    Result := 0;
  1707.    if (FSoundBuffer.DirectSoundBuffer <> nil) then
  1708.    begin
  1709.       Result := FSoundBuffer.BufferLength;
  1710.    end
  1711.    else if (Wave <> nil) and not Wave.Empty then
  1712.    begin
  1713.       if (Wave.FormatTag <> WAVE_FORMAT_PCM) then
  1714.       begin
  1715.          if (Wave.FormatTag = WAVE_FORMAT_ADPCM) then
  1716.          begin
  1717.             pwfxSrc := Wave.PWaveFormat;
  1718.             if adpcmBuildFormatHeader(pwfxSrc, @wfx, 16, 0, 0) then
  1719.             begin
  1720.                Result := PADPCMWaveFormat(pwfxSrc)^.wSamplesPerBlock * Longint(wfx.nBlockAlign);
  1721.                Result := Result*(Wave.PWaveIOInfo^.dwDataBytes div pwfxSrc^.nBlockAlign);
  1722.                exit;
  1723.             end;
  1724.          end;
  1725.          wfx := acmSuggestPCMFormat(Wave.PWaveFormat);
  1726.          if acmQueryConvert(Wave.PWaveFormat,@wfx,False) then
  1727.             Result := acmSizeOutputData(Wave.PWaveFormat,@wfx,Wave.PWaveIOInfo^.dwDataBytes);
  1728.       end
  1729.       else Result := Wave.PWaveIOInfo^.dwDataBytes;
  1730.    end;
  1731. end;
  1732. {-- TMMDSMixChannel -----------------------------------------------------}
  1733. procedure TMMDSMixChannel.SetVolume(aValue: Longint);
  1734. begin
  1735.    FSoundBuffer.Volume := aValue;
  1736. end;
  1737. {-- TMMDSMixChannel -----------------------------------------------------}
  1738. function TMMDSMixChannel.GetVolume: Longint;
  1739. begin
  1740.    Result := FSoundBuffer.Volume;
  1741. end;
  1742. {-- TMMDSMixChannel -----------------------------------------------------}
  1743. procedure TMMDSMixChannel.SetPanning(aValue: Longint);
  1744. begin
  1745.    FSoundBuffer.Panning := aValue;
  1746. end;
  1747. {-- TMMDSMixChannel -----------------------------------------------------}
  1748. function TMMDSMixChannel.GetPanning: Longint;
  1749. begin
  1750.    Result := FSoundBuffer.Panning;
  1751. end;
  1752. {-- TMMDSMixChannel -----------------------------------------------------}
  1753. procedure TMMDSMixChannel.SetFrequency(aValue: Longint);
  1754. begin
  1755.    FSoundBuffer.Frequency := aValue;
  1756. end;
  1757. {-- TMMDSMixChannel -----------------------------------------------------}
  1758. function TMMDSMixChannel.GetFrequency: Longint;
  1759. begin
  1760.    Result := FSoundBuffer.Frequency;
  1761. end;
  1762. {-- TMMDSMixChannel -----------------------------------------------------}
  1763. procedure TMMDSMixChannel.SetMuted(aValue: Boolean);
  1764. begin
  1765.    FSoundBuffer.Muted := aValue;
  1766. end;
  1767. {-- TMMDSMixChannel -----------------------------------------------------}
  1768. function TMMDSMixChannel.GetMuted: Boolean;
  1769. begin
  1770.    Result := FSoundBuffer.Muted;
  1771. end;
  1772. {-- TMMDSMixChannel -----------------------------------------------------}
  1773. procedure TMMDSMixChannel.SetLooping(aValue: Boolean);
  1774. begin
  1775.    FSoundBuffer.Looping := aValue;
  1776. end;
  1777. {-- TMMDSMixChannel -----------------------------------------------------}
  1778. function TMMDSMixChannel.GetLooping: Boolean;
  1779. begin
  1780.    Result := FSoundBuffer.Looping;
  1781. end;
  1782. {-- TMMDSMixChannel -----------------------------------------------------}
  1783. function TMMDSMixChannel.GetPlaying: Boolean;
  1784. begin
  1785.    Result := FSoundBuffer.Playing;
  1786. end;
  1787. {-- TMMDSMixChannel -----------------------------------------------------}
  1788. function TMMDSMixChannel.GetPaused: Boolean;
  1789. begin
  1790.    Result := FSoundBuffer.Paused;
  1791. end;
  1792. {-- TMMDSMixChannel -----------------------------------------------------}
  1793. procedure TMMDSMixChannel.GetVUMeter(var LeftValue, RightValue, BothValue: integer; Interval: integer);
  1794. var
  1795.    PeakLeft,PeakRight: Smallint;
  1796.    nBytes,dwPos,VolLeft,VolRight: Longint;
  1797. begin
  1798.    LeftValue  := 0;
  1799.    RightValue := 0;
  1800.    BothValue  := 0;
  1801.    if not Wave.Empty and (Wave.FormatTag = WAVE_FORMAT_PCM) and
  1802.       Playing and not Paused and not Muted then
  1803.    begin
  1804.       nBytes := wioTimeToBytes(PWaveFormat,Interval);
  1805.       dwPos  := Position;
  1806.       if (dwPos+nBytes < Wave.PWaveIOInfo.dwDataBytes) then
  1807.       begin
  1808.          pcmFindPeak(Wave.PWaveFormat,
  1809.                      PChar(Wave.PWaveData)+dwPos,
  1810.                      nBytes, PeakLeft, PeakRight);
  1811.          if (Wave.BitLength = 8) then
  1812.          begin
  1813.             PeakLeft := (PeakLeft-128)*255;
  1814.             PeakRight:= (PeakRight-128)*255;
  1815.          end;
  1816.          CalcVolume(2*VOLUMEBASE,
  1817.                     DBToVolume(Volume/100,VOLUMEBASE),
  1818.                     RangeScale(Panning, -10000, 10000, -32768, 32768),
  1819.                     VolLeft,VolRight);
  1820.          LeftValue := MulDiv(abs(PeakLeft),VolLeft,VOLUMEBASE);
  1821.          RightValue := MulDiv(abs(PeakRight),VolRight,VOLUMEBASE);
  1822.          BothValue := (LeftValue + RightValue) div 2;
  1823.       end;
  1824.    end;
  1825. end;
  1826. {== TMMDS3DControl ======================================================}
  1827. destructor  TMMDS3DControl.Destroy;
  1828. begin
  1829.     FreeBuffer;
  1830.     inherited Destroy;
  1831. end;
  1832. {-- TMMDS3DControl ------------------------------------------------------}
  1833. function    TMMDS3DControl.SetDirect: Boolean;
  1834. begin
  1835.     Result := ControlAllocated and (FUpdate = 0);
  1836. end;
  1837. {-- TMMDS3DControl ------------------------------------------------------}
  1838. function    TMMDS3DControl.GetDirect: Boolean;
  1839. begin
  1840.     Result := ControlAllocated and not FInApply;
  1841. end;
  1842. {-- TMMDS3DControl ------------------------------------------------------}
  1843. function    TMMDS3DControl.ApplyFlags: DWORD;
  1844. begin
  1845.     if FDeferred then
  1846.         Result := DS3D_DEFERRED
  1847.     else
  1848.         Result := DS3D_IMMEDIATE;
  1849. end;
  1850. {-- TMMDS3DControl -------------------------------------------------------}
  1851. procedure   TMMDS3DControl.SetDeferred(Value: Boolean);
  1852. begin
  1853.     FDeferred := Value;
  1854.     if not FDeferred then
  1855.         ApplySettings;
  1856. end;
  1857. {-- TMMDS3DControl -------------------------------------------------------}
  1858. procedure   TMMDS3DControl.CreateBuffer(DSBuffer: IDirectSoundBuffer);
  1859. var
  1860.     Caps: TDSBCAPS;
  1861. begin
  1862.     FreeBuffer;
  1863.     if DSBuffer <> nil then
  1864.     begin
  1865.         FillChar(Caps, SizeOf(Caps), 0);
  1866.         Caps.dwSize := SizeOf(Caps);
  1867.         DSCheck(DSBuffer.GetCaps(Caps));
  1868.         if (Caps.dwFlags and DSBCAPS_CTRL3D) = 0 then
  1869.             Exit;
  1870.         ObtainControl(DSBuffer);
  1871.         ApplySettings;
  1872.     end;
  1873. end;
  1874. {-- TMMDS3DControl -------------------------------------------------------}
  1875. procedure   TMMDS3DControl.FreeBuffer;
  1876. begin
  1877.     FreeControl;
  1878. end;
  1879. {-- TMMDS3DControl -------------------------------------------------------}
  1880. procedure   TMMDS3DControl.BeginUpdate;
  1881. begin
  1882.     Inc(FUpdate);
  1883. end;
  1884. {-- TMMDS3DControl -------------------------------------------------------}
  1885. procedure   TMMDS3DControl.EndUpdate;
  1886. begin
  1887.     Dec(FUpdate);
  1888.     if FUpdate = 0 then
  1889.         ApplySettings;
  1890. end;
  1891. {-- TMMDS3DControl -------------------------------------------------------}
  1892. procedure   TMMDS3DControl.ApplySettings;
  1893. begin
  1894.     FInApply := True;
  1895.     try
  1896.         DoApplySettings;
  1897.     finally
  1898.         FInApply := False;
  1899.     end;
  1900. end;
  1901. {== TMMDS3DBuffer =======================================================}
  1902. constructor TMMDS3DBuffer.Create(Loading: Boolean);
  1903. begin
  1904.     inherited Create;
  1905.     FDS3DBuffer         := nil;
  1906.     FMaxDistance        := defMaxDistance;
  1907.     FMinDistance        := defMinDistance;
  1908.     FMode               := defMode;
  1909.     FInsideConeAngle    := defInsideConeAngle;
  1910.     FOutsideConeAngle   := defOutsideConeAngle;
  1911.     FConeOutsideVolume  := defConeOutsideVolume;
  1912.     FPosition           := TMMVector3D.Create;
  1913.     FConeOrientation    := TMMVector3D.Create;
  1914.     FVelocity           := TMMVector3D.Create;
  1915.     if not Loading then
  1916.     begin
  1917.         FPosition.X         := defPosX;
  1918.         FPosition.Y         := defPosY;
  1919.         FPosition.Z         := defPosZ;
  1920.         FConeOrientation.X  := defConeOrientX;
  1921.         FConeOrientation.Y  := defConeOrientY;
  1922.         FConeOrientation.Z  := defConeOrientZ;
  1923.         FVelocity.X         := defVelX;
  1924.         FVelocity.Y         := defVelY;
  1925.         FVelocity.Z         := defVelZ;
  1926.     end;
  1927.     FPosition.OnChange          := VectorChanged;
  1928.     FConeOrientation.OnChange   := VectorChanged;
  1929.     FVelocity.OnChange          := VectorChanged;
  1930. end;
  1931. {-- TMMDS3DBuffer -------------------------------------------------------}
  1932. destructor  TMMDS3DBuffer.Destroy;
  1933. begin
  1934.     FPosition.Free;
  1935.     FConeOrientation.Free;
  1936.     FVelocity.Free;
  1937.     inherited Destroy;
  1938. end;
  1939. {-- TMMDS3DBuffer -------------------------------------------------------}
  1940. function    TMMDS3DBuffer.ControlAllocated: Boolean;
  1941. begin
  1942.     Result := FDS3DBuffer <> nil;
  1943. end;
  1944. {-- TMMDS3DBuffer -------------------------------------------------------}
  1945. procedure   TMMDS3DBuffer.SetMaxDistance(Value: D3DVALUE);
  1946. begin
  1947.     if FMaxDistance <> Value then
  1948.     begin
  1949.         FMaxDistance := Value;
  1950.         if SetDirect then
  1951.             DSCheck(FDS3DBuffer.SetMaxDistance(Value,ApplyFlags))
  1952.     end;
  1953. end;
  1954. {-- TMMDS3DBuffer -------------------------------------------------------}
  1955. procedure TMMDS3DBuffer.SetMinDistance(Value: D3DVALUE);
  1956. begin
  1957.     if FMinDistance <> Value then
  1958.     begin
  1959.         FMinDistance := Value;
  1960.         if SetDirect then
  1961.             DSCheck(FDS3DBuffer.SetMinDistance(Value,ApplyFlags))
  1962.     end;
  1963. end;
  1964. const
  1965.     BufferModes: array[TMMDS3DBufferMode] of DWORD =
  1966.         (DS3DMODE_NORMAL,DS3DMODE_HEADRELATIVE,DS3DMODE_DISABLE);
  1967. {-- TMMDS3DBuffer -------------------------------------------------------}
  1968. procedure TMMDS3DBuffer.SetMode(Value: TMMDS3DBufferMode);
  1969. begin
  1970.     if FMode <> Value then
  1971.     begin
  1972.         FMode := Value;
  1973.         if SetDirect then
  1974.             DSCheck(FDS3DBuffer.SetMode(BufferModes[Value],ApplyFlags))
  1975.     end;
  1976. end;
  1977. {-- TMMDS3DBuffer -------------------------------------------------------}
  1978. procedure TMMDS3DBuffer.SetPosition(Value: TMMVector3D);
  1979. begin
  1980.     FPosition.AsVector := Value.AsVector;
  1981. end;
  1982. {-- TMMDS3DBuffer -------------------------------------------------------}
  1983. procedure TMMDS3DBuffer.VectorChanged(Sender: TObject);
  1984. begin
  1985.     if SetDirect then
  1986.         if Sender = FPosition then
  1987.             DSCheck(FDS3DBuffer.SetPosition(FPosition.x,FPosition.y,FPosition.z,ApplyFlags))
  1988.         else if Sender = FVelocity then
  1989.             DSCheck(FDS3DBuffer.SetVelocity(FVelocity.x,FVelocity.y,FVelocity.z,ApplyFlags))
  1990.         else if Sender = FConeOrientation then
  1991.             DSCheck(FDS3DBuffer.SetConeOrientation(FConeOrientation.x,FConeOrientation.y,FConeOrientation.z,ApplyFlags));
  1992. end;
  1993. {-- TMMDS3DBuffer -------------------------------------------------------}
  1994. procedure TMMDS3DBuffer.SetInsideConeAngle(Value: LongInt);
  1995. begin
  1996.     if FInsideConeAngle <> Value then
  1997.     begin
  1998.         FInsideConeAngle := Value;
  1999.         if SetDirect then
  2000.             DSCheck(FDS3DBuffer.SetConeAngles(Value,OutsideConeAngle,ApplyFlags))
  2001.     end;
  2002. end;
  2003. {-- TMMDS3DBuffer -------------------------------------------------------}
  2004. procedure TMMDS3DBuffer.SetOutsideConeAngle(Value: LongInt);
  2005. begin
  2006.     if FOutsideConeAngle <> Value then
  2007.     begin
  2008.         FOutsideConeAngle := Value;
  2009.         if SetDirect then
  2010.             DSCheck(FDS3DBuffer.SetConeAngles(InsideConeAngle,Value,ApplyFlags))
  2011.     end;
  2012. end;
  2013. {-- TMMDS3DBuffer -------------------------------------------------------}
  2014. procedure TMMDS3DBuffer.SetConeOrientation(Value: TMMVector3D);
  2015. begin
  2016.     FConeOrientation.AsVector := Value.AsVector;
  2017. end;
  2018. {-- TMMDS3DBuffer -------------------------------------------------------}
  2019. procedure TMMDS3DBuffer.SetConeOutsideVolume(Value: LongInt);
  2020. begin
  2021.     if FConeOutsideVolume <> Value then
  2022.     begin
  2023.         FConeOutsideVolume := Value;
  2024.         if SetDirect then
  2025.             DSCheck(FDS3DBuffer.SetConeOutsideVolume(Value,ApplyFlags))
  2026.     end;
  2027. end;
  2028. {-- TMMDS3DBuffer -------------------------------------------------------}
  2029. procedure TMMDS3DBuffer.SetVelocity(Value: TMMVector3D);
  2030. begin
  2031.     FVelocity.AsVector := Value.AsVector;
  2032. end;
  2033. {-- TMMDS3DBuffer -------------------------------------------------------}
  2034. function  TMMDS3DBuffer.GetMaxDistance: D3DVALUE;
  2035. begin
  2036.     if GetDirect then
  2037.         DSCheck(FDS3DBuffer.GetMaxDistance(@FMaxDistance));
  2038.     Result := FMaxDistance;
  2039. end;
  2040. {-- TMMDS3DBuffer -------------------------------------------------------}
  2041. function  TMMDS3DBuffer.GetMinDistance: D3DVALUE;
  2042. begin
  2043.     if GetDirect then
  2044.         DSCheck(FDS3DBuffer.GetMinDistance(@FMinDistance));
  2045.     Result := FMinDistance;
  2046. end;
  2047. {-- TMMDS3DBuffer -------------------------------------------------------}
  2048. function  TMMDS3DBuffer.GetMode: TMMDS3DBufferMode;
  2049. var
  2050.     M: DWORD;
  2051.     i: TMMDS3DBufferMode;
  2052. begin
  2053.     if GetDirect then
  2054.     begin
  2055.         DSCheck(FDS3DBuffer.GetMode(@M));
  2056.         for i := Low(BufferModes) to High(BufferModes) do
  2057.             if BufferModes[i] = M then
  2058.             begin
  2059.                 FMode := i;
  2060.                 Break;
  2061.             end;
  2062.     end;
  2063.     Result := FMode;
  2064. end;
  2065. {-- TMMDS3DBuffer -------------------------------------------------------}
  2066. function  TMMDS3DBuffer.GetPosition: TMMVector3D;
  2067. var
  2068.     Vec: TD3DVECTOR;
  2069. begin
  2070.     if GetDirect then
  2071.     begin
  2072.         DSCheck(FDS3DBuffer.GetPosition(@Vec));
  2073.         FPosition.AsVector := D3DVectorToMM3DVector(Vec);
  2074.     end;
  2075.     Result := FPosition;
  2076. end;
  2077. {-- TMMDS3DBuffer -------------------------------------------------------}
  2078. function  TMMDS3DBuffer.GetInsideConeAngle: LongInt;
  2079. var
  2080.     Temp: LongInt;
  2081. begin
  2082.     if GetDirect then
  2083.         DSCheck(FDS3DBuffer.GetConeAngles(@FInsideConeAngle,@Temp));
  2084.     Result := FInsideConeAngle;
  2085. end;
  2086. {-- TMMDS3DBuffer -------------------------------------------------------}
  2087. function  TMMDS3DBuffer.GetOutsideConeAngle: LongInt;
  2088. var
  2089.     Temp: LongInt;
  2090. begin
  2091.     if GetDirect then
  2092.         DSCheck(FDS3DBuffer.GetConeAngles(@Temp,@FOutsideConeAngle));
  2093.     Result := FOutsideConeAngle;
  2094. end;
  2095. {-- TMMDS3DBuffer -------------------------------------------------------}
  2096. function  TMMDS3DBuffer.GetConeOrientation: TMMVector3D;
  2097. var
  2098.     Vec: TD3DVECTOR;
  2099. begin
  2100.     if GetDirect then
  2101.     begin
  2102.         DSCheck(FDS3DBuffer.GetConeOrientation(@Vec));
  2103.         FConeOrientation.AsVector := D3DVectorToMM3DVector(Vec);
  2104.     end;
  2105.     Result := FConeOrientation;
  2106. end;
  2107. {-- TMMDS3DBuffer -------------------------------------------------------}
  2108. function  TMMDS3DBuffer.GetConeOutsideVolume: LongInt;
  2109. begin
  2110.     if GetDirect then
  2111.         DSCheck(FDS3DBuffer.GetConeOutsideVolume(@FConeOutsideVolume));
  2112.     Result := FConeOutsideVolume;
  2113. end;
  2114. {-- TMMDS3DBuffer -------------------------------------------------------}
  2115. function    TMMDS3DBuffer.GetVelocity: TMMVector3D;
  2116. var
  2117.     Vec: TD3DVECTOR;
  2118. begin
  2119.     if GetDirect then
  2120.     begin
  2121.         DSCheck(FDS3DBuffer.GetVelocity(@Vec));
  2122.         FVelocity.AsVector := D3DVectorToMM3DVector(Vec);
  2123.     end;
  2124.     Result := FVelocity;
  2125. end;
  2126. {-- TMMDS3DBuffer -------------------------------------------------------}
  2127. procedure   TMMDS3DBuffer.ObtainControl(DSBuffer: IDirectSoundBuffer);
  2128. begin
  2129.     if not Succeeded(DSBuffer.QueryInterface(IID_IDirectSound3DBuffer,FDS3DBuffer)) then
  2130.         { TODO: Should be resource id }
  2131.         raise EDSMixError.Create('Error obtaining 3D interface');
  2132. end;
  2133. {-- TMMDS3DBuffer -------------------------------------------------------}
  2134. procedure   TMMDS3DBuffer.FreeControl;
  2135. begin
  2136.     if FDS3DBuffer <> nil then
  2137.     begin
  2138.         FDS3DBuffer.Release;
  2139.         FDS3DBuffer := nil;
  2140.     end;
  2141. end;
  2142. {-- TMMDS3DBuffer -------------------------------------------------------}
  2143. procedure   TMMDS3DBuffer.DoApplySettings;
  2144. var
  2145.     Buf: TDS3DBUFFER;
  2146. begin
  2147.     if SetDirect then
  2148.     begin
  2149.         Buf.dwSize              := SizeOf(Buf);
  2150.         Buf.vPosition           := MM3DVectorToD3DVector(FPosition.AsVector);
  2151.         Buf.vVelocity           := MM3DVectorToD3DVector(FVelocity.AsVector);
  2152.         Buf.dwInsideConeAngle   := FInsideConeAngle;
  2153.         Buf.dwOutsideConeAngle  := FOutsideConeAngle;
  2154.         Buf.vConeOrientation    := MM3DVectorToD3DVector(FConeOrientation.AsVector);
  2155.         Buf.lConeOutsideVolume  := FConeOutsideVolume;
  2156.         Buf.flMaxDistance       := FMaxDistance;
  2157.         Buf.flMinDistance       := FMinDistance;
  2158.         Buf.dwMode              := BufferModes[FMode];
  2159.         DSCheck(FDS3DBuffer.SetAllParameters(@Buf,ApplyFlags));
  2160.     end;
  2161. end;
  2162. {-- TMMDS3DBuffer -------------------------------------------------------}
  2163. procedure   TMMDS3DBuffer.Assign(Source: TPersistent);
  2164. var
  2165.     S: TMMDS3DBuffer;
  2166. begin
  2167.     if Source is TMMDS3DBuffer then
  2168.     begin
  2169.         S := Source as TMMDS3DBuffer;
  2170.         BeginUpdate;
  2171.         try
  2172.             MaxDistance         := S.MaxDistance;
  2173.             MinDistance         := S.MinDistance;
  2174.             Mode                := S.Mode;
  2175.             Position            := S.Position;
  2176.             InsideConeAngle     := S.InsideConeAngle;
  2177.             OutsideConeAngle    := S.OutsideConeAngle;
  2178.             ConeOrientation     := S.ConeOrientation;
  2179.             ConeOutsideVolume   := S.ConeOutsideVolume;
  2180.             Velocity            := S.Velocity;
  2181.         finally
  2182.             EndUpdate;
  2183.         end;
  2184.     end
  2185.     else
  2186.         inherited Assign(Source);
  2187. end;
  2188. {== TMMDS3DListener =====================================================}
  2189. constructor TMMDS3DListener.Create(Loading: Boolean);
  2190. begin
  2191.     inherited Create;
  2192.     FDS3DListener   := nil;
  2193.     FDistanceFactor := defDistanceFactor;
  2194.     FDopplerFactor  := defDopplerFactor;
  2195.     FRollOffFactor  := defRollOffFactor;
  2196.     FOrientFront    := TMMVector3D.Create;
  2197.     FOrientTop      := TMMVector3D.Create;
  2198.     FPosition       := TMMVector3D.Create;
  2199.     FVelocity       := TMMVector3D.Create;
  2200.     if not Loading then
  2201.     begin
  2202.         FOrientFront.X  := defOrientFrontX;
  2203.         FOrientFront.Y  := defOrientFrontY;
  2204.         FOrientFront.Z  := defOrientFrontZ;
  2205.         FOrientTop.X    := defOrientTopX;
  2206.         FOrientTop.Y    := defOrientTopY;
  2207.         FOrientTop.Z    := defOrientTopZ;
  2208.         FPosition.X     := defPositionX;
  2209.         FPosition.Y     := defPositionY;
  2210.         FPosition.Z     := defPositionZ;
  2211.         FVelocity.X     := defVelocityX;
  2212.         FVelocity.Y     := defVelocityY;
  2213.         FVelocity.Z     := defVelocityZ;
  2214.     end;
  2215.     FOrientFront.OnChange   := VectorChanged;
  2216.     FOrientTop.OnChange     := VectorChanged;
  2217.     FPosition.OnChange      := VectorChanged;
  2218.     FVelocity.OnChange      := VectorChanged;
  2219. end;
  2220. {-- TMMDS3DListener -----------------------------------------------------}
  2221. destructor  TMMDS3DListener.Destroy;
  2222. begin
  2223.     FOrientFront.Free;
  2224.     FOrientTop.Free;
  2225.     FPosition.Free;
  2226.     FVelocity.Free;
  2227.     inherited Destroy;
  2228. end;
  2229. {-- TMMDS3DListener -----------------------------------------------------}
  2230. procedure   TMMDS3DListener.ObtainControl(DSBuffer: IDirectSoundBuffer);
  2231. begin
  2232.     if not Succeeded(DSBuffer.QueryInterface(IID_IDirectSound3DListener,FDS3DListener)) then
  2233.         { TODO: Should be resource id }
  2234.         raise EDSMixError.Create('Error obtaining 3D interface');
  2235. end;
  2236. {-- TMMDS3DListener -----------------------------------------------------}
  2237. procedure   TMMDS3DListener.FreeControl;
  2238. begin
  2239.     if FDS3DListener <> nil then
  2240.     begin
  2241.         FDS3DListener.Release;
  2242.         FDS3DListener := nil;
  2243.     end;
  2244. end;
  2245. {-- TMMDS3DListener -----------------------------------------------------}
  2246. procedure   TMMDS3DListener.DoApplySettings;
  2247. var
  2248.     Buf: TDS3DLISTENER;
  2249. begin
  2250.     if SetDirect then
  2251.     begin
  2252.         with Buf do
  2253.         begin
  2254.             dwSize              := SizeOf(Buf);
  2255.             vPosition           := MM3DVectorToD3DVector(Position.AsVector);
  2256.             vVelocity           := MM3DVectorToD3DVector(Velocity.AsVector);
  2257.             vOrientFront        := MM3DVectorToD3DVector(OrientFront.AsVector);
  2258.             vOrientTop          := MM3DVectorToD3DVector(OrientTop.AsVector);
  2259.             flDistanceFactor    := DistanceFactor;
  2260.             flRolloffFactor     := RollOffFactor;
  2261.             flDopplerFactor     := DopplerFactor;
  2262.         end;
  2263.         DSCheck(FDS3DListener.SetAllParameters(@Buf,ApplyFlags));
  2264.     end;
  2265. end;
  2266. {-- TMMDS3DListener -----------------------------------------------------}
  2267. function    TMMDS3DListener.ControlAllocated: Boolean;
  2268. begin
  2269.     Result := FDS3DListener <> nil;
  2270. end;
  2271. {-- TMMDS3DListener -----------------------------------------------------}
  2272. procedure   TMMDS3DListener.Assign(Source: TPersistent);
  2273. var
  2274.     S: TMMDS3DListener;
  2275. begin
  2276.     if Source is TMMDS3DListener then
  2277.     begin
  2278.         S := Source as TMMDS3DListener;
  2279.         BeginUpdate;
  2280.         try
  2281.             DistanceFactor  := S.DistanceFactor;
  2282.             DopplerFactor   := S.DopplerFactor;
  2283.             OrientFront     := S.OrientFront;
  2284.             OrientTop       := S.OrientTop;
  2285.             Position        := S.Position;
  2286.             RollOffFactor   := S.RollOffFactor;
  2287.             Velocity        := S.Velocity;
  2288.         finally
  2289.             EndUpdate;
  2290.         end;
  2291.     end
  2292.     else
  2293.         inherited Assign(Source);
  2294. end;
  2295. {-- TMMDS3DListener -----------------------------------------------------}
  2296. function    TMMDS3DListener.GetDistanceFactor: D3DVALUE;
  2297. begin
  2298.     if GetDirect then
  2299.         DSCheck(FDS3DListener.GetDistanceFactor(@FDistanceFactor));
  2300.     Result := FDistanceFactor;
  2301. end;
  2302. {-- TMMDS3DListener -----------------------------------------------------}
  2303. function    TMMDS3DListener.GetDopplerFactor: D3DVALUE;
  2304. begin
  2305.     if GetDirect then
  2306.         DSCheck(FDS3DListener.GetDopplerFactor(@FDopplerFactor));
  2307.     Result := FDopplerFactor;
  2308. end;
  2309. {-- TMMDS3DListener -----------------------------------------------------}
  2310. function    TMMDS3DListener.GetOrientFront: TMMVector3D;
  2311. var
  2312.     Vec, Temp: TD3DVECTOR;
  2313. begin
  2314.     if GetDirect then
  2315.     begin
  2316.         DSCheck(FDS3DListener.GetOrientation(@Vec,@Temp));
  2317.         FOrientFront.AsVector := D3DVEctorToMM3DVector(Vec);
  2318.     end;
  2319.     Result := FOrientFront;
  2320. end;
  2321. {-- TMMDS3DListener -----------------------------------------------------}
  2322. function    TMMDS3DListener.GetOrientTop: TMMVector3D;
  2323. var
  2324.     Vec, Temp: TD3DVECTOR;
  2325. begin
  2326.     if GetDirect then
  2327.     begin
  2328.         DSCheck(FDS3DListener.GetOrientation(@Temp,@Vec));
  2329.         FOrientTop.AsVector := D3DVectorToMM3DVector(Vec);
  2330.     end;
  2331.     Result := FOrientTop;
  2332. end;
  2333. {-- TMMDS3DListener -----------------------------------------------------}
  2334. function    TMMDS3DListener.GetPosition: TMMVector3D;
  2335. var
  2336.     Vec: TD3DVECTOR;
  2337. begin
  2338.     if GetDirect then
  2339.     begin
  2340.         DSCheck(FDS3DListener.GetPosition(@Vec));
  2341.         FPosition.AsVector := D3DVectorToMM3DVector(Vec);
  2342.     end;
  2343.     Result := FPosition;
  2344. end;
  2345. {-- TMMDS3DListener -----------------------------------------------------}
  2346. function    TMMDS3DListener.GetRollOffFactor: D3DVALUE;
  2347. begin
  2348.     if GetDirect then
  2349.         DSCheck(FDS3DListener.GetRollOffFactor(@FRollOffFactor));
  2350.     Result := FRollOffFactor;
  2351. end;
  2352. {-- TMMDS3DListener -----------------------------------------------------}
  2353. function    TMMDS3DListener.GetVelocity: TMMVector3D;
  2354. var
  2355.     Vec: TD3DVECTOR;
  2356. begin
  2357.     if GetDirect then
  2358.     begin
  2359.         DSCheck(FDS3DListener.GetVelocity(@Vec));
  2360.         FVelocity.AsVector := D3DVectorToMM3DVector(Vec);
  2361.     end;
  2362.     Result := FVelocity;
  2363. end;
  2364. {-- TMMDS3DListener -----------------------------------------------------}
  2365. procedure   TMMDS3DListener.SetDistanceFactor(Value: D3DVALUE);
  2366. begin
  2367.     if FDistanceFactor <> Value then
  2368.     begin
  2369.         FDistanceFactor := Value;
  2370.         if SetDirect then
  2371.             DSCheck(FDS3DListener.SetDistanceFactor(Value,ApplyFlags))
  2372.     end;
  2373. end;
  2374. {-- TMMDS3DListener -----------------------------------------------------}
  2375. procedure   TMMDS3DListener.SetDopplerFactor(Value: D3DVALUE);
  2376. begin
  2377.     if FDopplerFactor <> Value then
  2378.     begin
  2379.         FDopplerFactor := Value;
  2380.         if SetDirect then
  2381.             DSCheck(FDS3DListener.SetDopplerFactor(Value,ApplyFlags))
  2382.     end;
  2383. end;
  2384. {-- TMMDS3DListener -----------------------------------------------------}
  2385. procedure   TMMDS3DListener.SetOrientFront(Value: TMMVector3D);
  2386. begin
  2387.     FOrientFront.AsVector := Value.AsVector;
  2388. end;
  2389. {-- TMMDS3DListener -----------------------------------------------------}
  2390. procedure   TMMDS3DListener.SetOrientTop(Value: TMMVector3D);
  2391. begin
  2392.     FOrientTop.AsVector := Value.AsVector;
  2393. end;
  2394. {-- TMMDS3DListener -----------------------------------------------------}
  2395. procedure   TMMDS3DListener.SetPosition(Value: TMMVector3D);
  2396. begin
  2397.     FPosition.AsVector := Value.AsVector;
  2398. end;
  2399. {-- TMMDS3DListener -----------------------------------------------------}
  2400. procedure   TMMDS3DListener.SetRollOffFactor(Value: D3DVALUE);
  2401. begin
  2402.     if FRollOffFactor <> Value then
  2403.     begin
  2404.         FRollOffFactor := Value;
  2405.         if SetDirect then
  2406.             DSCheck(FDS3DListener.SetRollOffFactor(Value,ApplyFlags))
  2407.     end;
  2408. end;
  2409. {-- TMMDS3DListener -----------------------------------------------------}
  2410. procedure   TMMDS3DListener.SetVelocity(Value: TMMVector3D);
  2411. begin
  2412.     FVelocity.AsVector := Value.AsVector;
  2413. end;
  2414. {-- TMMDS3DListener -----------------------------------------------------}
  2415. procedure   TMMDS3DListener.VectorChanged(Sender: TObject);
  2416. begin
  2417.     if SetDirect then
  2418.         if (Sender = FOrientFront) or (Sender = FOrientTop) then
  2419.             DSCheck(FDS3DListener.SetOrientation(FOrientFront.x,FOrientFront.y,FOrientFront.z,FOrientTop.x,FOrientTop.y,FOrientTop.z,ApplyFlags))
  2420.         else if Sender = FPosition then
  2421.             DSCheck(FDS3DListener.SetPosition(FPosition.x,FPosition.y,FPosition.z,ApplyFlags))
  2422.         else if Sender = FVelocity then
  2423.             DSCheck(FDS3DListener.SetVelocity(FVelocity.x,FVelocity.y,FVelocity.z,ApplyFlags));
  2424. end;
  2425. {-- TMMDS3DListener -----------------------------------------------------}
  2426. procedure   TMMDS3DListener.Commit;
  2427. begin
  2428.     if not SetDirect then
  2429.         { TODO: Should be resource id }
  2430.         raise EDSMixError.Create('Can''t commit changes in this state');
  2431.     DSCheck(FDS3DListener.CommitDeferredSettings);
  2432. end;
  2433. {== EDirectSoundError ===================================================}
  2434. constructor EDirectSoundError.CreateRes(Code: HResult);
  2435. var
  2436.     Msg: string;
  2437.     C: Longint;
  2438. begin
  2439.     FResult := Code;
  2440.     C := Code;
  2441.     { TODO: Should be resource ids }
  2442.     case C of
  2443.         DSERR_ALLOCATED         : Msg := 'Another caller already allocated resources';
  2444.         DSERR_CONTROLUNAVAIL    : Msg := 'Requested control unavailable';
  2445.         DSERR_INVALIDPARAM      : Msg := 'Invalid parameter';
  2446.         DSERR_INVALIDCALL       : Msg := 'Invalid call for current object''s state';
  2447.         DSERR_GENERIC           : Msg := 'Undetermined error';
  2448.         DSERR_PRIOLEVELNEEDED   : Msg := 'Priority not enough for success';
  2449.         DSERR_OUTOFMEMORY       : Msg := 'Out of memory';
  2450.         DSERR_BADFORMAT         : Msg := 'Bad format';
  2451.         DSERR_UNSUPPORTED       : Msg := 'Unsupported';
  2452.         DSERR_NODRIVER          : Msg := 'No driver';
  2453.         DSERR_ALREADYINITIALIZED: Msg := 'Object already initialized';
  2454.         DSERR_NOAGGREGATION     : Msg := 'Object does not support aggregation';
  2455.         DSERR_BUFFERLOST        : Msg := 'Buffer lost';
  2456.         DSERR_OTHERAPPHASPRIO   : Msg := 'Other app has a higher priority level';
  2457.         DSERR_UNINITIALIZED     : Msg := 'Initialize has not been called';
  2458.     else
  2459.         Msg := 'Unknown error code';
  2460.     end;
  2461.     inherited Create(Msg);
  2462. end;
  2463. {------------------------------------------------------------------------}
  2464. procedure DSCheck(Res: HRESULT);
  2465. begin
  2466.    if Res <> DS_OK then
  2467.       raise EDirectSoundError.CreateRes(Res);
  2468. end;
  2469. {------------------------------------------------------------------------}
  2470. function  DSCheckExcl(Res: HRESULT; const Excl: array of HRESULT): HRESULT;
  2471. var
  2472.     i: Integer;
  2473. begin
  2474.     Result := Res;
  2475.     for i := Low(Excl) to High(Excl) do
  2476.         if Excl[i] = Res then
  2477.             Exit;
  2478.     DSCheck(Res);
  2479. end;
  2480. end.