Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Delphi: load BASS DLL and play MP3

I want to load a bass dll manually from somewhere and then play a mp3 file. How to do that? Delphi XE2.

My attempt doesn't work:

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;

But BASS_StreamCreateFile returns 0 all time :(

The code from their example (Bass Test) and 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;

Added

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

GetLastError doesn't show any errors!

Added

There is BASS 2.4 Delphi unit (dynamic) too.

It's written:

How to install Copy DYNAMIC_BASS.PAS to the \LIB subdirectory of your Delphi path or your project dir Call Load_BASSDLL (eg. in FormCreate) to load BASS before using any functions, and
Unload_BASSDLL (eg. in FormDestory) to unload it when you're done.

NOTE: Delphi 2009 users should use the BASS_UNICODE flag where possible

I do:

 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;

It still doesn't work :(

Added:

If to do

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

then BASS_ChannelPlay(MP3Stream, False) returns true but I don't hear a sound:(

like image 407
maxfax Avatar asked Jan 22 '12 20:01

maxfax


1 Answers

You're missing the call to BASS_Init. From the same demo you quoted from, in the FormCreate event:

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

Also, look at the demo source's call:

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

Note what happens with the last parameter? The or BASS_UNICODE is required on D2009 and up, unless you're using PAnsiChar instead of PChar; Delphi's default string type is UnicodeString, and the default PChar is PWideChar.

You can use it with the {$IFDEF UNICODE} or without it; Delphi defines UNICODE, so if you use it your code will be backwards-compatible with earlier versions of Delphi (pre-D2009) as well.

You should also look at dynamic_bass.pas in the Bass\Delphi\dynamic folder. It has code to dynamically load the library and retrieve all the functions; if you don't want to use it directly, at least you could copy the function definitions and dynamic loading code you need from there instead.

like image 144
Ken White Avatar answered Oct 10 '22 17:10

Ken White