AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Multimedia Delphi WaveIn-Problem bei grossen Buffern (Waveform Audio API)
Thema durchsuchen
Ansicht
Themen-Optionen

WaveIn-Problem bei grossen Buffern (Waveform Audio API)

Ein Thema von HHick123 · begonnen am 4. Feb 2008 · letzter Beitrag vom 31. Mai 2008
Antwort Antwort
Seite 1 von 2  1 2      
HHick123

Registriert seit: 23. Jul 2007
73 Beiträge
 
#1

WaveIn-Problem bei grossen Buffern (Waveform Audio API)

  Alt 4. Feb 2008, 14:17
Hallo Leute!

Ich schreibe gerade ein Programm (XP Servicepack 2) mit WaveIn und WaveOut, wobei
ich EVENT_CALLBACK verwende.

Ich verwende jeweils 2 Buffer, wobei jeweils einer von mir vorbereitet wird,
während der andere aufgezeichnet bzw. gespielt wird.

Das klappt auch im Prinzip sehr gut, allerdings bekomme ich ein Problem
mit großen Buffergroessen (z.B. größer als 500ms oder größer als 1s)
und zwar nur bei manchen Soundkarten (z.B. beim Sennheiser PC-166-USB).

Das Problem äussert sich darin, dass in den aufgezeichneten Daten plötzlich
(teilweise mehrere 100ms lange) Stücke fehlen. Das Problem beginnt erst mit dem
Start von WaveOut (welches selber aber anstandslos funktioniert).

Bei der Benutzung von kleineren Buffern verschwindet das Problem plötzlich.

Die zurückgegebenen WaveIn-Buffer haben stets die erwartet Länge.
Alle Waveform-API-Calls liefern MMSYSERR_NOERROR.

Was könnte da sein???????
Ich bin schon reif fürs Irrenhaus!!!

Bin für jeden Hinweis dankbar.

Schönen Gruß, Helmut

Es folgt ein Trace der API-Calls eines Fehlerfalls (im Klammer stehen die Zeiten,
die der Call gedauert hat, Zeiten ermittelt mit PerformanceCounter). In dem Beispiel
läuft WaveIn immer und 2x wird etwas über WaveOut ausgegeben. Die Buffer sind 4 Sekunden lang.

0ms (160ms) WaveInOpen
160ms (24ms) WaveOutOpen
184ms (0ms) WaveOutPause
196ms (0ms) WaveInPrepareHeader 0
196ms (0ms) WaveInPrepareHeader 1
196ms (0ms) WaveOutPrepareHeader 0
196ms (0ms) WaveOutPrepareHeader 1
196ms (0ms) WaveInStart
197ms (0ms) WaveInAddBuffer 0
197ms (0ms) WaveInAddBuffer 1
4201ms -> EVENT OnInputBuffer 0
4201ms (0ms) WaveInUnprepareHeader 0
4201ms (0ms) WaveInPrepareHeader 0
4201ms (0ms) WaveInAddBuffer 0
8201ms -> EVENT OnInputBuffer 1
8201ms (0ms) WaveInUnprepareHeader 1
8201ms (0ms) WaveInPrepareHeader 1
8201ms (0ms) WaveInAddBuffer 1
8617ms (1ms) WaveOutWrite 0
8618ms (0ms) WaveOutRestart
8619ms (0ms) WaveInGetPosition
8619ms (0ms) WaveOutWrite 1
12471ms -> EVENT OnInputBuffer 0
12471ms (0ms) WaveInUnprepareHeader 0
12471ms (0ms) WaveInPrepareHeader 0
12471ms (0ms) WaveInAddBuffer 0
12762ms -> EVENT OnOutputBuffer 0
12762ms (0ms) WaveOutUnprepareHeader 0
12763ms (0ms) WaveOutPrepareHeader 0
12763ms (0ms) WaveOutWrite 0
16624ms -> EVENT OnOutputBuffer 1
16624ms (0ms) WaveOutUnprepareHeader 1
16624ms (0ms) WaveOutPrepareHeader 1
16624ms (0ms) WaveOutWrite 1
16685ms -> EVENT OnInputBuffer 1
16685ms (0ms) WaveInUnprepareHeader 1
16685ms (0ms) WaveInPrepareHeader 1
16685ms (0ms) WaveInAddBuffer 1
20624ms -> EVENT OnOutputBuffer 0
20624ms (0ms) WaveOutUnprepareHeader 0
20624ms (0ms) WaveOutPrepareHeader 0
20624ms -> EVENT OnTimeOut ENDOFPLAYBACK
20899ms -> EVENT OnInputBuffer 0
20899ms (0ms) WaveInUnprepareHeader 0
20899ms (0ms) WaveInPrepareHeader 0
20899ms (0ms) WaveInAddBuffer 0
24624ms -> EVENT OnOutputBuffer 1
24624ms (0ms) WaveOutUnprepareHeader 1
24624ms (0ms) WaveOutPrepareHeader 1
24624ms (0ms) WaveOutUnprepareHeader 0
24624ms (0ms) WaveOutUnprepareHeader 1
24625ms (33ms) WaveOutClose
24657ms (31ms) WaveOutOpen
24688ms (0ms) WaveOutPause
24688ms (0ms) WaveOutPrepareHeader 0
24688ms (0ms) WaveOutPrepareHeader 1
24899ms -> EVENT OnInputBuffer 1
24900ms (0ms) WaveInUnprepareHeader 1
24900ms (0ms) WaveInPrepareHeader 1
24900ms (0ms) WaveInAddBuffer 1
24901ms (0ms) WaveOutWrite 0
24901ms (0ms) WaveOutRestart
24901ms (0ms) WaveInGetPosition
24902ms (0ms) WaveOutWrite 1
28900ms -> EVENT OnInputBuffer 0
28900ms (0ms) WaveInUnprepareHeader 0
28900ms (0ms) WaveInPrepareHeader 0
28900ms (0ms) WaveInAddBuffer 0
28908ms -> EVENT OnOutputBuffer 0
28908ms (0ms) WaveOutUnprepareHeader 0
28908ms (0ms) WaveOutPrepareHeader 0
28908ms (0ms) WaveOutWrite 0
32900ms -> EVENT OnInputBuffer 1
32900ms (0ms) WaveInUnprepareHeader 1
32900ms (0ms) WaveInPrepareHeader 1
32900ms (0ms) WaveInAddBuffer 1
32908ms -> EVENT OnOutputBuffer 1
32908ms (0ms) WaveOutUnprepareHeader 1
32908ms (0ms) WaveOutPrepareHeader 1
32908ms (0ms) WaveOutWrite 1
36900ms -> EVENT OnInputBuffer 0
36900ms (0ms) WaveInUnprepareHeader 0
36900ms (0ms) WaveInPrepareHeader 0
36900ms (0ms) WaveInAddBuffer 0
36900ms -> EVENT OnTimeOut ENDOFPLAYBACK
36908ms -> EVENT OnOutputBuffer 0
36908ms (0ms) WaveOutUnprepareHeader 0
36908ms (0ms) WaveOutPrepareHeader 0
40900ms -> EVENT OnInputBuffer 1
40900ms (0ms) WaveInUnprepareHeader 1
40900ms (0ms) WaveInPrepareHeader 1
40900ms (0ms) WaveInAddBuffer 1
40908ms -> EVENT OnOutputBuffer 1
40908ms (0ms) WaveOutUnprepareHeader 1
40908ms (0ms) WaveOutPrepareHeader 1
40908ms (0ms) WaveOutUnprepareHeader 0
40908ms (0ms) WaveOutUnprepareHeader 1
40908ms (33ms) WaveOutClose
40941ms (37ms) WaveOutOpen
40978ms (0ms) WaveOutPause
40978ms (0ms) WaveOutPrepareHeader 0
40978ms (0ms) WaveOutPrepareHeader 1
40978ms (72ms) WaveInReset
41050ms (0ms) WaveInUnprepareHeader 0
41050ms (0ms) WaveInUnprepareHeader 1
41050ms (3ms) WaveInClose
41053ms (0ms) WaveOutUnprepareHeader 0
41053ms (0ms) WaveOutUnprepareHeader 1
41053ms (3ms) WaveOutClose

Hier noch ein Teil des Source-Codes:

--snipp--

[edit=Phoenix]Code auf Wunsch entfernt. War zu lang und hatte Fehler.
Die korrigierte Version als Download gibt es ein paar Beiträge weiter unten.
Mfg, Phoenix[/edit]
  Mit Zitat antworten Zitat
elliott

Registriert seit: 3. Apr 2006
17 Beiträge
 
Delphi 2005 Personal
 
#2

Re: WaveIn-Problem bei grossen Buffern (Waveform Audio API)

  Alt 5. Feb 2008, 17:39
Leider hab ich nicht die Zeit deinen ganzen Quelltext durchzusehen.
Als Hilfe kann ich nur dieses Tutorial empfehlen.
Dort wird zwar nur auf das Abspielen eingegangen, aber naja...
Zum Abspielen kannst und solltest du mehr als 2 Puffer benutzen! In dem Tutorial ist von 20 die Rede!!! Damit vermeidest du Lücken...
Ich weiss jetzt nicht genau was du vor hast weil du WaveOut und WaveIn benutzt. Willst du das Aufgenommene gleich wieder abspielen, dann kannst du den WAVEHDR vom Aufnehmen auch gleich zum Abspielen benutzen!

Nachtrag:
Deine Puffergrösse muss mit der Samplerate in Einklang sein! am Besten Puffergrösse = Samplerate *8 *x
  Mit Zitat antworten Zitat
HHick123

Registriert seit: 23. Jul 2007
73 Beiträge
 
#3

Re: WaveIn-Problem bei grossen Buffern (Waveform Audio API)

  Alt 5. Feb 2008, 20:24
Hallo elliott,

Zitat:
Leider hab ich nicht die Zeit deinen ganzen Quelltext durchzusehen.
Ich geb' zu, der war eigentlich ein bischen zu lang, um ihn zu posten - sorry...

Interessant am Tutorial finde ich, dass das andere Funktionen verwendet, um
den Speicher für die Buffer zu reservieren. Ich verwende bis jetzt GlobalAlloc und GlobalLock,
die noch aus 16bit-Windows-Zeiten stammen. Vielleicht ist hier ein Bug begraben,
werd' mal etwas nachgraben...

Zitat:
Dort wird zwar nur auf das Abspielen eingegangen, aber naja...
Ja. Das Abspielen funktioniert bei mir aber eigentlich eh problemlos.

Aus den aufgezeichneten Daten fehlen aber zwischen den Buffern unter Umständen
Zeitspannen (fängt an, wenn ein Playback beginnt),
obwohl ich im API-Trace nichts auffälliges erkennen kann...

Zitat:
Zum Abspielen kannst und solltest du mehr als 2 Puffer benutzen!
In dem Tutorial ist von 20 die Rede!!! Damit vermeidest du Lücken...
Vielleicht werd' ich wohl doch nicht herumkommen, den Fall mit mehreren Buffern durchzudenken.
Bis jetzt hab' ich es gescheut, weil es die Synchronisation zwischen Aufnahme und Wiedergabe eventuell verkompliziert (siehe unten). Ich versteh' aber nicht, warum es nicht mit 2 Buffern gehen soll:
Wenn ich den Buffer z.B. 4 Sekunden lang mache, dann wird es der Treiber doch bitte
hoffentlich schaffen, innerhalb von 8 Sekunden einen neuen Aufnahmebuffer von mir rechtzeitig anzufordern.... (eigentlich tut er das ja auch, aber er macht trotzdem "Denkpausen" zwischen den Buffern). Komischerweise beginnen, wenn dieser Effekt auftritt, dann auch die Samplingbuffer-Daten mit jeweils 6 Samples Nullen.

Zitat:
Ich weiss jetzt nicht genau was du vor hast weil du WaveOut und WaveIn benutzt.
Willst du das Aufgenommene gleich wieder abspielen,
Nein, eigentlich nicht, eher umgekehrt: Ich möchte permanent aufnehmen und gelegentlich
etwas abspielen, wobei mir die Synchronisation wichtig ist, denn dass Abgespielte
(welches über den Luftweg wieder ans Mikro kommt) möchte
ich aus dem aufgenommenen Samplestrom wieder herausschneiden, es soll
nämlich nicht analysiert werden!

Zitat:
Nachtrag:
Deine Puffergrösse muss mit der Samplerate in Einklang sein!
am Besten Puffergrösse = Samplerate *8 *x
Warum *8 *x ?

Viele Grüße, Helmut
  Mit Zitat antworten Zitat
elliott

Registriert seit: 3. Apr 2006
17 Beiträge
 
Delphi 2005 Personal
 
#4

Re: WaveIn-Problem bei grossen Buffern (Waveform Audio API)

  Alt 11. Feb 2008, 11:37
Habe leider nicht so viel Zeit...
Ähm, also Samplerate *8 *x weiss ich jetzt selbst garnicht mehr so genau, warum. Fakt ist, dass dein Puffer so dimensioniert sein muss, dass er mit deiner gewählten "Qualität" teilbar ist. Das heisst: 16-bit, stereo = 2Byte pro Kanal = 4Byte pro Sample...
Aber das ist eher nicht das Top-Thema.
Ich habe mal in meinen Aufzeichnungen nachgeschaut. Dein Problem könnte am CallBack-Event liegen.
Der Event in dem Fall ist nichts anderes als eine WindowsMessage.
Ich habe mal gelesen, dass der CallBack über Thread auf jeden Fall die Beste Methode sein soll.
  Mit Zitat antworten Zitat
HHick123

Registriert seit: 23. Jul 2007
73 Beiträge
 
#5

Re: WaveIn-Problem bei grossen Buffern (Waveform Audio API)

  Alt 12. Feb 2008, 17:23
Zitat:
dass dein Puffer so dimensioniert sein muss, dass er mit deiner gewählten "Qualität" teilbar ist.
Ist OK bei mir. Anders formuliert: Der Buffer muss eine ganze Anzahl an "Blocks" aufnehmen können, wobei ein "Block" aus den Bytes für die Samples aller Channels zu einem Zeitpunkt besteht. Ich verwende in erster Linie ganz einfaches 16bit, mono, das hiesse dann, dass die Buffergröße eine gerade Anzahl an bytes sein muss. Kein Problem.

Zitat:
Dein Problem könnte am CallBack-Event liegen. Der Event in dem Fall ist nichts anderes als eine WindowsMessage. Ich habe mal gelesen, dass der CallBack über Thread auf jeden Fall die Beste Methode sein soll.
Inwiefern ist "der Event eine Windowsmessage"? Meiner Meinung nach sind die Events, auf die ich mit WaitForMultipleObjects warte einfach Events (CreateEvent etc..). Oder steckt da doch irgendwie ein komplizierter Ablauf mit Messages (im Sinne von Postmessage etc..) dahinter?

Ansich wäre ich mit CALLBACK_EVENT recht zufrieden. Der einzige Nachteil, den ich sehe, ist, dass man nicht so ohne weiteres weiss, warum WaitForMultipleObjects zurückgekehrt ist, aber das Checken der Header-Flags der Buffer ist relativ billig (ist in wenigen Mikrosekunden erledigt)...

Hier findet sich auch ein Pro-CALLBACK_EVENT-Artikel:
http://www.tech-archive.net/Archive/...4-03/0130.html

Zitat:
Zum Abspielen kannst und solltest du mehr als 2 Puffer benutzen! In dem Tutorial ist von 20 die Rede!!!
Mittlerweile hab' ich meinen Code auf eine konfigurierbare Anzahl von Buffern erweitert, und tatsächlich tritt das Problem bei einer größeren Anzahl kleiner Buffer nicht auf. Schon aber bei einer größeren Anzahl großer Buffer! Anscheinend kommt es also tatsächlich auf die Größe der Buffer an.

Momentan verwende ich 16 Buffer zu je 1000Samples (= je 1/16Sekunde) um eine Sekunde Reserve zu haben. Das funktioniert jetzt ganz gut...

Was mich aber noch ein bischen beunruhigt ist, warum 2 grosse Buffer nicht funktionieren?!?
Momentan vermute ich vielleicht, dass es gar nicht an mir liegt, sondern dass vielleicht das Betriebssystem oder der Audiotreiber ein Problem mit den großen Buffern hat (es tritt ja auch nicht mit allen Soundkarten auf).

Letztlich bleibt natürlich ein gewisses Risiko, dass ich doch etwas falsch mache...

Viele Grüße, Helmut
  Mit Zitat antworten Zitat
HHick123

Registriert seit: 23. Jul 2007
73 Beiträge
 
#6

Re: WaveIn-Problem bei grossen Buffern (Waveform Audio API)

  Alt 20. Mär 2008, 12:37
Hallo Leute, ich hab' das Thema 'mal auf beantwortet gestellt.
Mittlerweile bin ich der Meinung, dass man die Anzahl der Buffer sowie die Bufferlaenge innerhalb gewisser Spezifikationen wählen muss, die halt den meisten Audiotreibern gefallen.

Eine größere Anzahl von kleineren Buffern (aber auch nicht zu klein) funktioniert vermutlich am besten. Mein erster Entwurf mit zwei grossen Buffern ist nicht für alle Audiotreiber zu empfehlen! Ich weiss aber immer noch nicht, warum eigentlich....

Bei meinem Source-Code ist kein Stein auf dem anderen geblieben. Hab' noch einige Nebenprobleme entdeckt und korregiert und EVENT_CALLBACK Beispiele gibt's ja nicht so viele im Netz:

Besteht Interesse daran, dass ich den momentan für mich endgültigen Source-Code hier nochmal poste?

Viele Grüße, Helmut
  Mit Zitat antworten Zitat
Muetze1
(Gast)

n/a Beiträge
 
#7

Re: WaveIn-Problem bei grossen Buffern (Waveform Audio API)

  Alt 20. Mär 2008, 12:50
Ich denke mal schon, schon allein da hier in der dp.net nicht soviele Beispiele sind und auch allgemein solche Beispiele rar sind, wie du ja selbst festgestellt hast. Somit wäre das für andere Hilfesuchenden eine gute Quelle zur Lösung ihrer Probleme. Vielleicht könnte man es sogar in die CodeLib aufnehmen.

Ich hatte damals auch aufgegeben mit dem Callback und habe es umgestellt, da ich damit nicht zu Rande kam.
  Mit Zitat antworten Zitat
Benutzerbild von SirThornberry
SirThornberry
(Moderator)

Registriert seit: 23. Sep 2003
Ort: Bockwen
12.235 Beiträge
 
Delphi 2006 Professional
 
#8

Re: WaveIn-Problem bei grossen Buffern (Waveform Audio API)

  Alt 20. Mär 2008, 13:16
am besten den source diesmal als Datei anhängen. Warum mehrere Puffer ist eigentlich einfach. Die Soundkarte wartet mit dem afordern des nächstes Puffers nicht so lange bis der erste gefüllt ist sondern nimmt mehrere entgegen. Denn wenn erst eine Message kommen würde und dann müsste gewartet werden bis endlich der nächste Puffer nachkommt vergeht zu viel zeit und es sind schon daten verloren gegangen.
Jens
Mit Source ist es wie mit Kunst - Hauptsache der Künstler versteht's
  Mit Zitat antworten Zitat
HHick123

Registriert seit: 23. Jul 2007
73 Beiträge
 
#9

Re: WaveIn-Problem bei grossen Buffern (Waveform Audio API)

  Alt 20. Mär 2008, 13:52
Ja, aber wenn ich, angenommen, der Soundkarte 2 Buffer gäbe, die z.B. je 2 Sekunden lang wären, und der Audiotreiber würde mich möglichst gleich nachdem der erste gefüllt ist benachrichtigen, dass ich ihn zurücknehmen kann, dann hätte ich ja fast noch 2 Sekunden Zeit, ihm einen neuen Buffer zu geben, bevor der zweite gefüllt ist. Das müsste sich doch zeitlich ausgehen, oder?

Anbei jedenfalls die momentane Datei...
Ist aus einem ziemlich umfangreichen Kontext herausgerissen: Dazu zu sagen ist nämlich, dass es da noch eine Unit MyMailbox gibt, die ich verwende, um strings zwischen Applikationen über ein SharedMemory herumzuschicken. Was MyWaveIO nun tut, ist folgendes:

1.) Es wartet, bis so ein string daherkommt (da sind die playfile daten hineingepackt),

2.) Nun startet er das Playback und möglichst zeitgleich die Aufnahme. Die aufgenommenen Samples werden als strings wieder mittels der unit MyMailbox weggeschickt.

3.) Wenn das Playback aus ist, läuft die Aufnahme weiter (im header der Aufnahmedaten wird ein flag gesetzt, das anzeigt, ob gleichzeitig ein Playback war. Anhand dessen - und einer soundkartenspezifischen und raumspezifischen Korrektur von ein paar duzend Millisekunden - kann man das Echo des Playbacks in der Aufnahme herausschneiden, wenn man will).

4.) Wenn ein neuer playback string daherkommt, werden Aufnahme und Wiedergabe gestoppt weiter -> 2.)

Das ganze ist quasi für einen Dialog mit einem Spracherkenner.
Viele Grüße, Helmut
Angehängte Dateien
Dateityp: pas mywaveio_138.pas (22,7 KB, 48x aufgerufen)
  Mit Zitat antworten Zitat
Benutzerbild von SirThornberry
SirThornberry
(Moderator)

Registriert seit: 23. Sep 2003
Ort: Bockwen
12.235 Beiträge
 
Delphi 2006 Professional
 
#10

Re: WaveIn-Problem bei grossen Buffern (Waveform Audio API)

  Alt 20. Mär 2008, 14:03
in dem moment wo er dir den ersten zurück geben würde wöllte er aber auch schon wieder den nächsten sonst kommts ja beim nächsten zyklus zu aussetztern. Und somit würdest du versuchen aus einem Buffer zu lesen der schon wieder in Verwendung ist.
Jens
Mit Source ist es wie mit Kunst - Hauptsache der Künstler versteht's
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 20:59 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