MMDSMix.pas
上传用户:hylc_2004
上传日期:2014-01-23
资源大小:46800k
文件大小:92k
- {========================================================================}
- {= (c) 1995-98 SwiftSoft Ronald Dittrich =}
- {========================================================================}
- {= All Rights Reserved =}
- {========================================================================}
- {= D 01099 Dresden = Fax.: +49(0)351-8037944 =}
- {= Loewenstr.7a = info@swiftsoft.de =}
- {========================================================================}
- {= Actual versions on http://www.swiftsoft.de/index.html =}
- {========================================================================}
- {= This code is for reference purposes only and may not be copied or =}
- {= distributed in any format electronic or otherwise except one copy =}
- {= for backup purposes. =}
- {= =}
- {= No Delphi Component Kit or Component individually or in a collection=}
- {= subclassed or otherwise from the code in this unit, or associated =}
- {= .pas, .dfm, .dcu, .asm or .obj files may be sold or distributed =}
- {= without express permission from SwiftSoft. =}
- {= =}
- {= For more licence informations please refer to the associated =}
- {= HelpFile. =}
- {========================================================================}
- {= $Date: 17.11.98 - 16:26:10 $ =}
- {========================================================================}
- unit MMDSMix;
- {$I COMPILER.INC}
- interface
- uses
- Windows,
- Messages,
- SysUtils,
- Classes,
- Graphics,
- Controls,
- Dialogs,
- Forms,
- MMOLE2,
- MMSystem,
- MMObj,
- MMUtils,
- MMDSound,
- MMD3DTyp,
- MM3D,
- MMRegs,
- MMWave,
- MMPCMSup,
- MMACMSup,
- MMADPCM,
- MMMulDiv,
- MMWaveIO,
- MMCCon;
- type
- EMMDSWaveMixError = class(Exception);
- TMMDSSpeakerConfig = (scHeadphone,scMono,scQuad,scStereo,scSurround);
- TMMDSLevel = (prNormal, prPriority, prExclusive);
- TMMDS3DBufferMode = (bmNormal,bmHeadRelative,bmNo3D);
- const
- {$IFDEF CBUILDER3} {$EXTERNALSYM defMaxDistance} {$ENDIF}
- defMaxDistance = 1e+09; {? Should be inf}
- {$IFDEF CBUILDER3} {$EXTERNALSYM defMinDistance} {$ENDIF}
- defMinDistance = 1.0;
- {$IFDEF CBUILDER3} {$EXTERNALSYM defMode} {$ENDIF}
- defMode = bmNormal;
- {$IFDEF CBUILDER3} {$EXTERNALSYM defPosX} {$ENDIF}
- defPosX = 0; {?}
- {$IFDEF CBUILDER3} {$EXTERNALSYM defPosY} {$ENDIF}
- defPosY = 0; {?}
- {$IFDEF CBUILDER3} {$EXTERNALSYM defPosZ} {$ENDIF}
- defPosZ = 0; {?}
- {$IFDEF CBUILDER3} {$EXTERNALSYM defInsideConeAngle} {$ENDIF}
- defInsideConeAngle = 360;
- {$IFDEF CBUILDER3} {$EXTERNALSYM defOutsideConeAngle} {$ENDIF}
- defOutsideConeAngle = 360;
- {$IFDEF CBUILDER3} {$EXTERNALSYM defConeOrientX} {$ENDIF}
- defConeOrientX = 0;
- {$IFDEF CBUILDER3} {$EXTERNALSYM defConeOrientY} {$ENDIF}
- defConeOrientY = 0;
- {$IFDEF CBUILDER3} {$EXTERNALSYM defConeOrientZ} {$ENDIF}
- defConeOrientZ = 1;
- {$IFDEF CBUILDER3} {$EXTERNALSYM defConeOutsideVolume} {$ENDIF}
- defConeOutsideVolume = 0; {?}
- {$IFDEF CBUILDER3} {$EXTERNALSYM defVelX} {$ENDIF}
- defVelX = 0; {?}
- {$IFDEF CBUILDER3} {$EXTERNALSYM defVelY} {$ENDIF}
- defVelY = 0; {?}
- {$IFDEF CBUILDER3} {$EXTERNALSYM defVelZ} {$ENDIF}
- defVelZ = 0; {?}
- {$IFDEF CBUILDER3} {$EXTERNALSYM defDistanceFactor} {$ENDIF}
- defDistanceFactor = DS3D_DEFAULTDISTANCEFACTOR;
- {$IFDEF CBUILDER3} {$EXTERNALSYM defDopplerFactor} {$ENDIF}
- defDopplerFactor = DS3D_DEFAULTDOPPLERFACTOR;
- {$IFDEF CBUILDER3} {$EXTERNALSYM defOrientFrontX} {$ENDIF}
- defOrientFrontX = 0;
- {$IFDEF CBUILDER3} {$EXTERNALSYM defOrientFrontY} {$ENDIF}
- defOrientFrontY = 0;
- {$IFDEF CBUILDER3} {$EXTERNALSYM defOrientFrontZ} {$ENDIF}
- defOrientFrontZ = 1;
- {$IFDEF CBUILDER3} {$EXTERNALSYM defOrientTopX} {$ENDIF}
- defOrientTopX = 0;
- {$IFDEF CBUILDER3} {$EXTERNALSYM defOrientTopY} {$ENDIF}
- defOrientTopY = 1;
- {$IFDEF CBUILDER3} {$EXTERNALSYM defOrientTopZ} {$ENDIF}
- defOrientTopZ = 0;
- {$IFDEF CBUILDER3} {$EXTERNALSYM defPositionX} {$ENDIF}
- defPositionX = 0; {?}
- {$IFDEF CBUILDER3} {$EXTERNALSYM defPositionY} {$ENDIF}
- defPositionY = 0; {?}
- {$IFDEF CBUILDER3} {$EXTERNALSYM defPositionZ} {$ENDIF}
- defPositionZ = 0; {?}
- {$IFDEF CBUILDER3} {$EXTERNALSYM defRollOffFactor} {$ENDIF}
- defRollOffFactor = DS3D_DEFAULTROLLOFFFACTOR;
- {$IFDEF CBUILDER3} {$EXTERNALSYM defVelocityX} {$ENDIF}
- defVelocityX = 0; {?}
- {$IFDEF CBUILDER3} {$EXTERNALSYM defVelocityY} {$ENDIF}
- defVelocityY = 0; {?}
- {$IFDEF CBUILDER3} {$EXTERNALSYM defVelocityZ} {$ENDIF}
- defVelocityZ = 0; {?}
- type
- {-- TMMDS3DControl -----------------------------------------------------}
- TMMDS3DControl = class(TMMObject)
- private
- FDeferred : Boolean;
- FUpdate : Integer;
- FInApply : Boolean;
- protected
- function SetDirect: Boolean;
- function GetDirect: Boolean;
- function ApplyFlags: DWORD;
- procedure SetDeferred(Value: Boolean);
- destructor Destroy; override;
- procedure CreateBuffer(DSBuffer: IDirectSoundBuffer);
- procedure FreeBuffer;
- procedure ApplySettings;
- procedure ObtainControl(DSBuffer: IDirectSoundBuffer); virtual; abstract;
- procedure FreeControl; virtual; abstract;
- procedure DoApplySettings; virtual; abstract;
- function ControlAllocated: Boolean; virtual; abstract;
- public
- procedure BeginUpdate;
- procedure EndUpdate;
- published
- property Deferred: Boolean read FDeferred write SetDeferred;
- end;
- {-- TMMDS3DBuffer ------------------------------------------------------}
- TMMDS3DBuffer = class(TMMDS3DControl)
- private
- FDS3DBuffer : IDirectSound3DBuffer;
- FMaxDistance : D3DVALUE;
- FMinDistance : D3DVALUE;
- FMode : TMMDS3DBufferMode;
- FPosition : TMMVector3D;
- FInsideConeAngle : LongInt;
- FOutsideConeAngle : LongInt;
- FConeOrientation : TMMVector3D;
- FConeOutsideVolume : LongInt;
- FVelocity : TMMVector3D;
- procedure SetMaxDistance(Value: D3DVALUE);
- procedure SetMinDistance(Value: D3DVALUE);
- procedure SetMode(Value: TMMDS3DBufferMode);
- procedure SetPosition(Value: TMMVector3D);
- procedure SetInsideConeAngle(Value: LongInt);
- procedure SetOutsideConeAngle(Value: LongInt);
- procedure SetConeOrientation(Value: TMMVector3D);
- procedure SetConeOutsideVolume(Value: LongInt);
- procedure SetVelocity(Value: TMMVector3D);
- function GetMaxDistance: D3DVALUE;
- function GetMinDistance: D3DVALUE;
- function GetMode: TMMDS3DBufferMode;
- function GetPosition: TMMVector3D;
- function GetInsideConeAngle: LongInt;
- function GetOutsideConeAngle: LongInt;
- function GetConeOrientation: TMMVector3D;
- function GetConeOutsideVolume: LongInt;
- function GetVelocity: TMMVector3D;
- procedure VectorChanged(Sender: TObject);
- protected
- procedure ObtainControl(DSBuffer: IDirectSoundBuffer); override;
- procedure FreeControl; override;
- procedure DoApplySettings; override;
- function ControlAllocated: Boolean; override;
- public
- constructor Create(Loading: Boolean);
- destructor Destroy; override;
- procedure Assign(Source: TPersistent); override;
- published
- property MaxDistance: D3DVALUE read GetMaxDistance write SetMaxDistance;
- property MinDistance: D3DVALUE read GetMinDistance write SetMinDistance;
- property Mode: TMMDS3DBufferMode read GetMode write SetMode default defMode;
- property Position: TMMVector3D read GetPosition write SetPosition;
- property InsideConeAngle: LongInt read GetInsideConeAngle write SetInsideConeAngle default defInsideConeAngle;
- property OutsideConeAngle: LongInt read GetOutsideConeAngle write SetOutsideConeAngle default defOutsideConeAngle;
- property ConeOrientation: TMMVector3D read GetConeOrientation write SetConeOrientation;
- property ConeOutsideVolume: LongInt read GetConeOutsideVolume write SetConeOutsideVolume default defConeOutsideVolume;
- property Velocity: TMMVector3D read GetVelocity write SetVelocity;
- end;
- {-- TMMDS3DListener ----------------------------------------------------}
- TMMDS3DListener = class(TMMDS3DControl)
- private
- FDS3DListener : IDirectSound3DListener;
- FDistanceFactor : D3DVALUE;
- FDopplerFactor : D3DVALUE;
- FOrientFront : TMMVector3D;
- FOrientTop : TMMVector3D;
- FPosition : TMMVector3D;
- FRollOffFactor : D3DVALUE;
- FVelocity : TMMVector3D;
- function GetDistanceFactor: D3DVALUE;
- function GetDopplerFactor: D3DVALUE;
- function GetOrientFront: TMMVector3D;
- function GetOrientTop: TMMVector3D;
- function GetPosition: TMMVector3D;
- function GetRollOffFactor: D3DVALUE;
- function GetVelocity: TMMVector3D;
- procedure SetDistanceFactor(Value: D3DVALUE);
- procedure SetDopplerFactor(Value: D3DVALUE);
- procedure SetOrientFront(Value: TMMVector3D);
- procedure SetOrientTop(Value: TMMVector3D);
- procedure SetPosition(Value: TMMVector3D);
- procedure SetRollOffFactor(Value: D3DVALUE);
- procedure SetVelocity(Value: TMMVector3D);
- procedure VectorChanged(Sender: TObject);
- protected
- procedure ObtainControl(DSBuffer: IDirectSoundBuffer); override;
- procedure FreeControl; override;
- procedure DoApplySettings; override;
- function ControlAllocated: Boolean; override;
- public
- constructor Create(Loading: Boolean);
- destructor Destroy; override;
- procedure Assign(Source: TPersistent); override;
- procedure Commit;
- published
- property DistanceFactor: D3DVALUE read GetDistanceFactor write SetDistanceFactor;
- property DopplerFactor: D3DVALUE read GetDopplerFactor write SetDopplerFactor;
- property OrientFront: TMMVector3D read GetOrientFront write SetOrientFront;
- property OrientTop: TMMVector3D read GetOrientTop write SetOrientTop;
- property Position: TMMVector3D read GetPosition write SetPosition;
- property RollOffFactor: D3DVALUE read GetRollOffFactor write SetRollOffFactor;
- property Velocity: TMMVector3D read GetVelocity write SetVelocity;
- end;
- {-- TMMDSSoundBuffer ---------------------------------------------------}
- TMMDSSoundBuffer = class(TMMObject)
- private
- DirectSoundBuffer: IDirectSoundBuffer;
- FName : string;
- FWave : TMMWave;
- FVolume : Longint;
- FPanning : Longint;
- FFrequency : Longint;
- FPosition : Longint;
- FMuted : Boolean;
- FPlaying : Boolean;
- FPaused : Boolean;
- FLooping : Boolean;
- FOnBufferEnd: TNotifyEvent;
- FOnRelease : TNotifyEvent;
- procedure SetMuted(aValue: Boolean);
- procedure SetVolume(aValue: Longint);
- function GetVolume: Longint;
- procedure SetPanning(aValue: Longint);
- function GetPanning: Longint;
- procedure SetFrequency(aValue: Longint);
- function GetFrequency: Longint;
- procedure SetPosition(aValue: Longint);
- function GetPosition: Longint;
- procedure SetLooping(aValue: Boolean);
- function GetLooping: Boolean;
- function GetPlaying: Boolean;
- function GetBufferLength: Longint;
- function GetCaps: TDSBCAPS;
- protected
- procedure Play;
- procedure Pause;
- procedure Stop;
- procedure ReleaseBuffer;
- procedure FreeBuffer;
- public
- FOwned : Boolean;
- constructor Create; virtual;
- property SoundBuffer: IDirectSoundBuffer read DirectSoundBuffer;
- property Caps: TDSBCAPS read GetCaps;
- property Wave: TMMWave read FWave;
- property Name: string read FName;
- property BufferLength: Longint read GetBufferLength;
- property Playing: Boolean read GetPlaying;
- property Paused: Boolean read FPaused;
- property Muted: Boolean read FMuted write SetMuted default False;
- property Volume: Longint read GetVolume write SetVolume default 0;
- property Panning: Longint read GetPanning write SetPanning default 0;
- property Frequency: Longint read GetFrequency write SetFrequency default 0;
- property Position: Longint read GetPosition write SetPosition default 0;
- property Looping: Boolean read GetLooping write SetLooping default False;
- end;
- {-- TMMDSSoundCaps ----------------------------------------------------}
- TMMDSSoundCaps = class(TMMObject)
- private
- FBDummy: Boolean;
- FLDummy: DWORD;
- FContinuousRate: Boolean;
- FEmulDriver: Boolean;
- FCertified: Boolean;
- FPrimary16Bit: Boolean;
- FPrimary8Bit: Boolean;
- FPrimaryMono: Boolean;
- FPrimaryStereo: Boolean;
- FSecondary16Bit: Boolean;
- FSecondary8Bit: Boolean;
- FSecondaryMono: Boolean;
- FSecondaryStero: Boolean;
- FMin2Sample: DWORD;
- FMax2Sample: DWORD;
- FPrimaryBuffers: DWORD;
- FMaxHWAll: DWORD;
- FMaxHWStatic: DWORD;
- FMaxHWStream: DWORD;
- FFreeHWAlls: DWORD;
- FFreeHWStatic: DWORD;
- FFreeHWStream: DWORD;
- FMaxHW3All: DWORD;
- FMaxHW3Static: DWORD;
- FMaxHW3Stream: DWORD;
- FFreeHW3Alls: DWORD;
- FFreeHW3Static: DWORD;
- FFreeHW3Stream: DWORD;
- FTotalHWMemBytes: DWORD;
- FFreeHWMemBytes: DWORD;
- FMaxContigFree: DWORD;
- FUnlockRate: DWORD;
- FPlayCPU: DWORD;
- published
- property ContinuousRate: Boolean read FContinuousRate write FBDummy stored False;
- property EmulDriver: Boolean read FEmulDriver write FBDummy stored False;
- property Certified: Boolean read FCertified write FBDummy stored False;
- property Primary16Bit: Boolean read FPrimary16Bit write FBDummy stored False;
- property Primary8Bit: Boolean read FPrimary8Bit write FBDummy stored False;
- property PrimaryMono: Boolean read FPrimaryMono write FBDummy stored False;
- property PrimaryStereo: Boolean read FPrimaryStereo write FBDummy stored False;
- property Secondary16Bit: Boolean read FSecondary16Bit write FBDummy stored False;
- property Secondary8Bit: Boolean read FSecondary8Bit write FBDummy stored False;
- property SecondaryMono: Boolean read FSecondaryMono write FBDummy stored False;
- property SecondaryStereo: Boolean read FSecondaryStero write FBDummy stored False;
- property MinSecondarySampleRate: DWORD read FMin2Sample write FLDummy stored False;
- property MaxSecondarySampleRate: DWORD read FMax2Sample write FLDummy stored False;
- property PrimaryBuffers: DWORD read FPrimaryBuffers write FLDummy stored False;
- property MaxHWMixingAllBuffers: DWORD read FMaxHWAll write FLDummy stored False;
- property MaxHWMixingStaticBuffers: DWORD read FMaxHWStatic write FLDummy stored False;
- property MaxHWMixingStreamingBuffers: DWORD read FMaxHWStream write FLDummy stored False;
- property FreeHWMixingAllBuffers: DWORD read FFreeHWAlls write FLDummy stored False;
- property FreeHWMixingStaticBuffers: DWORD read FFreeHWStatic write FLDummy stored False;
- property FreeHWMixingStreamingBuffers: DWORD read FFreeHWStream write FLDummy stored False;
- property MaxHW3DAllBuffers: DWORD read FMaxHW3All write FLDummy stored False;
- property MaxHW3DStaticBuffers: DWORD read FMaxHW3Static write FLDummy stored False;
- property MaxHW3DStreamingBuffers: DWORD read FMaxHW3Stream write FLDummy stored False;
- property FreeHW3DAllBuffers: DWORD read FFreeHW3Alls write FLDummy stored False;
- property FreeHW3DStaticBuffers: DWORD read FFreeHW3Static write FLDummy stored False;
- property FreeHW3DStreamingBuffers: DWORD read FFreeHW3Stream write FLDummy stored False;
- property TotalHWMemBytes: DWORD read FTotalHWMemBytes write FLDummy stored False;
- property FreeHWMemBytes: DWORD read FFreeHWMemBytes write FLDummy stored False;
- property MaxContigFreeHWMemBytes: DWORD read FMaxContigFree write FLDummy stored False;
- property UnlockTransferRateHWBuffers: DWORD read FUnlockRate write FLDummy stored False;
- property PlayCPUOverheadSWBuffers: DWORD read FPlayCPU write FLDummy stored False;
- end;
- TMMDSBufferLostEvent = procedure(Sender: TObject; Buffer: TMMDSSoundBuffer; var Abort: Boolean) of object;
- TMMDSBufferEndEvent = procedure(Sender: TObject; Buffer: TMMDSSoundBuffer) of object;
- {-- TMMDSWaveMixer ----------------------------------------------------}
- TMMDSWaveMixer = class(TMMNonVisualComponent)
- private
- DirectSoundObject: IDirectSound;
- FDevices : TList;
- FDeviceID : TMMDeviceID;
- FSampleRate : Longint; { sampling rate }
- FBits : TMMBits; { bit8 or bit16 }
- FMode : TMMMode; { mMono, mStereo }
- FProductName : String;
- FPrimaryBuffer : IDirectSoundBuffer;
- FBuffers : TList;
- FLevel : TMMDSLevel;
- FCaps : TMMDSSoundCaps;
- FSpeakerConfig : TMMDSSpeakerConfig;
- FVolume : Longint;
- FPanning : Longint;
- FMuted : Boolean;
- FHandle : THandle;
- FTimerInit : integer;
- FUse3D : Boolean;
- F3DListener : TMMDS3DListener;
- FWorkInDesign : Boolean;
- FCoopHandle : THandle;
- FOnBufferLost : TMMDSBufferLostEvent;
- FOnBufferEnd : TMMDSBufferEndEvent;
- procedure SetPrimaryWaveFormat;
- procedure SetPCMWaveFormat(wf: TPCMWaveFormat);
- function GetPCMWaveFormat: TPCMWaveFormat;
- procedure SetBits(aValue: TMMBits);
- procedure SetMode(aValue: TMMMode);
- procedure SetSampleRate(aValue: Longint);
- procedure SetCaps(aValue: TMMDSSoundCaps);
- function GetCaps: TMMDSSoundCaps;
- procedure SetLevel(aValue: TMMDSLevel);
- function GetNumDevs: integer;
- function GetDevices(Index: integer): PDSDRIVERDESC;
- procedure SetDeviceID(DeviceID: TMMDeviceID);
- procedure SetProductName(aValue: String);
- function GetBuffer(Index: integer): TMMDSSoundBuffer;
- function GetBufferName(aName: string): TMMDSSoundBuffer;
- function GetBufferCount: integer;
- function GetSpeaker: TMMDSSpeakerConfig;
- procedure SetSpeaker(aValue: TMMDSSpeakerConfig);
- procedure SetMuted(aValue: Boolean);
- procedure SetVolume(aValue: Longint);
- function GetVolume: Longint;
- procedure SetPanning(aValue: Longint);
- function GetPanning: Longint;
- procedure CopyData(Buffer: TMMDSSoundBuffer);
- procedure UpdateTimer(Enable: Boolean);
- function FindFreeName(aName: String): String;
- procedure SetUse3D(Value: Boolean);
- procedure Set3DListener(Value: TMMDS3DListener);
- function GetOpened: Boolean;
- protected
- procedure WndProc(var Msg: TMessage); virtual;
- procedure BufferLost(Buffer: TMMDSSoundBuffer; Abort: Boolean); dynamic;
- procedure BufferEnd(Buffer: TMMDSSoundBuffer); dynamic;
- procedure Loaded; override;
- public
- constructor Create(AOwner: TComponent); override;
- destructor Destroy; override;
- procedure Open;
- procedure Close;
- procedure CooperateWith(Handle: THandle);
- procedure CreateSoundBuffer(pwfx: PWaveFormatEx; dwLength: Longint; Buffer: TMMDSSoundBuffer; Static: Boolean);
- function AddBuffer(var aName: string; aWave: TMMWave): TMMDSSoundBuffer;
- procedure SetupBuffer(var aName: string; aWave: TMMWave; Buffer: TMMDSSoundBuffer);
- function DuplicateBuffer(var aName: string; Buffer: TMMDSSoundBuffer): TMMDSSoundBuffer;
- procedure ClearBuffer(Buffer: TMMDSSoundBuffer);
- procedure RemoveBuffer(Buffer: TMMDSSoundBuffer);
- procedure PlayBuffer(Buffer: TMMDSSoundBuffer);
- procedure PauseBuffer(Buffer: TMMDSSoundBuffer);
- procedure StopBuffer(Buffer: TMMDSSoundBuffer);
- procedure FreeBuffers;
- procedure OpenInDesignTime;
- procedure CloseInDesignTime;
- property PCMWaveFormat: TPCMWaveFormat read GetPCMWaveFormat write SetPCMWaveFormat;
- property Buffer[Index: integer]: TMMDSSoundBuffer read GetBuffer;
- property BufferByName[aName: string]: TMMDSSoundBuffer read GetBufferName;
- property BufferCount: integer read GetBufferCount;
- property NumDevs: integer read GetNumDevs;
- property Devices[Index: integer]: PDSDRIVERDESC read GetDevices;
- property DirectSound: IDirectSound read DirectSoundObject;
- property PrimaryBuffer: IDirectSoundBuffer read FPrimaryBuffer;
- property Muted: Boolean read FMuted write SetMuted default False;
- property Volume: Longint read GetVolume write SetVolume default 0;
- property Panning: Longint read GetPanning write SetPanning default 0;
- property Opened: Boolean read GetOpened;
- published
- property OnBufferLost: TMMDSBufferLostEvent read FOnBufferLost write FOnBufferLost;
- property OnBufferEnd: TMMDSBufferEndEvent read FOnBufferEnd write FOnBufferEnd;
- property Level: TMMDSLevel read FLevel write SetLevel default prPriority;
- property SoundCaps: TMMDSSoundCaps read GetCaps write SetCaps;
- property SpeakerConfiguration: TMMDSSpeakerConfig read GetSpeaker write SetSpeaker default scStereo;
- property DeviceID: TMMDeviceID read FDeviceID write SetDeviceID default 0;
- property ProductName: String read FProductName write SetProductName stored False;
- property BitLength: TMMBits read FBits write SetBits default b8bit;
- property SampleRate: Longint read FSampleRate write SetSampleRate default 11025;
- property Mode: TMMMode read FMode write SetMode default mMono;
- property Use3D: Boolean read FUse3D write SetUse3D default False;
- property Sound3D: TMMDS3DListener read F3DListener write Set3DListener;
- end;
- {-- TMMDSMixChannel ---------------------------------------------------}
- TMMDSMixChannel = class(TMMCustomMemoryWave)
- private
- FSoundBuffer : TMMDSSoundBuffer;
- F3DBuffer : TMMDS3DBuffer;
- FMixer : TMMDSWaveMixer;
- FOnPlayEnd : TNotifyEvent;
- procedure WaveChanged(Sender: TObject);
- procedure SetMuted(aValue: Boolean);
- function GetMuted: Boolean;
- procedure SetVolume(aValue: Longint);
- function GetVolume: Longint;
- procedure SetPanning(aValue: Longint);
- function GetPanning: Longint;
- procedure SetFrequency(aValue: Longint);
- function GetFrequency: Longint;
- procedure SetPosition(aValue: Longint);
- function GetPosition: Longint;
- procedure SetLooping(aValue: Boolean);
- function GetLooping: Boolean;
- function GetPlaying: Boolean;
- function GetPaused: Boolean;
- function GetBufferLength: Longint;
- procedure BufferEnd(Sender: TObject);
- procedure BufferRelease(Sender: TObject);
- procedure Set3DBuffer(Value: TMMDS3DBuffer);
- protected
- procedure Notification(AComponent: TComponent; Operation: TOperation); override;
- procedure Loaded; override;
- public
- constructor Create(aOwner: TComponent); override;
- destructor Destroy; override;
- procedure GetVUMeter(var LeftValue, RightValue, BothValue: integer; Interval: integer);
- procedure Init;
- procedure Play;
- procedure Pause;
- procedure Stop;
- property SoundBuffer: TMMDSSoundBuffer read FSoundBuffer;
- property BufferLength: Longint read GetBufferLength;
- property Position: Longint read GetPosition write SetPosition;
- property Playing: Boolean read GetPlaying;
- property Paused: Boolean read GetPaused;
-
- published
- property OnPlayEnd: TNotifyEvent read FOnPlayEnd write FOnPlayEnd;
- property Mixer: TMMDSWaveMixer read FMixer write FMixer;
- property Muted: Boolean read GetMuted write SetMuted default False;
- property Volume: Longint read GetVolume write SetVolume default 0;
- property Panning: Longint read GetPanning write SetPanning default 0;
- property Frequency: Longint read GetFrequency write SetFrequency default 0;
- property Looping: Boolean read GetLooping write SetLooping default False;
- property Sound3D: TMMDS3DBuffer read F3DBuffer write Set3DBuffer;
- end;
- {-- EDSMixError -------------------------------------------------------}
- EDSMixError = class(Exception)
- end;
- {-- EDirectSoundError -------------------------------------------------}
- EDirectSoundError = class(EDSMixError)
- private
- FResult : HResult;
- public
- constructor CreateRes(Code: HResult);
- property Result: HResult read FResult;
- end;
- procedure DSCheck(Res: HRESULT);
- function DSCheckExcl(Res: HRESULT; const Excl: array of HRESULT): HRESULT;
- implementation
- uses consts;
- {------------------------------------------------------------------------}
- function MM3DVectorToD3DVector(vec: TMM3DVector): TD3DVector;
- begin
- with Result do
- begin
- X := vec.X;
- Y := vec.Y;
- Z := vec.Z;
- end;
- end;
- {------------------------------------------------------------------------}
- function D3DVectorToMM3DVector(vec: TD3DVector): TMM3DVector;
- begin
- with Result do
- begin
- X := vec.X;
- Y := vec.Y;
- Z := vec.Z;
- end;
- end;
- {== TMMDSSoundBuffer ====================================================}
- constructor TMMDSSoundBuffer.Create;
- begin
- inherited Create;
- DirectSoundBuffer := nil;
- FPlaying := False;
- FPaused := False;
- FLooping := False;
- FMuted := False;
- FVolume := 0;
- FPanning := 0;
- FFrequency := 0;
- FOnBufferEnd := nil;
- end;
- {-- TMMDSSoundBuffer ----------------------------------------------------}
- function TMMDSSoundBuffer.GetCaps: TDSBCaps;
- begin
- FillChar(Result, SizeOf(TDSBCAPS), 0);
- Result.dwSize := SizeOf(TDSBCAPS);
- if (DirectSoundBuffer <> nil) then DirectSoundBuffer.GetCaps(Result);
- end;
- {-- TMMDSSoundBuffer ----------------------------------------------------}
- procedure TMMDSSoundBuffer.SetLooping(aValue: Boolean);
- const
- LoopFlags: array[Boolean] of Integer = (0, DSBPLAY_LOOPING);
- begin
- if (aValue <> FLooping) then
- begin
- FLooping := aValue;
- if Playing then
- begin
- DirectSoundBuffer.Play(0, 0, LoopFlags[FLooping]);
- end;
- end;
- end;
- {-- TMMDSSoundBuffer ----------------------------------------------------}
- function TMMDSSoundBuffer.GetLooping: Boolean;
- var
- aValue: DWORD;
- begin
- if not Playing then Result := FLooping
- else
- begin
- DirectSoundBuffer.GetStatus(aValue);
- Result := (aValue and DSBSTATUS_LOOPING) > 0;
- end;
- end;
- {-- TMMDSSoundBuffer ----------------------------------------------------}
- function TMMDSSoundBuffer.GetPlaying: Boolean;
- var
- aResult: DWORD;
- begin
- if (DirectSoundBuffer <> nil) then
- begin
- DirectSoundBuffer.GetStatus(aResult);
- Result := (aResult and DSBSTATUS_PLAYING) > 0;
- end
- else Result := False;
- end;
- {-- TMMDSSoundBuffer ----------------------------------------------------}
- procedure TMMDSSoundBuffer.Play;
- const
- LoopFlags: array[Boolean] of Integer = (0, DSBPLAY_LOOPING);
- begin
- if Playing then Position := 0
- else if (DirectSoundBuffer <> nil) then
- begin
- DirectSoundBuffer.Play(0, 0, LoopFlags[FLooping]);
- FPlaying := True;
- FPaused := False;
- end;
- end;
- {-- TMMDSSoundBuffer ----------------------------------------------------}
- procedure TMMDSSoundBuffer.Pause;
- begin
- if (DirectSoundBuffer <> nil) then
- begin
- FPaused := True;
- DirectSoundBuffer.Stop;
- end;
- end;
- {-- TMMDSSoundBuffer ----------------------------------------------------}
- procedure TMMDSSoundBuffer.Stop;
- begin
- if (DirectSoundBuffer <> nil) then
- begin
- FPlaying := False;
- FPaused := False;
- DirectSoundBuffer.Stop;
- Position := 0;
- end;
- end;
- {-- TMMDSSoundBuffer ----------------------------------------------------}
- procedure TMMDSSoundBuffer.ReleaseBuffer;
- begin
- if DirectSoundBuffer <> nil then
- begin
- DirectSoundBuffer.Release;
- DirectSoundBuffer := nil;
- if Assigned(FOnRelease) then FOnRelease(Self);
- end;
- end;
- {-- TMMDSSoundBuffer ----------------------------------------------------}
- procedure TMMDSSoundBuffer.FreeBuffer;
- begin
- if DirectSoundBuffer <> nil then
- ReleaseBuffer;
- if not FOwned then Free;
- end;
- {-- TMMDSSoundBuffer ----------------------------------------------------}
- procedure TMMDSSoundBuffer.SetMuted(aValue: Boolean);
- var
- m: integer;
- begin
- if (aValue <> FMuted) then
- begin
- if aValue then
- begin
- if (DirectSoundBuffer <> nil) then
- begin
- m := -10000;
- DirectSoundBuffer.SetVolume(m);
- end;
- FMuted := True;
- end
- else
- begin
- { restore the volume setting }
- if (DirectSoundBuffer <> nil) then
- DirectSoundBuffer.SetVolume(FVolume);
- FMuted := False;
- end;
- end;
- end;
- {-- TMMDSSoundBuffer ----------------------------------------------------}
- procedure TMMDSSoundBuffer.SetVolume(aValue: Longint);
- begin
- if (aValue <> FVolume) then
- begin
- FVolume := MinMax(aValue,-10000,0);
- if (DirectSoundBuffer <> nil) and not FMuted then
- DirectSoundBuffer.SetVolume(FVolume);
- end;
- end;
- {-- TMMDSSoundBuffer ----------------------------------------------------}
- function TMMDSSoundBuffer.GetVolume: Longint;
- var
- aResult: DWORD;
- begin
- if (DirectSoundBuffer <> nil) and not FMuted then
- begin
- DirectSoundBuffer.GetVolume(aResult);
- FVolume := aResult;
- end;
- Result := FVolume;
- end;
- {-- TMMDSSoundBuffer ----------------------------------------------------}
- procedure TMMDSSoundBuffer.SetPanning(aValue: Longint);
- begin
- if (aValue <> FPanning) then
- begin
- FPanning := MinMax(aValue,-10000,10000);
- if (DirectSoundBuffer <> nil) then DirectSoundBuffer.SetPan(FPanning);
- end;
- end;
- {-- TMMDSSoundBuffer ----------------------------------------------------}
- function TMMDSSoundBuffer.GetPanning: Longint;
- var
- aResult: DWORD;
- begin
- if (DirectSoundBuffer <> nil) then
- begin
- DirectSoundBuffer.GetPan(aResult);
- FPanning := aResult;
- end;
- Result := FPanning;
- end;
- {-- TMMDSSoundBuffer ----------------------------------------------------}
- procedure TMMDSSoundBuffer.SetFrequency(aValue: Longint);
- begin
- if (aValue <> FFrequency) then
- begin
- FFrequency := min(aValue,100000);
- if (DirectSoundBuffer <> nil) then DirectSoundBuffer.SetFrequency(FFrequency);
- end;
- end;
- {-- TMMDSSoundBuffer ----------------------------------------------------}
- function TMMDSSoundBuffer.GetFrequency: Longint;
- var
- aResult: DWORD;
- begin
- if (DirectSoundBuffer <> nil) then
- begin
- DirectSoundBuffer.GetFrequency(aResult);
- FFrequency := aResult;
- end;
- Result := FFrequency;
- end;
- {-- TMMDSSoundBuffer ----------------------------------------------------}
- procedure TMMDSSoundBuffer.SetPosition(aValue: Longint);
- begin
- FPosition := aValue;
- if (DirectSoundBuffer <> nil) then
- DirectSoundBuffer.SetCurrentPosition(aValue);
- end;
- {-- TMMDSSoundBuffer ----------------------------------------------------}
- function TMMDSSoundBuffer.GetPosition: Longint;
- var
- aResult,dummy: DWORD;
- begin
- if (DirectSoundBuffer <> nil) then
- begin
- DirectSoundBuffer.GetCurrentPosition(aResult, dummy);
- FPosition := aResult;
- end;
- Result := FPosition;
- end;
- {-- TMMDSSoundBuffer ----------------------------------------------------}
- function TMMDSSoundBuffer.GetBufferLength: Longint;
- begin
- Result := 0;
- if (DirectSoundBuffer <> nil) then
- begin
- Result := Caps.dwBufferBytes;
- end;
- end;
- {== TMMDSWaveMixer ======================================================}
- constructor TMMDSWaveMixer.Create(AOwner: TComponent);
- begin
- inherited Create(AOwner);
- FLevel := prPriority;
- FBuffers := TList.Create;
- FCaps := TMMDSSoundCaps.Create;
- FSpeakerConfig := scStereo;
- FProductName := '';
- FMuted := False;
- FVolume := 0;
- FPanning := 0;
- FTimerInit := 0;
- DirectSoundObject := nil;
- FPrimaryBuffer := nil;
- FBits := b8Bit;
- FMode := mMono;
- FSampleRate := 11025;
- if _WinNT3_ then
- raise EMMDSWaveMixError.Create(LoadResStr(IDS_DSNOTSUPPORTED));
- if not LoadDSoundDLL then
- raise EMMDSWaveMixError.Create(LoadResStr(IDS_DLLERROR)+' DSOUND.DLL...');
- FDevices := TList.Create;
- DirectSoundEnumerate(DriverEnumerate, FDevices);
- SetDeviceID(0);
- FHandle := AllocateHWnd(WndProc);
- FCoopHandle := 0;
- F3DListener := TMMDS3DListener.Create((AOwner <> nil) and (csLoading in AOwner.ComponentState));
- ErrorCode := ComponentRegistered(InitCode, Self, ClassName);
- if (ErrorCode <> 0) then RegisterFailed(InitCode, Self , ClassName);
- end;
- {-- TMMDSWaveMixer ------------------------------------------------------}
- destructor TMMDSWaveMixer.Destroy;
- begin
- UpdateTimer(False);
- DeallocateHWnd(FHandle);
- { finally close the dsound device and free memory }
- Close;
- if (FCaps <> nil) then FCaps.Free;
- if (FBuffers <> nil) then FBuffers.Free;
- { free the device list }
- FreeDriverList(FDevices);
- FDevices.Free;
- F3DListener.Free;
- inherited Destroy;
- end;
- {-- TMMDSWaveMixer ------------------------------------------------------}
- procedure TMMDSWaveMixer.Loaded;
- begin
- inherited Loaded;
- with Sound3D do
- begin
- if MM3DVectorEqual(OrientFront.AsVector,ZeroVector) then
- OrientFront.AsVector := MM3DVector(defOrientFrontX,defOrientFrontY,defOrientFrontZ);
- if MM3DVectorEqual(OrientTop.AsVector,ZeroVector) then
- OrientTop.AsVector := MM3DVector(defOrientTopX,defOrientTopY,defOrientTopZ);
- end;
- end;
- {-- TMMDSWaveMixer ------------------------------------------------------}
- procedure TMMDSWaveMixer.UpdateTimer(Enable: Boolean);
- begin
- KillTimer(FHandle, 1);
- if Enable then
- if SetTimer(FHandle, 1, 50, nil) = 0 then
- raise EOutOfResources.Create({$IFDEF DELPHI3}SNoTimers{$ELSE}LoadStr(SNoTimers){$ENDIF});
- end;
- {-- TMMDSWaveMixer ------------------------------------------------------}
- procedure TMMDSWaveMixer.WndProc(var Msg: TMessage);
- var
- i: integer;
- begin
- if (Msg.Msg = WM_TIMER) and (Msg.wParam = 1) then
- begin
- for i := 0 to BufferCount-1 do
- with Buffer[i] do
- begin
- if FPlaying and not Playing and not Paused then
- begin
- FPlaying := False;
- dec(FTimerInit);
- if (FTimerInit = 0) then UpdateTimer(False);
- BufferEnd(Buffer[i]);
- end;
- end;
- end
- else with Msg do Result := DefWindowProc(FHandle, Msg, wParam, lParam);
- end;
- {-- TMMDSWaveMixer ------------------------------------------------------}
- procedure TMMDSWaveMixer.BufferLost(Buffer: TMMDSSoundBuffer; Abort: Boolean);
- begin
- if assigned(FOnBufferLost) then
- FOnBufferLost(Self, Buffer, Abort)
- else Abort := True;
- end;
- {-- TMMDSWaveMixer ------------------------------------------------------}
- procedure TMMDSWaveMixer.BufferEnd(Buffer: TMMDSSoundBuffer);
- begin
- if not assigned(Buffer) or (csDestroying in ComponentState) then exit;
- if assigned(FOnBufferEnd) then FOnBufferEnd(Self, Buffer);
- if assigned(Buffer.FOnBufferEnd) then Buffer.FOnBufferEnd(Buffer);
- end;
- {-- TMMDSWaveMixer ------------------------------------------------------}
- function TMMDSWaveMixer.GetDevices(Index: integer): PDSDRIVERDESC;
- begin
- if Index < NumDevs then
- Result := PDSDRIVERDESC(FDevices.Items[Index])
- else Result := nil;
- end;
- {-- TMMDSWaveMixer ------------------------------------------------------}
- procedure TMMDSWaveMixer.SetProductName(aValue: String);
- begin
- { dummy }
- end;
- {-- TMMDSWaveMixer ------------------------------------------------------}
- Procedure TMMDSWaveMixer.SetLevel(aValue: TMMDSLevel);
- begin
- if (DirectSoundObject <> nil) then
- raise EMMDSWaveMixError.Create(LoadResStr(IDS_PROPERTYOPEN));
- if (FLevel <> aValue) then
- begin
- FLevel := aValue;
- end;
- end;
- {-- TMMDSWaveMixer ------------------------------------------------------}
- function TMMDSWaveMixer.GetNumDevs: integer;
- begin
- Result := FDevices.Count;
- end;
- {-- TMMDSWaveMixer ------------------------------------------------------}
- Procedure TMMDSWaveMixer.SetDeviceID(DeviceID: TMMDeviceID);
- begin
- if (DirectSoundObject <> nil) then
- raise EMMDSWaveMixError.Create(LoadResStr(IDS_PROPERTYOPEN));
- FProductName := LoadResStr(IDS_DSNODEVICE);
- if (NumDevs > 1) and (DeviceID >= 0) and (DeviceID < NumDevs) then
- begin
- GetCaps;
- FProductName := Devices[DeviceID]^.Description;
- end;
- { set the new device }
- FDeviceID := DeviceID;
- if (FDeviceID >= NumDevs) or (FDeviceID < 0) or (NumDevs < 2) then
- FDeviceID := InvalidID;
- end;
- {-- TMMDSWaveMixer ------------------------------------------------------}
- procedure TMMDSWaveMixer.SetUse3D(Value: Boolean);
- begin
- if (DirectSoundObject <> nil) then
- raise EMMDSWaveMixError.Create(LoadResStr(IDS_PROPERTYOPEN));
- FUse3D := Value;
- end;
- {-- TMMDSWaveMixer ------------------------------------------------------}
- procedure TMMDSWaveMixer.Set3DListener(Value: TMMDS3DListener);
- begin
- F3DListener.Assign(Value);
- end;
- {-- TMMDSWaveMixer ------------------------------------------------------}
- Procedure TMMDSWaveMixer.SetPrimaryWaveFormat;
- var
- wf: TPCMWaveFormat;
- begin
- if not (csDesigning in ComponentState) or FWorkInDesign then
- begin
- wf := PCMWaveFormat;
- if (FLevel <> prNormal) and (FPrimaryBuffer <> nil) then
- begin
- if FPrimaryBuffer.SetFormat(@wf) <> DS_OK then
- raise EMMDSWaveMixError.Create('DirectSound PrimaryBuffer SetFormat failed');
- end;
- end;
- end;
- {-- TMMDSWaveMixer ------------------------------------------------------}
- Procedure TMMDSWaveMixer.SetPCMWaveFormat(wf: TPCMWaveFormat);
- var
- pwfx: PWaveFormatEx;
- begin
- pwfx := @wf;
- if not pcmIsValidFormat(pwfx) then
- raise EMMDSWaveMixError.Create(LoadResStr(IDS_INVALIDFORMAT));
- SampleRate := pwfx^.nSamplesPerSec;
- BitLength := TMMBits(pwfx^.wBitsPerSample div 8 - 1);
- Mode := TMMMode(pwfx^.nChannels-1);
- end;
- {-- TMMDSWaveMixer ------------------------------------------------------}
- function TMMDSWaveMixer.GetPCMWaveFormat: TPCMWaveFormat;
- var
- wfx: TWaveFormatEx;
- begin
- pcmBuildWaveHeader(@wfx, (Ord(FBits)+1)*8, Ord(FMode)+1, SampleRate);
- Result := PPCMWaveFormat(@wfx)^;
- end;
- {-- TMMDSWaveMixer ------------------------------------------------------}
- Procedure TMMDSWaveMixer.SetBits(aValue: TMMBits);
- begin
- if (aValue <> FBits) then
- begin
- FBits := aValue;
- SetPrimaryWaveFormat;
- end;
- end;
- {-- TMMDSWaveMixer ------------------------------------------------------}
- Procedure TMMDSWaveMixer.SetMode(aValue: TMMMode);
- begin
- if (aValue <> FMode) then
- begin
- FMode := aValue;
- SetPrimaryWaveFormat;
- end;
- end;
- {-- TMMDSWaveMixer ------------------------------------------------------}
- procedure TMMDSWaveMixer.SetSampleRate(aValue: Longint);
- begin
- if (aValue <> FSampleRate) then
- begin
- FSampleRate := MinMax(aValue, 8000, 100000);
- SetPrimaryWaveFormat;
- end;
- end;
- {-- TMMDSWaveMixer ------------------------------------------------------}
- procedure TMMDSWaveMixer.Open;
- var
- aResult: DWORD;
- BufferDesc: TDSBUFFERDESC;
- H: THandle;
- begin
- if LoadDSoundDLL and (DirectSoundObject = nil) then
- begin
- if (NumDevs < 2) then
- raise EMMDSWaveMixError.Create(LoadResStr(IDS_DSNODEVICE));
- if (DeviceID = InvalidID) then
- raise EMMDSWaveMixError.Create(LoadResStr(IDS_INVALIDDEVICEID));
- try
- DSCheck(DirectSoundCreate(Devices[FDeviceID]^.lpGUID, DirectSoundObject, nil));
- if (FCoopHandle = 0) then
- begin
- H := 0;
- if (Owner <> nil) and (Owner is TForm) then
- H := TForm(Owner).Handle
- {$IFDEF BUILD_ACTIVEX}
- else
- H := ParentWindow
- {$ENDIF}
- ;
- if (H <> 0) then
- CooperateWith(H);
- end
- else
- CooperateWith(FCoopHandle);
- FillChar(BufferDesc, SizeOf(TDSBUFFERDESC), 0);
- with BufferDesc do
- begin
- dwSize := SizeOf(TDSBUFFERDESC);
- dwFlags := DSBCAPS_CTRLVOLUME or DSBCAPS_CTRLPAN or DSBCAPS_PRIMARYBUFFER;
- if Use3D then
- dwFlags := (dwFlags or DSBCAPS_CTRL3D) and not DSBCAPS_CTRLPAN;
- end;
- aResult := DirectSoundObject.CreateSoundBuffer(BufferDesc, FPrimaryBuffer, nil);
- if Use3D then
- begin
- if aResult <> DS_OK then
- if (csDesigning in ComponentState) and not FWorkInDesign then
- begin
- with BufferDesc do
- dwFlags := (dwFlags and not DSBCAPS_CTRL3D) or DSBCAPS_CTRLPAN;
- DSCheck(DirectSoundObject.CreateSoundBuffer(BufferDesc, FPrimaryBuffer, nil));
- end
- else
- { TODO: Should be resource id }
- raise EDSMixError.Create('3D sound not available')
- else
- F3DListener.CreateBuffer(FPrimaryBuffer);
- end
- else
- begin
- if (aResult = DSERR_CONTROLUNAVAIL) then
- begin
- with BufferDesc do dwFlags := dwFlags and not DSBCAPS_CTRLVOLUME and not DSBCAPS_CTRLPAN;
- aResult := DirectSoundObject.CreateSoundBuffer(BufferDesc, FPrimaryBuffer, nil);
- end;
- DSCheck(aResult);
- end;
- SetPrimaryWaveFormat;
- SetSpeaker(FSpeakerConfig);
- FPrimaryBuffer.Play(0,0,DSBPLAY_LOOPING);
-
- except
- Close;
- raise;
- end;
- end;
- end;
- {-- TMMDSWaveMixer ------------------------------------------------------}
- function TMMDSWaveMixer.GetOpened: Boolean;
- begin
- Result := FPrimaryBuffer <> nil;
- end;
- {-- TMMDSWaveMixer ------------------------------------------------------}
- procedure TMMDSWaveMixer.CooperateWith(Handle: THandle);
- var
- dwLevel: Longint;
- begin
- FCoopHandle := Handle;
- if (DirectSoundObject <> nil) then
- begin
- case FLevel of
- prPriority : dwLevel := DSSCL_PRIORITY;
- prExclusive: dwLevel := DSSCL_EXCLUSIVE;
- else dwLevel := DSSCL_NORMAL;
- end;
- DSCheck(DirectSoundObject.SetCooperativeLevel(FCoopHandle, dwLevel));
- end;
- end;
- {-- TMMDSWaveMixer ------------------------------------------------------}
- procedure TMMDSWaveMixer.Close;
- begin
- FreeBuffers;
- if (DirectSoundObject <> nil) then
- begin
- if Use3D then
- F3DListener.FreeBuffer;
- if (FPrimaryBuffer <> nil) then
- begin
- FPrimaryBuffer.Release;
- FPrimaryBuffer := nil;
- end;
- DirectSoundObject.Release;
- DirectSoundObject := nil;
- end;
- end;
- {-- TMMDSWaveMixer ------------------------------------------------------}
- procedure TMMDSWaveMixer.SetCaps(aValue: TMMDSSoundCaps);
- begin
- { dummy }
- end;
- {-- TMMDSWaveMixer ------------------------------------------------------}
- function TMMDSWaveMixer.GetCaps: TMMDSSoundCaps;
- var
- aCaps: TDSCAPS;
- wasClosed: Boolean;
- begin
- wasClosed := False;
- FillChar(aCaps, SizeOf(TDSCAPS), 0);
- if (DeviceID <> InvalidID) and (NumDevs > 1) then
- try
- { open the device if not open }
- if DirectSoundObject = nil then
- begin
- wasClosed := True;
- Open;
- end;
- try
- aCaps.dwSize := SizeOf(TDSCAPS);
- DirectSoundObject.GetCaps(aCaps);
- with FCaps do
- begin
- FContinuousRate := (aCaps.dwFlags and DSCAPS_CONTINUOUSRATE) > 0;
- FEmulDriver := (aCaps.dwFlags and DSCAPS_EMULDRIVER) > 0;
- FCertified := (aCaps.dwFlags and DSCAPS_CERTIFIED) > 0;
- FPrimary16Bit := (aCaps.dwFlags and DSCAPS_PRIMARY16BIT) > 0;
- FPrimary8Bit := (aCaps.dwFlags and DSCAPS_PRIMARY8BIT) > 0;
- FPrimaryMono := (aCaps.dwFlags and DSCAPS_PRIMARYMONO) > 0;
- FPrimaryStereo := (aCaps.dwFlags and DSCAPS_PRIMARYSTEREO) > 0;
- FSecondary16Bit := (aCaps.dwFlags and DSCAPS_SECONDARY16BIT) > 0;
- FSecondary8Bit := (aCaps.dwFlags and DSCAPS_SECONDARY8BIT) > 0;
- FSecondaryMono := (aCaps.dwFlags and DSCAPS_SECONDARYMONO) > 0;
- FSecondaryStero := (aCaps.dwFlags and DSCAPS_SECONDARYSTEREO) > 0;
- FMin2Sample := aCaps.dwMinSecondarySampleRate;
- FMax2Sample := aCaps.dwMaxSecondarySampleRate;
- FPrimaryBuffers := aCaps.dwPrimaryBuffers;
- FMaxHWAll := aCaps.dwMaxHWMixingAllBuffers;
- FMaxHWStatic := aCaps.dwMaxHWMixingStaticBuffers;
- FMaxHWStream := aCaps.dwMaxHWMixingStreamingBuffers;
- FFreeHWAlls := aCaps.dwFreeHWMixingAllBuffers;
- FFreeHWStatic := aCaps.dwFreeHWMixingStaticBuffers;
- FFreeHWStream := aCaps.dwFreeHWMixingStreamingBuffers;
- FMaxHW3All := aCaps.dwMaxHw3DAllBuffers;
- FMaxHW3Static := aCaps.dwMaxHw3DStaticBuffers;
- FMaxHW3Stream := aCaps.dwMaxHw3DStreamingBuffers;
- FFreeHW3Alls := aCaps.dwFreeHw3DAllBuffers;
- FFreeHW3Static := aCaps.dwFreeHw3DStaticBuffers;
- FFreeHW3Stream := aCaps.dwFreeHw3DStreamingBuffers;
- FTotalHWMemBytes := aCaps.dwTotalHwMemBytes;
- FFreeHWMemBytes := aCaps.dwFreeHwMemBytes;
- FMaxContigFree := aCaps.dwMaxContigFreeHwMemBytes;
- FUnlockRate := aCaps.dwUnlockTransferRateHwBuffers;
- FPlayCPU := aCaps.dwPlayCpuOverheadSwBuffers;
- end;
- finally
- { close the device if it was closed }
- if wasClosed then Close;
- end;
- except
- on E: Exception do
- if (csDesigning in ComponentState) then
- MessageDlg(E.Message,mtError,[mbOk],0)
- else
- raise;
- end;
- Result := FCaps;
- end;
- {-- TMMDSWaveMixer ------------------------------------------------------}
- procedure TMMDSWaveMixer.SetMuted(aValue: Boolean);
- var
- m: integer;
- begin
- if (aValue <> FMuted) then
- begin
- if aValue then
- begin
- if (FPrimaryBuffer <> nil) then
- begin
- m := -10000;
- FPrimaryBuffer.SetVolume(m);
- end;
- FMuted := True;
- end
- else
- begin
- { restore the volume setting }
- if (FPrimaryBuffer <> nil) then
- FPrimaryBuffer.SetVolume(FVolume);
- FMuted := False;
- end;
- end;
- end;
- {-- TMMDSWaveMixer ------------------------------------------------------}
- procedure TMMDSWaveMixer.SetVolume(aValue: Longint);
- begin
- if (aValue <> FVolume) then
- begin
- FVolume := MinMax(aValue,-10000,0);
- if (FPrimaryBuffer <> nil) and not FMuted then
- FPrimaryBuffer.SetVolume(FVolume);
- end;
- end;
- {-- TMMDSWaveMixer ------------------------------------------------------}
- function TMMDSWaveMixer.GetVolume: Longint;
- var
- aResult: DWORD;
- begin
- if (FPrimaryBuffer <> nil) and not FMuted then
- begin
- FPrimaryBuffer.GetVolume(aResult);
- FVolume := aResult;
- end;
- Result := FVolume;
- end;
- {-- TMMDSWaveMixer ------------------------------------------------------}
- procedure TMMDSWaveMixer.SetPanning(aValue: Longint);
- begin
- if (aValue <> FPanning) then
- begin
- FPanning := MinMax(aValue,-10000,10000);
- if (FPrimaryBuffer <> nil) then FPrimaryBuffer.SetPan(aValue);
- end;
- end;
- {-- TMMDSWaveMixer ------------------------------------------------------}
- function TMMDSWaveMixer.GetPanning: Longint;
- var
- aResult: DWORD;
- begin
- if (FPrimaryBuffer <> nil) then
- begin
- FPrimaryBuffer.GetPan(aResult);
- FPanning := aResult;
- end;
- Result := FPanning;
- end;
- {-- TMMDSWaveMixer ------------------------------------------------------}
- function TMMDSWaveMixer.GetBuffer(Index: integer): TMMDSSoundBuffer;
- begin
- Result := TMMDSSoundBuffer(FBuffers[Index]);
- end;
- {-- TMMDSWaveMixer ------------------------------------------------------}
- function TMMDSWaveMixer.GetBufferName(aName: string): TMMDSSoundBuffer;
- var
- i: integer;
- begin
- Result := nil;
- for i := 0 to FBuffers.Count-1 do
- if TMMDSSoundBuffer(FBuffers[i]).Name = aName then
- begin
- Result := TMMDSSoundBuffer(FBuffers[i]);
- break;
- end;
- end;
- {-- TMMDSWaveMixer ------------------------------------------------------}
- function TMMDSWaveMixer.FindFreeName(aName: String): String;
- var
- i: integer;
- begin
- Result := aName;
- if (BufferByName[aName] <> nil) or (aName = '') then
- begin
- i := 1;
- while BufferByName[aName+IntToStr(i)] <> nil do inc(i);
- Result := aName + IntToStr(i);
- end;
- end;
- {-- TMMDSWaveMixer ------------------------------------------------------}
- function TMMDSWaveMixer.GetBufferCount: integer;
- begin
- Result := FBuffers.Count;
- end;
- {-- TMMDSWaveMixer ------------------------------------------------------}
- procedure TMMDSWaveMixer.CopyData(Buffer: TMMDSSoundBuffer);
- Label Ready;
- var
- p, pDummy: PChar;
- Length, Dummy: DWORD;
- BufSize: DWORD;
- wfx: TWaveFormatEx;
- pwfxSrc: PWaveFormatEx;
- lpACMConvert: PACMConvert;
- begin
- if Buffer.DirectSoundBuffer = nil then exit;
- BufSize := Buffer.Caps.dwBufferBytes;
- if Buffer.DirectSoundBuffer.Lock(0, BufSize, p, Length, pDummy, Dummy, 0) <> DS_OK then
- begin
- Buffer.ReleaseBuffer;
- raise EMMDSWaveMixError.Create('DirectSoundBuffer Lock failed');
- end;
- try
- if (Buffer.Wave.FormatTag <> WAVE_FORMAT_PCM) then
- begin
- if (Buffer.Wave.FormatTag = WAVE_FORMAT_ADPCM) then
- begin
- pwfxSrc := Buffer.Wave.PWaveFormat;
- if adpcmBuildFormatHeader(pwfxSrc, @wfx, 16, 0, 0) then
- begin
- adpcmDecode4Bit(Pointer(pwfxSrc), @wfx, Buffer.Wave.PWaveData, p,
- Buffer.Wave.PWaveIOInfo^.dwDataBytes);
- goto Ready;
- end;
- end;
- wfx := acmSuggestPCMFormat(Buffer.Wave.PWaveFormat);
- lpACMConvert := acmBeginConvert(Buffer.Wave.PWaveFormat,@wfx,
- Buffer.Wave.PWaveData,
- Buffer.Wave.PWaveIOInfo^.dwDataBytes,
- False);
- if (lpACMConvert <> nil) then
- begin
- acmDoConvert(lpACMConvert, Buffer.Wave.PWaveIOInfo^.dwDataBytes);
- Move(lpACMConvert^.lpDstBuffer^, p^, lpACMConvert^.dwBytesConverted);
- acmDoneConvert(lpACMConvert);
- end
- else raise EMMDSWaveMixError.Create('Unable to convert sound data');
- end
- else
- begin
- Move(Buffer.Wave.PWaveData^, p^, Buffer.Wave.PWaveIOInfo^.dwDataBytes);
- end;
- Ready:
- finally
- Buffer.DirectSoundBuffer.Unlock(p, BufSize, nil, 0);
- end;
- end;
- {-- TMMDSWaveMixer ------------------------------------------------------}
- procedure TMMDSWaveMixer.CreateSoundBuffer(pwfx: PWaveFormatEx; dwLength: Longint; Buffer: TMMDSSoundBuffer; Static: Boolean);
- var
- BufferDesc: TDSBUFFERDESC;
- m: integer;
- begin
- FillChar(BufferDesc, SizeOf(TDSBUFFERDESC), 0);
- with BufferDesc do
- begin
- dwSize := SizeOf(TDSBUFFERDESC);
- dwFlags := DSBCAPS_CTRLDEFAULT or DSBCAPS_STICKYFOCUS or DSBCAPS_GLOBALFOCUS or DSBCAPS_GETCURRENTPOSITION2;
- if Static then
- dwFlags := dwFlags or DSBCAPS_STATIC;
- if Use3D then
- dwFlags := (dwFlags or DSBCAPS_CTRL3D) and not DSBCAPS_CTRLPAN;
- dwBufferBytes := dwLength;
- lpwfxFormat := pwfx;
- end;
- Buffer.DirectSoundBuffer := nil;
- if DirectSoundObject.CreateSoundBuffer(BufferDesc, Buffer.DirectSoundBuffer, nil) <> DS_OK then
- begin
- { May be we've no 3D sound? }
- if Use3D then
- if (csDesigning in ComponentState) and not FWorkInDesign then
- begin
- with BufferDesc do
- dwFlags := (dwFlags and not DSBCAPS_CTRL3D) or DSBCAPS_CTRLPAN;
- DSCheck(DirectSoundObject.CreateSoundBuffer(BufferDesc, Buffer.DirectSoundBuffer, nil));
- end
- else
- { TODO: should be resource id }
- raise EDSMixError.Create('3D sound not available')
- else
- begin
- { ev. older DSound version which doesn't support DSBCAPS_STICKYFOCUS }
- BufferDesc.dwFlags := DSBCAPS_CTRLDEFAULT;
- if Static then
- BufferDesc.dwFlags := BufferDesc.dwFlags or DSBCAPS_STATIC;
- DSCheck(DirectSoundObject.CreateSoundBuffer(BufferDesc, Buffer.DirectSoundBuffer, nil));
- end;
- end;
- if Buffer.Muted then
- begin
- m := -10000;
- Buffer.DirectSoundBuffer.SetVolume(m);
- end
- else Buffer.DirectSoundBuffer.SetVolume(Buffer.FVolume);
- Buffer.DirectSoundBuffer.SetPan(Buffer.FPanning);
- Buffer.DirectSoundBuffer.SetFrequency(Buffer.FFrequency);
- FBuffers.Add(Buffer);
- end;
- {-- TMMDSWaveMixer ------------------------------------------------------}
- procedure TMMDSWaveMixer.SetupBuffer(var aName: string; aWave: TMMWave; Buffer: TMMDSSoundBuffer);
- Label Ready;
- var
- pwfxSrc: PWaveFormatEx;
- wfx: TWaveFormatEx;
- BufSize: Longint;
- begin
- if (Buffer = nil) then exit;
- if not aWave.IsMemWave then
- raise EMMDSWaveMixError.Create(LoadResStr(IDS_NOMEMWAVE));
- if (aWave.FormatTag <> WAVE_FORMAT_PCM) then
- begin
- if (aWave.FormatTag = WAVE_FORMAT_ADPCM) then
- begin
- pwfxSrc := aWave.PWaveFormat;
- if adpcmBuildFormatHeader(pwfxSrc, @wfx, 16, 0, 0) then
- begin
- BufSize := PADPCMWaveFormat(pwfxSrc)^.wSamplesPerBlock * Longint(wfx.nBlockAlign);
- BufSize := BufSize*(aWave.PWaveIOInfo^.dwDataBytes div pwfxSrc^.nBlockAlign);
- goto Ready;
- end;
- end;
- wfx := acmSuggestPCMFormat(aWave.PWaveFormat);
- if not acmQueryConvert(aWave.PWaveFormat,@wfx,False) then
- raise EMMDSWaveMixError.Create(LoadResStr(IDS_INVALIDFORMAT));
- BufSize := acmSizeOutputData(aWave.PWaveFormat,@wfx,aWave.PWaveIOInfo^.dwDataBytes);
- end
- else
- begin
- wfx := aWave.PWaveFormat^;
- BufSize := aWave.PWaveIOInfo^.dwDataBytes;
- end;
- Ready:
- with Buffer do
- begin
- aName := FindFreeName(aName);
- FName := aName;
- FWave := aWave;
- end;
- CreateSoundBuffer(@wfx, BufSize, Buffer, True);
- try
- CopyData(Buffer);
- except
- RemoveBuffer(Buffer);
- end;
- end;
- {-- TMMDSWaveMixer ------------------------------------------------------}
- function TMMDSWaveMixer.AddBuffer(var aName: string; aWave: TMMWave): TMMDSSoundBuffer;
- var
- Buffer: TMMDSSoundBuffer;
- begin
- Buffer := TMMDSSoundBuffer.Create;
- try
- SetupBuffer(aName,aWave,Buffer);
- except
- Buffer.Free;
- raise;
- end;
- Result := Buffer;
- end;
- {-- TMMDSWaveMixer ------------------------------------------------------}
- procedure TMMDSWaveMixer.FreeBuffers;
- begin
- while BufferCount > 0 do RemoveBuffer(Buffer[0]);
- end;
- {-- TMMDSWaveMixer ------------------------------------------------------}
- procedure TMMDSWaveMixer.ClearBuffer(Buffer: TMMDSSoundBuffer);
- var
- i: integer;
- begin
- i := FBuffers.IndexOf(Buffer);
- if i >= 0 then
- begin
- StopBuffer(Buffer);
- Buffer.ReleaseBuffer;
- FBuffers.Delete(i);
- FBuffers.Pack;
- end;
- end;
- {-- TMMDSWaveMixer ------------------------------------------------------}
- procedure TMMDSWaveMixer.RemoveBuffer(Buffer: TMMDSSoundBuffer);
- begin
- ClearBuffer(Buffer);
- Buffer.FreeBuffer;
- end;
- {-- TMMDSWaveMixer ------------------------------------------------------}
- function TMMDSWaveMixer.DuplicateBuffer(var aName: string; Buffer: TMMDSSoundBuffer): TMMDSSoundBuffer;
- var
- NewBuffer: TMMDSSoundBuffer;
- begin
- Result := nil;
- if (Buffer = nil) or (Buffer.DirectSoundBuffer = nil) then exit;
- NewBuffer := TMMDSSoundBuffer.Create;
- aName := FindFreeName(aName);
- NewBuffer.FName := aName;
- NewBuffer.FWave := Buffer.Wave;
- if DirectSoundObject.DuplicateSoundBuffer(Buffer.DirectSoundBuffer, NewBuffer.DirectSoundBuffer) <> DS_OK then
- begin
- NewBuffer.Free;
- raise EMMDSWaveMixError.Create('DirectSound DuplicateSoundBuffer failed');
- end;
- if Buffer.Muted then
- begin
- NewBuffer.Volume := Buffer.FVolume;
- NewBuffer.Muted := Buffer.Muted;
- end
- else NewBuffer.Volume := Buffer.Volume;
- NewBuffer.Panning := Buffer.Panning;
- NewBuffer.Frequency := Buffer.Frequency;
- NewBuffer.Position := Buffer.Position;
- NewBuffer.Looping := Buffer.Looping;
- FBuffers.Add(NewBuffer);
- Result := NewBuffer;
- end;
- {-- TMMDSWaveMixer ------------------------------------------------------}
- procedure TMMDSWaveMixer.SetSpeaker(aValue: TMMDSSpeakerConfig);
- begin
- FSpeakerConfig := aValue;
- if (DirectSoundObject <> nil) then
- DirectSoundObject.SetSpeakerConfig(Ord(aValue)+1);
- end;
- {-- TMMDSWaveMixer ------------------------------------------------------}
- function TMMDSWaveMixer.GetSpeaker: TMMDSSpeakerConfig;
- var
- aResult: DWORD;
- begin
- if (DirectSoundObject <> nil) then
- begin
- DirectSoundObject.GetSpeakerConfig(aResult);
- Result := TMMDSSpeakerConfig(aResult-1);
- end
- else Result := FSpeakerConfig;
- end;
- {-- TMMDSWaveMixer ------------------------------------------------------}
- procedure TMMDSWaveMixer.PlayBuffer(Buffer: TMMDSSoundBuffer);
- var
- Status: DWORD;
- Abort : Boolean;
- begin
- if (Buffer = nil) or (Buffer.DirectSoundBuffer = nil) then exit;
- Buffer.DirectSoundBuffer.GetStatus(Status);
- if (Status and DSBSTATUS_BUFFERLOST) > 0 then
- begin
- { Restore the buffer, rewrite data, and play }
- if Buffer.DirectSoundBuffer.Restore <> DS_OK then
- raise EMMDSWaveMixError.Create('DirectSoundBuffer restore failed');
- Abort := False;
- BufferLost(Buffer, Abort);
- if Abort then
- begin
- RemoveBuffer(Buffer);
- exit;
- end;
- CopyData(Buffer);
- end;
- if not Buffer.Playing and not Buffer.Paused then
- begin
- inc(FTimerInit);
- if (FTimerInit = 1) then UpdateTimer(True);
- end;
- Buffer.Play;
- end;
- {-- TMMDSWaveMixer ------------------------------------------------------}
- procedure TMMDSWaveMixer.PauseBuffer(Buffer: TMMDSSoundBuffer);
- begin
- if (Buffer = nil) or (Buffer.DirectSoundBuffer = nil) then exit;
- Buffer.Pause;
- end;
- {-- TMMDSWaveMixer ------------------------------------------------------}
- procedure TMMDSWaveMixer.StopBuffer(Buffer: TMMDSSoundBuffer);
- begin
- if (Buffer = nil) or (Buffer.DirectSoundBuffer = nil) then exit;
- if Buffer.Playing or Buffer.Paused then
- begin
- dec(FTimerInit);
- if (FTimerInit = 0) then UpdateTimer(False);
- Buffer.Stop;
- BufferEnd(Buffer);
- end
- else Buffer.Stop;
- end;
- {-- TMMDSWaveMixer ------------------------------------------------------}
- procedure TMMDSWaveMixer.OpenInDesignTime;
- begin
- if not (csDesigning in ComponentState) then
- raise EMMDSWaveMixError.Create('OpenInDesignTime called in run-time');
- FWorkInDesign := True;
- Open;
- SetPrimaryWaveFormat;
- end;
- {-- TMMDSWaveMixer ------------------------------------------------------}
- procedure TMMDSWaveMixer.CloseInDesignTime;
- begin
- if not (csDesigning in ComponentState) then
- raise EMMDSWaveMixError.Create('CloseInDesignTime called in run-time');
- Close;
- FWorkInDesign := False;
- end;
- {== TMMDSMixChannel =====================================================}
- constructor TMMDSMixChannel.Create(aOwner: TComponent);
- begin
- inherited Create(aOwner);
- FMixer := nil;
- if _WinNT3_ then
- raise EMMDSWaveMixError.Create(LoadResStr(IDS_DSNOTSUPPORTED));
- if not LoadDSoundDLL then
- raise EMMDSWaveMixError.Create(LoadResStr(IDS_DLLERROR)+' DSOUND.DLL...');
- FSoundBuffer := TMMDSSoundBuffer.Create;
- FSoundBuffer.FOnBufferEnd := BufferEnd;
- FSoundBuffer.FOnRelease := BufferRelease;
- FSoundBuffer.FOwned := True;
- Wave.OnChange := WaveChanged;
- F3DBuffer := TMMDS3DBuffer.Create((aOwner <> nil) and (csLoading in aOwner.ComponentState));
- ErrorCode := ComponentRegistered(InitCode, Self, ClassName);
- if (ErrorCode <> 0) then RegisterFailed(InitCode, Self , ClassName);
- end;
- {-- TMMDSMixChannel -----------------------------------------------------}
- destructor TMMDSMixChannel.Destroy;
- begin
- if FMixer <> nil then FMixer.Close;
- F3DBuffer.Free;
- inherited Destroy;
- end;
- {-- TMMDSMixChannel -----------------------------------------------------}
- procedure TMMDSMixChannel.Loaded;
- begin
- inherited Loaded;
- with Sound3D do
- if MM3DVectorEqual(ConeOrientation.AsVector,ZeroVector) then
- ConeOrientation.AsVector := MM3DVector(defConeOrientX,defConeOrientY,defConeOrientZ);
- end;
- {-- TMMDSMixChannel -----------------------------------------------------}
- procedure TMMDSMixChannel.Notification(AComponent: TComponent; Operation: TOperation);
- begin
- inherited Notification(AComponent, Operation);
- if (Operation = opRemove) and (AComponent = FMixer) then FMixer := Nil;
- end;
- {-- TMMDSMixChannel -----------------------------------------------------}
- procedure TMMDSMixChannel.WaveChanged(Sender: TObject);
- begin
- if (FMixer <> nil) and (FSoundBuffer <> nil) then
- begin
- FMixer.ClearBuffer(FSoundBuffer);
- end;
- end;
- {-- TMMDSMixChannel -----------------------------------------------------}
- procedure TMMDSMixChannel.Set3DBuffer(Value: TMMDS3DBuffer);
- begin
- F3DBuffer.Assign(Value);
- end;
- {-- TMMDSMixChannel -----------------------------------------------------}
- procedure TMMDSMixChannel.BufferEnd(Sender: TObject);
- begin
- if (Sender = FSoundBuffer) then
- begin
- if assigned(FOnPlayEnd) then FOnPlayEnd(Self);
- end;
- end;
- {-- TMMDSMixChannel -----------------------------------------------------}
- procedure TMMDSMixChannel.BufferRelease(Sender: TObject);
- begin
- F3DBuffer.FreeBuffer;
- end;
- {-- TMMDSMixChannel -----------------------------------------------------}
- procedure TMMDSMixChannel.Init;
- var
- aName: String;
- begin
- if (FMixer <> nil) and not Wave.Empty then
- with FMixer do
- begin
- if (FSoundBuffer.DirectSoundBuffer = nil) then
- begin
- FMixer.Open;
- aName := Wave.FileName;
- SetupBuffer(aName,Wave,FSoundBuffer);
- if Use3D then
- F3DBuffer.CreateBuffer(FSoundBuffer.DirectSoundBuffer);
- end;
- end;
- end;
- {-- TMMDSMixChannel -----------------------------------------------------}
- procedure TMMDSMixChannel.Play;
- begin
- Init;
- if (FMixer <> nil) then FMixer.PlayBuffer(FSoundBuffer);
- end;
- {-- TMMDSMixChannel -----------------------------------------------------}
- procedure TMMDSMixChannel.Pause;
- begin
- if (FMixer <> nil) then FMixer.PauseBuffer(FSoundBuffer);
- end;
- {-- TMMDSMixChannel -----------------------------------------------------}
- procedure TMMDSMixChannel.Stop;
- begin
- if (FMixer <> nil) then FMixer.StopBuffer(FSoundBuffer);
- end;
- {-- TMMDSMixChannel -----------------------------------------------------}
- procedure TMMDSMixChannel.SetPosition(aValue: Longint);
- begin
- FSoundBuffer.Position := aValue;
- end;
- {-- TMMDSMixChannel -----------------------------------------------------}
- function TMMDSMixChannel.GetPosition: Longint;
- begin
- Result := FSoundBuffer.Position;
- end;
- {-- TMMDSMixChannel -----------------------------------------------------}
- function TMMDSMixChannel.GetBufferLength: Longint;
- var
- wfx: TWaveFormatEx;
- pwfxSrc: PWaveFormatEx;
-
- begin
- Result := 0;
- if (FSoundBuffer.DirectSoundBuffer <> nil) then
- begin
- Result := FSoundBuffer.BufferLength;
- end
- else if (Wave <> nil) and not Wave.Empty then
- begin
- if (Wave.FormatTag <> WAVE_FORMAT_PCM) then
- begin
- if (Wave.FormatTag = WAVE_FORMAT_ADPCM) then
- begin
- pwfxSrc := Wave.PWaveFormat;
- if adpcmBuildFormatHeader(pwfxSrc, @wfx, 16, 0, 0) then
- begin
- Result := PADPCMWaveFormat(pwfxSrc)^.wSamplesPerBlock * Longint(wfx.nBlockAlign);
- Result := Result*(Wave.PWaveIOInfo^.dwDataBytes div pwfxSrc^.nBlockAlign);
- exit;
- end;
- end;
- wfx := acmSuggestPCMFormat(Wave.PWaveFormat);
- if acmQueryConvert(Wave.PWaveFormat,@wfx,False) then
- Result := acmSizeOutputData(Wave.PWaveFormat,@wfx,Wave.PWaveIOInfo^.dwDataBytes);
- end
- else Result := Wave.PWaveIOInfo^.dwDataBytes;
- end;
- end;
- {-- TMMDSMixChannel -----------------------------------------------------}
- procedure TMMDSMixChannel.SetVolume(aValue: Longint);
- begin
- FSoundBuffer.Volume := aValue;
- end;
- {-- TMMDSMixChannel -----------------------------------------------------}
- function TMMDSMixChannel.GetVolume: Longint;
- begin
- Result := FSoundBuffer.Volume;
- end;
- {-- TMMDSMixChannel -----------------------------------------------------}
- procedure TMMDSMixChannel.SetPanning(aValue: Longint);
- begin
- FSoundBuffer.Panning := aValue;
- end;
- {-- TMMDSMixChannel -----------------------------------------------------}
- function TMMDSMixChannel.GetPanning: Longint;
- begin
- Result := FSoundBuffer.Panning;
- end;
- {-- TMMDSMixChannel -----------------------------------------------------}
- procedure TMMDSMixChannel.SetFrequency(aValue: Longint);
- begin
- FSoundBuffer.Frequency := aValue;
- end;
- {-- TMMDSMixChannel -----------------------------------------------------}
- function TMMDSMixChannel.GetFrequency: Longint;
- begin
- Result := FSoundBuffer.Frequency;
- end;
- {-- TMMDSMixChannel -----------------------------------------------------}
- procedure TMMDSMixChannel.SetMuted(aValue: Boolean);
- begin
- FSoundBuffer.Muted := aValue;
- end;
- {-- TMMDSMixChannel -----------------------------------------------------}
- function TMMDSMixChannel.GetMuted: Boolean;
- begin
- Result := FSoundBuffer.Muted;
- end;
- {-- TMMDSMixChannel -----------------------------------------------------}
- procedure TMMDSMixChannel.SetLooping(aValue: Boolean);
- begin
- FSoundBuffer.Looping := aValue;
- end;
- {-- TMMDSMixChannel -----------------------------------------------------}
- function TMMDSMixChannel.GetLooping: Boolean;
- begin
- Result := FSoundBuffer.Looping;
- end;
- {-- TMMDSMixChannel -----------------------------------------------------}
- function TMMDSMixChannel.GetPlaying: Boolean;
- begin
- Result := FSoundBuffer.Playing;
- end;
- {-- TMMDSMixChannel -----------------------------------------------------}
- function TMMDSMixChannel.GetPaused: Boolean;
- begin
- Result := FSoundBuffer.Paused;
- end;
- {-- TMMDSMixChannel -----------------------------------------------------}
- procedure TMMDSMixChannel.GetVUMeter(var LeftValue, RightValue, BothValue: integer; Interval: integer);
- var
- PeakLeft,PeakRight: Smallint;
- nBytes,dwPos,VolLeft,VolRight: Longint;
- begin
- LeftValue := 0;
- RightValue := 0;
- BothValue := 0;
- if not Wave.Empty and (Wave.FormatTag = WAVE_FORMAT_PCM) and
- Playing and not Paused and not Muted then
- begin
- nBytes := wioTimeToBytes(PWaveFormat,Interval);
- dwPos := Position;
- if (dwPos+nBytes < Wave.PWaveIOInfo.dwDataBytes) then
- begin
- pcmFindPeak(Wave.PWaveFormat,
- PChar(Wave.PWaveData)+dwPos,
- nBytes, PeakLeft, PeakRight);
- if (Wave.BitLength = 8) then
- begin
- PeakLeft := (PeakLeft-128)*255;
- PeakRight:= (PeakRight-128)*255;
- end;
- CalcVolume(2*VOLUMEBASE,
- DBToVolume(Volume/100,VOLUMEBASE),
- RangeScale(Panning, -10000, 10000, -32768, 32768),
- VolLeft,VolRight);
- LeftValue := MulDiv(abs(PeakLeft),VolLeft,VOLUMEBASE);
- RightValue := MulDiv(abs(PeakRight),VolRight,VOLUMEBASE);
- BothValue := (LeftValue + RightValue) div 2;
- end;
- end;
- end;
- {== TMMDS3DControl ======================================================}
- destructor TMMDS3DControl.Destroy;
- begin
- FreeBuffer;
- inherited Destroy;
- end;
- {-- TMMDS3DControl ------------------------------------------------------}
- function TMMDS3DControl.SetDirect: Boolean;
- begin
- Result := ControlAllocated and (FUpdate = 0);
- end;
- {-- TMMDS3DControl ------------------------------------------------------}
- function TMMDS3DControl.GetDirect: Boolean;
- begin
- Result := ControlAllocated and not FInApply;
- end;
- {-- TMMDS3DControl ------------------------------------------------------}
- function TMMDS3DControl.ApplyFlags: DWORD;
- begin
- if FDeferred then
- Result := DS3D_DEFERRED
- else
- Result := DS3D_IMMEDIATE;
- end;
- {-- TMMDS3DControl -------------------------------------------------------}
- procedure TMMDS3DControl.SetDeferred(Value: Boolean);
- begin
- FDeferred := Value;
- if not FDeferred then
- ApplySettings;
- end;
- {-- TMMDS3DControl -------------------------------------------------------}
- procedure TMMDS3DControl.CreateBuffer(DSBuffer: IDirectSoundBuffer);
- var
- Caps: TDSBCAPS;
- begin
- FreeBuffer;
- if DSBuffer <> nil then
- begin
- FillChar(Caps, SizeOf(Caps), 0);
- Caps.dwSize := SizeOf(Caps);
- DSCheck(DSBuffer.GetCaps(Caps));
- if (Caps.dwFlags and DSBCAPS_CTRL3D) = 0 then
- Exit;
- ObtainControl(DSBuffer);
- ApplySettings;
- end;
- end;
- {-- TMMDS3DControl -------------------------------------------------------}
- procedure TMMDS3DControl.FreeBuffer;
- begin
- FreeControl;
- end;
- {-- TMMDS3DControl -------------------------------------------------------}
- procedure TMMDS3DControl.BeginUpdate;
- begin
- Inc(FUpdate);
- end;
- {-- TMMDS3DControl -------------------------------------------------------}
- procedure TMMDS3DControl.EndUpdate;
- begin
- Dec(FUpdate);
- if FUpdate = 0 then
- ApplySettings;
- end;
- {-- TMMDS3DControl -------------------------------------------------------}
- procedure TMMDS3DControl.ApplySettings;
- begin
- FInApply := True;
- try
- DoApplySettings;
- finally
- FInApply := False;
- end;
- end;
- {== TMMDS3DBuffer =======================================================}
- constructor TMMDS3DBuffer.Create(Loading: Boolean);
- begin
- inherited Create;
- FDS3DBuffer := nil;
- FMaxDistance := defMaxDistance;
- FMinDistance := defMinDistance;
- FMode := defMode;
- FInsideConeAngle := defInsideConeAngle;
- FOutsideConeAngle := defOutsideConeAngle;
- FConeOutsideVolume := defConeOutsideVolume;
- FPosition := TMMVector3D.Create;
- FConeOrientation := TMMVector3D.Create;
- FVelocity := TMMVector3D.Create;
- if not Loading then
- begin
- FPosition.X := defPosX;
- FPosition.Y := defPosY;
- FPosition.Z := defPosZ;
- FConeOrientation.X := defConeOrientX;
- FConeOrientation.Y := defConeOrientY;
- FConeOrientation.Z := defConeOrientZ;
- FVelocity.X := defVelX;
- FVelocity.Y := defVelY;
- FVelocity.Z := defVelZ;
- end;
- FPosition.OnChange := VectorChanged;
- FConeOrientation.OnChange := VectorChanged;
- FVelocity.OnChange := VectorChanged;
- end;
- {-- TMMDS3DBuffer -------------------------------------------------------}
- destructor TMMDS3DBuffer.Destroy;
- begin
- FPosition.Free;
- FConeOrientation.Free;
- FVelocity.Free;
- inherited Destroy;
- end;
- {-- TMMDS3DBuffer -------------------------------------------------------}
- function TMMDS3DBuffer.ControlAllocated: Boolean;
- begin
- Result := FDS3DBuffer <> nil;
- end;
- {-- TMMDS3DBuffer -------------------------------------------------------}
- procedure TMMDS3DBuffer.SetMaxDistance(Value: D3DVALUE);
- begin
- if FMaxDistance <> Value then
- begin
- FMaxDistance := Value;
- if SetDirect then
- DSCheck(FDS3DBuffer.SetMaxDistance(Value,ApplyFlags))
- end;
- end;
- {-- TMMDS3DBuffer -------------------------------------------------------}
- procedure TMMDS3DBuffer.SetMinDistance(Value: D3DVALUE);
- begin
- if FMinDistance <> Value then
- begin
- FMinDistance := Value;
- if SetDirect then
- DSCheck(FDS3DBuffer.SetMinDistance(Value,ApplyFlags))
- end;
- end;
- const
- BufferModes: array[TMMDS3DBufferMode] of DWORD =
- (DS3DMODE_NORMAL,DS3DMODE_HEADRELATIVE,DS3DMODE_DISABLE);
- {-- TMMDS3DBuffer -------------------------------------------------------}
- procedure TMMDS3DBuffer.SetMode(Value: TMMDS3DBufferMode);
- begin
- if FMode <> Value then
- begin
- FMode := Value;
- if SetDirect then
- DSCheck(FDS3DBuffer.SetMode(BufferModes[Value],ApplyFlags))
- end;
- end;
- {-- TMMDS3DBuffer -------------------------------------------------------}
- procedure TMMDS3DBuffer.SetPosition(Value: TMMVector3D);
- begin
- FPosition.AsVector := Value.AsVector;
- end;
- {-- TMMDS3DBuffer -------------------------------------------------------}
- procedure TMMDS3DBuffer.VectorChanged(Sender: TObject);
- begin
- if SetDirect then
- if Sender = FPosition then
- DSCheck(FDS3DBuffer.SetPosition(FPosition.x,FPosition.y,FPosition.z,ApplyFlags))
- else if Sender = FVelocity then
- DSCheck(FDS3DBuffer.SetVelocity(FVelocity.x,FVelocity.y,FVelocity.z,ApplyFlags))
- else if Sender = FConeOrientation then
- DSCheck(FDS3DBuffer.SetConeOrientation(FConeOrientation.x,FConeOrientation.y,FConeOrientation.z,ApplyFlags));
- end;
- {-- TMMDS3DBuffer -------------------------------------------------------}
- procedure TMMDS3DBuffer.SetInsideConeAngle(Value: LongInt);
- begin
- if FInsideConeAngle <> Value then
- begin
- FInsideConeAngle := Value;
- if SetDirect then
- DSCheck(FDS3DBuffer.SetConeAngles(Value,OutsideConeAngle,ApplyFlags))
- end;
- end;
- {-- TMMDS3DBuffer -------------------------------------------------------}
- procedure TMMDS3DBuffer.SetOutsideConeAngle(Value: LongInt);
- begin
- if FOutsideConeAngle <> Value then
- begin
- FOutsideConeAngle := Value;
- if SetDirect then
- DSCheck(FDS3DBuffer.SetConeAngles(InsideConeAngle,Value,ApplyFlags))
- end;
- end;
- {-- TMMDS3DBuffer -------------------------------------------------------}
- procedure TMMDS3DBuffer.SetConeOrientation(Value: TMMVector3D);
- begin
- FConeOrientation.AsVector := Value.AsVector;
- end;
- {-- TMMDS3DBuffer -------------------------------------------------------}
- procedure TMMDS3DBuffer.SetConeOutsideVolume(Value: LongInt);
- begin
- if FConeOutsideVolume <> Value then
- begin
- FConeOutsideVolume := Value;
- if SetDirect then
- DSCheck(FDS3DBuffer.SetConeOutsideVolume(Value,ApplyFlags))
- end;
- end;
- {-- TMMDS3DBuffer -------------------------------------------------------}
- procedure TMMDS3DBuffer.SetVelocity(Value: TMMVector3D);
- begin
- FVelocity.AsVector := Value.AsVector;
- end;
- {-- TMMDS3DBuffer -------------------------------------------------------}
- function TMMDS3DBuffer.GetMaxDistance: D3DVALUE;
- begin
- if GetDirect then
- DSCheck(FDS3DBuffer.GetMaxDistance(@FMaxDistance));
- Result := FMaxDistance;
- end;
- {-- TMMDS3DBuffer -------------------------------------------------------}
- function TMMDS3DBuffer.GetMinDistance: D3DVALUE;
- begin
- if GetDirect then
- DSCheck(FDS3DBuffer.GetMinDistance(@FMinDistance));
- Result := FMinDistance;
- end;
- {-- TMMDS3DBuffer -------------------------------------------------------}
- function TMMDS3DBuffer.GetMode: TMMDS3DBufferMode;
- var
- M: DWORD;
- i: TMMDS3DBufferMode;
- begin
- if GetDirect then
- begin
- DSCheck(FDS3DBuffer.GetMode(@M));
- for i := Low(BufferModes) to High(BufferModes) do
- if BufferModes[i] = M then
- begin
- FMode := i;
- Break;
- end;
- end;
- Result := FMode;
- end;
- {-- TMMDS3DBuffer -------------------------------------------------------}
- function TMMDS3DBuffer.GetPosition: TMMVector3D;
- var
- Vec: TD3DVECTOR;
- begin
- if GetDirect then
- begin
- DSCheck(FDS3DBuffer.GetPosition(@Vec));
- FPosition.AsVector := D3DVectorToMM3DVector(Vec);
- end;
- Result := FPosition;
- end;
- {-- TMMDS3DBuffer -------------------------------------------------------}
- function TMMDS3DBuffer.GetInsideConeAngle: LongInt;
- var
- Temp: LongInt;
- begin
- if GetDirect then
- DSCheck(FDS3DBuffer.GetConeAngles(@FInsideConeAngle,@Temp));
- Result := FInsideConeAngle;
- end;
- {-- TMMDS3DBuffer -------------------------------------------------------}
- function TMMDS3DBuffer.GetOutsideConeAngle: LongInt;
- var
- Temp: LongInt;
- begin
- if GetDirect then
- DSCheck(FDS3DBuffer.GetConeAngles(@Temp,@FOutsideConeAngle));
- Result := FOutsideConeAngle;
- end;
- {-- TMMDS3DBuffer -------------------------------------------------------}
- function TMMDS3DBuffer.GetConeOrientation: TMMVector3D;
- var
- Vec: TD3DVECTOR;
- begin
- if GetDirect then
- begin
- DSCheck(FDS3DBuffer.GetConeOrientation(@Vec));
- FConeOrientation.AsVector := D3DVectorToMM3DVector(Vec);
- end;
- Result := FConeOrientation;
- end;
- {-- TMMDS3DBuffer -------------------------------------------------------}
- function TMMDS3DBuffer.GetConeOutsideVolume: LongInt;
- begin
- if GetDirect then
- DSCheck(FDS3DBuffer.GetConeOutsideVolume(@FConeOutsideVolume));
- Result := FConeOutsideVolume;
- end;
- {-- TMMDS3DBuffer -------------------------------------------------------}
- function TMMDS3DBuffer.GetVelocity: TMMVector3D;
- var
- Vec: TD3DVECTOR;
- begin
- if GetDirect then
- begin
- DSCheck(FDS3DBuffer.GetVelocity(@Vec));
- FVelocity.AsVector := D3DVectorToMM3DVector(Vec);
- end;
- Result := FVelocity;
- end;
- {-- TMMDS3DBuffer -------------------------------------------------------}
- procedure TMMDS3DBuffer.ObtainControl(DSBuffer: IDirectSoundBuffer);
- begin
- if not Succeeded(DSBuffer.QueryInterface(IID_IDirectSound3DBuffer,FDS3DBuffer)) then
- { TODO: Should be resource id }
- raise EDSMixError.Create('Error obtaining 3D interface');
- end;
- {-- TMMDS3DBuffer -------------------------------------------------------}
- procedure TMMDS3DBuffer.FreeControl;
- begin
- if FDS3DBuffer <> nil then
- begin
- FDS3DBuffer.Release;
- FDS3DBuffer := nil;
- end;
- end;
- {-- TMMDS3DBuffer -------------------------------------------------------}
- procedure TMMDS3DBuffer.DoApplySettings;
- var
- Buf: TDS3DBUFFER;
- begin
- if SetDirect then
- begin
- Buf.dwSize := SizeOf(Buf);
- Buf.vPosition := MM3DVectorToD3DVector(FPosition.AsVector);
- Buf.vVelocity := MM3DVectorToD3DVector(FVelocity.AsVector);
- Buf.dwInsideConeAngle := FInsideConeAngle;
- Buf.dwOutsideConeAngle := FOutsideConeAngle;
- Buf.vConeOrientation := MM3DVectorToD3DVector(FConeOrientation.AsVector);
- Buf.lConeOutsideVolume := FConeOutsideVolume;
- Buf.flMaxDistance := FMaxDistance;
- Buf.flMinDistance := FMinDistance;
- Buf.dwMode := BufferModes[FMode];
- DSCheck(FDS3DBuffer.SetAllParameters(@Buf,ApplyFlags));
- end;
- end;
- {-- TMMDS3DBuffer -------------------------------------------------------}
- procedure TMMDS3DBuffer.Assign(Source: TPersistent);
- var
- S: TMMDS3DBuffer;
- begin
- if Source is TMMDS3DBuffer then
- begin
- S := Source as TMMDS3DBuffer;
- BeginUpdate;
- try
- MaxDistance := S.MaxDistance;
- MinDistance := S.MinDistance;
- Mode := S.Mode;
- Position := S.Position;
- InsideConeAngle := S.InsideConeAngle;
- OutsideConeAngle := S.OutsideConeAngle;
- ConeOrientation := S.ConeOrientation;
- ConeOutsideVolume := S.ConeOutsideVolume;
- Velocity := S.Velocity;
- finally
- EndUpdate;
- end;
- end
- else
- inherited Assign(Source);
- end;
- {== TMMDS3DListener =====================================================}
- constructor TMMDS3DListener.Create(Loading: Boolean);
- begin
- inherited Create;
- FDS3DListener := nil;
- FDistanceFactor := defDistanceFactor;
- FDopplerFactor := defDopplerFactor;
- FRollOffFactor := defRollOffFactor;
- FOrientFront := TMMVector3D.Create;
- FOrientTop := TMMVector3D.Create;
- FPosition := TMMVector3D.Create;
- FVelocity := TMMVector3D.Create;
- if not Loading then
- begin
- FOrientFront.X := defOrientFrontX;
- FOrientFront.Y := defOrientFrontY;
- FOrientFront.Z := defOrientFrontZ;
- FOrientTop.X := defOrientTopX;
- FOrientTop.Y := defOrientTopY;
- FOrientTop.Z := defOrientTopZ;
- FPosition.X := defPositionX;
- FPosition.Y := defPositionY;
- FPosition.Z := defPositionZ;
- FVelocity.X := defVelocityX;
- FVelocity.Y := defVelocityY;
- FVelocity.Z := defVelocityZ;
- end;
- FOrientFront.OnChange := VectorChanged;
- FOrientTop.OnChange := VectorChanged;
- FPosition.OnChange := VectorChanged;
- FVelocity.OnChange := VectorChanged;
- end;
- {-- TMMDS3DListener -----------------------------------------------------}
- destructor TMMDS3DListener.Destroy;
- begin
- FOrientFront.Free;
- FOrientTop.Free;
- FPosition.Free;
- FVelocity.Free;
- inherited Destroy;
- end;
- {-- TMMDS3DListener -----------------------------------------------------}
- procedure TMMDS3DListener.ObtainControl(DSBuffer: IDirectSoundBuffer);
- begin
- if not Succeeded(DSBuffer.QueryInterface(IID_IDirectSound3DListener,FDS3DListener)) then
- { TODO: Should be resource id }
- raise EDSMixError.Create('Error obtaining 3D interface');
- end;
- {-- TMMDS3DListener -----------------------------------------------------}
- procedure TMMDS3DListener.FreeControl;
- begin
- if FDS3DListener <> nil then
- begin
- FDS3DListener.Release;
- FDS3DListener := nil;
- end;
- end;
- {-- TMMDS3DListener -----------------------------------------------------}
- procedure TMMDS3DListener.DoApplySettings;
- var
- Buf: TDS3DLISTENER;
- begin
- if SetDirect then
- begin
- with Buf do
- begin
- dwSize := SizeOf(Buf);
- vPosition := MM3DVectorToD3DVector(Position.AsVector);
- vVelocity := MM3DVectorToD3DVector(Velocity.AsVector);
- vOrientFront := MM3DVectorToD3DVector(OrientFront.AsVector);
- vOrientTop := MM3DVectorToD3DVector(OrientTop.AsVector);
- flDistanceFactor := DistanceFactor;
- flRolloffFactor := RollOffFactor;
- flDopplerFactor := DopplerFactor;
- end;
- DSCheck(FDS3DListener.SetAllParameters(@Buf,ApplyFlags));
- end;
- end;
- {-- TMMDS3DListener -----------------------------------------------------}
- function TMMDS3DListener.ControlAllocated: Boolean;
- begin
- Result := FDS3DListener <> nil;
- end;
- {-- TMMDS3DListener -----------------------------------------------------}
- procedure TMMDS3DListener.Assign(Source: TPersistent);
- var
- S: TMMDS3DListener;
- begin
- if Source is TMMDS3DListener then
- begin
- S := Source as TMMDS3DListener;
- BeginUpdate;
- try
- DistanceFactor := S.DistanceFactor;
- DopplerFactor := S.DopplerFactor;
- OrientFront := S.OrientFront;
- OrientTop := S.OrientTop;
- Position := S.Position;
- RollOffFactor := S.RollOffFactor;
- Velocity := S.Velocity;
- finally
- EndUpdate;
- end;
- end
- else
- inherited Assign(Source);
- end;
- {-- TMMDS3DListener -----------------------------------------------------}
- function TMMDS3DListener.GetDistanceFactor: D3DVALUE;
- begin
- if GetDirect then
- DSCheck(FDS3DListener.GetDistanceFactor(@FDistanceFactor));
- Result := FDistanceFactor;
- end;
- {-- TMMDS3DListener -----------------------------------------------------}
- function TMMDS3DListener.GetDopplerFactor: D3DVALUE;
- begin
- if GetDirect then
- DSCheck(FDS3DListener.GetDopplerFactor(@FDopplerFactor));
- Result := FDopplerFactor;
- end;
- {-- TMMDS3DListener -----------------------------------------------------}
- function TMMDS3DListener.GetOrientFront: TMMVector3D;
- var
- Vec, Temp: TD3DVECTOR;
- begin
- if GetDirect then
- begin
- DSCheck(FDS3DListener.GetOrientation(@Vec,@Temp));
- FOrientFront.AsVector := D3DVEctorToMM3DVector(Vec);
- end;
- Result := FOrientFront;
- end;
- {-- TMMDS3DListener -----------------------------------------------------}
- function TMMDS3DListener.GetOrientTop: TMMVector3D;
- var
- Vec, Temp: TD3DVECTOR;
- begin
- if GetDirect then
- begin
- DSCheck(FDS3DListener.GetOrientation(@Temp,@Vec));
- FOrientTop.AsVector := D3DVectorToMM3DVector(Vec);
- end;
- Result := FOrientTop;
- end;
- {-- TMMDS3DListener -----------------------------------------------------}
- function TMMDS3DListener.GetPosition: TMMVector3D;
- var
- Vec: TD3DVECTOR;
- begin
- if GetDirect then
- begin
- DSCheck(FDS3DListener.GetPosition(@Vec));
- FPosition.AsVector := D3DVectorToMM3DVector(Vec);
- end;
- Result := FPosition;
- end;
- {-- TMMDS3DListener -----------------------------------------------------}
- function TMMDS3DListener.GetRollOffFactor: D3DVALUE;
- begin
- if GetDirect then
- DSCheck(FDS3DListener.GetRollOffFactor(@FRollOffFactor));
- Result := FRollOffFactor;
- end;
- {-- TMMDS3DListener -----------------------------------------------------}
- function TMMDS3DListener.GetVelocity: TMMVector3D;
- var
- Vec: TD3DVECTOR;
- begin
- if GetDirect then
- begin
- DSCheck(FDS3DListener.GetVelocity(@Vec));
- FVelocity.AsVector := D3DVectorToMM3DVector(Vec);
- end;
- Result := FVelocity;
- end;
- {-- TMMDS3DListener -----------------------------------------------------}
- procedure TMMDS3DListener.SetDistanceFactor(Value: D3DVALUE);
- begin
- if FDistanceFactor <> Value then
- begin
- FDistanceFactor := Value;
- if SetDirect then
- DSCheck(FDS3DListener.SetDistanceFactor(Value,ApplyFlags))
- end;
- end;
- {-- TMMDS3DListener -----------------------------------------------------}
- procedure TMMDS3DListener.SetDopplerFactor(Value: D3DVALUE);
- begin
- if FDopplerFactor <> Value then
- begin
- FDopplerFactor := Value;
- if SetDirect then
- DSCheck(FDS3DListener.SetDopplerFactor(Value,ApplyFlags))
- end;
- end;
- {-- TMMDS3DListener -----------------------------------------------------}
- procedure TMMDS3DListener.SetOrientFront(Value: TMMVector3D);
- begin
- FOrientFront.AsVector := Value.AsVector;
- end;
- {-- TMMDS3DListener -----------------------------------------------------}
- procedure TMMDS3DListener.SetOrientTop(Value: TMMVector3D);
- begin
- FOrientTop.AsVector := Value.AsVector;
- end;
- {-- TMMDS3DListener -----------------------------------------------------}
- procedure TMMDS3DListener.SetPosition(Value: TMMVector3D);
- begin
- FPosition.AsVector := Value.AsVector;
- end;
- {-- TMMDS3DListener -----------------------------------------------------}
- procedure TMMDS3DListener.SetRollOffFactor(Value: D3DVALUE);
- begin
- if FRollOffFactor <> Value then
- begin
- FRollOffFactor := Value;
- if SetDirect then
- DSCheck(FDS3DListener.SetRollOffFactor(Value,ApplyFlags))
- end;
- end;
- {-- TMMDS3DListener -----------------------------------------------------}
- procedure TMMDS3DListener.SetVelocity(Value: TMMVector3D);
- begin
- FVelocity.AsVector := Value.AsVector;
- end;
- {-- TMMDS3DListener -----------------------------------------------------}
- procedure TMMDS3DListener.VectorChanged(Sender: TObject);
- begin
- if SetDirect then
- if (Sender = FOrientFront) or (Sender = FOrientTop) then
- DSCheck(FDS3DListener.SetOrientation(FOrientFront.x,FOrientFront.y,FOrientFront.z,FOrientTop.x,FOrientTop.y,FOrientTop.z,ApplyFlags))
- else if Sender = FPosition then
- DSCheck(FDS3DListener.SetPosition(FPosition.x,FPosition.y,FPosition.z,ApplyFlags))
- else if Sender = FVelocity then
- DSCheck(FDS3DListener.SetVelocity(FVelocity.x,FVelocity.y,FVelocity.z,ApplyFlags));
- end;
- {-- TMMDS3DListener -----------------------------------------------------}
- procedure TMMDS3DListener.Commit;
- begin
- if not SetDirect then
- { TODO: Should be resource id }
- raise EDSMixError.Create('Can''t commit changes in this state');
- DSCheck(FDS3DListener.CommitDeferredSettings);
- end;
- {== EDirectSoundError ===================================================}
- constructor EDirectSoundError.CreateRes(Code: HResult);
- var
- Msg: string;
- C: Longint;
- begin
- FResult := Code;
- C := Code;
- { TODO: Should be resource ids }
- case C of
- DSERR_ALLOCATED : Msg := 'Another caller already allocated resources';
- DSERR_CONTROLUNAVAIL : Msg := 'Requested control unavailable';
- DSERR_INVALIDPARAM : Msg := 'Invalid parameter';
- DSERR_INVALIDCALL : Msg := 'Invalid call for current object''s state';
- DSERR_GENERIC : Msg := 'Undetermined error';
- DSERR_PRIOLEVELNEEDED : Msg := 'Priority not enough for success';
- DSERR_OUTOFMEMORY : Msg := 'Out of memory';
- DSERR_BADFORMAT : Msg := 'Bad format';
- DSERR_UNSUPPORTED : Msg := 'Unsupported';
- DSERR_NODRIVER : Msg := 'No driver';
- DSERR_ALREADYINITIALIZED: Msg := 'Object already initialized';
- DSERR_NOAGGREGATION : Msg := 'Object does not support aggregation';
- DSERR_BUFFERLOST : Msg := 'Buffer lost';
- DSERR_OTHERAPPHASPRIO : Msg := 'Other app has a higher priority level';
- DSERR_UNINITIALIZED : Msg := 'Initialize has not been called';
- else
- Msg := 'Unknown error code';
- end;
- inherited Create(Msg);
- end;
- {------------------------------------------------------------------------}
- procedure DSCheck(Res: HRESULT);
- begin
- if Res <> DS_OK then
- raise EDirectSoundError.CreateRes(Res);
- end;
- {------------------------------------------------------------------------}
- function DSCheckExcl(Res: HRESULT; const Excl: array of HRESULT): HRESULT;
- var
- i: Integer;
- begin
- Result := Res;
- for i := Low(Excl) to High(Excl) do
- if Excl[i] = Res then
- Exit;
- DSCheck(Res);
- end;
- end.