5

我要制作一个虚拟音频环回电缆/管道(一个虚拟音频设备)。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
//============================================================================

提前致谢 :)

4

0 回答 0