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

altEF_4

Новичок
Попробовал реализовать воспроизведение музыки (BASS.dll) из памяти (стрим или буфер), с помощью Delphi - получилось, Inno - нет, попробовал написать библиотеку - вроде как написал, но вот проблема Inno никак не хочет корректно с ней работать (точнее с BASS)
Код:
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.
Код:
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 далеко не мастер :)
 

ProFrager

Знаток
Проверенный
а можно более подробно описать проблему? "не хочет работать" - как-то совсем малоинформативно
 

altEF_4

Новичок
при использовании тестовой программы работают оба способа (и с буфера и со стрима) но при работе с Inno - Runtime error, если с библиотеки убрать любые обращения к BASS.dll, оставить только обработку стрима и буфера, то все прекрасно работает.
 
Последнее редактирование:

ProFrager

Знаток
Проверенный
не знаю на сколько это валидно для inno (давно в нем не программировал), но я бы напрямую из скрипта вызывал функции bass.dll примерно с таким содержанием (не пробовал, т.к. inno не установлен):
Код:
FileSize := ExtractTemporaryFileSize(FileName);
SetLength(Buffer, FileSize);
ExtractTemporaryFileToBuffer(FileName, CastAnsiStringToInteger(Buffer));
BH:=BASS_StreamCreateFile(True, PChar(Buffer), 0, FileSize, 4);
BASS_ChannelPlay(BH, True);
 

altEF_4

Новичок
не знаю на сколько это валидно для inno (давно в нем не программировал), но я бы напрямую из скрипта вызывал функции bass.dll примерно с таким содержанием (не пробовал, т.к. inno не установлен):
Код:
FileSize := ExtractTemporaryFileSize(FileName);
SetLength(Buffer, FileSize);
ExtractTemporaryFileToBuffer(FileName, CastAnsiStringToInteger(Buffer));
BH:=BASS_StreamCreateFile(True, PChar(Buffer), 0, FileSize, 4);
BASS_ChannelPlay(BH, True);
после изменения параметров вызова пол секунды идет звук и сетапник крашится

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

Код:
BASS_StreamCreateFile(mem: BOOL; file: void; offset: QWORD; length: QWORD;flags: DWORD);
Код:
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';
 

ProFrager

Знаток
Проверенный
altEF_4, по всей видимости твоя дллка написана на делфях и скомпилена с опцией внешнего рантайма и потому требует для работы rtl120.bpl. На компах, где не установлена твоя версия делфей сетапник не будет работать.
 

altEF_4

Новичок
altEF_4, по всей видимости твоя дллка написана на делфях и скомпилена с опцией внешнего рантайма и потому требует для работы rtl120.bpl. На компах, где не установлена твоя версия делфей сетапник не будет работать.
спасибо за информацию, так и есть, вот версия без внешнего рантайма
 

Вложения

  • 44.9 KB Просмотры: 54
Последнее редактирование:
Сверху