Delphi: загрузить BASS DLL и воспроизвести MP3

Я хочу загрузить откуда-нибудь вручную bass dll, а затем воспроизвести файл mp3. Как это сделать? Delphi 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.

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;

Все равно не работает :(

Добавлен:

If to do

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

то BASS_ChannelPlay(MP3Stream, False) возвращает истину, но я не слышу звука :(


person maxfax    schedule 22.01.2012    source источник
comment
Опять же, прочтите мой отредактированный ответ. Если вы посмотрите на dynamic_bass.pas, особенно на код для Load_BASSDLL, он НЕ вызывает BASS_Init. Он просто загружает библиотеку и выполняет все GetProcAddress вызовы.   -  person Ken White    schedule 23.01.2012


Ответы (3)


Вам не хватает звонка на 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, а PChar по умолчанию - PWideChar.

Вы можете использовать его с {$IFDEF UNICODE} или без него; Delphi определяет UNICODE, поэтому, если вы его используете, ваш код будет обратно совместим с более ранними версиями Delphi (до D2009).

Вам также следует посмотреть на dynamic_bass.pas в папке Bass\Delphi\dynamic. В нем есть код для динамической загрузки библиотеки и получения всех функций; если вы не хотите использовать его напрямую, по крайней мере, вы можете скопировать определения функций и код динамической загрузки, который вам нужен, вместо этого.

person Ken White    schedule 22.01.2012
comment
Я добавил or $80000000 (BASS_UNICODE const), BASS_StreamCreateFile возвращает 0 - person maxfax; 23.01.2012
comment
Где вы пытаетесь создать файл (какое имя файла)? Какую версию Windows вы используете? Это 32-битный или 64-битный проект? - person Ken White; 23.01.2012
comment
Путь к файлу - c: \ users \ v \ desktop \ 1.mp3; Windows 7 x32; 32-битный проект. - person maxfax; 23.01.2012
comment
Тогда я не знаю, что это еще может быть. Я действительно не понимаю, почему вы так усложняете для себя; у вас есть отличная демонстрация, из которой вы можете просто скопировать и вставить код, а затем удалить ссылки OpenDialog и ListBox и изменить на принятие имени файла в качестве параметра. Вы также настаиваете на выполнении таких действий, как жесткое кодирование уже определенных констант (BASS_UNICODE, но вы жестко запрограммировали $80000000 вместо того, чтобы просто использовать его), и вручную загружать DLL и использовать GetProcAddress вместо того, чтобы просто загружать ее статически. - person Ken White; 23.01.2012
comment
DLL не должна находиться в папке приложения, потому что это однофайловое приложение (только EXE). Я не хочу держать программу на рабочем столе с DLL (а где-то во временной папке). Это небольшой проект с большим количеством файлов, в том числе DLL, и хранить их в EXE - нормальное явление. - person maxfax; 23.01.2012
comment
И самое главное - очень редко буду использовать DLL! Статическая загрузка мне не нужна (это не плеер). - person maxfax; 23.01.2012
comment
Справедливо. См. Мой отредактированный ответ. (Я только что загрузил Bass 2.4 по указанной вами ссылке, разархивировал его в папку, открыл BTMain.pas в Notepad ++ и взглянул на код.) - person Ken White; 23.01.2012
comment
Спасибо, это работает!!! BASS_ChannelPlay (MP3Stream, False) возвращает true ... но я не слышу звука :( - person maxfax; 23.01.2012
comment
Тогда вы можете принять мой ответ. :) Не слышно звука - отдельный вопрос; этот (со всеми вашими правками и обсуждением комментариев) стал довольно шумным. - person Ken White; 23.01.2012

Предложение - просто не загружайте .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:

person paulsm4    schedule 22.01.2012

Вот пример использования bass.dll http://delphimagic.blogspot.com.es/2013/05/escuchar-la-radio-por-streaming.html

person Charles Brown    schedule 22.05.2013
comment
Поскольку ваш веб-сайт на испанском языке, а это на английском языке, подумайте о том, чтобы объяснить, как получить исходный код (если кто-то не понимает испанский, это будет немного сложно). - person Nunser; 22.05.2013
comment
Привет, добро пожаловать в SO. Часто рекомендуется опубликовать краткий фрагмент кода вместо ссылки на внешние ресурсы по нескольким причинам: (1) внешний ресурс может исчезнуть в будущем, что сделает ваш ответ недействительным (2) как правило, ссылки содержат слишком много нерелевантной информации, которая может сбивать с толку людей. - person Marc Claesen; 22.05.2013