Click here to Skip to main content
15,885,365 members
Please Sign up or sign in to vote.
1.00/5 (2 votes)
See more: , +
I am going to make an audio Loopback device driver(a virtual audio device).MSVAD source code getting along with WDK only perform capture and save audio data which apears at the input port of the device, I don't know how to implement CopyTo and CopyFrom functions to make an audio Loopback device such that any audio apears at the input port of Loopback device (Virtual Audio Device) is available at the output port of Loopback device (similar to Virtual Audio Cable).Please help me to code CopyTo and CopyFrom functions? Recently I got a source code of Audio Loopback Driver. Here I'm writing the looping part of code. The code is working but output have crakling sounds. Please write what is wrong with this code?

Code:
C++
 //================================================
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, RTSDAUDIO_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
Posted
Updated 18-Sep-13 11:42am
v3
Comments
SYAMKUMAR S 27-Sep-13 4:25am    
How double buffering can be implemented in this project?
srabbis 27-Sep-15 10:47am    
Hello Syam, did you able to make it working? Would you please share your code? I used your code but no audio sound while playing any music in youtube or anything.

Help would be appreciated.
Thanks.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900