Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien
Toon posts:

[C++] Synth programmeren met WaveOut

Pagina: 1
Acties:

Verwijderd

Topicstarter
Hallo,

Ik probeer sinds een tijdje een softsynth te maken in C++. Ik heb niet veel ervaring met C++ of audioprogrammeren, dus het is allemaal een beetje nieuw. Tot nu toe ging het wel, maar nu heb ik echt een probleem.

Ik ben me eerst wat gaan verdiepen in de verschillende mogelijkheden om geluid te streamen. Ik wou een zo simpel mogelijke interface, waar ik het liefst alleen de samplerate, bufferlengte en het stereo of mono zijn van het outputsignaal aan hoef te geven. Dat is me inmiddels, na veel experimenteren gelukt met behulp van de waveOut interface. Ik weet dat deze verouderd is, maar ik kreeg het gewoon niet voor elkaar op andere manieren. Ik heb gekeken naar wasapi, xaudio2, VST, maar uiteindelijk kreeg ik het alleen met de waveOut interface voor elkaar om een sinus te streamen.

Ik heb eerst een console applicatietje gemaakt waarin je kan pianospelen op het keyboard (en er een sinus met de juiste toonhoogte gestreamd wordt). Dit werkte allemaal. Toen ik echter een windows applicatie wou maken (met de winApi), ben ik tegen een probleem aangelopen. In de console-applicatie kon ik gewoon een eindeloze loop gebruiken, maar bij de winapi moeten de window messages ook nog afgehandeld worden.

Ik heb er uiteindelijk voor gekozen een timer te zetten, die dus elke ~0.1 seconde (ik heb met meerdere intervallen geëxperimenteerd) afgaat. Over het algemeen gaat dit redelijk, maar als ik het venster kleiner maak, gaat er iets mis, waardoor de synth begint te 'stotteren'. Dit gebeurt ook als ik gewoon even, zeg 7 seconden, wacht, maar in veel mindere mate (je hoort klikjes door het geluid).

Ik vermoed dat het geheel gewoon te langzaam is. Dit is een beetje opmerkelijk, want doe niks meer dan een sinus streamen, terwijl DAW's toch hele nummers ter plekke kunnen synthesizen en streamen (ten minste, ik weet niet precies hoe veel ze daar precalculaten, maar een sinus moet toch wel realtime kunnen). Het kan zijn dat de interface die ik gemaakt heb het geheel wat langzamer maakt, maar ik kan me niet voorstellen dat dat zo'n enorm verschil maakt.

Heeft iemand een idee hoe dit kan komen? Is de waveOut interface zo langzaam of is een timer zetten gewoon niet de juiste manier? Als het nodig is kan ik mijn code (twee klassen met elk < 100 regels code) ergens online zetten, er is ongetwijfeld het éen en ander mee mis.

Alvast dank (en hulde als je je mijn vraag uit deze wall of text hebt weten te extraheren :P )!

  • Radiant
  • Registratie: Juli 2003
  • Niet online

Radiant

Certified MS Bob Administrator

Zit je synth in dezelfde thread als je GUI en hoe doe je je timers? Denk eraan dat timers op een PC niet echt precies zijn (het is meer zoiets van "vanaf dit tijdstip wil mijn thread weer eens aandacht"). Voor betere precisie kan je eens kijken naar Multimedia Timers.
En mocht je synth in dezelfde thread zitten als de GUI zou ik eens proberen dit te splitsen.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:12

.oisyn

Moderator Devschuur®

Demotivational Speaker

Ik zou gewoon DirectSound gebruiken, de API is iets uitgebreider maar er zijn zat samples te vinden. Dan kun je een audiobuffer maken met meerdere notification events zodat je weet wanneer een stukje buffer gestreamed is en dus vrij is gekomen.

Met waveOut heb ik geen ervaring, maar als ik zo snel even google dan zie ik zat tutorials die eveneens beschrijven dat je kliks hoort als je de API verkeerd gebruikt.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

Topicstarter
Radiant schreef op maandag 01 juli 2013 @ 14:39:
Zit je synth in dezelfde thread als je GUI en hoe doe je je timers? Denk eraan dat timers op een PC niet echt precies zijn (het is meer zoiets van "vanaf dit tijdstip wil mijn thread weer eens aandacht"). Voor betere precisie kan je eens kijken naar Multimedia Timers.
En mocht je synth in dezelfde thread zitten als de GUI zou ik eens proberen dit te splitsen.
Ohja, goed punt, wilde ik ook nog wat over zeggen, maar ben ik vergeten. Dat doe ik op dit moment inderdaad niet. Ik had al door dat die timers inderdaad niet echt precies zijn, op zich zou dit geen probleem hoeven zijn, maar die timers zijn natuurlijk absoluut niet bedoeld waarvoor ik ze nu gebruik.
Ik moet inderdaad maar eens gaan kijken naar threads. *zucht*, moet ik dat ook weer leren :P
.oisyn schreef op maandag 01 juli 2013 @ 15:14:
Ik zou gewoon DirectSound gebruiken, de API is iets uitgebreider maar er zijn zat samples te vinden. Dan kun je een audiobuffer maken met meerdere notification events zodat je weet wanneer een stukje buffer gestreamed is en dus vrij is gekomen.

Met waveOut heb ik geen ervaring, maar als ik zo snel even google dan zie ik zat tutorials die eveneens beschrijven dat je kliks hoort als je de API verkeerd gebruikt.
Mm, ok. Ik had het idee dat directSound en xaudio meer voor het gebruik in spellen waren, ik zal er nog eens naar kijken. Volgens mij heb ik destijds alleen xaudio2 geprobeerd, omdat dat de opvolger van directSound en xaudio was (achteraf misschien een beetje raar dat ik toch voor waveOut ben gegaan, maar dat was gewoon het enige wat ik gelijk aan de praat kreeg).

Uiteindelijk is het natuurlijk makkelijker om voor een library te gaan, maar ik vind de low-level kant van dingen ook altijd wel interessant. Ik kom net ook sharpDX (een managed directX library voor C#) tegen, misschien dat ik dat maar eens probeer.

Verwijderd

Topicstarter
En dank voor de reacties natuurlijk :)

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:12

.oisyn

Moderator Devschuur®

Demotivational Speaker

Verwijderd schreef op maandag 01 juli 2013 @ 15:35:
Mm, ok. Ik had het idee dat directSound en xaudio meer voor het gebruik in spellen waren
Zo'n beetje alle software synths gebruiken DirectSound (naast het superieure ASIO uiteraard). Bovendien zijn de overeenkomsten tussen een softsynth en een game natuurlijk enorm - beide real time gegenereerd geluid met een zo laag mogelijke latency :)

[ Voor 21% gewijzigd door .oisyn op 01-07-2013 16:00 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

Topicstarter
.oisyn schreef op maandag 01 juli 2013 @ 15:59:
[...]

Zo'n beetje alle software synths gebruiken DirectSound (naast het superieure ASIO uiteraard). Bovendien zijn de overeenkomsten tussen een softsynth en een game natuurlijk enorm - beide real time gegenereerd geluid met een zo laag mogelijke latency :)
Ah, ok, dat wist ik niet. Mag ik nog wat advies? Ik heb meer ervaring met C#.NET, maar ben bezig met C++ leren. Heeft unmanaged directSound nog voordelen? Ik kan me zo voorstellen dat het net wat sneller werkt, wat wel belangrijk kan zijn als je low-latency wil werken (als het puur om gebruiksgemak gaat, wint managed directSound in C# natuurlijk). Zou je één van de twee aan- of afraden, of maakt het allemaal niet zo heel veel uit?

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:12

.oisyn

Moderator Devschuur®

Demotivational Speaker

Ik heb niet zoveel ervaring met managed DirectX, ik schrijf zelf voornamelijk C++ code. Maar ik denk niet dat het hebben van een managed omgeving een grote bottleneck zou vormen.

[ Voor 34% gewijzigd door .oisyn op 01-07-2013 17:18 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

Topicstarter
Ok, bedankt voor je hulp, ik ga er nog maar eens aan zitten binnenkort! :)
Ik kwam er net op codeproject al iets over tegen. Het zou wel voor een iets grotere latency zorgen, maar niet zo erg dat je ervoor over zou stappen naar een unmanaged omgeving.

  • PrisonerOfPain
  • Registratie: Januari 2003
  • Laatst online: 26-05 17:08
Als je plopjes of klikjes in je audio hoord, heb je eigenlijk een gap in de samples die je met waveOutWrite aanlevert. Je zult je data moeten double bufferen en sneller (en precieser) moeten zijn met het aanleveren van data.

Wellicht kun je van mijn mixer het een en ander leren: https://code.google.com/p...nk/audio_output_win32.cpp

  • Adion
  • Registratie: Januari 2001
  • Laatst online: 15:15
Voor zover ik me herinner was waveOut nooit echt de beste keuze voor lage latency.
DirectSound is inderdaad wat beter, maar sinds Vista is WASAPI eigenlijk aan te raden.
Geen idee of je daar eenvoudige c# voorbeelden voor vind.

VirtualDJ 2024 - Fast Image Resizer - Instagram


Verwijderd

Topicstarter
Adion schreef op maandag 01 juli 2013 @ 18:58:
Voor zover ik me herinner was waveOut nooit echt de beste keuze voor lage latency.
DirectSound is inderdaad wat beter, maar sinds Vista is WASAPI eigenlijk aan te raden.
Geen idee of je daar eenvoudige c# voorbeelden voor vind.
Heb ik inderdaad naar gekeken, dat was echt een ramp (ik krijg zelfs de code samples van microsoft niet werkend). Het kan aan mij liggen, maar ik kon er helemaal niks mee. Maar sowieso hoef ik niet echt hele lage latency omdat ik niks op hoef te nemen, ik wil alleen dat er een beetje tijdig gereageerd wordt als je bijv. een toets indrukt.

[ Voor 4% gewijzigd door Verwijderd op 01-07-2013 19:35 ]


  • PrisonerOfPain
  • Registratie: Januari 2003
  • Laatst online: 26-05 17:08
Verwijderd schreef op maandag 01 juli 2013 @ 19:32:
[...]

Heb ik inderdaad naar gekeken, dat was echt een ramp (ik krijg zelfs de code samples van microsoft niet werkend). Het kan aan mij liggen, maar ik kon er helemaal niks mee. Maar sowieso hoef ik niet echt hele lage latency omdat ik niks op hoef te nemen, ik wil alleen dat er een beetje tijdig gereageerd wordt als je bijv. een toets indrukt.
Daar is de waveOut API prima voor geschikt, goed het is niet de eenvoudigste API die er is maar met de code die ik gepost heb zou je er wel uit moeten kunnen komen :). Houd er ook rekening mee dat je het mixen zelf moet doen.

Verwijderd

Topicstarter
PrisonerOfPain schreef op maandag 01 juli 2013 @ 21:34:
[...]


Daar is de waveOut API prima voor geschikt, goed het is niet de eenvoudigste API die er is maar met de code die ik gepost heb zou je er wel uit moeten kunnen komen :). Houd er ook rekening mee dat je het mixen zelf moet doen.
PrisonerOfPain schreef op maandag 01 juli 2013 @ 18:44:
Als je plopjes of klikjes in je audio hoord, heb je eigenlijk een gap in de samples die je met waveOutWrite aanlevert. Je zult je data moeten double bufferen en sneller (en precieser) moeten zijn met het aanleveren van data.

Wellicht kun je van mijn mixer het een en ander leren: https://code.google.com/p...nk/audio_output_win32.cpp
Ik had je eerste post helemaal over het hoofd gezien! Ik kan er vast wat mee, hoewel het nog een hele klus wordt om door de code heen te spitten. Bedankt!
Ik gebruik nu wel double buffering, met maar twee buffers die ik de hele tijd 'prepared' hou: ik unprepare ze dus pas op het eind. Hoewel ik niet weet of dit de bedoeling is, werkt het op zich prima (tot nu dus).
Maargoed, ik ga eerst maar eens een aparte thread maken om die audio te synthesizen (en oja, ik heb ook nog een wiskundetentamen morgen :P ). Nogmaals bedankt, ik laat deze week nog wel even horen hier of ik verder ben gekomen.

Verwijderd

Topicstarter
O, hier is nog even de code die ik nu heb:
http://codepad.org/0Zjjcrx3

Ik zal binnenkort even commentaar toevoegen, nu geen tijd...

Korte uitleg: ik gebruik twee buffers met twee headers. Als de buffer vol is, wordt waveOutWrite aangeroepen met de header die bij de volle buffer hoort, en worden de buffers omgewisseld, zodat de volgende samples naar de buffer die op dat moment niet wordt afgespeeld wordt geschreven.

[ Voor 52% gewijzigd door Verwijderd op 02-07-2013 01:28 ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:12

.oisyn

Moderator Devschuur®

Demotivational Speaker

Je pakt het niet heel erg handig aan. Je gebruikt maar 1 event, dus je weet nooit voor welke buffer het event getriggerd wordt. Daarnaast roep je éérst waveOutWrite() aan, en daarna ResetEvent(). Wat als tussen die 2 calls de waveOutWrite() het event al op signaled heeft gezet?

Ik zou twee auto-reset events maken (dus ook van ResetEvent() afblijven), dan eerst wachten tot de buffer waarnaar je gaat schrijven daadwerkelijk klaar is (check ook dat de state WOM_DONE is, het event wordt getriggered bij elke change, niet alleen als ie klaar is), en dan waveOutWrite aanroepen voor die buffer.

[ Voor 4% gewijzigd door .oisyn op 02-07-2013 12:40 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • PrisonerOfPain
  • Registratie: Januari 2003
  • Laatst online: 26-05 17:08
Verwijderd schreef op dinsdag 02 juli 2013 @ 01:14:
Ik gebruik nu wel double buffering, met maar twee buffers die ik de hele tijd 'prepared' hou: ik unprepare ze dus pas op het eind. Hoewel ik niet weet of dit de bedoeling is, werkt het op zich prima (tot nu dus).
Dat mag niet, je past de lpData member aan terwijl 'ie prepared is. De enige members die je aan mag passen zijn:
Set the lpData, dwBufferLength, and dwFlags members of the WAVEHDR structure before calling this function. Set the dwFlags member to zero.

The dwFlags, dwBufferLength, and dwLoops members of the WAVEHDR structure can change between calls to this function and the waveOutWrite function. If you change the size specified by dwBufferLength before the call to waveOutWrite, the new value must be less than the prepared value.
Verder handel je WOM_DONE niet af.

[ Voor 3% gewijzigd door PrisonerOfPain op 02-07-2013 12:28 ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:12

.oisyn

Moderator Devschuur®

Demotivational Speaker

Waar past ie lpData aan dan?

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • PrisonerOfPain
  • Registratie: Januari 2003
  • Laatst online: 26-05 17:08
De inhoud word aangepast boven in setSample, maar als ik naar mijn code kijk lijkt dat niet zo veel uit te maken.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:12

.oisyn

Moderator Devschuur®

Demotivational Speaker

De buffer waar de pointer naar wijst is nou niet echt een member van WAVEHDR, wel? ;)

lpData mag je niet wijzigen, ergo, je mag 'm niet naar iets anders laten pointen. Over *lpData wordt geen woord gerept.

[ Voor 41% gewijzigd door .oisyn op 02-07-2013 13:44 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

Topicstarter
Thanks voor alle feedback, ik was al bang dat ik allerlei dingen verkeerd deed. Ik ga ernaar kijken wanneer ik tijd heb, de moeite die jullie erin hebben gestoken wordt zeer op prijs gesteld!

Ik kon niet echt echt een goede tutorial vinden, en de reference op msdn zei me ook niet zoveel, vandaar dat ik gewoon heb geëxperimenteerd tot het werkte. Ik ben ook nog eens een beginnende C++er, vandaar mijn code die (voor zover ik kan peilen uit jullie reacties) vrij brak is...

Op naar verbetering zal ik maar zeggen :P

ResetEvent() heb ik gebruikt omdat dat in een tutorial die ik destijds gebruikte gebruikt werd. Ik ga toch nog eens naar de MSDN reference kijken, hopelijk kan ik er nu wat meer mee.

[ Voor 15% gewijzigd door Verwijderd op 02-07-2013 22:56 ]


Verwijderd

Topicstarter
.oisyn schreef op dinsdag 02 juli 2013 @ 10:52:
Je pakt het niet heel erg handig aan. Je gebruikt maar 1 event, dus je weet nooit voor welke buffer het event getriggerd wordt. Daarnaast roep je éérst waveOutWrite() aan, en daarna ResetEvent(). Wat als tussen die 2 calls de waveOutWrite() het event al op signaled heeft gezet?

Ik zou twee auto-reset events maken (dus ook van ResetEvent() afblijven), dan eerst wachten tot de buffer waarnaar je gaat schrijven daadwerkelijk klaar is (check ook dat de state WOM_DONE is, het event wordt getriggered bij elke change, niet alleen als ie klaar is), en dan waveOutWrite aanroepen voor die buffer.
Ik begrijp niet heel goed wat je bedoelt met auto-reset events?

Ik kan, als ik het goed begrijp, een callback functie a la wndProc opgeven bij waveOutOpen, die aangeroepen wordt met de messages WOM_OPEN, WOM_CLOSE en WOM_DONE (en ik zie net ook dat ik die door een window kan laten afhandelen, maar dat staat er verder een beetje los van). Ik zie niet hoe je er in die callback functie achter kan komen welke buffer/header klaar is met afspelen.

Ik wil bovendien dat er niet naar de buffer kan worden geschreven als bijv. buffer1 nog afgespeeld wordt, en buffer2 al vol is. Dit om te zorgen dat het schrijven van data niet te veel vooruitloopt op het indrukken/loslaten van toetsen. Dat doe ik nu gewoon met een WaitForSingleObject(handle, INFINITE), en ik zie niet helemaal hoe ik dat met een callback functie zou moeten doen.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:12

.oisyn

Moderator Devschuur®

Demotivational Speaker

Verwijderd schreef op woensdag 03 juli 2013 @ 00:32:
[...]

Ik begrijp niet heel goed wat je bedoelt met auto-reset events?
Zie de documentatie van CreateEvent() :)
Ik kan, als ik het goed begrijp, een callback functie a la wndProc opgeven bij waveOutOpen, die aangeroepen wordt met de messages WOM_OPEN, WOM_CLOSE en WOM_DONE (en ik zie net ook dat ik die door een window kan laten afhandelen, maar dat staat er verder een beetje los van). Ik zie niet hoe je er in die callback functie achter kan komen welke buffer/header klaar is met afspelen.
Ik zou gewoon events blijven gebruiken. Mijn punt is dat je nu 1 event gebruikt voor beide buffers, het is handiger als je voor iedere buffer een apart event maakt.
Ik wil bovendien dat er niet naar de buffer kan worden geschreven als bijv. buffer1 nog afgespeeld wordt, en buffer2 al vol is.
En daarom kun je wachten op het event van buffer1 voordat je wilt schrijven naar buffer1.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • PrisonerOfPain
  • Registratie: Januari 2003
  • Laatst online: 26-05 17:08
Verwijderd schreef op woensdag 03 juli 2013 @ 00:32:
[...]

Ik begrijp niet heel goed wat je bedoelt met auto-reset events?
Auto-reset events zijn gewone win32 events zoals je ze nu gebruikt, alleen worden ze meteen ge-reset nadat je ze triggert met SetEvent. Kijk eens naar de documentatie van CreateEvent, specifiek de bManualReset parameter.
Ik kan, als ik het goed begrijp, een callback functie a la wndProc opgeven bij waveOutOpen, die aangeroepen wordt met de messages WOM_OPEN, WOM_CLOSE en WOM_DONE (en ik zie net ook dat ik die door een window kan laten afhandelen, maar dat staat er verder een beetje los van). Ik zie niet hoe je er in die callback functie achter kan komen welke buffer/header klaar is met afspelen.
Mijn code spin-locked op een atomic, zodra de spin-lock word vrijgegeven swap ik m'n buffers.

Verwijderd

Topicstarter
.oisyn schreef op woensdag 03 juli 2013 @ 11:26:
[...]

Zie de documentatie van CreateEvent() :)
Ik zie nu dat ik inderdaad zelf die callback functie heb verzonnen (of nou ja, ik geloof dat ik het in de documentatie tegenkwam), jij had er in ieder geval niet over :P.
Ik zie alleen bij waveOutOpen een mogelijkheid om een event op te geven, je kan voor zover ik kan zien niet per buffer een event meegeven? Verder kan ik WOM_DONE alleen afhandelen als ik aan waveOutOpen een callback functie of afhandelingsfunctie meegeef in plaats van een event...

Ik gebruikte al (per ongeluk?) een auto-reset event: de code die gebruik werkt ook prima als je ResetEvent weglaat.

Die documentatie is ook niet fantastisch, ik kan bijvoorbeeld niet vinden welke argumenten de callback functie moet hebben, of wat er met dwInstance gebeurt. Hoewel ik het meeste wel uit de code van PrisonerOfPain kan halen :)

Maar, wat ik ook tegenkwam, in deze tutorial (onder 'Streaming Audio to the Device'), is dat double buffering nooit voor een continue output zorgt. Het lijkt me onzin, wat als ik mijn programma uitvoer lijkt het (in het begin) verdacht veel op een continue toon, dus ik denk dat er in die tutorial vanuit wordt gegaan dat je muziek wil afspelen terwijl de CPU ook andere taken heeft. Sowieso lijkt het me niet heel logisch om meer dan drie blokken te gebruiken als je toch nog vooruit kan streamen omdat je nog niet weet of de gebruiker een toets los gaat laten of in gaat drukken.

Dit is overigens de voorbeeldcode die ik gebruikt heb.
En, nogmaals, dank voor de hulp allebei, ik ben er erg blij mee :)

Verwijderd

Topicstarter
Ik heb inmiddels een aparte thread aangemaakt, wat wel ietsje beter werkt, maar niet veel. Ik merk met name dat het window nu wél gelijk reageert als je hem sleept, resized of wegklikt.

edit: Excuses voor het bumpen! Dit paste niet zo goed bij het laatste bericht, dus ik typte maar even een nieuwe in. Maar ik had niet gerekend op de scherpe modjes hier :P

[ Voor 32% gewijzigd door Verwijderd op 03-07-2013 23:46 ]


  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Verwijderd

Topicstarter
Laatste bump, ik geloof dat ik er helemaal uit ben!
Ik heb een heel simpel softsynthje gemaakt, ik vind het experiment geslaagd!
Bedankt voor jullie hulp, zonder jullie was het niet gelukt :)

Ik het projectje hier geupload, misschien heeft iemand er nog wat aan (zelf vind ik vooral de audiostream-klasse mooi). Ik zie net trouwens dat het bestand vrij groot is geworden omdat ik erg grote iconen in het zipje heb staan. Ach, het is 2013, bandwidth genoeg :)

Ik heb op de meeste plekken vrij uitgebreid commentaar geschreven, en op twee plekken een readme gezet waarvan de tekst ook nog eens in de code is te vinden, dus ik denk dat iedereen er wel uit komt :P

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:12

.oisyn

Moderator Devschuur®

Demotivational Speaker

Verwijderd schreef op woensdag 03 juli 2013 @ 20:57:
Ik zie alleen bij waveOutOpen een mogelijkheid om een event op te geven, je kan voor zover ik kan zien niet per buffer een event meegeven?
My bad, ik dacht dat dat kon, maar je geeft 'm idd mee aan waveOutOpen(), en niet via de WAVEHDR struct.
Verder kan ik WOM_DONE alleen afhandelen als ik aan waveOutOpen een callback functie of afhandelingsfunctie meegeef in plaats van een event...
Nee, wat je moet doen nadat je event is geraised is kijken wat de huidige status is van de headers van je buffers (WOM_DONE is een van de bits van het flags member van de header). Op die manier kun je dus ook bepalen welke van de twee buffers klaar is met spelen.
Ik gebruikte al (per ongeluk?) een auto-reset event: de code die gebruik werkt ook prima als je ResetEvent weglaat.
"Prima werken" is een groot woord. Als het event nooit gereset wordt en hij geraised blijft is het niet heel raar dat je code nog steeds "werkt" - ik kan me namelijk prima voorstellen dat waveOutWrite() gewoon een error geeft als de buffer nog niet klaar is met spelen.

Beter kijk je naar hoe je je event creëert, en daaruit blijkt inderdaad dat dat je een auto-reset event maakt (de tweede parameter van CreateEvent() is FALSE) :)

[ Voor 8% gewijzigd door .oisyn op 08-07-2013 11:15 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.

Pagina: 1