[wdmaudiodev] Re: Need help in Passing a test case from KS-Position test

  • From: Gaurav Khuntale <gauravkhuntale@xxxxxxxxx>
  • To: wdmaudiodev@xxxxxxxxxxxxx
  • Date: Wed, 4 Jun 2014 12:24:14 +0530

Hello Matthew,

Thanks for the code snippet.

Gaurav


On Fri, May 23, 2014 at 5:44 AM, Matthew van Eerde <
Matthew.van.Eerde@xxxxxxxxxxxxx> wrote:

>  OK, here’s what I came up with.
>
>
>
> Features:
>
>
>
> 1)      A TODO for the driver developer who is using this as a template,
> to remind them to hook up the clock to the layer below them
>
> 2)      No artificially introduced jitter at all (not even 0.29 ms)
>
> 3)      No random slop introduced by rounding
>
> 4)      An arbitrary startup delay controlled by
> m_ullStartupDelayRemaining, which I set to 8 * HNS_PER_MILLISECOND in the
> transition to KSSTATE_RUN; this makes MSVad have a measurable delay between
> SetState(KSSTATE_RUN) and the first non-zero device position
>
>
>
>
> //=============================================================================
>
> STDMETHODIMP
>
> CMiniportWaveCyclicStreamMSVAD::GetPosition
>
> (
>
>     _Out_ PULONG                  Position
>
> )
>
> /*++
>
>
>
> Routine Description:
>
>
>
>   The GetPosition function gets the current position of the DMA read or
> write
>
>   pointer for the stream. Callers of GetPosition should run at
>
>   IRQL <= DISPATCH_LEVEL.
>
>
>
> Arguments:
>
>
>
>   Position - Position of the DMA pointer
>
>
>
> Return Value:
>
>
>
>   NT status code.
>
>
>
> --*/
>
> {
>
>     if (m_fDmaActive)
>
>     {
>
>         // TODO: Query the physical layer below us and
>
>         // report the byte position of the sample,
>
>         // either emerging from the speaker (if this is render)
>
>         // or coming in to the microphone (if this is capture)
>
>         //
>
>         // Alas, WaveCyclic does not allow us to report a correlated
> position + QPC,
>
>         // just a position.
>
>         // So if the layer below us gives us a correlated position + QPC,
>
>         // we have to do our own extrapolation and hand the extrapolated
> position to portcls
>
>         //
>
>         // Since this is only a virtual driver, we use
> KeQueryInterruptTime as a clock
>
>         //
>
>         ULONGLONG CurrentTime = KeQueryInterruptTime();
>
>         ULONGLONG TimeElapsed = CurrentTime - m_ullDmaTimeStamp;
>
>
>
>         // Simulate a startup delay
>
>         //
>
>         if (m_ullStartupDelayRemaining > 0)
>
>         {
>
>             // burn down some startup delay
>
>             if (TimeElapsed > m_ullStartupDelayRemaining)
>
>             {
>
>                 TimeElapsed -= m_ullStartupDelayRemaining;
>
>                 m_ullStartupDelayRemaining = 0;
>
>             }
>
>             else
>
>             {
>
>                 m_ullStartupDelayRemaining -= TimeElapsed;
>
>                 TimeElapsed = 0;
>
>             }
>
>         }
>
>
>
>         // We have an elapsed time in hundred-nanoseconds, which we'll
> call "ticks"
>
>         // but we want to convert it into a DMA position, which is in bytes
>
>         //
>
>         // Let H = 10 * 1000 * 1000;
>
>         // this is the number of ticks which pass in a second
>
>         //
>
>         // Let B = m_ulDmaMovementRate = pwfx->nAvgBytesPerSec;
>
>         // this is the number of bytes processed in a second
>
>         //
>
>         // Let h = ullElapsed;
>
>         // this is the number of ticks that have elapsed
>
>         //
>
>         // We want to know b = the number of bytes that been processed
>
>         //
>
>         // b / B = h / H = the number of seconds that have elapsed
>
>         // Solving for b, we get: b = B h / H
>
>         //
>
>         // In particular, floor(B h / H) bytes have completely been
> processed,
>
>         // and we are (B h mod H) / H of the way into the next byte (this
> is between 0 and 1)
>
>         //
>
>         // To avoid dealing with floating-point arithmetic:
>
>         // Let br = the byte rollover (B h mod H) which is a number in [0,
> H)
>
>         //
>
>         // But wait!
>
>         // We need to consider the possibility that we had nonzero
> rollover from before;
>
>         // "b = B h / H" was too naive, it should have been "b = (B h +
> br_prev) / H"
>
>         //
>
>         // In summary:
>
>         // H = 10 * 1000 * 1000 = the number of ticks in a second
>
>         // B = the number of bytes processed in a second
>
>         // h = the number of ticks that have passed since the last time
>
>         // br_prev = how far into the current byte we already were the
> last time, in [0, H)
>
>         //
>
>         // So we calculate:
>
>         // b = floor((B h + br_prev) / H) = how many bytes have no
> completely passed
>
>         // br_next = (B h + br_prev) mod H
>
>         //
>
>         ULONG ulByteDisplacement =
>
>             (ULONG)( (m_ulDmaMovementRate * TimeElapsed +
> m_ullDmaPartialByte) / HNS_PER_SECOND );
>
>
>
>         m_ullDmaPartialByte =
>
>             (m_ulDmaMovementRate * TimeElapsed + m_ullDmaPartialByte) %
> HNS_PER_SECOND;
>
>
>
>         // Now we have the number of bytes that have been newly processed
>
>         // Advance the position by that much, relative to the circular
> buffer
>
>         //
>
>         m_ulDmaPosition = (m_ulDmaPosition + ulByteDisplacement) %
> m_ulDmaBufferSize;
>
>
>
>         // Return the new DMA position
>
>         //
>
>         *Position = m_ulDmaPosition;
>
>
>
>         // Update the DMA time stamp for the next call to GetPosition()
>
>         //
>
>         m_ullDmaTimeStamp = CurrentTime;
>
>     }
>
>     else
>
>     {
>
>         // DMA is inactive so just return the current DMA position.
>
>         //
>
>         *Position = m_ulDmaPosition;
>
>     }
>
>
>
>     return STATUS_SUCCESS;
>
> } // GetPosition
>

Other related posts: