Autor Beitrag
galagher
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 2510
Erhaltene Danke: 44

Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
BeitragVerfasst: Fr 20.11.15 20:03 
Hallo!

Wie kann ich eine MP3-Datei in mein Programm einbinden und daraus dann abspielen?

Mit WAV klappt das ja, aber geht es auch mit einer MP3-Datei? Hab's auf die "klassische" Art mit einer .rc versucht, und ja, die Daten der MP3-Datei werden eingebunden, aber das Abspielen funktioniert nicht, jedenfalls nicht mit PlaySound und auch nicht mit SndPlaySound!

_________________
gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
SMO
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 120
Erhaltene Danke: 18


D2005 Personal
BeitragVerfasst: Fr 20.11.15 22:20 
Dass es mit diesen alten APIs nicht klappt ist klar. Die sind nur für WAV ausgelegt.
Früher gab es den ACM in Windows, Audio Compression Manager. Damit konnte man diverse Audiocodecs installieren und nutzen, unter anderen auch MP3.
Den ACM gibt es natürlich aus Kompatibilitätsgründen noch immer, aber Microsoft rät schon lange davon ab, ihn noch zu benutzen. Er unterstützt z.B. auch keine Formate mit variablen Bitraten (VBR), wie sie MP3 durchaus haben kann.

Ich kenne drei Möglichkeiten, wie du eine MP3-Datei abspielen kannst.
  1. Mit der MCI/MMSystem API. Auch die ist veraltet und sollte nicht mehr verwendet werden. Ist relativ einfach zu benutzen, jedenfalls für Dateien. Deine MP3-Ressource direkt aus dem Arbeitsspeicher abzuspielen wäre wahrscheinlich möglich, aber komplizierter.
  2. Mit DirectShow. Ist anfangs etwas kompliziert, wird über Interface-Objecte angesprochen. Hier gibt's Beispielcode, der aber wahrscheinlich etwas angepasst werden muss (die DirectX Header sollten in deinem Delphi XE2 dabei sein und brauchen nicht separat installiert zu werden).
  3. Mit einer Drittlösung wie z.B. BASS.DLL. Vorteil: unterstützt sehr viele Formate, relativ einfach zu benutzen (eine Delphi-Unit für die API ist vorhanden). Nachteil: benötigt die zusätzliche DLL, darf nicht kommerziell eingesetzt werden ohne zu zahlen.

Für diesen Beitrag haben gedankt: galagher
galagher Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 2510
Erhaltene Danke: 44

Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
BeitragVerfasst: Sa 21.11.15 09:18 
user profile iconSMO hat folgendes geschrieben Zum zitierten Posting springen:
Dass es mit diesen alten APIs nicht klappt ist klar. Die sind nur für WAV ausgelegt.
Ich hatte die Hoffnung, dass es mit ein paar "Hintertüren" doch geht! Ok, danke!

_________________
gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
SMO
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 120
Erhaltene Danke: 18


D2005 Personal
BeitragVerfasst: Sa 21.11.15 16:54 
Was möchtest du denn genau mit der MP3-Datei machen? Einfach nur im Hintergrund abspielen von Anfang bis Ende?

Hier mal ein kleines Codebeispiel für MCI (ja, ich sagte man soll es eigentlich nicht mehr verwenden, aber zur Not geht es noch ;)).
ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
uses
  // ...
  MMSystem;

const
  // über diesen beliebigen Alias wird die zu spielende Datei für die MCI API identifiziert
  MyAlias = 'myfile';

type
  TForm1 = class(TForm)
  // ...
  private
    procedure PlayFile(const FileName: string);
    procedure MciNotify(var Msg: TMessage); message MM_MCINOTIFY;
  // ...
  end;


// MyMciSendString: kleiner Wrapper für mciSendString
function MyMciSendString(const Command: string; CallbackWnd: HWND; out MciReturn: string): MCIERROR;
var
  mciReturnStr: array [Byte] of Char;
begin
  Result := mciSendString(PChar(Command), @mciReturnStr[0], SizeOf(mciReturnStr), CallbackWnd);
  MciReturn := mciReturnStr;
  if Result <> 0 then
  begin
    if not mciGetErrorString(Result, @mciReturnStr[0], Length(mciReturnStr)) then
      mciReturnStr[0] := #0;
    ShowMessage('MCI Fehler %d (%s) nach Befehl "%s"', [Result, mciReturnStr, Command]);
  end;
end;

procedure TForm1.PlayFile(const FileName: string);
var
  MciReturn: string;
begin
  if MyMciSendString(Format('open "%s" alias %s wait', [FileName, MyAlias]), Self.Handle, MciReturn) = ERROR_SUCCESS then
  begin
    // numerisches Handle für diese Datei merken, falls man es für MciNotify braucht
    // MciHandle := StrToInt(MciReturn);
    MyMciSendString(Format('play %s notify', [MyAlias]), Self.Handle, MciReturn);

    // Vorzeitiges terminieren des Abspielvorgangs einfach per
    // MyMciSendString(Format('close %s', [MyAlias]), Self.Handle, MciReturn);
    // Analog für 'pause', 'resume', 'stop'...
    // 'status %s mode' liefert in MciReturn den aktuellen Zustand ('playing', 'paused', 'stopped')
  end;
end;

procedure TForm1.MciNotify(var Msg: TMessage);
begin
{ Wenn man einen MCI-Befehl mit dem "notify"-Flag startet, bekommt man hier zu bestimmten
  Ereignissen eine Nachricht.
    Msg.WParam = Flags (Typ der Nachricht)
    Msg.LParam = DeviceID/MciHandle (Sender der Nachricht)
  Play mit notify:
    MCI_NOTIFY_SUCCESSFUL = Die Datei wurde fertig abgespielt (egal ob mit oder ohne Pause)
    MCI_NOTIFY_ABORTED = es wurde ein Stop oder Close empfangen, bevor das Abspielen fertig war
    MCI_NOTIFY_SUPERSEDED = ein anderer Befehl (z.B. Pause) hat sich notify geschnappt und alle
                            folgenden Nachrichten beziehen sich deswegen auf den neuen Befehl
    MCI_NOTIFY_FAILURE = ein Fehler ist aufgetreten

  Andere Befehle (Pause, Resume, Play, Stop) senden in der Regel nur MCI_NOTIFY_SUCCESSFUL,
  wenn für sie das notify-Flag gesetzt wurde. }


  if Msg.WParam = MCI_NOTIFY_SUCCESSFUL then
    ShowMessage(Format('Vorgang für MciHandle %d wurde erfolgreich beendet', [Msg.LParam]))
  else if Msg.WParam = MCI_NOTIFY_ABORTED then
    ShowMessage(Format('Vorgang für MciHandle %d wurde abgebrochen', [Msg.LParam]));
end;
galagher Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 2510
Erhaltene Danke: 44

Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
BeitragVerfasst: Sa 21.11.15 19:02 
user profile iconSMO hat folgendes geschrieben Zum zitierten Posting springen:
Was möchtest du denn genau mit der MP3-Datei machen? Einfach nur im Hintergrund abspielen von Anfang bis Ende?
Ja, soll aber gestoppt werden können, ...

user profile iconSMO hat folgendes geschrieben Zum zitierten Posting springen:
PlayFile(const FileName: string);
... und soll vor allem keine separate Datei sein, sondern als Ressource in der Programmdatei enthalten sein. Genauso, wie ich es momentan mit der WAV-Datei mache. Genügt mir im Prinzip ja, ich wollte nur wissen, ob nicht ebenso eine MP3-Datei als Ressource eingebunden werden und vor allem abgespielt(!) werden kann!
Denn einbinden kann ich die MP3-Datei, nur weiss ich nicht, wie ich sie abspiele.

_________________
gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
SMO
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 120
Erhaltene Danke: 18


D2005 Personal
BeitragVerfasst: Sa 21.11.15 21:01 
user profile icongalagher hat folgendes geschrieben Zum zitierten Posting springen:
Ja, soll aber gestoppt werden können

Das ist kein Problem. Wie das mit MCI ginge ist ja im obigen Code ersichtlich.

user profile icongalagher hat folgendes geschrieben Zum zitierten Posting springen:
... und soll vor allem keine separate Datei sein, sondern als Ressource in der Programmdatei enthalten sein. Genauso, wie ich es momentan mit der WAV-Datei mache. Genügt mir im Prinzip ja, ich wollte nur wissen, ob nicht ebenso eine MP3-Datei als Ressource eingebunden werden und vor allem abgespielt(!) werden kann!
Denn einbinden kann ich die MP3-Datei, nur weiss ich nicht, wie ich sie abspiele.

Dass die Datei am besten aus dem Speicher abgespielt werden soll, ist mir klar. Das ist leider weder bei MCI noch DirectShow ohne weiteres möglich. Du könntest zur Not die MP3-Ressource "entpacken" und als temporäre Datei zwischenspeichern. Oder eben BASS.DLL benutzen. Da geht das Abspielen aus dem Speicher genau wie aus einer Datei (BASS_StreamCreateFile).
galagher Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 2510
Erhaltene Danke: 44

Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
BeitragVerfasst: Sa 21.11.15 21:08 
user profile iconSMO hat folgendes geschrieben Zum zitierten Posting springen:
Du könntest zur Not die MP3-Ressource "entpacken" und als temporäre Datei zwischenspeichern.

Das habe ich auch schon angedacht, gefällt mir aber nicht so recht.

user profile iconSMO hat folgendes geschrieben Zum zitierten Posting springen:
Oder eben BASS.DLL benutzen. Da geht das Abspielen aus dem Speicher genau wie aus einer Datei (BASS_StreamCreateFile).

Das werde ich mir zumindest mal ansehen, also BASS.DLL runterladen usw. und dann damit rumtesten.
Immerhin läuft es ja auch mit der WAV-Datei, nur bläht diese halt die EXE ziemlich auf. MP3 wäre da schon besser!

_________________
gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
Perlsau
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: So 22.11.15 05:30 
user profile icongalagher hat folgendes geschrieben Zum zitierten Posting springen:
Immerhin läuft es ja auch mit der WAV-Datei, nur bläht diese halt die EXE ziemlich auf. MP3 wäre da schon besser!

Wenn's nicht so sehr auf die Qualität ankommt, wäre das Ogg-Format eine brauchbare Alternative, das komprimiert noch stärker als MP3. Ich hab hier eine Firebird-Datenbank mit Diskussionen, Vorträgen und Interviews, die alle im Ogg-Format in der DB gespeichert sind, zudem noch in Mono und mit 11025 Hz. Die DB-Anwendung setzt ebenfalls die Bass.dll ein.

Die Datenbank belegt derzeit 7.770.193.920 Bytes (7,7 Gig), was 770 Stunden und 25 Minuten "Geschwätz" entspricht. Pro Stunde wären das dann rund 10.091.160 Bytes, also rund 10 MB. Konkret belegt eine Ogg-Datei, die eine Spieldauer von einer Stunde und 4 Sekunden aufweist, eine Speichergröße von 10.240.169 Bytes. Egal wie ich's auch anstelle, ich schaffe es nicht, mit dem MP3-Format eine gleichgroße oder gar kleinere Datei zu erzeugen, obwohl ich eingestehen muß, daß die kleinste MP3-Datei, die sich aus dieser Ogg-Datei via Audacity erzeugen läßt, lediglich 800 KB größer ist als die Ogg-Datei.
Einloggen, um Attachments anzusehen!

Für diesen Beitrag haben gedankt: galagher
galagher Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 2510
Erhaltene Danke: 44

Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
BeitragVerfasst: Sa 28.11.15 09:37 
user profile iconPerlsau hat folgendes geschrieben Zum zitierten Posting springen:
Wenn's nicht so sehr auf die Qualität ankommt, wäre das Ogg-Format eine brauchbare Alternative, das komprimiert noch stärker als MP3.
Sollte schon eine gewisse Qualität haben!
Wie gesagt, mit der WAV geht es ja, ich habe nur momentan nicht viel Zeit, mir die bass.dll anzusehen, werde dies aber definitiv noch machen. Kann man ja immer mal brauchen! Danke!

_________________
gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
Holgerx
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 62
Erhaltene Danke: 27

Win95 - Win11 / MSServer2000 - MSServer2019
Delphi 6pro / XE4
BeitragVerfasst: Sa 28.11.15 13:31 
Hab mal nen bischen gegooglt..

libzplay.sourceforge.net/

Scheint eine einfache und als 'PF'-Version sogar Licence-Free Lib zu sein, um u.a. OGG-Streams abspielen zu können..
Daniel_DT
ontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic starofftopic star
Beiträge: 16



BeitragVerfasst: Di 25.04.17 11:02 
user profile icongalagher hat folgendes geschrieben Zum zitierten Posting springen:
Sollte schon eine gewisse Qualität haben!

Seh ich ähnlich.. OGG macht keinen Spaß finde ich.
t.roller
ontopic starontopic starontopic starontopic starontopic starofftopic starofftopic starofftopic star
Beiträge: 118
Erhaltene Danke: 34



BeitragVerfasst: Di 25.04.17 16:48 
user profile icongalagher hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconSMO hat folgendes geschrieben Zum zitierten Posting springen:
Dass es mit diesen alten APIs nicht klappt ist klar. Die sind nur für WAV ausgelegt.
Ich hatte die Hoffnung, dass es mit ein paar "Hintertüren" doch geht! Ok, danke!


Guckst Du hier:
www.delphipraxis.net/1363110-post13.html