[wdmaudiodev] Re: HD Audio WaveCyclic timing problems

  • From: Lex Nahumury <nahumury.l@xxxxxxxxx>
  • To: wdmaudiodev@xxxxxxxxxxxxx
  • Date: Tue, 12 Jan 2010 12:14:36 +0100

Hello Mike,
Thanks for your reply!

>> I'm developing a HD Audio function driver targeting WIN XP SP3.
>> Everything so far works fine but I can't get the stream's position timing
>> right.
>> That is, although the playback rate sounds ok, the rendered sound is
>> always garbled and I can't seem to find the solution.
>> Here is what I do;
>> Based on the "Microsoft Device Driver Interface for HD Audio"
>> documentation I
>> use WaveCyclic and obtain a HDAUDIO_BUS_INTERFACE_BDL from the HD Audio
>> DDI.
>> Since the function driver doesn't have a physical DMA object itself,
>> my stream class inherits from IDmaChannel and implements the
>> IMP_IDmaChannel member functions. (pretty much how it is done in the
>> MSVAD sample)
>> At pin creation time I do AllocateRenderDmaEngine() followed by
>> AllocateContiguousDmaBuffer() to create a PAGE_SIZE sized buffer.
> That might be too small. I found I needed a larger buffer than this for
> playback/record operations involving high sample rates, sample widths and
> number of channels. In the end I ended up computing a size relative to
> nAvgBytesPerSec.
Yes you are right of course.
However in this (testing) stage I only support 2 channel @44100hz.

>> In SetNotificationFreq() I compute the needed 10msec FramingSize,
>>   FramingSize_in_bytes = nBlockAlign * sampleRate * Interval / 1000;
>> I use that FramingSize;
>> - to set the current buffersize via SetBufferSize(FramingSize_in_bytes)
>> - to program the length of the first (and only) BDL entry
>> - and in the call to SetupDmaEngineWithBdl() with LVI = 1
>> In GetPosition() I readout the address I obtained earlier via
>> GetLinkPositionRegister().
>>   *Position = READ_REGISTER_ULONG( pPositionRegister )
> That's not quite right for a HD audio device (at least in my experience).
> For GetPosition you need the position of the current sample actually being
> played or recorded. To do this for HD Audio you need to to adjust the link
> position register value using the FifoSize (you can get this from the HD
> Audio interface). For Capture streams return LinkPosition - FifoSize, for
> render streams return LinkPosition + FifoSize. Return 0 if the stream is
> stopped.
Yes, I already tried something like this in GetPosition(),

        if(isRunning && pPositionRegister )
            ULONG pos =  READ_REGISTER_ULONG( pPositionRegister );
                pos += fifo_size;
                if(pos > FramingSize_in_bytes)
                        pos =  pos - FramingSize_in_bytes; // wrap

                *Position = pos;        
                *Position = 0;

Unfortunately the stream keeps crackling even if I fine tune the
fifo_size value:(

Btw, I also noticed that if I readout the LinkPositionRegister in my
ISR routine it always reads 1576 as if the Interrupt fires too early
.I would expect it to be close around 1764 which is the
FramingSize_in_bytes for a 2 channel 44100hz stream.
It has probably something to do with the reported fifo size which is 191 bytes.

WDMAUDIODEV addresses:
Post message: mailto:wdmaudiodev@xxxxxxxxxxxxx
Subscribe:    mailto:wdmaudiodev-request@xxxxxxxxxxxxx?subject=subscribe
Unsubscribe:  mailto:wdmaudiodev-request@xxxxxxxxxxxxx?subject=unsubscribe
Moderator:    mailto:wdmaudiodev-moderators@xxxxxxxxxxxxx


Other related posts: