我要制作一个虚拟音频环回电缆/管道(一个虚拟音频设备)。MSVAD 源代码与 WDK 一起只执行捕获和保存在设备输入端口出现的音频数据,我不知道如何实现 CopyTo 和 CopyFrom 函数来制作一个VALC,这样在VALC(虚拟音频设备)的输入端口上的任何音频都可以在VALC的输出端口上使用(类似于Virtual Audio Cable v4.13)。请帮我编写CopyTo代码和 CopyFrom 功能?我得到了一个音频环回驱动程序的源代码,它的功能与VALC相似/相同。在这里,我正在编写代码的音频循环部分。该代码正在运行,但输出中有音乐的咔嗒声和噼啪声。我期待有关此代码的有价值的建议/代码,还请指定此代码有什么问题?
代码:
//================================================
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
//============================================================================
提前致谢 :)