zoukankan      html  css  js  c++  java
  • 在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.

  • 相关阅读:
    [MetaHook] Find a function signature
    [MetaHook] GameUI hook
    [MetaHook] BaseUI hook
    一些常用软件的网络端口协议分类介绍
    Visual C++中最常用的类与API函数
    Ubuntu常用软件安装
    C++字符串完全指引
    C++资源之不完全导引
    超过 130 个你需要了解的 vim 命令
    Little-endian和Big-endian
  • 原文地址:https://www.cnblogs.com/yehuiyan/p/2264430.html
Copyright © 2011-2022 走看看