在dll中使用 DirectSound,编译能通过,但会出现内存问题,而且不能发声

学习了万一老师的博客,想在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.

原文地址:https://www.cnblogs.com/yehuiyan/p/2264430.html