【问题标题】:Delphi: load BASS DLL and play MP3Delphi:加载 BASS DLL 并播放 MP3
【发布时间】:2012-02-16 09:08:17
【问题描述】:

我想从某处手动加载bass dll,然后播放一个mp3 文件。怎么做?德尔福 XE2。

我的尝试不起作用:

type
  QWORD = Int64;
  HSTREAM = LongWord;
type
  TBASS_ChannelPlay = function(handle: HSTREAM; restart: LongBool): LongBool; stdcall;

type
  TBASS_StreamCreateFile = function(mem: LongBool; f: Pointer;
    offset, length: QWORD; flags: LongWord): HSTREAM; stdcall;

procedure PlayMP3(FileName: string);
var
  BASS_ChannelPlay: TBASS_ChannelPlay;
  BASS_StreamCreateFile: TBASS_StreamCreateFile;
  DllHandle: THandle;
  MP3Stream: HSTREAM;
  DllPath:string;
  pFileName:pchar;
begin
  DllPath:= 'c:\dll\bass.dll';
  DllHandle := LoadLibrary(pchar(DLLPath));
  try
    if DllHandle = 0 then
      Exit;
    @BASS_StreamCreateFile := GetProcAddress(DllHandle,
      'BASS_StreamCreateFile');
    if @BASS_StreamCreateFile <> nil then
    begin
      pfilename:=pchar(FileName);
      MP3Stream := BASS_StreamCreateFile(false, Pfilename, 0, 0, 0);
      if MP3Stream <> 0 then
      begin
        @BASS_ChannelPlay := GetProcAddress(DllHandle, 'BASS_ChannelPlay');
        if @BASS_ChannelPlay <> nil then
          BASS_ChannelPlay(MP3Stream,false);
      end;
    end;
  finally
    FreeLibrary(DllHandle);
  end;
end;

但是 BASS_StreamCreateFile 一直返回 0 :(

他们的示例(Bass Test)和 Bass.pas 中的代码:

type
  DWORD = LongWord;
  BOOL = LongBool;
  QWORD = Int64;
  HSTREAM = DWORD;

function BASS_StreamCreateFile(mem: BOOL; f: Pointer; offset, length: QWORD; flags: DWORD): HSTREAM; {$IFDEF WIN32}stdcall{$ELSE}cdecl{$ENDIF}; external bassdll;

strs: array[0..128] of HSTREAM;

procedure TForm1.Button15Click(Sender: TObject);
var
    f: PChar;
begin
    if not OpenDialog2.Execute then Exit;
    f := PChar(OpenDialog2.FileName);
    strs[strc] := BASS_StreamCreateFile(False, f, 0, 0, 0 {$IFDEF UNICODE} or BASS_UNICODE {$ENDIF});
    if strs[strc] <> 0 then
    begin
        ListBox3.Items.Add(OpenDialog2.FileName);
        Inc(strc);
    end
    else
        Error('Error creating stream!');
end;

添加

  MP3Stream := BASS_StreamCreateFile(false, Pfilename, 0, 0, 0);
  ShowMessage(SysErrorMessage(GetLastError));

GetLastError 没有显示任何错误!

添加

还有 BASS 2.4 Delphi 单元(动态)。

上面写着:

如何安装 将 DYNAMIC_BASS.PAS 复制到 \LIB 的子目录 您的 Delphi 路径或您的项目目录调用 Load_BASSDLL(例如在 FormCreate) 在使用任何功能之前加载 BASS,以及
Unload_BASSDLL(例如在 FormDestory 中)在您完成后将其卸载。

注意:Delphi 2009 用户应使用 BASS_UNICODE 标志,其中 可能

我愿意:

 if Load_BASSDLL(DllPath) then
  begin
  FileName:='C:\Users\V\Desktop\cmd.mp3';
  MP3Stream:=BASS_StreamCreateFile(False, pchar(FileName), 0, 0, 0 {$IFDEF UNICODE} or BASS_UNICODE {$ENDIF});
    if MP3Stream <> 0 then
     BASS_ChannelPlay(MP3Stream, False);
     Unload_BASSDLL;
  end;

还是不行:(

补充:

如果这样做

BASS_Init(-1, 44100, 0, Form1.Handle, nil);

然后BASS_ChannelPlay(MP3Stream, False) 返回 true 但我没有听到声音:(

【问题讨论】:

  • 再次阅读我编辑的答案。如果您查看dynamic_bass.pas,尤其是Load_BASSDLL 的代码,它不会调用BASS_Init。它只是加载库并执行所有GetProcAddress 调用。

标签: delphi function mp3 bass.dll


【解决方案1】:

您错过了对BASS_Init 的呼叫。来自您在FormCreate 事件中引用的同一个演示:

// Initialize audio - default device, 44100hz, stereo, 16 bits
if not BASS_Init(-1, 44100, 0, Handle, nil) then
  Error('Error initializing audio!'); 

另外,看看演示源的调用:

BASS_StreamCreateFile(False, f, 0, 0, 
 0 {$IFDEF UNICODE} or BASS_UNICODE {$ENDIF});

注意最后一个参数会发生什么? or BASS_UNICODE 在 D2009 及更高版本上是必需的,除非您使用 PAnsiChar 而不是 PChar; Delphi默认的字符串类型是UnicodeString,默认的PCharPWideChar

您可以将它与{$IFDEF UNICODE} 一起使用,也可以不使用它; Delphi 定义了UNICODE,因此如果您使用它,您的代码也将向后兼容早期版本的 Delphi(D2009 之前)。

您还应该查看Bass\Delphi\dynamic 文件夹中的dynamic_bass.pas。它具有动态加载库和检索所有函数的代码;如果你不想直接使用它,至少你可以从那里复制你需要的函数定义和动态加载代码。

【讨论】:

  • 我添加了or $80000000 (BASS_UNICODE const)BASS_StreamCreateFile 返回“0”
  • 你想在哪里创建文件(什么文件名)?您使用的是哪个 Windows 版本?这是 32 位还是 64 位项目?
  • 文件路径为“c:\users\v\desktop\1.mp3”;视窗 7 x32; 32 位项目。
  • 那我不知道还有什么可能。不过,我真的不明白你为什么要让自己变得如此复杂;您有一个非常好的演示,您可以从中复制和粘贴代码,然后从中删除引用 OpenDialogListBox 并更改为接受文件名作为参数。你还坚持做一些事情,比如硬编码已经定义的常量(BASS_UNICODE,但是你硬编码$80000000而不是仅仅使用它),手动加载DLL并使用GetProcAddress而不是仅仅静态加载它。
  • DLL 不能在应用程序的文件夹中,因为它是一个单文件应用程序(仅限 EXE)。我不想将程序保留在带有 DLL 的桌面上(但在临时文件夹中的某个位置)。这不是一个包含许多文件(包括 DLL)的大项目,将它们与 EXE 一起保存是正常的。
【解决方案2】:

建议 - 只是不要手动加载 .dll。忘掉“LoadDll”,尤其忘掉那些邋遢的低级 Win3.0 时代的“GetProcAddress()”废话。

只需声明一个外部,就像工作中的 Bass 示例代码成功所做的那样:

function BASS_StreamCreateFile(
           mem: BOOL; 
           f: Pointer; 
           offset, length: QWORD; 
           flags: DWORD): HSTREAM; 
{$IFDEF WIN32}stdcall{$ELSE}cdecl{$ENDIF}; external bassdll;

PS: 如果你真的、真的、真的坚持LoadDll()和朋友,那么:

  1. 记住 Delphi XE 字符串现在是 16 位 Unicode

  2. 检查 GetLastError () 以确定 为什么 LoadDll 返回了一个空句柄。

PPS:

【讨论】:

    【解决方案3】:

    【讨论】:

    • 由于您的网站是西班牙文,而且这是一个英文网站,请考虑解释如何获取源代码(如果有人不懂西班牙文会有点困难)。跨度>
    • 嗨,欢迎来到 SO。发布简洁的代码片段而不是链接到外部资源通常是一个好主意,原因如下:(1)外部资源将来可能会消失,使您的答案无效(2)通常,链接包含太多不相关的信息,这可能会使人感到困惑。
    猜你喜欢
    • 1970-01-01
    • 2010-09-24
    • 2011-11-03
    • 1970-01-01
    • 1970-01-01
    • 2022-11-10
    • 1970-01-01
    • 2021-11-27
    • 1970-01-01
    相关资源
    最近更新 更多