none
Making Virtual Audio Loopback Devices from WDK MSVAD samples RRS feed

  • Question

  • Hi friends,
             I am going to make a Virtual Audio Loopback Cable/Pipeline(a Virtual Audio Device). MSVAD source code getting along with WDK only perform capture and save audio data which appears at the input port of the device, I don't know how to implement CopyTo and CopyFrom functions to make a VALC such that any audio data appears at the input port of VALC (Virtual Audio Device) is available at the output port of VALC (similar to Virtual Audio Cable v4.13).Please help me to code CopyTo and CopyFrom functions?  I got a source code of an Audio Loopback Driver whose functions similar to VALC. Here I'm writing the audio looping part of the code. The code is working but output have clicking and crakling sounds along with music when increased number of channels. I expect valuable suggessions/codes to reduce latency,also specify what is wrong with this code? -Thanks in advance.

    Code:

    //================================================
    STDMETHODIMP_(void) CMiniportWaveCyclicStream::CopyFrom( 
        IN  PVOID                   Destination,
        IN  PVOID                   Source,
        IN  ULONG                   ByteCount 
    )
    /*
    Routine Description:
      The CopyFrom function copies sample data from the DMA buffer. 
      Callers of CopyFrom can run at any IRQL
     
    Arguments:
      Destination - Points to the destination buffer. 
      Source - Points to the source buffer. 
      ByteCount - Points to the source buffer. 
     
    Return Value:
      void
    */
    {
      ULONG i=0;
      ULONG FrameCount = ByteCount/2; //we guess 16-Bit sample rate
      //DbgPrint(DBGMESSAGE "CopyFrom - ReadPos=%d",myBufferReadPos);  DbgPrint(DBGMESSAGE "CopyFrom - WritePos=%d",myBufferWritePos);
      if (!m_pMiniport->myBufferLocked) {
    	//DbgPrint(DBGMESSAGE "CopyFrom - ByteCount=%d", ByteCount);
        InterlockedExchange(&m_pMiniport->myBufferLocked, TRUE);
    	
    	ULONG umyBufferSize=(ULONG)m_pMiniport->myBufferSize;
    	ULONG availableDataCount = (umyBufferSize + m_pMiniport->myBufferWritePos) - m_pMiniport->myBufferReadPos;
    	if (availableDataCount >= umyBufferSize)
    		availableDataCount -= umyBufferSize;
        if (availableDataCount < FrameCount)  {
    	  //if the caller wants to read more data than the buffer size is,
    	  //we fill the rest with silence
    	  //we write the silence at the beginning,
    	  //because in the most cases we need to do this the caller begins to read - so we care
    	  //for a continually stream of sound data
    	  ULONG silenceCount = FrameCount - availableDataCount;
          //DbgPrint(DBGMESSAGE "CopyFrom - need more data! NeedCount=%d", silenceCount);
    	  for (i=0; i<=silenceCount ; i++) {
    		  ((PWORD)Destination)[i]=0;
    	  }
        }
     
        //i=0;
        while ((i < FrameCount) && //we have more data in the buffer than the caller would like to get
    		((m_pMiniport->myBufferWritePos != m_pMiniport->myBufferReadPos+1) && !((m_pMiniport->myBufferWritePos==0) && (m_pMiniport->myBufferReadPos==m_pMiniport->myBufferSize))) ) {
          ((PWORD)Destination)[i]=((PWORD)m_pMiniport->myBuffer)[m_pMiniport->myBufferReadPos];
          i++;
          m_pMiniport->myBufferReadPos++;
          if (m_pMiniport->myBufferReadPos >= m_pMiniport->myBufferSize) //Loop the buffer
    	    m_pMiniport->myBufferReadPos=0;
        }
    	InterlockedExchange(&m_pMiniport->myBufferReading, TRUE); //now the caller reads from the buffer - so we can notify the CopyTo function
    
        //DbgPrint(DBGMESSAGE "CopyFrom TRUE ByteCount=%d", ByteCount);
        InterlockedExchange(&m_pMiniport->myBufferLocked, FALSE);
      } else {
        //in this case we can't obtain the data from buffer because it is locked
        //the best we can do (to satisfy the caller) is to fill the whole buffer with silence
        for (i=0; i < FrameCount ; i++) {
          ((PWORD)Destination)[i]=0;
        }
        DBGPRINT("CopyFrom FALSE");
      }
    } // CopyFrom
    
    //====================================================
    STDMETHODIMP_(void) CMiniportWaveCyclicStream::CopyTo( 
      IN  PVOID                   Destination,
      IN  PVOID                   Source,
      IN  ULONG                   ByteCount
    )
    /*
    Routine Description:
      The CopyTo function copies sample data to the DMA buffer. 
      Callers of CopyTo can run at any IRQL. 
     
    Arguments:
      Destination - Points to the destination buffer. 
      Source - Points to the source buffer
      ByteCount - Number of bytes to be copied
     
    Return Value:
      void
    */
     
    {
      ULONG i=0;
      ULONG FrameCount = ByteCount/2; //we guess 16-Bit sample rate
      if (m_pMiniport->myBuffer==NULL) {
        ULONG bufSize=64*1024; //size in bytes
        DBGPRINT("Try to allocate buffer");
        m_pMiniport->myBuffer = (PVOID) ExAllocatePoolWithTag(NonPagedPool, bufSize, SAUDIO_POOLTAG);
        if (!m_pMiniport->myBuffer) {
          DBGPRINT("FAILED to allocate buffer");
        } else {
          DBGPRINT("Successfully allocated buffer");
          m_pMiniport->myBufferSize = bufSize/2; //myBufferSize in frames
          InterlockedExchange(&m_pMiniport->myBufferLocked, FALSE);
    	}
      }
     
      if (!m_pMiniport->myBufferLocked) {
        //DbgPrint(DBGMESSAGE "Fill Buffer ByteCount=%d", ByteCount);
        InterlockedExchange(&m_pMiniport->myBufferLocked, TRUE);
     
        i=0;
        while (i < FrameCount) {//while data is available
          //test wether we arrived at the read-pos
          //if (! ((myBufferWritePos+1 != myBufferReadPos) && !((myBufferReadPos==0) && (myBufferWritePos==myBufferSize)))) {
    	  if ((m_pMiniport->myBufferWritePos+1==m_pMiniport->myBufferReadPos) || (m_pMiniport->myBufferReadPos==0 && m_pMiniport->myBufferWritePos==m_pMiniport->myBufferSize)){
            //DbgPrint(DBGMESSAGE "CopyTo - there is no space for new data! NeedCount=%d", FrameCount-i);
    		if (m_pMiniport->myBufferReadPos==m_pMiniport->myBufferSize)
    			m_pMiniport->myBufferReadPos=0;
    		else
    			m_pMiniport->myBufferReadPos++;
            //break; //we have to break - because there is no space for the rest data
          }
     
          ((PWORD)m_pMiniport->myBuffer)[m_pMiniport->myBufferWritePos]=((PWORD)Source)[i];
          i++;
          m_pMiniport->myBufferWritePos++;
          if (m_pMiniport->myBufferWritePos >= m_pMiniport->myBufferSize) //Loop the buffer
    	    m_pMiniport->myBufferWritePos=0;
        }
      //DbgPrint(DBGMESSAGE "CopyTo - ReadPos=%d",myBufferReadPos);  DbgPrint(DBGMESSAGE "CopyTo - WritePos=%d",myBufferWritePos);
      InterlockedExchange(&m_pMiniport->myBufferLocked, FALSE);
      //DbgPrint(DBGMESSAGE "(2) CopyTo - ReadPos=%d",myBufferReadPos);  DbgPrint(DBGMESSAGE "(2) CopyTo - WritePos=%d",myBufferWritePos);
      //DbgPrint(DBGMESSAGE "(2) CopyTo - Locked=%d",myBufferLocked);
      }
    } // CopyTo

    • Changed type Syamkumar S Monday, September 23, 2013 10:50 AM
    • Changed type Syamkumar S Monday, September 23, 2013 10:50 AM
    Monday, September 23, 2013 10:48 AM