📄 dxsounds.pas
字号:
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: TDSBufferDesc): 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: TDSBufferDesc ;
begin
{ IDirectSoundBuffer made. }
FillChar(BufferDesc, SizeOf(BufferDesc), 0);
with BufferDesc do
begin
dwSize := SizeOf(TDSBufferDesc);
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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -