Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Delphi waveIn Problem mit Callback (https://www.delphipraxis.net/141703-wavein-problem-mit-callback.html)

iphi 14. Okt 2009 13:01


waveIn Problem mit Callback
 
Hallo,

ich möchte von der Soundkarte mittels WaveIn... Sounds aufnehmen, das ganze mittels Callback Funktion.
Das Aufnehmen klappt auch ganz gut, aber mein Programm beendet nicht mehr sauber.

Symptom: Wenn mein Programm läuft und ich starte die Aufnahme, werden sichtbar im Task Manager zwei neue Threads gestartet. Wenn ich die Aufnahme beende, werden die Threads aber nicht mehr beendet. Bei erneuter Aufnahme werden weitere zwei Threads erzeugt. Bei Beendigung des Programms verschwindet zwar die MainForm, aber die Threads arbeiten im Hintergrund weiter.

Wenn ich das ganze mit Windowsmessages statt mit Callback mache, tritt das Problem nicht auf.

Könnte es daran liegen, dass ich das Sounddevice aus der Callbackfunktion heraus stoppe?

Gruß, Thomas

igel457 14. Okt 2009 14:17

Re: waveIn Problem mit Callback
 
Zitat:

Zitat von iphi
Könnte es daran liegen, dass ich das Sounddevice aus der Callbackfunktion heraus stoppe?

Ja...

Zitat aus der MSDN:
Zitat:

Applications should not call any system-defined functions from inside a callback function, except for EnterCriticalSection, LeaveCriticalSection, midiOutLongMsg, midiOutShortMsg, OutputDebugString, PostMessage, PostThreadMessage, SetEvent, timeGetSystemTime, timeGetTime, timeKillEvent, and timeSetEvent. Calling other wave functions will cause deadlock.
Edit:
Achso, das habe ich ganz vergessen:

Herzlich Willkommen in der Delphi Praxis :dp:

Das wollte ich schon immer mal machen

iphi 14. Okt 2009 14:52

Re: waveIn Problem mit Callback
 
Danke für die prompte Antwort!

Jetzt drängt sich mir nur die Frage auf, wie ichs richtig mache.

Ich möchte mein Programm von Windows-Messages auf Callback umstellen, weil ich bisher beobachte, dass der Audiodatenstrom bei CPU-Lastspitzen (die kommen z.B. zustande, wenn ich die Fenstergröße ändere, da wird einiges geplottet), Unterbrechungen ausweist.
Mein Verdacht: Die Windows Messages werden dann nicht zeitnah abgearbeitet und das sollte mit der Callback Funktion besser sein (die hoffentlich in einem Realtime Thread aufgerufen wird).

Wenn ich allderdings in der Callbackfunktion wieder nur ein PostMessage absetze und alles andere außerhalb erledige, ist der Vorteil der Callback-Funktion doch wieder dahin, oder?

Was sollte ich denn in der Callback-Funktion erledigen?

Zeitkritisch ist wohl
-das Speichern der Audiodaten
-das Requeueing eines neuen Audiobuffers (das darf ich aber wohl nicht in der Callback Funktion erledigen, richtig?)

Gruß,
Thomas

P.S. Hab mal alles aus der Callback-Funktion rausgeschmissen und nur einen PostMessage reingesetzt und das Problem war behoben. Du hast also Recht.

igel457 14. Okt 2009 15:05

Re: waveIn Problem mit Callback
 
Hallo,

ich kenne mich jetzt nicht direkt mit WaveIn aus, sondern nur mit WaveOut. Allgemein darfst/solltest du die Callbackfunktionen nur zum setzen von Flags verwenden, die dann entsprechend von einem anderen Thread in periodischen Abständen "kontrolliert" werden.

Bei WaveOut mache ich das zum Beispiel so:
Delphi-Quellcode:
procedure stream_callback(hwo: HWAVEOUT; uMsg: Cardinal; dwInstance, dwParam1, dwParam2: DWORD);stdcall;
begin
  if (uMsg = WOM_DONE) then
  begin
    with TAuWaveOutStreamDriver(Pointer(dwInstance)) do
      FFreeblocks := FFreeblocks + 1;
  end;
end;
Das Hochzählen der Variable informiert hierbei den Ausgabethread darüber, dass neue Daten zur Ausgabe bereitgestellt werden müssen.

Entsprechend anders herum musst du das dann wohl bei WaveIn machen. Dort müssen dann die beschriebenen Pakete abgeholt werden.

Hoffe das hilft dir ein wenig,
Andreas

PS: Wenn dir das was hilft: Hier ist eine Unit von mir, die WaveOut verwendet - das sollte entsprechend übertragbar sein: http://audorra.svn.sourceforge.net/v...w=markup#l_408

iphi 14. Okt 2009 19:26

Re: waveIn Problem mit Callback
 
D.h. Du beschäftigst einen eigenen Thread, der ständig FFreeblocks monitort und die Buffer füllt wenn nötig? Der muss natürlich Realtime-Priorität haben, wenns lückenlos gehen soll.

Ich hab mal ein wenig rumgespielt. Buffer requeuen kann man in der Callback Funktion schon. Nur die Aufnahme abbrechen darf man von da aus nicht. Das führt wie MS es ausdrückt zum Deadlock.

Gruß, Thomas

P.S.
Ich hab hier die Schwarte von Alan Moore (Win32 Multimedia API), aber der Beispielcode von der Buch-CD zu waveIn (Kapitel 3) macht auch einen Deadlock :-). Bin also in guter Gesellschaft.


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

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