学习了万一老师的博客,想在dll中使用DirectSound,但问题
在dll中使用 DirectSound,编译能通过,但会出现内存问题,而且不能发声
library Readwave;
uses
windows,
System.SysUtils,
System.Classes,
DirectSound,
MMSystem;
{$R *.res}
const wavPath= 'C:\Temp\Test.wav'; //测试用的 Wave, 须保证文件存在并注意路径权限, 且只能是 PCM 格
式的 Wave 文件
var
myDSound: IDirectSound8;
buf: IDirectSoundBuffer; //缓冲区对象
dllHandle:THandle;
{从 Wave 文件中获取 TWaveFormatEx 结构的函数}
function GetWaveFmt(FilePath: string; var fmt: TWaveFormatEx): Boolean;
var
hFile: HMMIO;
ckiRIFF,ckiFmt: TMMCKInfo;
begin
Result := False;
hFile := mmioOpen(PChar(FilePath), nil, MMIO_READ);
if hFile = 0 then Exit;
ZeroMemory(@ckiRIFF, SizeOf(TMMCKInfo));
ZeroMemory(@ckiFmt, SizeOf(TMMCKInfo));
ZeroMemory(@fmt, SizeOf(TWaveFormatEx));
ckiFmt.ckid := mmioStringToFOURCC('fmt', 0);
mmioDescend(hFile, @ckiRIFF, nil, MMIO_FINDRIFF);
if (ckiRIFF.ckid = FOURCC_RIFF) and
(ckiRIFF.fccType = mmioStringToFOURCC('WAVE',0)) and
(mmioDescend(hFile, @ckiFmt, @ckiRIFF, MMIO_FINDCHUNK) = MMSYSERR_NOERROR) then
Result := (mmioRead(hFile, @fmt, ckiFmt.cksize) = ckiFmt.cksize);
mmioClose(hFile, 0);
end;
{从 Wave 文件中获取波形数据的函数}
function GetWaveData(FilePath: string; var stream: TMemoryStream): Boolean;
var
hFile: HMMIO;
ckiRIFF,ckiData: TMMCKInfo;
begin
Result := False;
hFile := mmioOpen(PChar(FilePath), nil, MMIO_READ);
if hFile = 0 then Exit;
ZeroMemory(@ckiRIFF, SizeOf(TMMCKInfo));//ZeroMemory要window单元的支持
ZeroMemory(@ckiData, SizeOf(TMMCKInfo));
ckiData.ckid := mmioStringToFOURCC('data', 0);
mmioDescend(hFile, @ckiRIFF, nil, MMIO_FINDRIFF);
if (ckiRIFF.ckid = FOURCC_RIFF) and
(ckiRIFF.fccType = mmioStringToFOURCC('WAVE',0)) and
(mmioDescend(hFile, @ckiData, @ckiRIFF, MMIO_FINDCHUNK) = MMSYSERR_NOERROR) then
begin
stream.Size := ckiData.cksize;
Result := (mmioRead(hFile, stream.Memory, ckiData.cksize) = ckiData.cksize);
end;
mmioClose(hFile, 0);
end;
function cFormCreate: Boolean; stdcall;
begin
system.ReportMemoryLeaksOnShutdown := True; //让程序自动报告内存泄露
end;
function cb1: Boolean; stdcall;
var
bufDesc: TDSBufferDesc; //建立缓冲区需要的结构
wavFormat: TWaveFormatEx; //从 Wave 中提取的结构
wavData: TMemoryStream; //从 Wave 中提取的波形数据
p1: Pointer; //从缓冲区获取的写指针
n1: DWORD; //要写入缓冲区的数据大小
begin
{从 Wave 文件中读取格式与波形数据}
if not GetWaveFmt(wavPath, wavFormat) then Exit;
wavData := TMemoryStream.Create;
if not GetWaveData(wavPath, wavData) then begin wavData.Free; Exit; end;
{建立设备对象, 并设置写作优先级}
dllHandle:=GetModuleHandle('KeyBoarHook.dll'); //取得dll自己的句柄
DirectSoundCreate8(nil, myDSound, nil);
myDSound.SetCooperativeLevel(dllHandle, DSSCL_NORMAL);
{填充建立缓冲区需要的结构}
ZeroMemory(@bufDesc, SizeOf(TDSBufferDesc));
bufDesc.dwSize := SizeOf(TDSBufferDesc);
bufDesc.dwFlags := DSBCAPS_STATIC; //指定使用静态缓冲区
bufDesc.dwBufferBytes := wavData.Size; //数据大小
bufDesc.lpwfxFormat := @wavFormat; //数据格式
// bufDesc.guid3DAlgorithm := DS3DALG_DEFAULT; //这个暂不需要
{建立缓冲区}
myDSound.CreateSoundBuffer(bufDesc, buf, nil);
{锁定缓冲区内存以获取写入地址和写入大小}
buf.Lock(0, 0, @p1, @n1, nil, nil, DSBLOCK_ENTIREBUFFER);
{写入}
wavData.Position := 0;
CopyMemory(p1, wavData.Memory, n1);
wavData.Free;
{解锁}
buf.Unlock(p1, n1, nil, 0);
{播放}
buf.Play(0, 0, 0);
end;
function cb2: Boolean; stdcall;
begin
buf.Play(0, 0, DSBPLAY_LOOPING);
end;
function cb3: Boolean; stdcall;
begin
buf.Stop;
end;
function cb4: Boolean; stdcall;
begin
buf := nil;
myDSound := nil;
end;
exports cFormCreate,cb1,cb2,cb3,cb4;
begin
end.