Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Mehrere WAV aus Resource gleichzeitig abspielen (https://www.delphipraxis.net/193492-mehrere-wav-aus-resource-gleichzeitig-abspielen.html)

Danny92 6. Aug 2017 11:57

Mehrere WAV aus Resource gleichzeitig abspielen
 
Hey,

ich plane ein Spiel zu programmieren. Dazu muss ich mehrere wav-Dateien, die in in einer Ressource geladen habe, abspielen können.

Mit SndPlaySound funktioniert das auch soweit. Nur wenn ich diese gleichzeitig abspiele, wird das eins von beiden unterbrochen.

Ich möchte keine Dateien auf der Platte schreiben müssen, sonst wär das mit der Resource ja völlig unnötig.

Wie kann ich das realisieren?

Lieben Dank!
Danny

jaenicke 6. Aug 2017 13:19

AW: Mehrere WAV aus Resource gleichzeitig abspielen
 
Ich würde dafür die BASS Audio Bibliothek benutzen:
https://www.un4seen.com/

Danny92 6. Aug 2017 15:12

AW: Mehrere WAV aus Resource gleichzeitig abspielen
 
Und wie genau nützt mir das was?
Was genau mach ich mit der Bass.dll?
:o

jaenicke 6. Aug 2017 17:38

AW: Mehrere WAV aus Resource gleichzeitig abspielen
 
Hört sich so an als hättest du bisher nicht in die Beispiele oder Doku geschaut.

Ganz kurz: Du rufst BASS_StreamCreateFile auf um eine Datei oder einen Stream zu laden und spielst dann mit BASS_ChannelPlay ab. Das geht auch parallel mit mehreren Sounds.

Danny92 6. Aug 2017 19:30

AW: Mehrere WAV aus Resource gleichzeitig abspielen
 
Okay aber da muss ich doch die Bass.dll benutzen? Wie geht das?
Sorry aber ich bin damit nicht so vertraut^^

Danny92 7. Aug 2017 12:43

AW: Mehrere WAV aus Resource gleichzeitig abspielen
 
Hat da wirklich keiner ne Ahnung?

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, bass;

type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
private
{ Private-Deklarationen }
public
{ Public-Deklarationen }
end;

var
Form1: TForm1;
strs: HStream;

implementation

{$R *.dfm}
{$R fx.res}

procedure TForm1.FormCreate(Sender: TObject);
var
rs: TResourceStream;
begin
rs:=TResourceStream.Create(hInstance,'intro','WAV' );
strs:=BASS_StreamCreateFile(false,rs.Memory,0,0,0) ;
BASS_ChannelPlay(handle,false);
rs.Free;
end;

end.

jaenicke 7. Aug 2017 13:26

AW: Mehrere WAV aus Resource gleichzeitig abspielen
 
Doch schon, aber ich habe darauf gewartet, dass du etwas zeigst wie du etwas versucht hast. ;-)

Schau dir mal die Doku zu BASS_StreamCreateFile an:
https://www.un4seen.com/doc/#bass/BA...reateFile.html
Speziell den ersten und vierten Parameter. Da sollte dir etwas auffallen.

Erklärung zum vierten Parameter:
Wenn du nur einen Pointer auf einen Speicherbereich übergibst, kann BASS anders als bei einer Datei nicht selbst feststellen wie lang dieser Speicherbereich ist.

Außerdem fehlt die Fehlerauswertung. Dazu steht da auch ein Hinweis drin:
Zitat:

Return value
If successful, the new stream's handle is returned, else 0 is returned. Use BASS_ErrorGetCode to get the error code.

Danny92 7. Aug 2017 13:41

AW: Mehrere WAV aus Resource gleichzeitig abspielen
 
procedure TForm1.FormCreate(Sender: TObject);
var
rs: TResourceStream;
begin
rs:=TResourceStream.Create(hInstance,'intro','WAV' );
rs.Position:=0;
strs:=BASS_StreamCreateFile(true,rs.Memory,0,rs.Si ze,0);
BASS_ChannelPlay(handle,false);
rs.Free;
end;

Sieht das so besser aus?

jaenicke 7. Aug 2017 13:58

AW: Mehrere WAV aus Resource gleichzeitig abspielen
 
Auf den ersten Blick ja, aber du solltest noch den Rückgabewert prüfen und ggf. den Fehlercode abrufen, wenn es nicht geklappt hat.

Dann kommen wir zum nächsten Befehl. Aktuell übergibst du das Handle des Formulars an BASS_ChannelPlay. Das macht keinen Sinn, meinst du nicht auch?
http://www.un4seen.com/doc/#bass/BASS_ChannelPlay.html

Danny92 7. Aug 2017 14:06

AW: Mehrere WAV aus Resource gleichzeitig abspielen
 
procedure TForm1.FormCreate(Sender: TObject);
var
rs: TResourceStream;
code: bool;
begin
rs:=TResourceStream.Create(hInstance,'intro','WAV' );
rs.Position:=0;
strs:=BASS_StreamCreateFile(true,rs.Memory,0,rs.Si ze,0);
//BASS_ErrorGetCode;
code:=BASS_ChannelPlay(strs,false);
showmessage(inttostr(integer(code)));
rs.Free;
end;

Also würde das in etwa so aussehen? Wenn ich die Rückmeldung ausgebe, kommt 0 zurück. Scheint also alles in Ordnung zu sein? Höre aber trotzdem nichts...ich seh's nicht. :shock:

Amateurprofi 8. Aug 2017 00:46

AW: Mehrere WAV aus Resource gleichzeitig abspielen
 
Zitat:

Zitat von Danny92 (Beitrag 1378265)
procedure TForm1.FormCreate(Sender: TObject);
var
rs: TResourceStream;
code: bool;
begin
rs:=TResourceStream.Create(hInstance,'intro','WAV' );
rs.Position:=0;
strs:=BASS_StreamCreateFile(true,rs.Memory,0,rs.Si ze,0);
//BASS_ErrorGetCode;
code:=BASS_ChannelPlay(strs,false);
showmessage(inttostr(integer(code)));
rs.Free;
end;

Also würde das in etwa so aussehen? Wenn ich die Rückmeldung ausgebe, kommt 0 zurück. Scheint also alles in Ordnung zu sein? Höre aber trotzdem nichts...ich seh's nicht. :shock:

Na ja, wenn du die Meldung ausgibst und da 0 zurückkommt, dann bedeutet das, dass BASS_ChannelPlay False zurückgegeben hat, und das würde ich so interpretieren dass da etwas NICHT in Ordnung ist.
Ich weiß aber nicht, was das falsch ist.

jaenicke 8. Aug 2017 03:24

AW: Mehrere WAV aus Resource gleichzeitig abspielen
 
Welchen Wert hat denn strs?
Das ist ja erst einmal wichtig um zu schauen, ob das Laden erfolgreich war.
Denn ich sehe kein BASS_Init, so dass dort ggf. als Fehler auftritt, dass das nicht aufgerufen wurde.

Danny92 9. Aug 2017 00:23

AW: Mehrere WAV aus Resource gleichzeitig abspielen
 
Ja die BASS_Init hat noch gefehlt. Jetzt spielt es.

Delphi-Quellcode:
procedure TForm1.FormCreate(Sender: TObject);
var
  rs: TResourceStream;
begin
  rs:=TResourceStream.Create(hInstance,'intro','WAV');
  Bass_Init(-1,44100,0,Application.Handle,nil);
  rs.Position:=0;
  strs:=BASS_StreamCreateFile(true,rs.Memory,0,rs.Size,0);
  BASS_ChannelPlay(strs,false);
  rs.Free;
end;
Noch eine letzte Frage: Sieht das soweit in Ordnung aus? Programmiertechnisch betrachtet :D Die Rückgabewerte brauch ich für den Fall ja eigentlich nicht wirklich oder? Wie würde das sonst eleganterweise aussehen? Und wenn ich bei ChannelPlay den zweiten Parameter Restart auf true setze, spielt es trotzdem nur einmal. Bestimmt hab ich da was übersehen?

Auf jeden Fall ein großes Danke!

Aviator 9. Aug 2017 08:37

AW: Mehrere WAV aus Resource gleichzeitig abspielen
 
Rückgabewerte von Funktionen die einem einen Fehlercode liefern sollte man immer auswerten um im Programmablauf entsprechend darauf reagieren zu können.

Irgendwann versucht du bspw. mal eine Datei abzuspielen die defekt ist. Wenn du die Rückgabewerte jetzt nicht auswertest und entsprechende Fehlermeldungen anzeigst/protokollierst, dann wunderst du dich warum kein Sound kommt. Wenn du dann irgendwann darauf kommst das die Datei defekt ist, dann sagst du dir: "Wieso habe ich damals in mein Programm keine Fehlerbehandlung eingebaut?! Dann wäre mir die halbe Stunde Suche erspart geblieben!"


Und ein Hinweis: Fasse SourceCode doch bitte in Delphi-Tags ein (das Delphi Helm Symbol über dem Editor). Dein SourceCode sieht dann gleich viel besser aus und lässt sich auch viel leichter lesen.

Code:
[DELPHI]
  SourceCode hier
[/DELPHI]
Beispiel wie dein SourceCode dann aussehen würde:

Delphi-Quellcode:
procedure TForm1.FormCreate(Sender: TObject);
var
  rs: TResourceStream;
begin
  rs:=TResourceStream.Create(hInstance,'intro','WAV' );
  Bass_Init(-1,44100,0,Application.Handle,nil);
  rs.Position:=0;
  strs:=BASS_StreamCreateFile(true,rs.Memory,0,rs.Si ze,0);
  BASS_ChannelPlay(strs,false);
  rs.Free;
end;

Danny92 10. Aug 2017 13:11

AW: Mehrere WAV aus Resource gleichzeitig abspielen
 
Ok das hab ich soweit verstanden.

Nun noch das letzte Problem: Die bass.dll wird ja noch verwendet. Die muss ich in die Resource als RCDATA mit einbinden zum kompilieren, was ich schon mal getan habe.
Wie kann ich nun zur Laufzeit auf diese zugreifen?

Ich hab schon einiges mit PBTMemoryModule ausprobiert, wo mir Delphi aber nicht wirklich weiterhilft.

Delphi-Quellcode:
procedure TForm1.FormCreate(Sender: TObject);
var
  i: byte;
  ms: TMemoryStream;
  rs: TResourceStream;
  m_DLLDataSize: int64;
  mp_DllData: Pointer;
  btMM: PBTMemoryModule;
begin
  if 0 <> FindResource(hInstance, 'DllDatei', RT_RCDATA) then
  begin
    rs := TResourceStream.Create(hInstance, 'DllDatei', RT_RCDATA);
    ms := TMemoryStream.Create;
    try
      ms.LoadFromStream(rs);

      ms.Position := 0;
      m_DllDataSize := ms.Size;
      mp_DllData := GetMemory(m_DllDataSize);

      ms.Read(mp_DllData^, m_DllDataSize);
    finally
      ms.Free;
      rs.Free;
    end;
  end;
**btMM := BTMemoryLoadLibary(mp_DllData, m_DllDataSize);
**try
****if btMM = nil then Abort;
****@m_TestCallstd := BTMemoryGetProcAddress(btMM, 'TestCallstd');
****if @m_TestCallstd = nil then Abort;
****m_TestCallstd('Das ist ein DLL-Speicher Aufruf!');
**except
****Showmessage(Ein Fehler ist enstanden bei Aufruf der DLL : ' + BTMemoryGetLastError);
end;
if Assigned(btMM) then BTMemoryFreeLibrary(btMM);
end;
Sowas hab ich schon gefunden, Delphi kann mit PBTMemoryModule nix anfangen.

Kann mir da noch jemand helfen bitte?

jaenicke 10. Aug 2017 13:34

AW: Mehrere WAV aus Resource gleichzeitig abspielen
 
Google hilft:
https://github.com/DSPlayer/memorymodule

Aber gerade bei einem Spiel sehe ich die Notwendigkeit nicht. Da ist es doch eher komisch, wenn nicht noch DLLs und andere Dateien neben der Exe liegen.

Danny92 10. Aug 2017 21:09

AW: Mehrere WAV aus Resource gleichzeitig abspielen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Wenn ich die BTMemoryModule einbinde, kommt ne Fehlermeldung "ungültige Compileranweisung" in Zeile 50 der Datei (siehe Anhang)

Hää? Was is das denn für ne Scheiße...:o

jaenicke 10. Aug 2017 21:37

AW: Mehrere WAV aus Resource gleichzeitig abspielen
 
Du benutzt noch eine sehr alte Delphiversion. Da wirst du Anpassungen machen müssen, in den letzten knapp 20 Jahren seit dem Erscheinen von Delphi 6 hat sich nun einmal einiges getan. Mit neueren Delphiversionen funktioniert es direkt.

Wie wäre es mit der kostenlosen Starter Edition der aktuellen Delphiversion?
https://www.embarcadero.com/de/products/delphi/starter
Damit sollte der Quelltext kompilieren.

Danny92 13. Aug 2017 13:56

AW: Mehrere WAV aus Resource gleichzeitig abspielen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Ja danke das sieht schon viel besser aus! Jetzt kompiliert es auch.

Allerdings muss bei Ausführung der exe immer noch die Bass.dll im Verzeichnis vorhanden sein, und ich weiß nicht warum. Wo im Code (Anhang) benutze ich die denn? Ich wäre echt dankbar, wenn mir jemand sagen könnte, wie ich die Bass.dll, die ich in der Resource schon hab und brauche, jetzt verwenden kann.

jaenicke 14. Aug 2017 05:29

AW: Mehrere WAV aus Resource gleichzeitig abspielen
 
Naja, du lädst zwar die DLL aus dem Stream, benutzt sie aber danach gar nicht. Stattdessen benutzt du die statische Bindung via external:
Delphi-Quellcode:
const
{$IFDEF MSWINDOWS}
  bassdll = 'bass.dll';
{$ENDIF}
{$IFDEF LINUX}
  bassdll = 'libbass.so';
{$ENDIF}
{$IFDEF MACOS}
  bassdll = 'libbass.dylib';
{$ENDIF}

function BASS_SetConfig(option, value: DWORD): BOOL; {$IFDEF MSWINDOWS}stdcall{$ELSE}cdecl{$ENDIF}; external bassdll;
Wenn du das so benutzt, sucht Windows beim Start der Anwendung nach der DLL bevor dein Code überhaupt ausgeführt wird. Stattdessen musst du die Funktionen dynamisch laden:
https://de.wikibooks.org/wiki/Progra...ches_Einbinden

Danny92 14. Aug 2017 14:02

AW: Mehrere WAV aus Resource gleichzeitig abspielen
 
Jo vielen Dank! Es funktioniert. Ich habe das dynamische Einbinden gestern noch probiert, da ist mein Programm aber immer abgestürzt. Und jetzt weiß ich woran es gelegen hat: Ich hab die Aufrufkonvention stdcall vergessen! Super danke nochmal. Du bist spitze!


Alle Zeitangaben in WEZ +1. Es ist jetzt 01:03 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz