|
|
|
date: Tue, 19 Feb 2008 19:07:13 -0800 (PST),
group: microsoft.public.win32.programmer.directx.audio
back
Problem with audio on Vista
Hi!
I hope this is the right group for this question - suggestions of
active groups where this question would be better posed are welcome.
I'm having trouble with audio playback. My environment is Vista 64,
Visual Studio 2005, Vista SDK. The approach I'm using is very simple:
0. Get ready for audio playback with waveOutOpen.
1. Load buffer A with raw audio samples.
2. Load buffer B with raw audio samples.
3. Prepare buffer A with waveOutPrepareHeader.
4. Prepare buffer B with waveOutPrepareHeader.
5. Start buffer A playing, using waveOutWrite.
6. Wait for MM_WOM_DONE.
7. Start buffer B playing, using waveOutWrite.
8. Wait for MM_WOM_DONE.
9. Go to 5.
This approach works fine on Windows 2000 and XP. But on Vista, it
produces audio corruption. For small buffers, (c. 4k) audio plays at
about half speed, with dead air between short (4k?) bursts of audio.
At 16k, the dead air seems to be mostly gone, but there's a notable
clicking when changing buffers. This decreases until it's not very
noticeable at 22k, and with 32k buffers, audio sounds perfect. Does
anyone have any clues? For my purposes, it's important to have small
buffers to keep playback position indicators very accurate. As far as
I can tell, the new buffer is being queued up quickly on completion of
the old one, and even if it wasn't, I'd expect that to cause a
constant delay between buffer playbacks, independent of buffer size.
If anyone would like to see more code (header setup, function calls
etc) please let me know!
Thanks,
Mike.
date: Tue, 19 Feb 2008 19:07:13 -0800 (PST)
author: Mike
Re: Problem with audio on Vista
On Feb 21, 4:16 am, "Chris P." wrote:
> Your running on Vista 64 but are you compiling a 32 or 64-bit executable?
It's a 32-bit executable.
> Your technique above is flawed and in theory shouldn't work at all even on
> XP or 2K. You need to have a minimum of 2 buffers in queue at all times.
> Buffer B must be queued *before* you received the MM_WOM_DONE message for
> buffer A. With only 1 buffer in queue MM_WOM_DONE indicates that the first
> buffer playback is complete - which in your case also means that the output
> has starved for data as there is no more buffers in queue. I think the
> only reason that it worked on 2K and XP is due to a flaw in their KMixer
> implementation that returned the WOM_DONE message prematurely. Regardless
> you should still be able to get accurate stream information with
> waveOutGetPosition(), I usually have between .25 and 1 second queued up and
> can still sync with visual indicators using that.
Thanks for that thought - the code isn't mine originally, I'm
modifying it (it's pretty ancient!). So, it's quite possible that I've
misread the code (and given an incorrect algorithm above), perhaps it
is trying to keep two buffers in the queue all the time. I'll recheck
and modify as required.
I did actually wonder about exactly this possibility, but assumed that
the _DONE message was sent out early enough to allow for queuing the
next buffer. One thing I wasn't sure about was whether waveOutWrite
can be called multiple times immediately consecutively, to place more
than one buffer in the audio playback queue, without causing problems.
Thinking about it, I'm sure it must be possible, to avoid the exact
problem you describe above. This may also explain the problems I had
when porting the code to Windows CE...!
Thanks very much for the info - will post a note here when I get a
chance to have a go at the code!
Mike.
date: Wed, 20 Feb 2008 17:23:36 -0800 (PST)
author: Mike
Re: Problem with audio on Vista
On Feb 21, 2:23 pm, Mike wrote:
> > Your technique above is flawed and in theory shouldn't work at all even on
> > XP or 2K. You need to have a minimum of 2 buffers in queue at all times.
> > Buffer B must be queued *before* you received the MM_WOM_DONE message for
> Thanks for that thought - the code isn't mine originally, I'm
> modifying it (it's pretty ancient!). So, it's quite possible that I've
> misread the code (and given an incorrect algorithm above), perhaps it
> is trying to keep two buffers in the queue all the time. I'll recheck
> and modify as required.
Well, I checked - turns out I didn't read the code carefully enough,
it does in fact queue both buffers at the outset. The fixed algorithm
is this:
0. Get ready for audio playback with waveOutOpen.
1. Load buffer A with raw audio samples.
2. Prepare buffer A with waveOutPrepareHeader.
3. Start buffer A playing, using waveOutWrite.
4. Load buffer B with raw audio samples.
5. Prepare buffer B with waveOutPrepareHeader.
6. Start buffer B playing, using waveOutWrite.
7. Wait for MM_WOM_DONE.
8. Reload buffer A with raw audio samples.
9. Queue buffer A, using waveOutWrite.
10. Wait for MM_WOM_DONE.
11. Reload buffer B with raw audio samples.
12. Queue buffer B, using waveOutWrite.
13. Go to 7.
Does anyone have any further clues? The same executable seems to run
very well on XP and older; it's a bit baffling.
Mike.
date: Wed, 20 Feb 2008 23:20:56 -0800 (PST)
author: Mike
Re: Problem with audio on Vista
On Feb 21, 7:20�am, Mike wrote:
<snip>
> The fixed algorithm is this:
>
> 0. Get ready for audio playback with waveOutOpen.
> 1. Load buffer A with raw audio samples.
> 2. Prepare buffer A with waveOutPrepareHeader.
> 3. Start buffer A playing, using waveOutWrite.
> 4. Load buffer B with raw audio samples.
> 5. Prepare buffer B with waveOutPrepareHeader.
> 6. Start buffer B playing, using waveOutWrite.
> 7. Wait for MM_WOM_DONE.
> 8. Reload buffer A with raw audio samples.
> 9. Queue buffer A, using waveOutWrite.
> 10. Wait for MM_WOM_DONE.
> 11. Reload buffer B with raw audio samples.
> 12. Queue buffer B, using waveOutWrite.
> 13. Go to 7.
>
> Does anyone have any further clues? The same executable seems to run
> very well on XP and older; it's a bit baffling.
>
The algorithm I use is slightly different in text, but may be same in
implementation.
0. Get ready for audio playback with waveOutOpen.
1. Allocate memory for all headers
2. Allocate memory for all buffers
3 waveOutPrepareHeader() for all headers;
// the above is usually done with arrays of buffers & headers
4 Load all buffers from input source
5 waveOutWrite all buffers (incrementing QueueCount variable)
when MM_WOM_DONE. is received
6 Decrement QueueCount
if not end of audio source
{7. Reload the returned header buffer with audio.
8 waveOutWrite the refilled buffer
9. increment QueueCount
}
if queueCount = 0, tidy up all memory & waveOutClose
I find the QueueCount is necessary to cater for waveOutReset,
otherwise one frees the memory when the first buffer after an empty
input source is returned, and MM_WOM_DONE has nowhere to come back to.
Note that you don't need to re-Unprepare & Prepare headers when a
buffer is returned, unless you want to change the size of the buffer.
Using arrays for the multiple buffers & headers is more convenient. I
usually use three buffers, because on occasion quite a lot of code
occurs between buffers. (although as an ancient coder I am totally
flabbergasted by the amount of stuff I can do apparently
instantaneously).
Alan Lloyd
date: Thu, 21 Feb 2008 01:50:11 -0800 (PST)
author: unknown
Re: Problem with audio on Vista
On Wed, 20 Feb 2008 23:20:56 -0800 (PST), Mike wrote:
> Well, I checked - turns out I didn't read the code carefully enough,
> it does in fact queue both buffers at the outset. The fixed algorithm
> is this:
>
> 0. Get ready for audio playback with waveOutOpen.
> 1. Load buffer A with raw audio samples.
> 2. Prepare buffer A with waveOutPrepareHeader.
> 3. Start buffer A playing, using waveOutWrite.
> 4. Load buffer B with raw audio samples.
> 5. Prepare buffer B with waveOutPrepareHeader.
> 6. Start buffer B playing, using waveOutWrite.
> 7. Wait for MM_WOM_DONE.
> 8. Reload buffer A with raw audio samples.
> 9. Queue buffer A, using waveOutWrite.
> 10. Wait for MM_WOM_DONE.
> 11. Reload buffer B with raw audio samples.
> 12. Queue buffer B, using waveOutWrite.
> 13. Go to 7.
>
> Does anyone have any further clues? The same executable seems to run
> very well on XP and older; it's a bit baffling.
I use a similar technique to Alan except that I use events rather than the
Windows message. I always found there was too much delay in the Window
message which meant that you had to buffer twice as much data to get smooth
playback.
waveOut on Vista is wrapped and no longer goes directly to the windows
audio mixer like it used to, it is instead redirected through the WASAPI
audio interface. You might need to either increase the number of buffers
or the size to compensate. I remember that on a Windows CE project I did
years back I had to use large amounts of buffering.
--
http://www.chrisnet.net/code.htm
[MS MVP for DirectShow / MediaFoundation]
date: Thu, 21 Feb 2008 10:27:29 -0500
author: Chris P.
|
|