📄 dxsounds.pas
字号:
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);
begin
inherited Create;
FBufferList := TList.Create;
if DXDirectSoundCreate(GUID, FIDSound, nil)<>DS_OK then
raise EDirectSoundError.CreateFmt(SCannotInitialized, [SDirectSound]);
end;
destructor TDirectSound.Destroy;
begin
while BufferCount>0 do
Buffers[BufferCount-1].Free;
FBufferList.Free;
FIDSound := nil;
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(ADirectSound: TDirectSound);
begin
inherited Create;
FDSound := ADirectSound;
FDSound.FBufferList.Add(Self);
end;
destructor TDirectSoundBuffer.Destroy;
begin
IDSBuffer := nil;
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;
begin
Result := Format.wBitsPerSample;
end;
function TDirectSoundBuffer.GetFormat: PWaveFormatEx;
begin
GetIBuffer;
Result := FFormat;
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 := (GetStatus 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.GetSize: Integer;
begin
Result := FCaps.dwBufferBytes;
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) then
begin
try
Move(Data^, Data1^, Data1Size);
if Data2<>nil then
Move(Pointer(Longint(Data)+Data1Size)^, Data2^, Data2Size);
finally
UnLock;
end;
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(LockPosition, LockSize: Longint;
var AudioPtr1: Pointer; var AudioSize1: Longint;
var AudioPtr2: Pointer; var AudioSize2: Longint): Boolean;
begin
Result := False;
if IDSBuffer=nil then Exit;
if FLockCount>High(FLockAudioPtr1) then Exit;
DXResult := IBuffer.Lock(LockPosition, LockSize,
FLockAudioPtr1[FLockCount], FLockAudioSize1[FLockCount],
FLockAudioPtr2[FLockCount], FLockAudioSize2[FLockCount], 0);
Result := DXResult=DS_OK;
if Result then
begin
AudioPtr1 := FLockAudioPtr1[FLockCount];
AudioPtr2 := FLockAudioPtr2[FLockCount];
AudioSize1 := FLockAudioSize1[FLockCount];
AudioSize2 := FLockAudioSize2[FLockCount];
Inc(FLockCount);
end;
end;
function TDirectSoundBuffer.Play(Loop: Boolean): Boolean;
begin
if Loop then
DXResult := IBuffer.Play(0, 0, DSBPLAY_LOOPING)
else
DXResult := IBuffer.Play(0, 0, 0);
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;
if Result then
begin
FreeMem(FFormat);
FFormat := nil;
FFormatSize := 0;
if IBuffer.GetFormat(PWaveFormatEx(nil)^, 0, DWORD(FFormatSize))=DS_OK then
begin
GetMem(FFormat, FFormatSize);
IBuffer.GetFormat(FFormat^, FFormatSize, PDWORD(nil)^);
end;
end;
end;
procedure TDirectSoundBuffer.SetFrequency(Value: Integer);
begin
DXResult := IBuffer.SetFrequency(Value);
end;
procedure TDirectSoundBuffer.SetIDSBuffer(Value: IDirectSoundBuffer);
begin
if FIDSBuffer=Value then Exit;
FIDSBuffer := Value;
FillChar(FCaps, SizeOf(FCaps), 0);
FreeMem(FFormat);
FFormat := nil;
FFormatSize := 0;
FLockCount := 0;
if FIDSBuffer<>nil then
begin
FCaps.dwSize := SizeOf(FCaps);
IBuffer.GetCaps(FCaps);
if IBuffer.GetFormat(PWaveFormatEx(nil)^, 0, DWORD(FFormatSize))=DS_OK then
begin
GetMem(FFormat, FFormatSize);
IBuffer.GetFormat(FFormat^, FFormatSize, PDWORD(nil)^);
end;
end;
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;
procedure TDirectSoundBuffer.Stop;
begin
DXResult := IBuffer.Stop;
end;
procedure TDirectSoundBuffer.Unlock;
begin
if IDSBuffer=nil then Exit;
if FLockCount=0 then Exit;
Dec(FLockCount);
DXResult := IBuffer.UnLock(FLockAudioPtr1[FLockCount], FLockAudioSize1[FLockCount],
FLockAudioPtr2[FLockCount], FLockAudioSize2[FLockCount]);
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);
FAudio.FNotifyThread := nil;
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
Synchronize(Update);
end;
procedure TAudioStreamNotify.Update;
begin
if not FAudio.Playing then
begin
SetEvent(FAudio.FNotifyEvent);
EXit;
end;
try
FAudio.Update2(True);
except
on E: Exception do
begin
Application.HandleException(E);
SetEvent(FAudio.FNotifyEvent);
end;
end;
end;
constructor TAudioStream.Create(ADirectSound: TDirectSound);
begin
inherited Create;
FDSound := ADirectSound;
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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -