Precisely.
Without the timer as an option, it seems to me that there are two ways I
could do this:
1) Rely solely on OS calls to my
IMiniportWaveRTOutputStream::SetWritePacket() and
IMiniportWaveRTInputStream::GetReadPacket() implementations. Spin-lock
both streams, figure out the current state of render and capture
buffers, and conditionally copy or silence-fill a packet, then release
the lock and return.
-or-
2) Create a long-running thread (managed by the topology object), and
have it wait for a render packet to be full and a capture packet to be
empty, then copy the packet from render to capture. This would allow me
to wait on notification events for one or both streams.
Right now I'm coding up the first approach, because it doesn't involve
creating a long-running thread (something I'm not sure I can find enough
information about to do properly).
-S
On 11/2/20 8:47 AM, Matthew van Eerde (Redacted sender Matthew.van.Eerde
for DMARC) wrote:
Okay, so you are both a virtual speaker and a virtual microphone, and your virtual microphone gets its data from the virtual speaker?
------------------------------------------------------------------------
*From:* wdmaudiodev-bounce@xxxxxxxxxxxxx <wdmaudiodev-bounce@xxxxxxxxxxxxx> on behalf of wdmaudiodev@xxxxxxxxxxxxxx <wdmaudiodev@xxxxxxxxxxxxxx>
*Sent:* Saturday, October 31, 2020 6:25:52 AM
*To:* wdmaudiodev@xxxxxxxxxxxxx <wdmaudiodev@xxxxxxxxxxxxx>
*Subject:* [wdmaudiodev] Re: [EXTERNAL] Understanding IMiniportWaveRtStreamNotification::RegisterNotificationEvent
This driver creates a virtual capture endpoint ("microphone") that third-party chat apps like Zoom or Skype will consume.
So whenever the capture stream requests data, if there is a new packet available from the render stream, I copy it across. If the render stream isn't in RUN mode, then I silence-fill the capture buffer.
-S
On 10/30/20 9:45 AM, Matthew van Eerde (Redacted sender Matthew.van.Eerde for DMARC) wrote:
Who consumes the data that Windows writes to you? Do they have a clock?
*From: *wdmaudiodev@xxxxxxxxxxxxxx <mailto:wdmaudiodev@xxxxxxxxxxxxxx>
*Sent: *Friday, October 30, 2020 9:26 AM
*To: *wdmaudiodev@xxxxxxxxxxxxx <mailto:wdmaudiodev@xxxxxxxxxxxxx>
*Subject: *[wdmaudiodev] Re: [EXTERNAL] Understanding IMiniportWaveRtStreamNotification::RegisterNotificationEvent
> Please don’t do this.
I'd rather go with the prevailing wisdom and do it 'properly', vs. produce another crappy, battery-draining Windows driver. So, OK, no timer.
SYSVAD is the only example of this that I have, and it says (paraphrasing) "in a real driver, you wouldn't use a timer like we show here; your DMA hardware and position registers would handle ...".
My driver is virtual, though, so there is no hardware. It just copies packets from RENDER[1] to CAPTURE, without buffering.
I could create a worker thread that waits on both render-data-ready and capture-buffer-available events. I don't have any driver-specific examples of this, but I've done this in desktop apps in the past.
Any suggestions/advice? Any insight on the SetWritePacket/SetReadPacket question?
--S
[1] Or, if I can get a custom interface working, copy data passed-from-app-to-driver via backchannel
On 10/30/20 8:44 AM, Matthew van Eerde (Redacted sender Matthew.van.Eerde for DMARC) wrote:
* I have a timer function that monitors this
Please don’t do this.
*From: *wdmaudiodev@xxxxxxxxxxxxxx
<mailto:wdmaudiodev@xxxxxxxxxxxxxx>
*Sent: *Friday, October 30, 2020 6:31 AM
*To: *wdmaudiodev@xxxxxxxxxxxxx <mailto:wdmaudiodev@xxxxxxxxxxxxx>
*Subject: *[EXTERNAL] [wdmaudiodev] Understanding
IMiniportWaveRtStreamNotification::RegisterNotificationEvent
Hi,
I was a bit confused by the function of the
IMiniportWaveRtOutputStream::SetWritePacket and
IMiniportWaveRtInputStream::SetReadPacket methods, and the KEVENT
passed into RegisterNotificationEvent.
If I understand it correctly, AllocateBufferWithNotification gets
called with notificationCount=2, and a buffer large enough for
two 'packets'. Packets seem to be sized to contain about 1/100
sec worth of audio frames. RegisterNotificationEvent gets called
with a single (in my case) event.
In the RENDER case, SetWritePacket(n, ...) is called when the OS
has finished copying packet <n> into whichever half of the
buffer. I have a timer function that monitors this, and transfers
the packet to hardware (let's say). To let the OS know that
packet <n> has been processed (i.e., that packet in the buffer is
available), I call KeSetEvent(pNotificationEvent, 0, FALSE).
So this part isn't clear to me:
...kernel event that must be notified as DMA progresses.
Depending on the notification count parameter used with
AllocateBufferWithNotification
<https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fwindows-hardware%2Fdrivers%2Fddi%2Fhdaudio%2Fnc-hdaudio-pallocate_dma_buffer_with_notification&data=04%7C01%7CMatthew.van.Eerde%40microsoft.com%7Ce86354349b8f42d73f9208d87da0df32%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637397477231502141%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&sdata=2hBMswlt1IWsY6psSwMo74HF7BZKkUdev5W4IqZcWfc%3D&reserved=0>,
the registered event is signaled __one or two times__ for
every time that the DMA passes through the audio buffer.
I expected there to be two calls to RegisterNotificationEvent,
and thus two KEVENT objects at any given time (one for each
packet in the buffer). Instead, I only see one getting added. The
doc quote above seems to suggest that a single event has to be
set TWICE (or maybe set once, then the OS clears, then set
again)? I've looked at the KEVENT struct and related APIs, but
I'm still confused. Is this event supposed to signify "Buffer
Complete" or "Packet Complete"?
In the CAPTURE case, it looks like things are reversed. The OS
calls SetReadPacket to query the driver about which packet is
available for reading (transferring to client).
RegisterNotificationEvent is getting called, so I think the same
(single) event is SET/CLEARED? by the OS to signal ME that it has
finished transferring data out of a packet, and that packet is
available for DMA again.
Thanks in advance for any and all help. :-)