5

仮想オーディオ ループバック ケーブル/パイプライン (仮想オーディオ デバイス) を作成します。WDK と連携する MSVAD ソース コードは、デバイスの入力ポートに表示されるオーディオ データのキャプチャと保存のみを実行します。方法がわかりません。 CopyTo および CopyFrom 関数を実装して、VALC (Virtual Audio Device) の入力ポートにオーディオが表示され、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