1. Уважаемые гости и пользователи форума.
    Администрация настоятельно рекомендует не регистрировать несколько аккаунтов для одного пользователя. При выявлении наличия мультиаккаунтов будут заблокированы все учетные записи данного пользователя.
    Аккаунты, зарегистрированные на временную почту будут также заблокированы.

Воспроизведение музыки (BASS.dll) из памяти

Тема в разделе "Delphi", создана пользователем altEF_4, 19 окт 2013.

  1. Ветеран

    Регистрация:
    24 май 2012
    Сообщения:
    70
    Симпатии:
    80
    Пол:
    Мужской
    Попробовал реализовать воспроизведение музыки (BASS.dll) из памяти (стрим или буфер), с помощью Delphi - получилось, Inno - нет, попробовал написать библиотеку - вроде как написал, но вот проблема Inno никак не хочет корректно с ней работать (точнее с BASS)
    Код (Text):
    library BP;

    uses
      Classes,Windows;

    function BASS_Init(device: Integer; freq, flags: DWORD; win: hwnd; CLSID: Pointer): BOOL; stdcall; external 'BASS.dll' Name 'BASS_Init';
    function BASS_StreamCreateFile(mem: BOOL; f: Pointer; offset, lenght: Int64; flags: DWORD): Cardinal; stdcall; external 'BASS.dll' Name 'BASS_StreamCreateFile';
    function BASS_Start: Boolean; stdcall; external 'BASS.dll' Name 'BASS_Start';
    function BASS_ChannelPlay(handle: DWORD; restart: BOOL): BOOL; stdcall; external 'BASS.dll' Name 'BASS_ChannelPlay';
    function BASS_Stop: BOOL; stdcall; external 'BASS.dll' Name 'BASS_Stop';
    function BASS_Free: BOOL; stdcall; external 'BASS.dll' Name 'BASS_Free';

    function StreamToByteArray(Stream: TMemoryStream): Pointer;
    begin
      if Assigned(Stream) then
        begin
          Result := AllocMem(Stream.Size);
          Stream.Position := 0;
          Stream.Read(Result^, Stream.Size);
        end
      else
        Result := nil;
    end;

    procedure BASS_PrepareBuffer(Buffer:AnsiString); stdcall;
    var
      MP: Pointer;
      BH: Cardinal;
      MS: TMemoryStream;
    begin
      BASS_Init(-1, 44100, 0, 0, nil);
      BASS_Start;
      MS:=TMemoryStream.Create;
      try
        MS.Position:=0;
        MS.Write(Pointer(Buffer)^, length(Buffer));
        //MS.SaveToFile('Buffer.mp3');
        MP:=StreamToByteArray(MS);
        BH:=BASS_StreamCreateFile(True, MP, 0, MS.Size, 4);
        BASS_ChannelPlay(BH, True);
      finally
        MS.Free;
      end;
    end;

    procedure BASS_Prepare(MStream:TMemoryStream); stdcall;
    var
    MP: Pointer;
    BH: Cardinal;
    begin
      BASS_Init(-1, 44100, 0, 0, nil);
      BASS_Start;
      MStream.Position:=0;
      //MStream.SaveToFile('Stream.mp3');
      MP:=StreamToByteArray(MStream);
      BH:=BASS_StreamCreateFile(True, MP, 0, MStream.Size, 4);
      BASS_ChannelPlay(BH, True);
    end;

    exports
      BASS_Prepare,BASS_PrepareBuffer;
    end.
    Код (Text):
    unit BassStream;

    interface

    uses
    Windows, SysUtils, Classes, Forms, Dialogs,
    StdCtrls, Controls;

    type
    TForm1 = class(TForm)
        Button1: TButton;
        OpenDialog1: TOpenDialog;
        Button2: TButton;
       procedure Button1Click(Sender: TObject);
        procedure Button2Click(Sender: TObject);
    private
    public
    end;

    var
    Form1: TForm1;

    implementation

    {$R *.DFM}

    function BASS_Init(device: Integer; freq, flags: DWORD; win: hwnd; CLSID: integer): BOOL; stdcall; external 'BASS.dll' Name 'BASS_Init';
    function BASS_StreamCreateFile(mem: BOOL; f: Pointer; offset, lenght: Int64; flags: DWORD): Cardinal; stdcall; external 'BASS.dll' Name 'BASS_StreamCreateFile';
    function BASS_Start: Boolean; stdcall; external 'BASS.dll' Name 'BASS_Start';
    function BASS_ChannelPlay(handle: DWORD; restart: BOOL): BOOL; stdcall; external 'BASS.dll' Name 'BASS_ChannelPlay';
    function BASS_Stop: BOOL; stdcall; external 'BASS.dll' Name 'BASS_Stop';
    function BASS_Free: BOOL; stdcall; external 'BASS.dll' Name 'BASS_Free';

    function BASS_PrepareBuffer(Buffer:AnsiString):BOOL; stdcall; external 'BP.dll' Name 'BASS_PrepareBuffer';
    function BASS_Prepare(MStream:TMemoryStream):BOOL; stdcall; external 'BP.dll' Name 'BASS_Prepare';

    function FileToStr(const FileName : string):AnsiString;
    var
      Stream : TFileStream;
    begin
      Stream:= TFileStream.Create(FileName, fmOpenRead);
      try
        SetLength(Result, Stream.Size);
        Stream.Position:=0;
        Stream.ReadBuffer(Pointer(Result)^, Stream.Size);
      finally
        Stream.Free;
      end;
    end;

    function StreamToByteArray(Stream: TMemoryStream): Pointer;
    begin
      if Assigned(Stream) then
        begin
          Result := AllocMem(Stream.Size);
          Stream.Position := 0;
          Stream.Read(Result^, Stream.Size);
        end
      else
        Result := nil;
    end;

    procedure TForm1.Button1Click(Sender: TObject);
    var
    Buffer:AnsiString;
    begin
    if OpenDialog1.Execute then begin
    Buffer:=FileToStr(OpenDialog1.FileName);
    Bass_PrepareBuffer(Buffer);
    end;
    end;

    procedure TForm1.Button2Click(Sender: TObject);
    var
      MS:TMemoryStream;
      FS:TFileStream;
    begin
    if OpenDialog1.Execute then begin
    try
      FS:=TFileStream.Create(OpenDialog1.FileName,fmOpenRead);
      MS:=TMemoryStream.Create;
      MS.Position:=0;
      MS.LoadFromStream(FS);
      Bass_Prepare(MS);
    finally
      FS.Free;
      MS.Free;
    end;
    end;
    end;

    end.
    #define Buffer
    [Setup]
    AppName=bass

    AppVerName=bass v2.4.10
    DefaultDirName={pf}\My Program
    DefaultGroupName=My Program

    [Languages]
    Name: "rus"; MessagesFile: "compiler:Languages\Russian.isl"


    [Files]
    Source: "BASS.dll"; Flags: dontcopy noencryption nocompression

    Source: "sound.mp3"; Flags: dontcopy noencryption nocompression
    Source: "bp.dll"; Flags: dontcopy noencryption nocompression

    [_Code]
    #ifdef Buffer

    procedure BASS_PrepareBuffer(Buffer:AnsiString); external 'BASS_PrepareBuffer@{tmp}\bp.dll stdcall delayload';
    #else
    procedure BASS_Prepare(MStream:TMemoryStream); external 'BASS_Prepare@{tmp}\bp.dll stdcall delayload';
    #endif

    function InitializeSetup(): Boolean;
    var
    FileName: String;
    FileSize: Cardinal;
    #ifdef Buffer

    Buffer: AnsiString;
    #else
    ms:TMemoryStream;
    #endif
    begin
    ExtractTemporaryFile('BASS.dll');
    ExtractTemporaryFile('bp.dll');
    FileName := 'sound.mp3';
    #ifdef Buffer
    FileSize := ExtractTemporaryFileSize(FileName);
    SetLength(Buffer, FileSize);
    ExtractTemporaryFileToBuffer(FileName, CastAnsiStringToInteger(Buffer));
    BASS_PrepareBuffer(Buffer);
    #else

    ms:=TMemoryStream.Create;
    try
    ExtractTemporaryFileToStream(FileName, ms);
    ms.Position := 0;
    BASS_Prepare(ms);
    finally

    ms.Free;
    end;
    #endif
    Result := True;
    end;


    кто может, пожалуйста помогите разобраться в чем проблема

    P.S в Delphi далеко не мастер :)
     
  2. Знаток Проверенный

    Регистрация:
    16 июн 2011
    Сообщения:
    321
    Симпатии:
    450
    а можно более подробно описать проблему? "не хочет работать" - как-то совсем малоинформативно
     
  3. Ветеран

    Регистрация:
    24 май 2012
    Сообщения:
    70
    Симпатии:
    80
    Пол:
    Мужской
    при использовании тестовой программы работают оба способа (и с буфера и со стрима) но при работе с Inno - Runtime error, если с библиотеки убрать любые обращения к BASS.dll, оставить только обработку стрима и буфера, то все прекрасно работает.
     
    Последнее редактирование: 21 окт 2013
  4. Знаток Проверенный

    Регистрация:
    16 июн 2011
    Сообщения:
    321
    Симпатии:
    450
    не знаю на сколько это валидно для inno (давно в нем не программировал), но я бы напрямую из скрипта вызывал функции bass.dll примерно с таким содержанием (не пробовал, т.к. inno не установлен):
    Код (Text):
    FileSize := ExtractTemporaryFileSize(FileName);
    SetLength(Buffer, FileSize);
    ExtractTemporaryFileToBuffer(FileName, CastAnsiStringToInteger(Buffer));
    BH:=BASS_StreamCreateFile(True, PChar(Buffer), 0, FileSize, 4);
    BASS_ChannelPlay(BH, True);
     
  5. Ветеран

    Регистрация:
    24 май 2012
    Сообщения:
    70
    Симпатии:
    80
    Пол:
    Мужской
    после изменения параметров вызова пол секунды идет звук и сетапник крашится

    заметил, что пример использования BASS_StreamCreateFile из .chm справки идущей в комплекте с библиотекой не работает в Inno,

    Код (Text):
    BASS_StreamCreateFile(mem: BOOL; file: void; offset: QWORD; length: QWORD;flags: DWORD);
     
    Код (Text):
    function BASS_StreamCreateFile(mem: BOOL; f: PAnsiChar; offset1: DWORD; offset2: DWORD; length1: DWORD; length2: DWORD; flags: DWORD): DWORD; external 'BASS_StreamCreateFile@files:BASS.dll stdcall delayload';
     
     
  6. Ветеран

    Регистрация:
    24 май 2012
    Сообщения:
    70
    Симпатии:
    80
    Пол:
    Мужской
    немного доработал, может кому надо
     

    Вложения:

    • bp.7z
      Размер файла:
      3,9 КБ
      Просмотров:
      14
    AlexanderSergeev, Winst@n, Krinkels и ещё 1-му нравится это.
  7. Знаток Проверенный

    Регистрация:
    16 июн 2011
    Сообщения:
    321
    Симпатии:
    450
    altEF_4, по всей видимости твоя дллка написана на делфях и скомпилена с опцией внешнего рантайма и потому требует для работы rtl120.bpl. На компах, где не установлена твоя версия делфей сетапник не будет работать.
     
    altEF_4 нравится это.
  8. Ветеран

    Регистрация:
    24 май 2012
    Сообщения:
    70
    Симпатии:
    80
    Пол:
    Мужской
    спасибо за информацию, так и есть, вот версия без внешнего рантайма
     

    Вложения:

    • bp.7z
      Размер файла:
      44,9 КБ
      Просмотров:
      38
    Последнее редактирование: 22 ноя 2013
    AlexanderSergeev, vint56 и Krinkels нравится это.

Поделиться этой страницей