home *** CD-ROM | disk | FTP | other *** search
- unit DXSounds;
-
- interface
-
- {$INCLUDE DelphiXcfg.inc}
-
- uses
- Windows, Messages, SysUtils, Classes, Controls, Forms, ExtCtrls, MMSystem,
- DirectX, DXClass, Wave;
-
- type
-
- { EDirectSoundError }
-
- EDirectSoundError = class(EDirectXError);
- EDirectSoundBufferError = class(EDirectSoundError);
-
- { TDirectSound }
-
- TDirectSoundBuffer = class;
-
- TDirectSound = class(TDirectX)
- private
- FBufferList: TList;
- FGlobalFocus: Boolean;
- FIDSound: IDirectSound;
- FInRestoreBuffer: Boolean;
- FStickyFocus: Boolean;
- function GetBuffer(Index: Integer): TDirectSoundBuffer;
- function GetBufferCount: Integer;
- function GetIDSound: IDirectSound;
- function GetISound: IDirectSound;
- protected
- procedure CheckBuffer(Buffer: TDirectSoundBuffer);
- procedure DoRestoreBuffer; virtual;
- public
- constructor Create(GUID: PGUID);
- constructor CreateFromInterface(DSound: IDirectSound);
- destructor Destroy; override;
- class function Drivers: TDirectXDrivers;
- property BufferCount: Integer read GetBufferCount;
- property Buffers[Index: Integer]: TDirectSoundBuffer read GetBuffer;
- property GlobalFocus: Boolean read FGlobalFocus write FGlobalFocus;
- property IDSound: IDirectSound read GetIDSound;
- property ISound: IDirectSound read GetISound;
- property StickyFocus: Boolean read FStickyFocus write FStickyFocus;
- end;
-
- { TDirectSoundBuffer }
-
- TDirectSoundBuffer = class(TDirectX)
- private
- FDSound: TDirectSound;
- FIDSBuffer: IDirectSoundBuffer;
- function GetBitCount: Longint;
- function GetFrequency: Integer;
- function GetIDSBuffer: IDirectSoundBuffer;
- function GetIBuffer: IDirectSoundBuffer;
- function GetPlaying: Boolean;
- function GetPan: Integer;
- function GetPosition: Longint;
- function GetStatus: Integer;
- function GetVolume: Integer;
- procedure SetFrequency(Value: Integer);
- procedure SetIDSBuffer(Value: IDirectSoundBuffer);
- procedure SetPan(Value: Integer);
- procedure SetPosition(Value: Longint);
- procedure SetVolume(Value: Integer);
- protected
- procedure Check; override;
- public
- constructor Create(ADSound: TDirectSound);
- destructor Destroy; override;
- procedure Assign(Source: TPersistent); override;
- function CreateBuffer(const BufferDesc: DSBUFFERDESC): Boolean;
- function GetFormat(var Format: TWaveFormatEx;
- dwSizeAllocated: Longint; var dwSizeWritten: Longint): Boolean;
- function GetFormatAlloc(var Format: PWaveFormatEx; var Size: Longint): Boolean;
- function Lock(dwWriteCursor, dwWriteBytes: Longint;
- var lpvAudioPtr1: Pointer; var dwAudioBytes1: Longint;
- var lpvAudioPtr2: Pointer; var dwAudioBytes2: Longint;
- dwFlags: Longint): Boolean;
- procedure LoadFromFile(const FileName: string);
- procedure LoadFromMemory(const Format: TWaveFormatEx;
- Data: Pointer; Size: Integer);
- procedure LoadFromStream(Stream: TStream);
- procedure LoadFromWave(Wave: TWave);
- function Play(Flags: Longint{$IFNDEF VER100}=0{$ENDIF}): Boolean;
- function Restore: Boolean;
- function SetFormat(const Format: TWaveFormatEx): Boolean;
- procedure SetSize(const Format: TWaveFormatEx; Size: Integer);
- function Stop: Boolean;
- function Unlock(lpvAudioPtr1: Pointer; dwAudioBytes1: Longint;
- lpvAudioPtr2: Pointer; dwAudioBytes2: Longint): Boolean;
- property BitCount: Longint read GetBitCount;
- property DSound: TDirectSound read FDSound;
- property Frequency: Integer read GetFrequency write SetFrequency;
- property IBuffer: IDirectSoundBuffer read GetIBuffer;
- property IDSBuffer: IDirectSoundBuffer read GetIDSBuffer write SetIDSBuffer;
- property Playing: Boolean read GetPlaying;
- property Pan: Integer read GetPan write SetPan;
- property Position: Longint read GetPosition write SetPosition;
- property Status: Integer read GetStatus;
- property Volume: Integer read GetVolume write SetVolume;
- end;
-
- { EAudioStreamError }
-
- EAudioStreamError = class(Exception);
-
- { TAudioStream }
-
- TAudioStream = class
- private
- FAutoUpdate: Boolean;
- FBuffer: TDirectSoundBuffer;
- FBufferLength: Integer;
- FBufferPos: DWORD;
- FPlayBufferPos: DWORD;
- FBufferSize: DWORD;
- FDSound: TDirectSound;
- FLooped: Boolean;
- FPlayedSize: Integer;
- FPlaying: Boolean;
- FPosition: Integer;
- FWaveStream: TCustomWaveStream;
- FWritePosition: Integer;
- FNotifyEvent: THandle;
- FNotifyThread: TThread;
- FInThread: Boolean;
- function GetFormat: PWaveFormatEX;
- function GetFormatSize: Integer;
- function GetFrequency: Integer;
- function GetPan: Integer;
- function GetPlayedSize: Integer;
- function GetSize: Integer;
- function GetVolume: Integer;
- function GetWriteSize: Integer;
- procedure SetAutoUpdate(Value: Boolean);
- procedure SetBufferLength(Value: Integer);
- procedure SetFrequency(Value: Integer);
- procedure SetLooped(Value: Boolean);
- procedure SetPan(Value: Integer);
- procedure SetPlayedSize(Value: Integer);
- procedure SetPosition(Value: Integer);
- procedure SetVolume(Value: Integer);
- procedure SetWaveStream(Value: TCustomWaveStream);
- procedure UpdatePlayedSize;
- function WriteWave(WriteSize: Integer): Integer;
- public
- constructor Create(ADSound: TDirectSound);
- destructor Destroy; override;
- procedure Play;
- procedure RecreateBuf;
- procedure Stop;
- procedure Update;
- property AutoUpdate: Boolean read FAutoUpdate write SetAutoUpdate;
- property BufferLength: Integer read FBufferLength write SetBufferLength;
- property Format: PWaveFormatEx read GetFormat;
- property FormatSize: Integer read GetFormatSize;
- property Frequency: Integer read GetFrequency write SetFrequency;
- property Pan: Integer read GetPan write SetPan;
- property PlayedSize: Integer read GetPlayedSize write SetPlayedSize;
- property Playing: Boolean read FPlaying;
- property Position: Integer read FPosition write SetPosition;
- property Looped: Boolean read FLooped write SetLooped;
- property Size: Integer read GetSize;
- property Volume: Integer read GetVolume write SetVolume;
- property WaveStream: TCustomWaveStream read FWaveStream write SetWaveStream;
- end;
-
- { TAudioFileStream }
-
- TAudioFileStream = class(TAudioStream)
- private
- FFileName: string;
- FWaveFileStream: TWaveFileStream;
- procedure SetFileName(const Value: string);
- public
- destructor Destroy; override;
- property FileName: string read FFileName write SetFileName;
- end;
-
- { TSoundCaptureFormat }
-
- TSoundCaptureFormat = class(TCollectionItem)
- private
- FBitsPerSample: Integer;
- FChannels: Integer;
- FSamplesPerSec: Integer;
- public
- property BitsPerSample: Integer read FBitsPerSample;
- property Channels: Integer read FChannels;
- property SamplesPerSec: Integer read FSamplesPerSec;
- end;
-
- { TSoundCaptureFormats }
-
- TSoundCaptureFormats = class(TCollection)
- private
- function GetItem(Index: Integer): TSoundCaptureFormat;
- public
- constructor Create;
- function IndexOf(ASamplesPerSec, ABitsPerSample, AChannels: Integer): Integer;
- property Items[Index: Integer]: TSoundCaptureFormat read GetItem; default;
- end;
-
- { TSoundCaptureStream }
-
- ESoundCaptureStreamError = class(EWaveStreamError);
-
- TSoundCaptureStream = class(TCustomWaveStream2)
- private
- FBuffer: IDirectSoundCaptureBuffer;
- FBufferLength: Integer;
- FBufferPos: DWORD;
- FBufferSize: DWORD;
- FCapture: IDirectSoundCapture;
- FCaptureFormat: Integer;
- FCapturing: Boolean;
- FNotifyEvent: THandle;
- FNotifyThread: TThread;
- FOnFilledBuffer: TNotifyEvent;
- FSupportedFormats: TSoundCaptureFormats;
- function GetReadSize: Integer;
- procedure SetBufferLength(Value: Integer);
- procedure SetOnFilledBuffer(Value: TNotifyEvent);
- protected
- procedure DoFilledBuffer; virtual;
- function GetFilledSize: Integer; override;
- function ReadWave(var Buffer; Count: Integer): Integer; override;
- public
- constructor Create(GUID: PGUID);
- destructor Destroy; override;
- class function Drivers: TDirectXDrivers;
- procedure Start;
- procedure Stop;
- property BufferLength: Integer read FBufferLength write SetBufferLength;
- property CaptureFormat: Integer read FCaptureFormat write FCaptureFormat;
- property Capturing: Boolean read FCapturing;
- property OnFilledBuffer: TNotifyEvent read FOnFilledBuffer write SetOnFilledBuffer;
- property SupportedFormats: TSoundCaptureFormats read FSupportedFormats;
- end;
-
- { TSoundEngine }
-
- TSoundEngine = class
- private
- FDSound: TDirectSound;
- FEffectList: TList;
- FEnabled: Boolean;
- FTimer: TTimer;
- function GetEffect(Index: Integer): TDirectSoundBuffer;
- function GetEffectCount: Integer;
- procedure SetEnabled(Value: Boolean);
- procedure TimerEvent(Sender: TObject);
- public
- constructor Create(ADSound: TDirectSound);
- destructor Destroy; override;
- procedure Clear;
- procedure EffectFile(const Filename: string; Loop, Wait: Boolean);
- procedure EffectStream(Stream: TStream; Loop, Wait: Boolean);
- procedure EffectWave(Wave: TWave; Loop, Wait: Boolean);
- property EffectCount: Integer read GetEffectCount;
- property Effects[Index: Integer]: TDirectSoundBuffer read GetEffect;
- property Enabled: Boolean read FEnabled write SetEnabled;
- end;
-
- { EDXSoundError }
-
- EDXSoundError = class(Exception);
-
- { TCustomDXSound }
-
- TCustomDXSound = class;
-
- TDXSoundOption = (soGlobalFocus, soStickyFocus, soExclusive, soWritePrimary);
- TDXSoundOptions = set of TDXSoundOption;
-
- TDXSoundNotifyType = (dsntDestroying, dsntInitializing, dsntInitialize, dsntFinalize, dsntRestore);
- TDXSoundNotifyEvent = procedure(Sender: TCustomDXSound; NotifyType: TDXSoundNotifyType) of object;
-
- TCustomDXSound = class(TComponent)
- private
- FAutoInitialize: Boolean;
- FCalledDoInitialize: Boolean;
- FDriver: PGUID;
- FDriverGUID: TGUID;
- FDSound: TDirectSound;
- FForm: TCustomForm;
- FInitialized: Boolean;
- FInternalInitialized: Boolean;
- FNotifyEventList: TList;
- FNowOptions: TDXSoundOptions;
- FOnFinalize: TNotifyEvent;
- FOnInitialize: TNotifyEvent;
- FOnInitializing: TNotifyEvent;
- FOnRestore: TNotifyEvent;
- FOptions: TDXSoundOptions;
- FPrimary: TDirectSoundBuffer;
- FSubClass: TControlSubClass;
- procedure FormWndProc(var Message: TMessage; DefWindowProc: TWndMethod);
- procedure NotifyEventList(NotifyType: TDXSoundNotifyType);
- procedure SetDriver(Value: PGUID);
- procedure SetForm(Value: TCustomForm);
- procedure SetOptions(Value: TDXSoundOptions);
- protected
- procedure DoFinalize; virtual;
- procedure DoInitialize; virtual;
- procedure DoInitializing; virtual;
- procedure DoRestore; virtual;
- procedure Loaded; override;
- public
- constructor Create(AOwner: TComponent); override;
- destructor Destroy; override;
- class function Drivers: TDirectXDrivers;
- procedure Finalize;
- procedure Initialize;
- procedure Restore;
- procedure RegisterNotifyEvent(NotifyEvent: TDXSoundNotifyEvent);
- procedure UnRegisterNotifyEvent(NotifyEvent: TDXSoundNotifyEvent);
- property AutoInitialize: Boolean read FAutoInitialize write FAutoInitialize;
- property Driver: PGUID read FDriver write SetDriver;
- property DSound: TDirectSound read FDSound;
- property Initialized: Boolean read FInitialized;
- property NowOptions: TDXSoundOptions read FNowOptions;
- property Primary: TDirectSoundBuffer read FPrimary;
- property OnFinalize: TNotifyEvent read FOnFinalize write FOnFinalize;
- property OnInitialize: TNotifyEvent read FOnInitialize write FOnInitialize;
- property OnInitializing: TNotifyEvent read FOnInitializing write FOnInitializing;
- property OnRestore: TNotifyEvent read FOnRestore write FOnRestore;
- property Options: TDXSoundOptions read FOptions write SetOptions;
- end;
-
- { TDXSound }
-
- TDXSound = class(TCustomDXSound)
- published
- property AutoInitialize;
- property Options;
- property OnFinalize;
- property OnInitialize;
- property OnInitializing;
- property OnRestore;
- end;
-
- { EWaveCollectionError }
-
- EWaveCollectionError = class(Exception);
-
- { TWaveCollectionItem }
-
- TWaveCollection = class;
-
- TWaveCollectionItem = class(THashCollectionItem)
- private
- FBuffer: TDirectSoundBuffer;
- FFrequency: Integer;
- FInitialized: Boolean;
- FLooped: Boolean;
- FPan: Integer;
- FVolume: Integer;
- FWave: TWave;
- function CreateBuffer: TDirectSoundBuffer;
- procedure Finalize;
- procedure Initialize;
- function GetBuffer: TDirectSoundBuffer;
- function GetWaveCollection: TWaveCollection;
- procedure SetFrequency(Value: Integer);
- procedure SetLooped(Value: Boolean);
- procedure SetPan(Value: Integer);
- procedure SetVolume(Value: Integer);
- procedure SetWave(Value: TWave);
- public
- constructor Create(Collection: TCollection); override;
- destructor Destroy; override;
- procedure Play(Wait: Boolean);
- procedure Restore;
- procedure Stop;
- property Buffer: TDirectSoundBuffer read GetBuffer;
- property Frequency: Integer read FFrequency write SetFrequency;
- property Initialized: Boolean read FInitialized;
- property Pan: Integer read FPan write SetPan;
- property Volume: Integer read FVolume write SetVolume;
- property WaveCollection: TWaveCollection read GetWaveCollection;
- published
- property Looped: Boolean read FLooped write SetLooped;
- property Wave: TWave read FWave write SetWave;
- end;
-
- { TWaveCollection }
-
- TWaveCollection = class(THashCollection)
- private
- FBufferList: TList;
- FDXSound: TCustomDXSound;
- FOwner: TPersistent;
- FTimer: TTimer;
- procedure AddBuffer(Buffer: TDirectSoundBuffer);
- procedure ClearBuffers;
- function GetBuffer(Index: Integer): TDirectSoundBuffer;
- function GetBufferCount: Integer;
- function GetItem(Index: Integer): TWaveCollectionItem;
- function Initialized: Boolean;
- procedure TimerEvent(Sender: TObject);
- property BufferCount: Integer read GetBufferCount;
- property Buffers[Index: Integer]: TDirectSoundBuffer read GetBuffer;
- protected
- function GetOwner: TPersistent; override;
- public
- constructor Create(AOwner: TPersistent);
- destructor Destroy; override;
- function Find(const Name: string): TWaveCollectionItem;
- procedure Finalize;
- procedure Initialize(DXSound: TCustomDXSound);
- procedure Restore;
- procedure LoadFromFile(const FileName: string);
- procedure LoadFromStream(Stream: TStream);
- procedure SaveToFile(const FileName: string);
- procedure SaveToStream(Stream: TStream);
- property DXSound: TCustomDXSound read FDXSound;
- property Items[Index: Integer]: TWaveCollectionItem read GetItem; default;
- end;
-
- { TCustomDXWaveList }
-
- TCustomDXWaveList = class(TComponent)
- private
- FDXSound: TCustomDXSound;
- FItems: TWaveCollection;
- procedure DXSoundNotifyEvent(Sender: TCustomDXSound; NotifyType: TDXSoundNotifyType);
- procedure SetDXSound(Value: TCustomDXSound);
- procedure SetItems(Value: TWaveCollection);
- protected
- procedure Notification(AComponent: TComponent; Operation: TOperation); override;
- public
- constructor Create(AOwner: TComponent); override;
- destructor Destroy; override;
- property DXSound: TCustomDXSound read FDXSound write SetDXSound;
- property Items: TWaveCollection read FItems write SetItems;
- end;
-
- { TDXWaveList }
-
- TDXWaveList = class(TCustomDXWaveList)
- published
- property DXSound;
- property Items;
- end;
-
- implementation
-
- uses DXConsts;
-
- function DXDirectSoundCreate(lpGUID: PGUID; out lpDS: IDirectSound;
- pUnkOuter: IUnknown): HRESULT;
- type
- TDirectSoundCreate = function(lpGUID: PGUID; out lplpDD: IDirectSound;
- pUnkOuter: IUnknown): HRESULT; stdcall;
- begin
- Result := TDirectSoundCreate(DXLoadLibrary('DSound.dll', 'DirectSoundCreate'))
- (lpGUID, lpDS, pUnkOuter);
- end;
-
- function DXDirectSoundEnumerate(lpCallback: LPDSENUMCALLBACKA;
- lpContext: Pointer): HRESULT;
- type
- TDirectSoundEnumerate = function(lpCallback: LPDSENUMCALLBACKA;
- lpContext: Pointer): HRESULT; stdcall;
- begin
- Result := TDirectSoundEnumerate(DXLoadLibrary('DSound.dll', 'DirectSoundEnumerateA'))
- (lpCallback, lpContext);
- end;
-
- function DXDirectSoundCaptureCreate(lpGUID: PGUID; out lplpDSC: IDirectSoundCapture;
- pUnkOuter: IUnknown): HRESULT;
- type
- TDirectSoundCaptureCreate = function(lpGUID: PGUID; out lplpDD: IDirectSoundCapture;
- pUnkOuter: IUnknown): HRESULT; stdcall;
- begin
- try
- Result := TDirectSoundCaptureCreate(DXLoadLibrary('DSound.dll', 'DirectSoundCaptureCreate'))
- (lpGUID, lplpDSC, pUnkOuter);
- except
- raise EDirectXError.Create(SSinceDirectX5);
- end;
- end;
-
- function DXDirectSoundCaptureEnumerate(lpCallback: LPDSENUMCALLBACKA;
- lpContext: Pointer): HRESULT;
- type
- TDirectSoundCaptureEnumerate = function(lpCallback: LPDSENUMCALLBACKA;
- lpContext: Pointer): HRESULT; stdcall;
- begin
- try
- Result := TDirectSoundCaptureEnumerate(DXLoadLibrary('DSound.dll', 'DirectSoundCaptureEnumerateA'))
- (lpCallback, lpContext);
- except
- raise EDirectXError.Create(SSinceDirectX5);
- end;
- end;
-
- var
- DirectSoundDrivers: TDirectXDrivers;
- DirectSoundCaptureDrivers: TDirectXDrivers;
-
- function EnumDirectSoundDrivers_DSENUMCALLBACK(lpGuid: PGUID; lpstrDescription: LPCSTR;
- lpstrModule: LPCSTR; lpContext: Pointer): BOOL; stdcall;
- begin
- Result := True;
- with TDirectXDriver.Create(TDirectXDrivers(lpContext)) do
- begin
- Guid := lpGuid;
- Description := lpstrDescription;
- DriverName := lpstrModule;
- end;
- end;
-
- function EnumDirectSoundDrivers: TDirectXDrivers;
- begin
- if DirectSoundDrivers=nil then
- begin
- DirectSoundDrivers := TDirectXDrivers.Create;
- try
- DXDirectSoundEnumerate(@EnumDirectSoundDrivers_DSENUMCALLBACK, DirectSoundDrivers);
- except
- DirectSoundDrivers.Free;
- raise;
- end;
- end;
-
- Result := DirectSoundDrivers;
- end;
-
- function EnumDirectSoundCaptureDrivers: TDirectXDrivers;
- begin
- if DirectSoundCaptureDrivers=nil then
- begin
- DirectSoundCaptureDrivers := TDirectXDrivers.Create;
- try
- DXDirectSoundCaptureEnumerate(@EnumDirectSoundDrivers_DSENUMCALLBACK, DirectSoundCaptureDrivers);
- except
- DirectSoundCaptureDrivers.Free;
- raise;
- end;
- end;
-
- Result := DirectSoundCaptureDrivers;
- end;
-
- { TDirectSound }
-
- constructor TDirectSound.Create(GUID: PGUID);
- var
- DSound: IDirectSound;
- begin
- if DXDirectSoundCreate(GUID, DSound, nil)=DD_OK then
- CreateFromInterface(DSound)
- else
- CreateFromInterface(nil);
- end;
-
- constructor TDirectSound.CreateFromInterface(DSound: IDirectSound);
- begin
- inherited Create;
- FBufferList := TList.Create;
-
- FIDSound := DSound;
- if FIDSound=nil then
- raise EDirectSoundError.CreateFmt(SCannotInitialized, [SDirectSound]);
- end;
-
- destructor TDirectSound.Destroy;
- begin
- FBufferList.Free;
- inherited Destroy;
- end;
-
- class function TDirectSound.Drivers: TDirectXDrivers;
- begin
- Result := EnumDirectSoundDrivers;
- end;
-
- procedure TDirectSound.CheckBuffer(Buffer: TDirectSoundBuffer);
- begin
- case Buffer.DXResult of
- DSERR_BUFFERLOST:
- begin
- if not FInRestoreBuffer then
- begin
- FInRestoreBuffer := True;
- try
- DoRestoreBuffer;
- finally
- FInRestoreBuffer := False;
- end;
- end;
- end;
- end;
- end;
-
- procedure TDirectSound.DoRestoreBuffer;
- begin
- end;
-
- function TDirectSound.GetBuffer(Index: Integer): TDirectSoundBuffer;
- begin
- Result := FBufferList[Index];
- end;
-
- function TDirectSound.GetBufferCount: Integer;
- begin
- Result := FBufferList.Count;
- end;
-
- function TDirectSound.GetIDSound: IDirectSound;
- begin
- if Self<>nil then
- Result := FIDSound
- else
- Result := nil;
- end;
-
- function TDirectSound.GetISound: IDirectSound;
- begin
- Result := IDSound;
- if Result=nil then
- raise EDirectSoundError.CreateFmt(SNotMade, ['IDirectSound']);
- end;
-
- { TDirectSoundBuffer }
-
- constructor TDirectSoundBuffer.Create(ADSound: TDirectSound);
- begin
- inherited Create;
- FDSound := ADSound;
- FDSound.FBufferList.Add(Self);
- end;
-
- destructor TDirectSoundBuffer.Destroy;
- begin
- FDSound.FBufferList.Remove(Self);
- inherited Destroy;
- end;
-
- procedure TDirectSoundBuffer.Assign(Source: TPersistent);
- var
- TempBuffer: IDirectSoundBuffer;
- begin
- if Source=nil then
- IDSBuffer := nil
- else if Source is TWave then
- LoadFromWave(TWave(Source))
- else if Source is TDirectSoundBuffer then
- begin
- if TDirectSoundBuffer(Source).IDSBuffer=nil then
- IDSBuffer := nil
- else begin
- FDSound.DXResult := FDSound.ISound.DuplicateSoundBuffer(TDirectSoundBuffer(Source).IDSBuffer,
- TempBuffer);
- if FDSound.DXResult=0 then
- begin
- IDSBuffer := TempBuffer;
- end;
- end;
- end else
- inherited Assign(Source);
- end;
-
- procedure TDirectSoundBuffer.Check;
- begin
- FDSound.CheckBuffer(Self);
- end;
-
- function TDirectSoundBuffer.CreateBuffer(const BufferDesc: DSBUFFERDESC): Boolean;
- var
- TempBuffer: IDirectSoundBuffer;
- begin
- IDSBuffer := nil;
-
- FDSound.DXResult := FDSound.ISound.CreateSoundBuffer(BufferDesc, TempBuffer, nil);
- FDXResult := FDSound.DXResult;
- Result := DXResult=DS_OK;
- if Result then
- IDSBuffer := TempBuffer;
- end;
-
- function TDirectSoundBuffer.GetBitCount: Longint;
- var
- fmtSize: Longint;
- Format: PWaveFormatEx;
- begin
- GetFormatAlloc(Format, fmtSize);
- try
- Result := Format^.wBitsPerSample;
- finally
- FreeMem(Format);
- end;
- end;
-
- function TDirectSoundBuffer.GetFormat(var Format: TWaveFormatEx;
- dwSizeAllocated: Longint; var dwSizeWritten: Longint): Boolean;
- begin
- DXResult := IBuffer.GetFormat(Format, dwSizeAllocated, DWORD(dwSizeWritten));
- Result := DXResult=DS_OK;
- end;
-
- function TDirectSoundBuffer.GetFormatAlloc(var Format: PWaveFormatEx; var Size: Longint): Boolean;
- begin
- Result := False;
- if GetFormat(PWaveFormatEx(nil)^, 0, Size) then
- begin
- GetMem(Format, Size);
- Result := GetFormat(Format^, Size, PLongint(nil)^);
- end;
- end;
-
- function TDirectSoundBuffer.GetFrequency: Integer;
- begin
- DXResult := IBuffer.GetFrequency(DWORD(Result));
- end;
-
- function TDirectSoundBuffer.GetIDSBuffer: IDirectSoundBuffer;
- begin
- if Self<>nil then
- Result := FIDSBuffer
- else
- Result := nil;
- end;
-
- function TDirectSoundBuffer.GetIBuffer: IDirectSoundBuffer;
- begin
- Result := IDSBuffer;
- if Result=nil then
- raise EDirectSoundBufferError.CreateFmt(SNotMade, ['IDirectSoundBuffer']);
- end;
-
- function TDirectSoundBuffer.GetPlaying: Boolean;
- begin
- Result := (Status and (DSBSTATUS_PLAYING or DSBSTATUS_LOOPING))<>0;
- end;
-
- function TDirectSoundBuffer.GetPan: Integer;
- begin
- DXResult := IBuffer.GetPan(Longint(Result));
- end;
-
- function TDirectSoundBuffer.GetPosition: Longint;
- var
- dwCurrentWriteCursor: Longint;
- begin
- IBuffer.GetCurrentPosition(DWORD(Result), DWORD(dwCurrentWriteCursor));
- end;
-
- function TDirectSoundBuffer.GetStatus: Integer;
- begin
- DXResult := IBuffer.GetStatus(DWORD(Result));
- end;
-
- function TDirectSoundBuffer.GetVolume: Integer;
- begin
- DXResult := IBuffer.GetVolume(Longint(Result));
- end;
-
- procedure TDirectSoundBuffer.LoadFromFile(const FileName: string);
- var
- Stream : TFileStream;
- begin
- Stream :=TFileStream.Create(FileName, fmOpenRead);
- try
- LoadFromStream(Stream);
- finally
- Stream.Free;
- end;
- end;
-
- procedure TDirectSoundBuffer.LoadFromMemory(const Format: TWaveFormatEx;
- Data: Pointer; Size: Integer);
- var
- Data1, Data2: Pointer;
- Data1Size, Data2Size: Longint;
- begin
- SetSize(Format, Size);
-
- if Data<>nil then
- begin
- if Lock(0, Size, Data1, Data1Size, Data2, Data2Size, 0) then
- begin
- Move(Data^, Data1^, Data1Size);
- if Data2<>nil then
- Move(Pointer(Longint(Data)+Data1Size)^, Data2^, Data2Size);
-
- UnLock(Data1, Data1Size, Data2, Data2Size);
- end else
- begin
- FIDSBuffer := nil;
- raise EDirectSoundBufferError.CreateFmt(SCannotLock, [SDirectSoundBuffer]);
- end;
- end;
- end;
-
- procedure TDirectSoundBuffer.LoadFromStream(Stream: TStream);
- var
- Wave: TWave;
- begin
- Wave := TWave.Create;
- try
- Wave.LoadFromStream(Stream);
- LoadFromWave(Wave);
- finally
- Wave.Free;
- end;
- end;
-
- procedure TDirectSoundBuffer.LoadFromWave(Wave: TWave);
- begin
- LoadFromMemory(Wave.Format^, Wave.Data, Wave.Size);
- end;
-
- function TDirectSoundBuffer.Lock(dwWriteCursor, dwWriteBytes: Longint;
- var lpvAudioPtr1: Pointer; var dwAudioBytes1: Longint;
- var lpvAudioPtr2: Pointer; var dwAudioBytes2: Longint;
- dwFlags: Longint): Boolean;
- begin
- DXResult := IBuffer.Lock(dwWriteCursor, dwWriteBytes,
- lpvAudioPtr1, DWORD(dwAudioBytes1),
- lpvAudioPtr2, DWORD(dwAudioBytes2), dwFlags);
- Result := DXResult=DS_OK;
- end;
-
- function TDirectSoundBuffer.Play(Flags: Longint): Boolean;
- begin
- DXResult := IBuffer.Play(0, 0, Flags);
- Result := DXResult=DS_OK;
- end;
-
- function TDirectSoundBuffer.Restore: Boolean;
- begin
- DXResult := IBuffer.Restore;
- Result := DXResult=DS_OK;
- end;
-
- function TDirectSoundBuffer.SetFormat(const Format: TWaveFormatEx): Boolean;
- begin
- DXResult := IBuffer.SetFormat(Format);
- Result := DXResult=DS_OK;
- end;
-
- procedure TDirectSoundBuffer.SetFrequency(Value: Integer);
- begin
- DXResult := IBuffer.SetFrequency(Value);
- end;
-
- procedure TDirectSoundBuffer.SetIDSBuffer(Value: IDirectSoundBuffer);
- begin
- FIDSBuffer := Value;
- end;
-
- procedure TDirectSoundBuffer.SetPan(Value: Integer);
- begin
- DXResult := IBuffer.SetPan(Value);
- end;
-
- procedure TDirectSoundBuffer.SetPosition(Value: Longint);
- begin
- DXResult := IBuffer.SetCurrentPosition(Value);
- end;
-
- procedure TDirectSoundBuffer.SetSize(const Format: TWaveFormatEx; Size: Integer);
- var
- BufferDesc: DSBUFFERDESC ;
- begin
- { IDirectSoundBuffer made. }
- FillChar(BufferDesc, SizeOf(BufferDesc), 0);
-
- with BufferDesc do
- begin
- dwSize := SizeOf(DSBUFFERDESC);
- dwFlags := DSBCAPS_CTRLDEFAULT;
- if DSound.FStickyFocus then
- dwFlags := dwFlags or DSBCAPS_STICKYFOCUS
- else if DSound.FGlobalFocus then
- dwFlags := dwFlags or DSBCAPS_GLOBALFOCUS;
- dwBufferBytes := Size;
- lpwfxFormat := @Format;
- end;
-
- if not CreateBuffer(BufferDesc) then
- raise EDirectSoundBufferError.CreateFmt(SCannotMade, [SDirectSoundBuffer]);
- end;
-
- procedure TDirectSoundBuffer.SetVolume(Value: Integer);
- begin
- DXResult := IBuffer.SetVolume(Value);
- end;
-
- function TDirectSoundBuffer.Stop: Boolean;
- begin
- DXResult := IBuffer.Stop;
- Result := DXResult=DS_OK;
- end;
-
- function TDirectSoundBuffer.Unlock(lpvAudioPtr1: Pointer; dwAudioBytes1: Longint;
- lpvAudioPtr2: Pointer; dwAudioBytes2: Longint): Boolean;
- begin
- DXResult := IBuffer.Unlock(lpvAudioPtr1, dwAudioBytes1,
- lpvAudioPtr2, dwAudioBytes2);
- Result := DXResult=DS_OK;
- end;
-
- { TAudioStream }
-
- type
- TAudioStreamNotify = class(TThread)
- private
- FAudio: TAudioStream;
- FSleepTime: Integer;
- FStopOnTerminate: Boolean;
- constructor Create(Audio: TAudioStream);
- destructor Destroy; override;
- procedure Execute; override;
- procedure Update;
- procedure ThreadTerminate(Sender: TObject);
- end;
-
- constructor TAudioStreamNotify.Create(Audio: TAudioStream);
- begin
- FAudio := Audio;
-
- OnTerminate := ThreadTerminate;
-
- FAudio.FNotifyEvent := CreateEvent(nil, False, False, nil);
- FAudio.FNotifyThread := Self;
-
- FSleepTime := Min(FAudio.FBufferLength div 4, 1000 div 20);
- FStopOnTerminate := True;
-
- FreeOnTerminate := True;
- inherited Create(False);
- end;
-
- destructor TAudioStreamNotify.Destroy;
- begin
- FreeOnTerminate := False;
- SetEvent(FAudio.FNotifyEvent);
- inherited Destroy;
- CloseHandle(FAudio.FNotifyEvent);
- end;
-
- procedure TAudioStreamNotify.ThreadTerminate(Sender: TObject);
- begin
- FAudio.FNotifyThread := nil;
- if FStopOnTerminate then FAudio.Stop;
- end;
-
- procedure TAudioStreamNotify.Execute;
- begin
- while WaitForSingleObject(FAudio.FNotifyEvent, FSleepTime)=WAIT_TIMEOUT do
- begin
- Synchronize(Update);
- end;
- end;
-
- procedure TAudioStreamNotify.Update;
- begin
- try
- FAudio.FInThread := True;
- try
- FAudio.Update;
- finally
- FAudio.FInThread := False;
- end;
- except
- on E: Exception do
- begin
- Application.HandleException(E);
- SetEvent(FAudio.FNotifyEvent);
- end;
- end;
- end;
-
- constructor TAudioStream.Create(ADSound: TDirectSound);
- begin
- inherited Create;
- FDSound := ADSound;
- FAutoUpdate := True;
- FBuffer := TDirectSoundBuffer.Create(FDSound);
- FBufferLength := 1000;
- end;
-
- destructor TAudioStream.Destroy;
- begin
- Stop;
- WaveStream := nil;
- FBuffer.Free;
- inherited Destroy;
- end;
-
- function TAudioStream.GetFormat: PWaveFormatEX;
- begin
- if WaveStream=nil then
- raise EAudioStreamError.Create(SWaveStreamNotSet);
- Result := WaveStream.Format;
- end;
-
- function TAudioStream.GetFormatSize: Integer;
- begin
- if WaveStream=nil then
- raise EAudioStreamError.Create(SWaveStreamNotSet);
- Result := WaveStream.FormatSize;
- end;
-
- function TAudioStream.GetFrequency: Integer;
- begin
- Result := FBuffer.Frequency;
- end;
-
- function TAudioStream.GetPan: Integer;
- begin
- Result := FBuffer.Pan;
- end;
-
- function TAudioStream.GetPlayedSize: Integer;
- begin
- if Playing then UpdatePlayedSize;
- Result := FPlayedSize;
- end;
-
- function TAudioStream.GetSize: Integer;
- begin
- if WaveStream<>nil then
- Result := WaveStream.Size
- else
- Result := 0;
- end;
-
- function TAudioStream.GetVolume: Integer;
- begin
- Result := FBuffer.Volume;
- end;
-
- procedure TAudioStream.UpdatePlayedSize;
- var
- PlayPosition, PlayedSize: DWORD;
- begin
- PlayPosition := FBuffer.Position;
-
- if FPlayBufferPos <= PlayPosition then
- begin
- PlayedSize := PlayPosition - FPlayBufferPos
- end else
- begin
- PlayedSize := PlayPosition + (FBufferSize - FPlayBufferPos);
- end;
-
- Inc(FPlayedSize, PlayedSize);
-
- FPlayBufferPos := PlayPosition;
- end;
-
- function TAudioStream.GetWriteSize: Integer;
- var
- PlayPosition: DWORD;
- i: Integer;
- begin
- PlayPosition := FBuffer.Position;
-
- if FBufferPos <= PlayPosition then
- begin
- Result := PlayPosition - FBufferPos
- end else
- begin
- Result := PlayPosition + (FBufferSize - FBufferPos);
- end;
-
- i := WaveStream.FilledSize;
- if i>=0 then Result := Min(Result, i);
- end;
-
- procedure TAudioStream.Play;
- begin
- if not FPlaying then
- begin
- if WaveStream=nil then
- raise EAudioStreamError.Create(SWaveStreamNotSet);
-
- if Size=0 then Exit;
-
- FPlaying := True;
- try
- SetPosition(FPosition);
- if FAutoUpdate then
- FNotifyThread := TAudioStreamNotify.Create(Self);
- except
- Stop;
- raise;
- end;
- end;
- end;
-
- procedure TAudioStream.RecreateBuf;
- var
- APlaying: Boolean;
- APosition: Integer;
- AFrequency: Integer;
- APan: Integer;
- AVolume: Integer;
- begin
- APlaying := Playing;
-
- APosition := Position;
- AFrequency := Frequency;
- APan := Pan;
- AVolume := Volume;
-
- WaveStream := WaveStream;
-
- Position := APosition;
- Frequency := AFrequency;
- Pan := APan;
- Volume := AVolume;
-
- if APlaying then Play;
- end;
-
- procedure TAudioStream.SetAutoUpdate(Value: Boolean);
- begin
- if FAutoUpdate<>Value then
- begin
- FAutoUpdate := Value;
- if FPlaying then
- begin
- if FNotifyThread<>nil then
- begin
- (FNotifyThread as TAudioStreamNotify).FStopOnTerminate := False;
- FNotifyThread.Free;
- end;
-
- if FAutoUpdate then
- FNotifyThread := TAudioStreamNotify.Create(Self);
- end;
- end;
- end;
-
- procedure TAudioStream.SetBufferLength(Value: Integer);
- begin
- if Value<10 then Value := 10;
- if FBufferLength<>Value then
- begin
- FBufferLength := Value;
- if WaveStream<>nil then RecreateBuf;
- end;
- end;
-
- procedure TAudioStream.SetFrequency(Value: Integer);
- begin
- FBuffer.Frequency := Value;
- end;
-
- procedure TAudioStream.SetLooped(Value: Boolean);
- begin
- if FLooped<>Value then
- begin
- FLooped := Value;
- Position := Position;
- end;
- end;
-
- procedure TAudioStream.SetPan(Value: Integer);
- begin
- FBuffer.Pan := Value;
- end;
-
- procedure TAudioStream.SetPlayedSize(Value: Integer);
- begin
- if Playing then UpdatePlayedSize;
- FPlayedSize := Value;
- end;
-
- procedure TAudioStream.SetPosition(Value: Integer);
- begin
- if WaveStream=nil then
- raise EAudioStreamError.Create(SWaveStreamNotSet);
-
- Value := Max(Min(Value, Size-1), 0);
- Value := Value div Format^.nBlockAlign * Format^.nBlockAlign;
-
- FPosition := Value;
-
- if Playing then
- begin
- try
- FBuffer.Stop;
-
- FBufferPos := 0;
- FPlayBufferPos := 0;
- FWritePosition := Value;
-
- WriteWave(FBufferSize);
-
- FBuffer.Position := 0;
- FBuffer.Play(DSBPLAY_LOOPING);
- except
- Stop;
- raise;
- end;
- end;
- end;
-
- procedure TAudioStream.SetVolume(Value: Integer);
- begin
- FBuffer.Volume := Value;
- end;
-
- procedure TAudioStream.SetWaveStream(Value: TCustomWaveStream);
- var
- BufferDesc: DSBUFFERDESC;
- begin
- Stop;
-
- FWaveStream := nil;
- FBufferPos := 0;
- FPosition := 0;
- FWritePosition := 0;
-
- if (Value<>nil) and (FBufferLength>0) then
- begin
- FBufferSize := FBufferLength * Integer(Value.Format^.nAvgBytesPerSec) div 1000;
-
- FillChar(BufferDesc, SizeOf(BufferDesc), 0);
- with BufferDesc do
- begin
- dwSize := SizeOf(DSBUFFERDESC);
- dwFlags := DSBCAPS_CTRLDEFAULT or DSBCAPS_GETCURRENTPOSITION2;
- if FDSound.FStickyFocus then
- dwFlags := dwFlags or DSBCAPS_STICKYFOCUS
- else if FDSound.FGlobalFocus then
- dwFlags := dwFlags or DSBCAPS_GLOBALFOCUS;
- dwBufferBytes := FBufferSize;
- lpwfxFormat := Value.Format;
- end;
-
- if not FBuffer.CreateBuffer(BufferDesc) then
- raise EDirectSoundBufferError.CreateFmt(SCannotMade, [SDirectSoundBuffer]);
- end else
- begin
- FBuffer.IDSBuffer := nil;
- FBufferSize := 0;
- end;
-
- FWaveStream := Value;
- end;
-
- procedure TAudioStream.Stop;
- begin
- if FPlaying then
- begin
- if FInThread then
- begin
- SetEvent(FNotifyEvent);
- end else
- begin
- FPlaying := False;
- FBuffer.Stop;
- FNotifyThread.Free;
- end;
- end;
- end;
-
- procedure TAudioStream.Update;
- var
- WriteSize: Integer;
- begin
- if not FPlaying then Exit;
-
- try
- UpdatePlayedSize;
-
- if Size<0 then
- begin
- WriteSize := GetWriteSize;
- if WriteSize>0 then
- begin
- WriteSize := WriteWave(WriteSize);
- FPosition := FPosition + WriteSize;
- end;
- end else
- begin
- if FLooped then
- begin
- WriteSize := GetWriteSize;
- if WriteSize>0 then
- begin
- WriteWave(WriteSize);
- FPosition := (FPosition + WriteSize) mod Size;
- end;
- end else
- begin
- if FPosition<Size then
- begin
- WriteSize := GetWriteSize;
- if WriteSize>0 then
- begin
- WriteWave(WriteSize);
- FPosition := FPosition + WriteSize;
- if FPosition>Size then FPosition := Size;
- end;
- end else
- Stop;
- end;
- end;
- except
- Stop;
- raise;
- end;
- end;
-
- function TAudioStream.WriteWave(WriteSize: Integer): Integer;
-
- procedure WriteData(Size: Integer);
- var
- Data1, Data2: Pointer;
- Data1Size, Data2Size: Longint;
- begin
- if FBuffer.Lock(FBufferPos, Size, Data1, Data1Size, Data2, Data2Size, 0) then
- begin
- try
- FWaveStream.Position := FWritePosition;
- FWaveStream.ReadBuffer(Data1^, Data1Size);
- FWritePosition := FWritePosition + Data1Size;
-
- if Data2<>nil then
- begin
- FWaveStream.ReadBuffer(Data2^, Data2Size);
- FWritePosition := FWritePosition + Data2Size;
- end;
-
- FBufferPos := (FBufferPos + DWORD(Data1Size) + DWORD(Data2Size)) mod FBufferSize;
- finally
- FBuffer.UnLock(Data1, Data1Size, Data2, Data2Size);
- end;
- end;
- end;
-
- procedure WriteData2(Size: Integer);
- var
- Data1, Data2: Pointer;
- Data1Size, Data2Size, s1, s2: Longint;
- begin
- if FBuffer.Lock(FBufferPos, Size, Data1, Data1Size, Data2, Data2Size, 0) then
- begin
- try
- FWaveStream.Position := FWritePosition;
- s1 := FWaveStream.Read(Data1^, Data1Size);
- FWritePosition := FWritePosition + s1;
- FBufferPos := (FBufferPos + DWORD(s1)) mod FBufferSize;
- Inc(Result, s1);
-
- if (Data2<>nil) and (s1=Data1Size) then
- begin
- s2 := FWaveStream.Read(Data2^, Data2Size);
- FWritePosition := FWritePosition + s2;
- FBufferPos := (FBufferPos + DWORD(s2)) mod FBufferSize;
- Inc(Result, s2);
- end;
- finally
- FBuffer.UnLock(Data1, Data1Size, Data2, Data2Size);
- end;
- end;
- end;
-
- procedure WriteSilence(Size: Integer);
- var
- C: Byte;
- Data1, Data2: Pointer;
- Data1Size, Data2Size: Longint;
- begin
- if Format^.wBitsPerSample=8 then C := $80 else C := 0;
-
- if FBuffer.Lock(FBufferPos, Size, Data1, Data1Size, Data2, Data2Size, 0) then
- begin
- FillChar(Data1^, Data1Size, C);
-
- if Data2<>nil then
- FillChar(Data2^, Data2Size, C);
-
- FBuffer.UnLock(Data1, Data1Size, Data2, Data2Size);
-
- FBufferPos := (FBufferPos + DWORD(Data1Size) + DWORD(Data2Size)) mod FBufferSize;
- FWritePosition := FWritePosition + Data1Size + Data2Size;
- end;
- end;
-
- var
- DataSize: Integer;
- begin
- if Size>=0 then
- begin
- Result := WriteSize;
- if FLooped then
- begin
- while WriteSize>0 do
- begin
- DataSize := Min(Size-FWritePosition, WriteSize);
-
- WriteData(DataSize);
- FWritePosition := FWritePosition mod Size;
-
- Dec(WriteSize, DataSize);
- end;
- end else
- begin
- DataSize := Size-FWritePosition;
-
- if DataSize<=0 then
- begin
- WriteSilence(WriteSize);
- end else
- if DataSize>=WriteSize then
- begin
- WriteData(WriteSize);
- end else
- begin
- WriteData(DataSize);
- WriteSilence(WriteSize-DataSize);
- end;
- end;
- end else
- begin
- Result := 0;
- WriteData2(WriteSize);
- end;
- end;
-
- { TAudioFileStream }
-
- destructor TAudioFileStream.Destroy;
- begin
- inherited Destroy;
- FWaveFileStream.Free;
- end;
-
- procedure TAudioFileStream.SetFileName(const Value: string);
- begin
- if FFileName=Value then Exit;
-
- FFileName := Value;
-
- if FWaveFileStream<>nil then
- begin
- WaveStream := nil;
- FWaveFileStream.Free;
- FWaveFileStream := nil;
- end;
-
- if Value<>'' then
- begin
- try
- FWaveFileStream := TWaveFileStream.Create(Value, fmOpenRead or fmShareDenyWrite);
- FWaveFileStream.Open(False);
- WaveStream := FWaveFileStream;
- except
- WaveStream := nil;
- FFileName := '';
- raise;
- end;
- end;
- end;
-
- { TSoundCaptureFormats }
-
- constructor TSoundCaptureFormats.Create;
- begin
- inherited Create(TSoundCaptureFormat);
- end;
-
- function TSoundCaptureFormats.GetItem(Index: Integer): TSoundCaptureFormat;
- begin
- Result := TSoundCaptureFormat(inherited Items[Index]);
- end;
-
- function TSoundCaptureFormats.IndexOf(ASamplesPerSec, ABitsPerSample, AChannels: Integer): Integer;
- var
- i: Integer;
- begin
- Result := -1;
- for i:=0 to Count-1 do
- with Items[i] do
- if (FSamplesPerSec=ASamplesPerSec) and (FBitsPerSample=ABitsPerSample) and (FChannels=AChannels) then
- begin
- Result := i;
- Break;
- end;
- end;
-
- { TSoundCaptureStream }
-
- type
- TSoundCaptureStreamNotify = class(TThread)
- private
- FCapture: TSoundCaptureStream;
- FSleepTime: Integer;
- constructor Create(Capture: TSoundCaptureStream);
- destructor Destroy; override;
- procedure Execute; override;
- procedure Update;
- end;
-
- constructor TSoundCaptureStreamNotify.Create(Capture: TSoundCaptureStream);
- begin
- FCapture := Capture;
-
- FCapture.FNotifyEvent := CreateEvent(nil, False, False, nil);
- FSleepTime := Min(FCapture.FBufferLength div 4, 1000 div 20);
-
- FreeOnTerminate := True;
- inherited Create(True);
- end;
-
- destructor TSoundCaptureStreamNotify.Destroy;
- begin
- FreeOnTerminate := False;
- SetEvent(FCapture.FNotifyEvent);
-
- inherited Destroy;
-
- CloseHandle(FCapture.FNotifyEvent);
- FCapture.FNotifyThread := nil;
-
- if Assigned(FCapture.FOnFilledBuffer) then FCapture.Stop;
- end;
-
- procedure TSoundCaptureStreamNotify.Execute;
- begin
- while WaitForSingleObject(FCapture.FNotifyEvent, FSleepTime)=WAIT_TIMEOUT do
- begin
- Synchronize(Update);
- end;
- end;
-
- procedure TSoundCaptureStreamNotify.Update;
- begin
- if FCapture.FilledSize>0 then
- begin
- try
- FCapture.DoFilledBuffer;
- except
- on E: Exception do
- begin
- Application.HandleException(E);
- SetEvent(FCapture.FNotifyEvent);
- end;
- end;
- end;
- end;
-
- constructor TSoundCaptureStream.Create(GUID: PGUID);
- const
- SamplesPerSecList: array[0..6] of Integer = (8000, 11025, 22050, 33075, 44100, 48000, 96000);
- BitsPerSampleList: array[0..3] of Integer = (8, 16, 24, 32);
- ChannelsList: array[0..1] of Integer = (1, 2);
- var
- ASamplesPerSec, ABitsPerSample, AChannels: Integer;
- dscbd: DSCBUFFERDESC;
- TempBuffer: IDirectSoundCaptureBuffer;
- Format: TWaveFormatEx;
- begin
- inherited Create;
- FBufferLength := 1000;
- FSupportedFormats := TSoundCaptureFormats.Create;
-
- if DXDirectSoundCaptureCreate(GUID, FCapture, nil)<>DS_OK then
- raise ESoundCaptureStreamError.CreateFmt(SCannotInitialized, [SDirectSoundCapture]);
-
- { The supported format list is acquired. }
- for ASamplesPerSec:=Low(SamplesPerSecList) to High(SamplesPerSecList) do
- for ABitsPerSample:=Low(BitsPerSampleList) to High(BitsPerSampleList) do
- for AChannels:=Low(ChannelsList) to High(ChannelsList) do
- begin
- { Test }
- MakePCMWaveFormatEx(Format, SamplesPerSecList[ASamplesPerSec], BitsPerSampleList[ABitsPerSample], ChannelsList[AChannels]);
-
- FillChar(dscbd, SizeOf(dscbd), 0);
- dscbd.dwSize := SizeOf(dscbd);
- dscbd.dwBufferBytes := Format.nAvgBytesPerSec;
- dscbd.lpwfxFormat := @Format;
-
- { If the buffer can be made, the format of present can be used. }
- if FCapture.CreateCaptureBuffer(dscbd, TempBuffer, nil)=DS_OK then
- begin
- TempBuffer := nil;
- with TSoundCaptureFormat.Create(FSupportedFormats) do
- begin
- FSamplesPerSec := Format.nSamplesPerSec;
- FBitsPerSample := Format.wBitsPerSample;
- FChannels := Format.nChannels;
- end;
- end;
- end;
- end;
-
- destructor TSoundCaptureStream.Destroy;
- begin
- Stop;
- FSupportedFormats.Free;
- inherited Destroy;
- end;
-
- procedure TSoundCaptureStream.DoFilledBuffer;
- begin
- if Assigned(FOnFilledBuffer) then FOnFilledBuffer(Self);
- end;
-
- class function TSoundCaptureStream.Drivers: TDirectXDrivers;
- begin
- Result := EnumDirectSoundCaptureDrivers;
- end;
-
- function TSoundCaptureStream.GetFilledSize: Integer;
- begin
- Result := GetReadSize;
- end;
-
- function TSoundCaptureStream.GetReadSize: Integer;
- var
- CapturePosition, ReadPosition: DWORD;
- begin
- if FBuffer.GetCurrentPosition(CapturePosition, ReadPosition)=DS_OK then
- begin
- if FBufferPos<=ReadPosition then
- Result := ReadPosition - FBufferPos
- else
- Result := FBufferSize - FBufferPos + ReadPosition;
- end else
- Result := 0;
- end;
-
- function TSoundCaptureStream.ReadWave(var Buffer; Count: Integer): Integer;
- var
- Size: Integer;
- Data1, Data2: Pointer;
- Data1Size, Data2Size: DWORD;
- C: Byte;
- begin
- if not FCapturing then
- Start;
-
- Result := 0;
- while Result<Count do
- begin
- Size := Min(Count-Result, GetReadSize);
- if Size>0 then
- begin
- if FBuffer.Lock(FBufferPos, Size, Data1, Data1Size, Data2, Data2Size, 0)=DS_OK then
- begin
- Move(Data1^, Pointer(Integer(@Buffer)+Result)^, Data1Size);
- Result := Result + Integer(Data1Size);
-
- if Data2<>nil then
- begin
- Move(Data2^, Pointer(Integer(@Buffer)+Result)^, Data2Size);
- Result := Result + Integer(Data1Size);
- end;
-
- FBuffer.UnLock(Data1, Data1Size, Data2, Data2Size);
- FBufferPos := (FBufferPos + Data1Size + Data2Size) mod FBufferSize;
- end else
- Break;
- end;
- if Result<Count then Sleep(50);
- end;
-
- case Format^.wBitsPerSample of
- 8: C := $80;
- 16: C := $00;
- else
- C := $00;
- end;
-
- FillChar(Pointer(Integer(@Buffer)+Result)^, Count-Result, C);
- Result := Count;
- end;
-
- procedure TSoundCaptureStream.SetBufferLength(Value: Integer);
- begin
- FBufferLength := Max(Value, 0);
- end;
-
- procedure TSoundCaptureStream.SetOnFilledBuffer(Value: TNotifyEvent);
- begin
- if CompareMem(@TMethod(FOnFilledBuffer), @TMethod(Value), SizeOf(TMethod)) then Exit;
-
- if FCapturing then
- begin
- if Assigned(FOnFilledBuffer) then
- FNotifyThread.Free;
-
- FOnFilledBuffer := Value;
-
- if Assigned(FOnFilledBuffer) then
- begin
- FNotifyThread := TSoundCaptureStreamNotify.Create(Self);
- FNotifyThread.Resume;
- end;
- end else
- FOnFilledBuffer := Value;
- end;
-
- procedure TSoundCaptureStream.Start;
- var
- dscbd: DSCBUFFERDESC;
- begin
- Stop;
- try
- FCapturing := True;
-
- FormatSize := SizeOf(TWaveFormatEx);
- with FSupportedFormats[CaptureFormat] do
- MakePCMWaveFormatEx(Format^, SamplesPerSec, BitsPerSample, Channels);
-
- FBufferSize := Max(MulDiv(Format^.nAvgBytesPerSec, FBufferLength, 1000), 8000);
-
- FillChar(dscbd, SizeOf(dscbd), 0);
- dscbd.dwSize := SizeOf(dscbd);
- dscbd.dwBufferBytes := FBufferSize;
- dscbd.lpwfxFormat := Format;
-
- if FCapture.CreateCaptureBuffer(dscbd, FBuffer, nil)<>DS_OK then
- raise ESoundCaptureStreamError.CreateFmt(SCannotMade, [SDirectSoundCaptureBuffer]);
-
- FBufferPos := 0;
-
- FBuffer.Start(DSCBSTART_LOOPING);
-
- if Assigned(FOnFilledBuffer) then
- begin
- FNotifyThread := TSoundCaptureStreamNotify.Create(Self);
- FNotifyThread.Resume;
- end;
- except
- Stop;
- raise;
- end;
- end;
-
- procedure TSoundCaptureStream.Stop;
- begin
- if FCapturing then
- begin
- FNotifyThread.Free;
- FCapturing := False;
- if FBuffer<>nil then
- FBuffer.Stop;
- FBuffer := nil;
- end;
- end;
-
- { TSoundEngine }
-
- constructor TSoundEngine.Create(ADSound: TDirectSound);
- begin
- inherited Create;
- FDSound := ADSound;
- FEnabled := True;
-
-
- FEffectList := TList.Create;
- FTimer := TTimer.Create(nil);
- FTimer.Interval := 500;
- FTimer.OnTimer := TimerEvent;
- end;
-
- destructor TSoundEngine.Destroy;
- begin
- Clear;
- FTimer.Free;
- FEffectList.Free;
- inherited Destroy;
- end;
-
- procedure TSoundEngine.Clear;
- var
- i: Integer;
- begin
- for i:=EffectCount-1 downto 0 do
- Effects[i].Free;
- FEffectList.Clear;
- end;
-
- procedure TSoundEngine.EffectFile(const Filename: string; Loop, Wait: Boolean);
- var
- Stream : TFileStream;
- begin
- Stream :=TFileStream.Create(Filename, fmOpenRead);
- try
- EffectStream(Stream, Loop, Wait);
- finally
- Stream.Free;
- end;
- end;
-
- procedure TSoundEngine.EffectStream(Stream: TStream; Loop, Wait: Boolean);
- var
- Wave: TWave;
- begin
- Wave := TWave.Create;
- try
- Wave.LoadfromStream(Stream);
- EffectWave(Wave, Loop, Wait);
- finally
- Wave.Free;
- end;
- end;
-
- procedure TSoundEngine.EffectWave(Wave: TWave; Loop, Wait: Boolean);
- var
- Buffer: TDirectSoundBuffer;
- begin
- if not FEnabled then Exit;
-
- if Wait then
- begin
- Buffer := TDirectSoundBuffer.Create(FDSound);
- try
- Buffer.LoadFromWave(Wave);
- Buffer.Play(0);
- while Buffer.Status and DSBSTATUS_PLAYING<>0 do
- Sleep(1);
- finally
- Buffer.Free;
- end;
- end else
- begin
- Buffer := TDirectSoundBuffer.Create(FDSound);
- try
- Buffer.LoadFromWave(Wave);
- if Loop then
- Buffer.Play(DSBPLAY_LOOPING)
- else
- Buffer.Play(0);
- except
- Buffer.Free;
- raise;
- end;
- FEffectList.Add(Buffer);
- end;
- end;
-
- function TSoundEngine.GetEffect(Index: Integer): TDirectSoundBuffer;
- begin
- Result := TDirectSoundBuffer(FEffectList[Index]);
- end;
-
- function TSoundEngine.GetEffectCount: Integer;
- begin
- Result := FEffectList.Count;
- end;
-
- procedure TSoundEngine.SetEnabled(Value: Boolean);
- var
- i: Integer;
- begin
- for i:=EffectCount-1 downto 0 do
- Effects[i].Free;
- FEffectList.Clear;
-
- FEnabled := Value;
- FTimer.Enabled := Value;
- end;
-
- procedure TSoundEngine.TimerEvent(Sender: TObject);
- var
- i: Integer;
- begin
- for i:=EffectCount-1 downto 0 do
- if not TDirectSoundBuffer(FEffectList[i]).Playing then
- begin
- TDirectSoundBuffer(FEffectList[i]).Free;
- FEffectList.Delete(i);
- end;
- end;
-
- { TCustomDXSound }
-
- type
- TDXSoundDirectSound = class(TDirectSound)
- private
- FDXSound: TCustomDXSound;
- protected
- procedure DoRestoreBuffer; override;
- end;
-
- procedure TDXSoundDirectSound.DoRestoreBuffer;
- begin
- inherited DoRestoreBuffer;
- FDXSound.Restore;
- end;
-
- constructor TCustomDXSound.Create(AOwner: TComponent);
- begin
- FNotifyEventList := TList.Create;
- inherited Create(AOwner);
- FAutoInitialize := True;
- Options := [];
- end;
-
- destructor TCustomDXSound.Destroy;
- begin
- Finalize;
- NotifyEventList(dsntDestroying);
- FNotifyEventList.Free;
- inherited Destroy;
- end;
-
- type
- PDXSoundNotifyEvent = ^TDXSoundNotifyEvent;
-
- procedure TCustomDXSound.RegisterNotifyEvent(NotifyEvent: TDXSoundNotifyEvent);
- var
- Event: PDXSoundNotifyEvent;
- begin
- UnRegisterNotifyEvent(NotifyEvent);
-
- New(Event);
- Event^ := NotifyEvent;
- FNotifyEventList.Add(Event);
-
- if Initialized then
- begin
- NotifyEvent(Self, dsntInitialize);
- NotifyEvent(Self, dsntRestore);
- end;
- end;
-
- procedure TCustomDXSound.UnRegisterNotifyEvent(NotifyEvent: TDXSoundNotifyEvent);
- var
- Event: PDXSoundNotifyEvent;
- i: Integer;
- begin
- for i:=0 to FNotifyEventList.Count-1 do
- begin
- Event := FNotifyEventList[i];
- if (TMethod(Event^).Code = TMethod(NotifyEvent).Code) and
- (TMethod(Event^).Data = TMethod(NotifyEvent).Data) then
- begin
- Dispose(Event);
- FNotifyEventList.Delete(i);
-
- if Initialized then
- NotifyEvent(Self, dsntFinalize);
-
- Break;
- end;
- end;
- end;
-
- procedure TCustomDXSound.NotifyEventList(NotifyType: TDXSoundNotifyType);
- var
- i: Integer;
- begin
- for i:=FNotifyEventList.Count-1 downto 0 do
- PDXSoundNotifyEvent(FNotifyEventList[i])^(Self, NotifyType);
- end;
-
- procedure TCustomDXSound.FormWndProc(var Message: TMessage; DefWindowProc: TWndMethod);
- begin
- case Message.Msg of
- WM_CREATE:
- begin
- DefWindowProc(Message);
- SetForm(FForm);
- Exit;
- end;
- end;
- DefWindowProc(Message);
- end;
-
- class function TCustomDXSound.Drivers: TDirectXDrivers;
- begin
- Result := EnumDirectSoundDrivers;
- end;
-
- procedure TCustomDXSound.DoFinalize;
- begin
- if Assigned(FOnFinalize) then FOnFinalize(Self);
- end;
-
- procedure TCustomDXSound.DoInitialize;
- begin
- if Assigned(FOnInitialize) then FOnInitialize(Self);
- end;
-
- procedure TCustomDXSound.DoInitializing;
- begin
- if Assigned(FOnInitializing) then FOnInitializing(Self);
- end;
-
- procedure TCustomDXSound.DoRestore;
- begin
- if Assigned(FOnRestore) then FOnRestore(Self);
- end;
-
- procedure TCustomDXSound.Finalize;
- begin
- if FInternalInitialized then
- begin
- try
- FSubClass.Free; FSubClass := nil;
-
- try
- if FCalledDoInitialize then
- begin
- FCalledDoInitialize := False;
- DoFinalize;
- end;
- finally
- NotifyEventList(dsntFinalize);
- end;
- finally
- FInitialized := False;
- FInternalInitialized := False;
-
- SetOptions(FOptions);
-
- FPrimary.Free; FPrimary := nil;
- FDSound.Free; FDSound := nil;
- end;
- end;
- end;
-
- procedure TCustomDXSound.Initialize;
- const
- PrimaryDesc: DSBUFFERDESC = (
- dwSize: SizeOf (PrimaryDesc);
- dwFlags: DSBCAPS_PRIMARYBUFFER);
- var
- Component: TComponent;
- begin
- Finalize;
-
- Component := Owner;
- while (Component<>nil) and (not (Component is TCustomForm)) do
- Component := Component.Owner;
- if Component=nil then
- raise EDXSoundError.Create(SNoForm);
-
- NotifyEventList(dsntInitializing);
- DoInitializing;
-
- FInternalInitialized := True;
- try
- { DirectSound initialization. }
- FDSound := TDXSoundDirectSound.Create(Driver);
- TDXSoundDirectSound(FDSound).FDXSound := Self;
-
- FDSound.GlobalFocus := soGlobalFocus in FNowOptions;
-
- { Primary buffer made. }
- FPrimary := TDirectSoundBuffer.Create(FDSound);
- if not FPrimary.CreateBuffer(PrimaryDesc) then
- raise EDXSoundError.CreateFmt(SCannotMade, [SDirectSoundPrimaryBuffer]);
-
- FInitialized := True;
-
- SetForm(TCustomForm(Component));
- except
- Finalize;
- raise;
- end;
-
- NotifyEventList(dsntInitialize);
-
- FCalledDoInitialize := True; DoInitialize;
-
- Restore;
- end;
-
- procedure TCustomDXSound.Loaded;
- begin
- inherited Loaded;
-
- if FAutoInitialize and (not (csDesigning in ComponentState)) then
- begin
- try
- Initialize;
- except
- end;
- end;
- end;
-
- procedure TCustomDXSound.Restore;
- begin
- if FInitialized then
- begin
- NotifyEventList(dsntRestore);
- DoRestore;
- end;
- end;
-
- procedure TCustomDXSound.SetDriver(Value: PGUID);
- begin
- if not IsBadHugeReadPtr(Value, SizeOf(TGUID)) then
- begin
- FDriverGUID := Value^;
- FDriver := @FDriverGUID;
- end else
- FDriver := Value;
- end;
-
- procedure TCustomDXSound.SetForm(Value: TCustomForm);
- var
- Level: Integer;
- begin
- FForm := Value;
-
- FSubClass.Free;
- FSubClass := TControlSubClass.Create(FForm, FormWndProc);
-
- if FInitialized then
- begin
- if soWritePrimary in FNowOptions then
- Level := DSSCL_WRITEPRIMARY
- else if soExclusive in FNowOptions then
- Level := DSSCL_EXCLUSIVE
- else
- Level := DSSCL_NORMAL;
-
- FDSound.DXResult := FDSound.ISound.SetCooperativeLevel(FForm.Handle, Level);
- end;
- end;
-
- procedure TCustomDXSound.SetOptions(Value: TDXSoundOptions);
- const
- DXSoundOptions = [soGlobalFocus, soStickyFocus, soExclusive, soWritePrimary];
- InitOptions: TDXSoundOptions = [soExclusive, soWritePrimary];
- var
- OldOptions: TDXSoundOptions;
- begin
- FOptions := Value;
-
- if Initialized then
- begin
- OldOptions := FNowOptions;
-
- FNowOptions := (FNowOptions - (DXSoundOptions - InitOptions)) +
- (Value - InitOptions);
-
- FDSound.GlobalFocus := soGlobalFocus in FNowOptions;
- FDSound.StickyFocus := soStickyFocus in FNowOptions;
- end else
- FNowOptions := FOptions;
- end;
-
- { TWaveCollectionItem }
-
- constructor TWaveCollectionItem.Create(Collection: TCollection);
- begin
- inherited Create(Collection);
- FWave := TWave.Create;
- end;
-
- destructor TWaveCollectionItem.Destroy;
- begin
- Finalize;
- FWave.Free;
- inherited Destroy;
- end;
-
- function TWaveCollectionItem.GetBuffer: TDirectSoundBuffer;
- begin
- if (WaveCollection.DXSound.Initialized) and (FBuffer=nil) then
- Restore;
- Result := FBuffer;
- end;
-
- function TWaveCollectionItem.GetWaveCollection: TWaveCollection;
- begin
- Result := Collection as TWaveCollection;
- end;
-
- procedure TWaveCollectionItem.Finalize;
- begin
- if FInitialized then
- begin
- FInitialized := False;
- FBuffer.Free; FBuffer := nil;
- end;
- end;
-
- procedure TWaveCollectionItem.Initialize;
- begin
- Finalize;
- if not WaveCollection.Initialized then
- raise EWaveCollectionError.CreateFmt(SCannotInitialized, [ClassName]);
- FInitialized := True;
- FBuffer := TDirectSoundBuffer.Create(WaveCollection.DXSound.DSound);
- end;
-
- function TWaveCollectionItem.CreateBuffer: TDirectSoundBuffer;
- begin
- if Buffer=nil then
- raise EWaveCollectionError.CreateFmt(SCannotInitialized, [ClassName]);
-
- Result := TDirectSoundBuffer.Create(WaveCollection.DXSound.DSound);
- try
- if Buffer.Status and DSBSTATUS_BUFFERLOST<>0 then
- Restore;
-
- Result.Assign(Buffer);
- except
- Result.Free;
- raise;
- end;
- end;
-
- procedure TWaveCollectionItem.Play(Wait: Boolean);
- var
- NewBuffer: TDirectSoundBuffer;
- begin
- if WaveCollection.Initialized then
- begin
- if FLooped then
- begin
- Buffer.Play(DSBPLAY_LOOPING);
- end else
- begin
- NewBuffer := CreateBuffer;
- try
- NewBuffer.Play(0);
- except
- NewBuffer.Free;
- raise;
- end;
- if Wait then
- begin
- try
- while NewBuffer.Playing do
- Sleep(10);
- finally
- NewBuffer.Free;
- end;
- end else
- WaveCollection.AddBuffer(NewBuffer);
- end;
- end;
- end;
-
- procedure TWaveCollectionItem.Restore;
- begin
- if WaveCollection.Initialized then
- begin
- if not FInitialized then
- Initialize;
- if FInitialized then
- begin
- FBuffer.LoadFromWave(FWave);
-
- FBuffer.Frequency := FFrequency;
- FBuffer.Pan := FPan;
- FBuffer.Volume := FVolume;
- end;
- end;
- end;
-
- procedure TWaveCollectionItem.Stop;
- begin
- if FInitialized then
- FBuffer.Stop;
- end;
-
- procedure TWaveCollectionItem.SetFrequency(Value: Integer);
- begin
- FFrequency := Value;
- if FInitialized then
- Buffer.Frequency := Value;
- end;
-
- procedure TWaveCollectionItem.SetLooped(Value: Boolean);
- begin
- if FLooped<>Value then
- begin
- Stop;
- FLooped := Value;
- end;
- end;
-
- procedure TWaveCollectionItem.SetPan(Value: Integer);
- begin
- FPan := Value;
- if FInitialized then
- Buffer.Pan := Value;
- end;
-
- procedure TWaveCollectionItem.SetVolume(Value: Integer);
- begin
- FVolume := Value;
- if FInitialized then
- Buffer.Volume := Value;
- end;
-
- procedure TWaveCollectionItem.SetWave(Value: TWave);
- begin
- FWave.Assign(Value);
- end;
-
- { TWaveCollection }
-
- constructor TWaveCollection.Create(AOwner: TPersistent);
- begin
- inherited Create(TWaveCollectionItem);
- FOwner := AOwner;
- FBufferList := TList.Create;
- end;
-
- destructor TWaveCollection.Destroy;
- begin
- ClearBuffers;
- FBufferList.Free;
- inherited Destroy;
- end;
-
- function TWaveCollection.GetItem(Index: Integer): TWaveCollectionItem;
- begin
- Result := TWaveCollectionItem(inherited Items[Index]);
- end;
-
- function TWaveCollection.GetOwner: TPersistent;
- begin
- Result := FOwner;
- end;
-
- function TWaveCollection.Find(const Name: string): TWaveCollectionItem;
- var
- i: Integer;
- begin
- i := IndexOf(Name);
- if i=-1 then
- raise EWaveCollectionError.CreateFmt(SWaveNotFound, [Name]);
- Result := Items[i];
- end;
-
- procedure TWaveCollection.Finalize;
- var
- i: Integer;
- begin
- FTimer.Free; FTimer := nil;
- ClearBuffers;
- for i:=0 to Count-1 do
- Items[i].Finalize;
- FDXSound := nil;
- end;
-
- procedure TWaveCollection.Initialize(DXSound: TCustomDXSound);
- var
- i: Integer;
- begin
- Finalize;
- FDXSound := DXSound;
- for i:=0 to Count-1 do
- Items[i].Initialize;
-
- FTimer := TTimer.Create(nil);
- FTimer.Enabled := True;
- FTimer.Interval := 500;
- FTimer.OnTimer := TimerEvent;
- end;
-
- function TWaveCollection.Initialized: Boolean;
- begin
- Result := (FDXSound<>nil) and (FDXSound.Initialized);
- end;
-
- procedure TWaveCollection.Restore;
- var
- i: Integer;
- begin
- for i:=0 to Count-1 do
- Items[i].Restore;
- end;
-
- procedure TWaveCollection.AddBuffer(Buffer: TDirectSoundBuffer);
- begin
- FBufferList.Add(Buffer);
- end;
-
- procedure TWaveCollection.ClearBuffers;
- var
- i: Integer;
- begin
- for i:=0 to BufferCount-1 do
- Buffers[i].Free;
- FBufferList.Clear;
- end;
-
- function TWaveCollection.GetBuffer(Index: Integer): TDirectSoundBuffer;
- begin
- Result := FBufferList[Index];
- end;
-
- function TWaveCollection.GetBufferCount: Integer;
- begin
- Result := FBufferList.Count;
- end;
-
- type
- TWaveCollectionComponent = class(TComponent)
- private
- FList: TWaveCollection;
- published
- property List: TWaveCollection read FList write FList;
- end;
-
- procedure TWaveCollection.LoadFromFile(const FileName: string);
- var
- Stream: TFileStream;
- begin
- Stream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
- try
- LoadFromStream(Stream);
- finally
- Stream.Free;
- end;
- end;
-
- procedure TWaveCollection.LoadFromStream(Stream: TStream);
- var
- Component: TWaveCollectionComponent;
- begin
- Clear;
- Component := TWaveCollectionComponent.Create(nil);
- try
- Component.FList := Self;
- Stream.ReadComponentRes(Component);
-
- if Initialized then
- begin
- Initialize(FDXSound);
- Restore;
- end;
- finally
- Component.Free;
- end;
- end;
-
- procedure TWaveCollection.SaveToFile(const FileName: string);
- var
- Stream: TFileStream;
- begin
- Stream := TFileStream.Create(FileName, fmCreate);
- try
- SaveToStream(Stream);
- finally
- Stream.Free;
- end;
- end;
-
- procedure TWaveCollection.SaveToStream(Stream: TStream);
- var
- Component: TWaveCollectionComponent;
- begin
- Component := TWaveCollectionComponent.Create(nil);
- try
- Component.FList := Self;
- Stream.WriteComponentRes('DelphiXWaveCollection', Component);
- finally
- Component.Free;
- end;
- end;
-
- procedure TWaveCollection.TimerEvent(Sender: TObject);
- var
- i: Integer;
- begin
- for i:=BufferCount-1 downto 0 do
- if not Buffers[i].Playing then
- begin
- Buffers[i].Free;
- FBufferList.Delete(i);
- end;
- end;
-
- { TCustomDXWaveList }
-
- constructor TCustomDXWaveList.Create(AOwner: TComponent);
- begin
- inherited Create(AOwner);
- FItems := TWaveCollection.Create(Self);
- end;
-
- destructor TCustomDXWaveList.Destroy;
- begin
- DXSound := nil;
- FItems.Free;
- inherited Destroy;
- end;
-
- procedure TCustomDXWaveList.Notification(AComponent: TComponent; Operation: TOperation);
- begin
- inherited Notification(AComponent, Operation);
- if (Operation=opRemove) and (DXSound=AComponent) then
- DXSound := nil;
- end;
-
- procedure TCustomDXWaveList.DXSoundNotifyEvent(Sender: TCustomDXSound;
- NotifyType: TDXSoundNotifyType);
- begin
- case NotifyType of
- dsntDestroying: DXSound := nil;
- dsntInitialize: FItems.Initialize(Sender);
- dsntFinalize : FItems.Finalize;
- dsntRestore : FItems.Restore;
- end;
- end;
-
- procedure TCustomDXWaveList.SetDXSound(Value: TCustomDXSound);
- begin
- if FDXSound<>nil then
- FDXSound.UnRegisterNotifyEvent(DXSoundNotifyEvent);
-
- FDXSound := Value;
-
- if FDXSound<>nil then
- FDXSound.RegisterNotifyEvent(DXSoundNotifyEvent);
- end;
-
- procedure TCustomDXWaveList.SetItems(Value: TWaveCollection);
- begin
- FItems.Assign(Value);
- end;
-
- initialization
- finalization
- DirectSoundDrivers.Free;
- DirectSoundCaptureDrivers.Free;
- end.
-