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 apears 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 apears 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/same to VALC. Here I'm writing the audio looping part of the code. The code is working but output have clicking and crakling sounds with music. I expect valuable suggessions/codes about this code,also specify what is wrong with this code?
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,
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
//============================================================================
Thanks in advance :)