Autor Beitrag
kissgdr
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 20



BeitragVerfasst: Mo 04.01.21 21:48 
Ich benötige Hilfe zur Lösung des folgenden Problems:
Ich möchte ein, in Delphi7 geschriebenes Programm mit kurzen Tonsignalen erweitern.
Die Audio-dateien sind 1-3 Sekunden lang (.wav oder .mp3) und sind in einem Memorystream gespeichert.
Bei .wav-Dateien löst MediaPlayer das Problem leider nicht, da nur externe Dateien verarbeitet werden können (FileName='string').
(Darüber hinaus kann ein .exe-Programm, das MediaPlayer verwendet, in einer Win10-Umgebung nicht ausgeführt werden, da ein 'Exception EMCIDeviceError' wird generiert.)
Ich suche nach einer Lösung, die
- kann Memorystream als Input verwenden
- das erstellte EXE-Modul wird auch in Win10-Umgebung laufen
Hotte123
Hält's aus hier
Beiträge: 1



BeitragVerfasst: Mo 04.01.21 23:06 
Moin,

schau dir mal die bass.dll an. Nette Beschreibung unter MeMP - Mein einfacher Mp3-Player.

Viel Spaß noch.

Moderiert von user profile iconTh69: URL-Titel hinzugefügt.
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4391
Erhaltene Danke: 943

Win10
C#, C++ (VS 2015/17/19)
BeitragVerfasst: Di 05.01.21 11:14 
Es gibt auch die WinAPI-Funktion sndPlaySound (für Waveform-Audio), s.a. Delphi: play sound from memorystream.
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 18988
Erhaltene Danke: 1685

W10 x64 (Chrome, Edge)
Delphi 10.4 Ent, Oxygene, C# (VS 2019), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Di 05.01.21 11:21 
Die Funktion kann man auch direkt auf Ressourcen verwenden ohne die Ressource vorher in einen MemoryStream zu kopieren (was ich hier einmal vermute): Playing WAVE Resources

Mit der genannten bass.dll hat man allerdings deutlich mehr Möglichkeiten.

Moderiert von user profile iconTh69: URL-Titel hinzugefügt.
kissgdr Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 20



BeitragVerfasst: Di 05.01.21 18:54 
Danke für die Ideen. Ich habe bisher keine Software außerhalb des offiziellen Delphi verwendet, ich kenne sie nicht. Ihr Studium dauert länger.

Die kurze Audiosignale derzeit sind im WAV-Format, und wegen das spezielle GSM-WAV-Format sind sie kürzer als das MP3-Format, und die Tonqualität ebenfalls akzeptabel ist. Da ich 10-12 solcher kleinen Audiodateien (jeweils 10-25 KB) verarbeiten möchte, finde ich es benutzerfreundlicher, sie in die EXE-Datei zu integrieren, daher möchte ich Memorystream verwenden.
kissgdr Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 20



BeitragVerfasst: Mi 06.01.21 14:08 
Das empfohlene Beispiel Delphi: play Sound from memorystream verwendet die PlayWaveStream-Prozedur, aber ich habe nur eine C ++ - Beschreibung dafür gefunden.
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 18988
Erhaltene Danke: 1685

W10 x64 (Chrome, Edge)
Delphi 10.4 Ent, Oxygene, C# (VS 2019), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mi 06.01.21 14:21 
user profile iconkissgdr hat folgendes geschrieben Zum zitierten Posting springen:
Das empfohlene Beispiel Delphi: play Sound from memorystream verwendet die PlayWaveStream-Prozedur, aber ich habe nur eine C ++ - Beschreibung dafür gefunden.
Die Prozedur ist doch dort komplett enthalten in dem Link.
kissgdr Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 20



BeitragVerfasst: Mi 06.01.21 19:13 
leider kann ich es nicht finden.
Signin oder Login ist ständig falsch (Timeout).
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 18988
Erhaltene Danke: 1685

W10 x64 (Chrome, Edge)
Delphi 10.4 Ent, Oxygene, C# (VS 2019), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mi 06.01.21 21:05 
user profile iconkissgdr hat folgendes geschrieben Zum zitierten Posting springen:
leider kann ich es nicht finden.
Signin oder Login ist ständig falsch (Timeout).
Du musst dich dort nicht einloggen. Das komplette Beispiel ist direkt zu sehen, hier der Teil mit der genannten Funktion:

PlayWaveStream
Einloggen, um Attachments anzusehen!
kissgdr Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 20



BeitragVerfasst: Do 07.01.21 16:38 
Ich sehe das auch, aber der referenzierte sndPlaySound kann nicht aufgelöst werden.
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 18988
Erhaltene Danke: 1685

W10 x64 (Chrome, Edge)
Delphi 10.4 Ent, Oxygene, C# (VS 2019), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Do 07.01.21 23:21 
Eine Suche in den bei Delphi normalerweise mitgelieferten Quelltexten oder bei Google zeigt, dass die Funktion in der Unit Winapi.MMSystem zu finden ist.
kissgdr Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 20



BeitragVerfasst: Fr 08.01.21 15:03 
user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Eine Suche in den bei Delphi normalerweise mitgelieferten Quelltexten oder bei Google zeigt, dass die Funktion in der Unit Winapi.MMSystem zu finden ist.

Vielen Dank.
Ich habe dies zuvor in der Delphi7-Help (Windows SDK), gefunden.
Ich habe viele Dokumentátionen durchgelest, leider habe ich bisher nirgends ein Beispiel gefunden, das zeigt, wie eine bestimmte win.api aus einer Delphi-Umgebung aufgerufen werden kann. (Was soll ich dazu tun?)
In meiner bisherigen Arbeit war Delphis eigenes Toolkit ausreichend.
kissgdr Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 20



BeitragVerfasst: Fr 08.01.21 15:42 
user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Eine Suche in den bei Delphi normalerweise mitgelieferten Quelltexten oder bei Google zeigt, dass die Funktion in der Unit Winapi.MMSystem zu finden ist.

Nochmal vielen Dank!
Ich habe die Lösung gefunden!! uses MMSystem;
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 18988
Erhaltene Danke: 1685

W10 x64 (Chrome, Edge)
Delphi 10.4 Ent, Oxygene, C# (VS 2019), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Fr 08.01.21 17:46 
Ach ja, bei Delphi 7 gab es die Namespaces noch nicht, da habe ich nicht dran gedacht. Damals hieß die Unit noch nur MMSystem wie du ja schon gemerkt hast.

Seit einigen Jahren heißt sie der besseren Übersicht halber Winapi.MMSystem.
kissgdr Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 20



BeitragVerfasst: Fr 08.01.21 21:47 
Basierend auf den Ideen, die ich erhalten habe, habe ich ein Testprogramm erstellt, das so funktioniert, wie ich es möchte:
- Kurze WAV-Signale werden von einem MemoryStream abgespielt
- Das Programm funktioniert auch in XP-, Win7- und Win10-Umgebungen

Ich mag diese Lösung wirklich nicht, weil ich das Ende des Streams beim Abspielen nicht kontrollieren kann.
Daher verwende ich eine sehr grobe Lösung.
Leider konnte ich nirgendwo ein Delphi7-Dokument finden, mit dem ich dieses Problem lösen konnte
(wie z.B. in TMediaPlayer die Notify-Properties)

Ich würde mich sehr freuen, wenn ich eine günstigere Lösung finden könnte

Wie kann ich das Testprogram aufladen? (minimum .pas, .dfm, .dpr)
Gausi
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 8495
Erhaltene Danke: 453

Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
BeitragVerfasst: Fr 08.01.21 21:52 
Ich hänge mich hier auch mal kurz dran, da ich per Mail dazu eine Anfrage bekommen habe:

Mein Tutorial zur bass.dll geht da ja etwas am Thema vorbei, aber man kann mit der bass.dll wohl auch aus dem Speicher heraus abspielen. Ansätze dazu sollten sich in der Dokumentation zur bass.dll finden. Wie das dort mit Notifications geht, weiß ich leider auch nicht genau.

Ich habe den Thread hier nebenbei verfolgt, und nicht auf die E-Mail geantwortet, da das hier im Topic ja durchaus in eine konstruktive Richtung läuft. :D


Testprogramm hochladen: am besten zippen und dann per "Dateianhang hinzufügen" an den Beitrag dran hängen.

_________________
We are, we were and will not be.
kissgdr Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 20



BeitragVerfasst: Fr 08.01.21 22:03 
Ich habe gefunden - Dateianhang hinzufügen
Einloggen, um Attachments anzusehen!
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 18988
Erhaltene Danke: 1685

W10 x64 (Chrome, Edge)
Delphi 10.4 Ent, Oxygene, C# (VS 2019), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Fr 08.01.21 22:06 
user profile iconkissgdr hat folgendes geschrieben Zum zitierten Posting springen:
Ich mag diese Lösung wirklich nicht, weil ich das Ende des Streams beim Abspielen nicht kontrollieren kann.
Möchtest du nur einen Teil des Sounds abspielen und das Ende angeben?

Oder möchtest du wissen wann das Abspielen beendet ist? Das geht sehr einfach, weil sndPlaySound mit dem Flag SND_SYNC erst nach dem Ende des Abspielens zurückkehrt. Wenn du das also in einen Thread packst, kannst du danach ein Event auslösen ohne etwas anderes als den Thread zu blockieren.

// EDIT:
Ich dachte es mir schon, dass das zweite gemeint ist. Einfaches Beispiel (allerdings reagiert die Exe dann während des Abspielens nicht, daher der Hinweis auf einen Thread):
ausblenden 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:
procedure PlayWaveStream(Stream: TMemoryStream);
begin
  if Stream = nil then
    sndPlaySound(nil, SND_SYNC)
  else
    sndPlaySound(Stream.Memory, (SND_SYNC or SND_MEMORY));
end;

procedure TForm1.ExitClick(Sender: TObject);
begin
  Close;
end;

procedure TForm1.StartClick(Sender: TObject);
begin
  wav_stream:= TMemoryStream.Create;
  try
    wav_stream.LoadFromFile('signal_1.wav');
    PlayWaveStream(wav_stream);
    wav_stream.LoadFromFile('signal_2.wav');
    PlayWaveStream(wav_stream);
  finally
    wav_stream.Free;
  end;
end;

Halt sollte man nie verwenden. Close schließt das Programm sauber.
kissgdr Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 20



BeitragVerfasst: Fr 08.01.21 22:20 
Ohne .exe file probiere ich nochmal
Einloggen, um Attachments anzusehen!
kissgdr Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 20



BeitragVerfasst: Fr 08.01.21 23:16 
Ich habe die Testdatei zweimal gesendet, da sowohl Google Chrome als auch Win10 beim Herunterladen aufgrund der EXE-Datei einen Virus gemeldet haben.

Danke für die schnelle Antwort - mit Delphi Code.
Leider kann ich dies aufgrund externer Dateien nicht verwenden.
ich muss sagen, dass ich in meinem Programm viele kleine externe Dateien verwende.
(Graphik von Schachfiguren, Hilfedokumenten und Audiodateien).
Ich speichere diese in einer Containedatei und platziere die erforderliche Segment - bei Bedarf - im Memorystream, aufgrund eine Seriennummer.
Wenn das Programm veröffentlicht wird, installiert der Benutzer zusätzlich zu .exe nur eine Containerdatei.

In meiner groben Lösung kann das Signal länger oder kürzer sein als waiting_for(x), es funktioniert immer gut.
Wenn das Signal länger ist, wird es abgeschaltet, wenn es kürzer ist, dauert es bis zum Ende des Intervalls.