Windows System Software -- Consulting, Training, Development -- Unique Expertise, Guaranteed Results

Home NTDEV

More Info on Driver Writing and Debugging


The free OSR Learning Library has more than 50 articles on a wide variety of topics about writing and debugging device drivers and Minifilters. From introductory level to advanced. All the articles have been recently reviewed and updated, and are written using the clear and definitive style you've come to expect from OSR over the years.


Check out The OSR Learning Library at: https://www.osr.com/osr-learning-library/


Before Posting...

Please check out the Community Guidelines in the Announcements and Administration Category.

Sysdriver: How to capture Input data and play user audio application data

124»

Comments

  • Tim_RobertsTim_Roberts Member - All Emails Posts: 14,095

    Any suggestion on above post.

    Here's one suggestion. Be patient, damn it. You posted this on Sunday afternoon here in the US, then prodded when you didn't get a reply in 6 hours.
    Most of us who do this for a living aren't working on Sundays. We don't need you to demand results.

    I can transfer that decode data to driver using IOCTL, but there I will receive inside driver.cpp custom IOCTL handler,
    from custom IOCTL handler how can I transfer the data to MiniportWaveRTStream::WriteBytes and copy it to m_pDmaBuffer.

    Your ioctl handler needs to copy your data into the circular buffer. You shouldn't need to change WriteBytes; it already knows how to read from the circular buffer. The only tricky part is finding the MiniPortWaveRTStream device so you can access its m_pDmaBuffer. That's just a matter of following the pointers for the objects you do have.

    Tim Roberts, [email protected]
    Providenza & Boekelheide, Inc.

  • chauhan_sumit001chauhan_sumit001 Member Posts: 35

    @chauhan_sumit001 said:
    Hi Tim,

    over the TCP connection I am receiving encoded mic output from source application ,at target app i am decoding the audio data , now
    I have decoded audio data(using AAC) in my target application, that I want to redirect to virtual audio mic(earlier i was playing it using SDL player). do I need to store that decoded data again in ring buffer within the driver code??,

    I can transfer that decode data to driver using IOCTL, but there I will receive inside driver.cpp custom IOCTL handler, from custom IOCTL handler how can I transfer the data to MiniportWaveRTStream::WriteBytes and copy it to m_pDmaBuffer. plz help with some sample code snippet.

    VOID MiniportWaveRTStream::WriteBytes
    (
    In ULONG ByteDisplacement
    )
    /*++

    Routine Description:

    This function writes the audio buffer using a sine wave generator
    Arguments:

    ByteDisplacement - # of bytes to process.

    --*/
    {

    ULONG bufferOffset = m_ullLinearPosition % m_ulDmaBufferSize;

    //// Normally this will loop no more than once for a single wrap, but if
    //// many bytes have been displaced then this may loops many times.
    while (ByteDisplacement > 0)
    {
    ULONG runWrite = min(ByteDisplacement, m_ulDmaBufferSize - bufferOffset);
    SIZE_T actuallyWritten;

    m_RingBuffer->Take(m_pDmaBuffer + bufferOffset, runWrite, &actuallyWritten);
    if (actuallyWritten < runWrite)
    {
    RtlZeroMemory(m_pDmaBuffer + bufferOffset + actuallyWritten, runWrite - actuallyWritten);
    }

    bufferOffset = (bufferOffset + runWrite) % m_ulDmaBufferSize;
    ByteDisplacement -= runWrite;
    }
    }

    if i have to feed my audio buffer to m_pDmaBuffer , do i need to write that much code inside WriteBytes(mentioned above), except
    memcpy(m_pDmaBuffer ,my audio buffer received USING IOCTL, length)????

    plz need your help.

  • chauhan_sumit001chauhan_sumit001 Member Posts: 35
    edited July 26

    Hi All,

    I am stuck at one point, i want to access ringbuffer and feed the data received from IOCTL inside IOCTL handler from user application, but currenly my ringbuffer is inside MiniportWaveRTStream class where inside WriteBytes I am taking data from ringbuffer and feeding it to dma buffer, so how can I access the same ringbuffer inside my IOCTL handler in adapter.cpp in SYSVAD class to put the data. plz provide some code snippet.

    need your help badly...

  • chauhan_sumit001chauhan_sumit001 Member Posts: 35

    @Tim_Roberts said:

    Any suggestion on above post.

    Here's one suggestion. Be patient, damn it. You posted this on Sunday afternoon here in the US, then prodded when you didn't get a reply in 6 hours.
    Most of us who do this for a living aren't working on Sundays. We don't need you to demand results.

    I can transfer that decode data to driver using IOCTL, but there I will receive inside driver.cpp custom IOCTL handler,
    from custom IOCTL handler how can I transfer the data to MiniportWaveRTStream::WriteBytes and copy it to m_pDmaBuffer.

    Your ioctl handler needs to copy your data into the circular buffer. You shouldn't need to change WriteBytes; it already knows how to read from the circular buffer. The only tricky part is finding the MiniPortWaveRTStream device so you can access its m_pDmaBuffer. That's just a matter of following the pointers for the objects you do have.

    Hi Tim,

    I am extremely sorry for being impatient, it was not at all intended.

    If I understood your point correctly, then I should not create one more ringbuffer inside driver class to store my audio data received using IOCTL handler.

    is m_pDmaBuffer is circular buffer???

    if yes then directly I can copy my data to m_pDmaBuffer. is that correct???

  • chauhan_sumit001chauhan_sumit001 Member Posts: 35

    Also plz provide some clue on,how to find MiniportWaveRTStream device inside custom IOCTL handler..

  • Tim_RobertsTim_Roberts Member - All Emails Posts: 14,095

    It is very easy to find things going UP an object tree. It is difficult to find things going DOWN a tree. Therefore, the right answer is to move the circular buffers into the top-level adapter object, where it can easily be found by the ioctl handlers. The miniport stream objects also have access to the adapter object, so they can call a function to fetch a pointer to the circular buffer.

    Tim Roberts, [email protected]
    Providenza & Boekelheide, Inc.

  • chauhan_sumit001chauhan_sumit001 Member Posts: 35
    edited July 29

    Dear Tim,

    first of all Thanks for all the help which u provided, with that i am able to transfer my audio to virtual microphone from my user application.

    But while playing the virtual mic recorded audio using audacity i observed lots of noise along with actual audio, may I know why i am getting noise along with actual audio.

    I am using ringbuffer to store transferred audio packet from user app, and calling RingBuffer::GetRingBufferInstance()->Put((BYTE*)_Irp->AssociatedIrp.SystemBuffer, inBufLength); inside my custom IOCTL handler api.

    NTSTATUS HandleCustomIoctl(In DEVICE_OBJECT* DeviceObject,
    _Inout
    IRP* _Irp)
    {

    //PIO_STACK_LOCATION  irpSp;// Pointer to current stack location
    //NTSTATUS            ntStatus = STATUS_SUCCESS;// Assume success
    ULONG               inBufLength; // Input buffer length
    ULONG               outBufLength; // Output buffer length
    PCHAR               /*inBuf,*/ outBuf; // pointer to Input and output buffer
    PCHAR               data = "This String is from Device Driver !!!";
    size_t              datalen = strlen(data) + 1;//Length of data including null
    //PMDL                mdl = NULL;
    //PCHAR               buffer = NULL;
    
    
    
    
    
    
    
    UNREFERENCED_PARAMETER(_DeviceObject);
    PAGED_CODE();
    PIO_STACK_LOCATION stackLocation = NULL;
    //CHAR* messageFromKernel = "ohai from them kernelz";
    NTSTATUS ntstatus = STATUS_SUCCESS;
    stackLocation = IoGetCurrentIrpStackLocation(_Irp);
    
    inBufLength = stackLocation->Parameters.DeviceIoControl.InputBufferLength;
    outBufLength = stackLocation->Parameters.DeviceIoControl.OutputBufferLength;
    
    if (stackLocation->Parameters.DeviceIoControl.IoControlCode == IOCTL_CSMT_READ_METHOD_DIRECT_IN)
    {
        RingBuffer::GetRingBufferInstance()->Put((BYTE*)_Irp->AssociatedIrp.SystemBuffer, inBufLength);
    
        DbgPrint("IOCTL_SPOTLESS (0x%x) issued", stackLocation->Parameters.DeviceIoControl.IoControlCode);
        DbgPrint("Input received from userland: %s", (char*)_Irp->AssociatedIrp.SystemBuffer);
    
        DbgPrint("Input bufferlength: %ld", inBufLength);
    
        //inBuf = (BYTE*)_Irp->AssociatedIrp.SystemBuffer;
        outBuf = (char*)_Irp->AssociatedIrp.SystemBuffer;
        //CAudioDataRingbuffer::getRingBufferInstance()->RingBuffer_Write(CAudioDataRingbuffer::getRingBufferInstance()->m_global_buffer_struct,
            //(SHORT*)_Irp->AssociatedIrp.SystemBuffer,4096);
        _Irp->IoStatus.Information = 0;// strlen(messageFromKernel);
        _Irp->IoStatus.Status = ntstatus;
    
        RtlCopyBytes(outBuf, data, outBufLength);
        _Irp->IoStatus.Information = (outBufLength < datalen ? outBufLength : datalen);
        //DbgPrint("Sending to userland: %s", messageFromKernel);
        //RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, messageFromKernel, strlen(Irp->AssociatedIrp.SystemBuffer));
    
        IoCompleteRequest(_Irp, IO_NO_INCREMENT);
    
        return ntstatus;
    }
    ntstatus = PcDispatchIrp(_DeviceObject, _Irp);
    return ntstatus;
    

    }
    }

    inside WriteBytes i do,

    ULONG bufferOffset = m_ullLinearPosition % m_ulDmaBufferSize;

    // Normally this will loop no more than once for a single wrap, but if
    // many bytes have been displaced then this may loops many times.
    while (ByteDisplacement > 0)
    {
        ULONG runWrite = min(ByteDisplacement, m_ulDmaBufferSize - bufferOffset);
        SIZE_T actuallyWritten;
    
        RingBuffer::GetRingBufferInstance()->Take(m_pDmaBuffer + bufferOffset, runWrite, &actuallyWritten);
        if (actuallyWritten < runWrite)
        {
            RtlZeroMemory(m_pDmaBuffer + bufferOffset + actuallyWritten, runWrite - actuallyWritten);
        }
        DbgPrint("bytes read : %ld", ByteDisplacement);
        bufferOffset = (bufferOffset + runWrite) % m_ulDmaBufferSize;
        ByteDisplacement -= runWrite;
    }
    

    Plz do let me know if u need any other part of code inorder to understand my issue.

  • Tim_RobertsTim_Roberts Member - All Emails Posts: 14,095
    edited July 29

    What do you mean by "noise"? Do you mean you get garbage static, or do you mean it's mostly OK but with lots of clicks? How often are you feeding the circular buffer, and how much data are you sending? There's no throttling here, so if you write 10,000 bytes and your circular buffer only holds 4096, you'll drop data. Your feeding application has to do careful timing to make sure you're feeding data at the same rate that the microphone is pulling it. You don't want to overflow, and you don't want WriteBytes to go dry.

    I see you're using METHOD_IN_DIRECT (based on the ioctl name), but you're using the first buffer (mistakenly called the "input" buffer). Remember that in a direct I/O IRP, the first buffer is always copied into kernel mode, but the second buffer (mistakenly called the "output" buffer) is directly mapped, not copied. If you're sending less than a couple of pages at a time, it's fine, but if you are sending more than that, you should switch to using the second buffer in the DeviceIoControl call, and get your data from Irp->MdlAddress.

    Tim Roberts, [email protected]
    Providenza & Boekelheide, Inc.

  • chauhan_sumit001chauhan_sumit001 Member Posts: 35

    @Tim_Roberts said:
    What do you mean by "noise"? Do you mean you get garbage static, or do you mean it's mostly OK but with lots of clicks? How often are you feeding the circular buffer, and how much data are you sending? There's no throttling here, so if you write 10,000 bytes and your circular buffer only holds 4096, you'll drop data. Your feeding application has to do careful timing to make sure you're feeding data at the same rate that the microphone is pulling it. You don't want to overflow, and you don't want WriteBytes to go dry.

    I see you're using METHOD_IN_DIRECT (based on the ioctl name), but you're using the first buffer (mistakenly called the "input" buffer). Remember that in a direct I/O IRP, the first buffer is always copied into kernel mode, but the second buffer (mistakenly called the "output" buffer) is directly mapped, not copied. If you're sending less than a couple of pages at a time, it's fine, but if you are sending more than that, you should switch to using the second buffer in the DeviceIoControl call, and get your data from Irp->MdlAddress.

    "noise" means some crackling noise which comes along with actual audio, my ring buffer size is 14112 bytes, and on each call of IOCTL i am sending 4096 bytes which gets stored in ring buffer and later pulled by WriteBytes...

    But what I observed is If i increase the input audio packet size from 4096 to some 6000 bytes then the crackling noise is less even though the audio quality degrades. is my buffer underflowing?

  • chauhan_sumit001chauhan_sumit001 Member Posts: 35

    @Tim_Roberts said:
    What do you mean by "noise"? Do you mean you get garbage static, or do you mean it's mostly OK but with lots of clicks? How often are you feeding the circular buffer, and how much data are you sending? There's no throttling here, so if you write 10,000 bytes and your circular buffer only holds 4096, you'll drop data. Your feeding application has to do careful timing to make sure you're feeding data at the same rate that the microphone is pulling it. You don't want to overflow, and you don't want WriteBytes to go dry.

    I see you're using METHOD_IN_DIRECT (based on the ioctl name), but you're using the first buffer (mistakenly called the "input" buffer). Remember that in a direct I/O IRP, the first buffer is always copied into kernel mode, but the second buffer (mistakenly called the "output" buffer) is directly mapped, not copied. If you're sending less than a couple of pages at a time, it's fine, but if you are sending more than that, you should switch to using the second buffer in the DeviceIoControl call, and get your data from Irp->MdlAddress.

    "noise" means some crackling noise which comes along with actual audio, my ring buffer size is 12000 bytes, and on each call of IOCTL i am sending 4096 bytes which gets stored in ring buffer and later pulled by WriteBytes...

    But what I observed is If i increase the input audio packet size from 4096 to some 6000 bytes then the crackling noise is less even though the audio quality degrades. is my buffer underflowing???

  • chauhan_sumit001chauhan_sumit001 Member Posts: 35

    Dear Tim,

    Currently I am using command prompt to install my driver,want to do it programatically ,could you please suggest how to do that, I wrote below code

    HINF HInf;
    LPCSTR szSourceFileName = "C:\Users\test\Desktop\virtual_mic_sumit_poc\wdm\exe\RemotePCVad.inf";
    UINT ErrorLine;
    HInf = SetupOpenInfFile(szSourceFileName, NULL, INF_STYLE_WIN4, &ErrorLine);
    PVOID Context = NULL;
    PBOOL FileWasInUse = FALSE;
    if (SetupInstallFileEx(HInf, NULL, "RemotePCVad.sys", "C:\Users\test\Desktop\virtual_mic_sumit_poc\wdm\exe",
    "C:\Users\test\Desktop\virtual_mic_sumit_poc\wdm\exe\RemotePCVad.sys", SP_COPY_NEWER_OR_SAME, NULL, Context, (FileWasInUse)) == 0) {
    DWORD dwVal = GetLastError();
    printf("\nsetup null: %d", dwVal);
    }

    I am getting 87 as value of GetlastError, need some help on this

  • Tim_RobertsTim_Roberts Member - All Emails Posts: 14,095

    There are three rather large problems here.

    First, all of your strings have a tab character in them ("\t"). You have to double all the backslashes in a constant string. I'm not sure how a Windows programmer would not know that.

    Second, it is a horrible practice to embed absolute paths in an application of any kind. Such an application will not work on any other computer. Put the files in the same directory as the executable, and run the program from there. Or, fetch the name of your executable and extract the path from there.

    Third, you can't install drivers using SetupInstallFileEx. That's only for applications. You have to create a fake device, then pre-install your driver package, then tell PnP to load your driver on that new device.

    Now, I wish I could speak authoritatively about this, but the process has changed in Windows 10, and I'm unsure. If you look in the devcon source code for the "devcon install" command, you'll see they use use SetupDiCreateDeviceInfo to create the new device, then UpdateDriverForPlugAndPlayDevices to load the driver package. On Win 10, however, this often results in two fake devices. As I understand it, Device Manager will now create a fake device automatically in some cases.

    Using the "pnputil -i -a" command does not result in two devices, but I'm not sure which APIs it uses, and we don't have source code for it. It looks like it uses SetupCopyOEMInf and DiInstallDriver, so maybe that's enough. Hopefully, someone else will respond.

    Tim Roberts, [email protected]
    Providenza & Boekelheide, Inc.

  • chauhan_sumit001chauhan_sumit001 Member Posts: 35

    Dear Tim,

    Now I am able to install driver programmatically, But In one use case i am stuck.

    Based on some condition i have to hide Virtual mic from sound control panel , but need to keep in device manager.

    how to achieve this, can I achieve using ioctl if yes then what i have to do in driver class.

    Thanks.

  • Tim_RobertsTim_Roberts Member - All Emails Posts: 14,095
    edited August 11

    This is actually a fairly easy one. Your virtual driver supports KSPROPERTY_JACK_DESCRIPTION (and I know that because Audio Engine won't talk to a driver that doesn't). The structure you return, KSJACK_DESCRIPTION, has a member IsConnected that says whether something is plugged in. If that member is false, you'll be in Device Manager, but will not be an audio device.

    So, add a backdoor ioctl to enable or disable the bit. In that ioctl handler, set the IsConneected field to the right state. Then, you need to signal Audio Engine that your jack state has changed. You do that by firing a KSEVENT_PINCAPS_JACKINFOCHANGE event. You'll have to add that to the list of events in the automation table for the topo filter. The sysvad sample has examples of this.

    Tim Roberts, [email protected]
    Providenza & Boekelheide, Inc.

  • chauhan_sumit001chauhan_sumit001 Member Posts: 35

    Dear Tim,

    i tried with below code

    NTSTATUS MiniportTopology::PropertyHandlerJackDescription
    (
    In PPCPROPERTY_REQUEST PropertyRequest
    )
    /*++

    Routine Description:

    Handles ( KSPROPSETID_Jack, KSPROPERTY_JACK_DESCRIPTION )

    Arguments:

    PropertyRequest -
    cJackDescriptions - # of elements in the jack descriptions array.
    JackDescriptions - Array of jack descriptions pointers.

    Return Value:

    NT status code.

    --*/
    {
    PAGED_CODE();

    ASSERT(PropertyRequest);
    
    DPF_ENTER(("[PropertyHandler_MicInJackDescription]"));
    
    NTSTATUS                ntStatus = STATUS_INVALID_DEVICE_REQUEST;
    ULONG                   nPinId = (ULONG)-1;
    
    ULONG                   cJackDescriptions = ARRAYSIZE(MicInJackDescriptions);
    PKSJACK_DESCRIPTION* JackDescriptions = MicInJackDescriptions;
    
    if (PropertyRequest->InstanceSize >= sizeof(ULONG))
    {
        nPinId = *(PULONG(PropertyRequest->Instance));
    
        if ((nPinId < cJackDescriptions) && (JackDescriptions[nPinId] != NULL))
        {
            if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT)
            {
                ntStatus =
                    KsHelper::PropertyHandler_BasicSupport
                    (
                        PropertyRequest,
                        KSPROPERTY_TYPE_BASICSUPPORT | KSPROPERTY_TYPE_GET,
                        VT_ILLEGAL
                    );
            }
            else
            {
                ULONG cbNeeded = sizeof(KSMULTIPLE_ITEM) + sizeof(KSJACK_DESCRIPTION);
    
                if (PropertyRequest->ValueSize == 0)
                {
                    PropertyRequest->ValueSize = cbNeeded;
                    ntStatus = STATUS_BUFFER_OVERFLOW;
                }
                else if (PropertyRequest->ValueSize < cbNeeded)
                {
                    ntStatus = STATUS_BUFFER_TOO_SMALL;
                }
                else
                {
                    if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET)
                    {
                        PKSMULTIPLE_ITEM pMI = (PKSMULTIPLE_ITEM)PropertyRequest->Value;
                        PKSJACK_DESCRIPTION pDesc = (PKSJACK_DESCRIPTION)(pMI + 1);
    
                        pMI->Size = cbNeeded;
                        pMI->Count = 1;
                        pDesc->IsConnected = FALSE;/////////////////////////setting it to false
                        RtlCopyMemory(pDesc, JackDescriptions[nPinId], sizeof(KSJACK_DESCRIPTION));
                        ntStatus = STATUS_SUCCESS;
                    }
                }
            }
        }
    }
    
    return ntStatus;
    

    }

    where I set pDesc->IsConnected to FALSE even after that I can see virtual mic in sound control panel...am I doing something wrong

    this API is getting called.

  • chauhan_sumit001chauhan_sumit001 Member Posts: 35

    got it fixed

    i was setting at wrong place

    static
    KSJACK_DESCRIPTION MicInJackDesc =
    {
    KSAUDIO_SPEAKER_MONO,
    JACKDESC_RGB(179, 201, 140),
    eConnTypeCombination,
    eGeoLocRear,
    eGenLocPrimaryBox,
    ePortConnJack,
    FALSE//TRUE///////////////////////////it works
    };

  • chauhan_sumit001chauhan_sumit001 Member Posts: 35
    edited August 13

    Dear Tim ,

    I have done some code change as per your suggestion.

    inside IOCTL:
    MicInJackDesc.IsConnected = FALSE

    inside topology properties class:

    static PCEVENT_ITEM JackInfoChangeEvent[] =
    {
    {
    &KSEVENTSETID_PinCapsChange, // Something changed
    KSEVENT_PINCAPS_JACKINFOCHANGE, // Jack Info Changes
    KSEVENT_TYPE_ENABLE | KSEVENT_TYPE_BASICSUPPORT,
    CMiniportTopology_EventHandler_JackState
    }
    };

    DEFINE_PCAUTOMATION_TABLE_PROP_EVENT(AutomationMicInTopoFilter, PropertiesTopoFilter, JackInfoChangeEvent);

    inside topology class:

    NTSTATUS CMiniportTopology_EventHandler_JackState
    (
    In PPCEVENT_REQUEST EventRequest
    )
    {
    DPF_ENTER(("[CMiniportTopologySYSVAD::CMiniportTopology_EventHandler_JackState]"));
    PCMiniportTopology miniport = reinterpret_cast(EventRequest->MajorTarget);
    if (EventRequest->Verb == PCEVENT_VERB_ADD)
    {
    miniport->AddEventToEventList(EventRequest->EventEntry);
    }
    return STATUS_SUCCESS;
    }

    even after that its not working, do I need to call GenerateEventList also??
    is there any thing else required????will this CMiniportTopology_EventHandler_JackState get called automatically and remove the mic from sound control panel after I set MicInJackDesc.IsConnected = FALSE in my IOCTL...…plz advice

  • Tim_RobertsTim_Roberts Member - All Emails Posts: 14,095

    That's 99% of it. The only thing remaining is that you need to TRIGGER the event by calling m_PortEvents->GenerateEventList when you change the jack state.

    Tim Roberts, [email protected]
    Providenza & Boekelheide, Inc.

  • chauhan_sumit001chauhan_sumit001 Member Posts: 35

    Dear Tim,

    inside below api i am calling GenerateEventList

    NTSTATUS CMiniportTopology_EventHandler_JackState
    (
    In PPCEVENT_REQUEST EventRequest
    )
    {
    DPF_ENTER(("[CMiniportTopologySYSVAD::CMiniportTopology_EventHandler_JackState]"));
    PCMiniportTopology miniport = reinterpret_cast(EventRequest->MajorTarget);
    if (EventRequest->Verb == PCEVENT_VERB_ADD)
    {
    miniport->AddEventToEventList(EventRequest->EventEntry);
    }
    miniport->GenerateEventList(
    (GUID*)&KSEVENTSETID_PinCapsChange, // event set. NULL is a wild card for all events.
    KSEVENT_PINCAPS_JACKINFOCHANGE, // event ID.
    TRUE, // use pid ID.
    (int)TopologyPin::Microphone, // pin ID.
    FALSE, // do not use node ID.
    ULONG(-1)); // node ID, not used.
    return STATUS_SUCCESS;
    }

    am I doing correct??

  • chauhan_sumit001chauhan_sumit001 Member Posts: 35

    Hi Tim,

    refering to above post,looks like calling GenerateEventList inside CMiniportTopology_EventHandler_JackState api is not correct, may I know from where and how to call GenerateEventList .

    need your help to understand this.

    Thanks

  • Tim_RobertsTim_Roberts Member - All Emails Posts: 14,095

    No, you didn't read what I wrote. Whenever YOU change the jack state, YOU need to call GenerateEventList. That EventHandler_JackState function is called by port class to get the event registered. Leave that the way it was.

    Tim Roberts, [email protected]
    Providenza & Boekelheide, Inc.

  • chauhan_sumit001chauhan_sumit001 Member Posts: 35

    Hi Tim,

    I am facing buffer overflow issue.

    I am using ring buffer to store audio data in driver, from that ringbuffer i am fetching and assigning to mdl buffer.
    but after 5 min ringbuffer overflows and after that i start getting some noise instead of actual audio.

    how to avoid this buffer overflow .
    need your help.

  • Tim_RobertsTim_Roberts Member - All Emails Posts: 14,095

    It probably means that the clock on your data source does not exactly match the clock in your receiving system. Common problem. You need to be able to handle that, usually by dropping the oldest samples. You will get one click, then it should resume until it fills again.

    If you're serious about quality, so one glitch in 5 minutes isn't acceptable, then you need to monitor the circular buffer level, and use that to make fractional adjustments in your sample rate.

    Tim Roberts, [email protected]
    Providenza & Boekelheide, Inc.

  • chauhan_sumit001chauhan_sumit001 Member Posts: 35

    Hi Tim,

    What could be the reason of audio delay in virtual mic.
    I am getting approx 2 sec delay in audio.

  • Tim_RobertsTim_Roberts Member - All Emails Posts: 14,095

    Two seconds delay based on what? How are you measuring that? That usually means your circular buffer is too large. If you have a 200k byte circular buffer, that would hold 2 seconds of 48kHz mono 16-bit PCM audio. If your data is coming in from a network source, you could also be seeing network delays.

    Tim Roberts, [email protected]
    Providenza & Boekelheide, Inc.

Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. Sign in or register to get started.

Upcoming OSR Seminars
OSR has suspended in-person seminars due to the Covid-19 outbreak. But, don't miss your training! Attend via the internet instead!
Internals & Software Drivers 15 November 2021 Live, Online
Writing WDF Drivers TBD Live, Online
Developing Minifilters 7 February 2022 Live, Online
Kernel Debugging 21 March 2022 Live, Online