WASAPI - Streamcopy mittels thread
-
Mahlzeit,
Ich versuche den Audio-stream von einer Endpointdevice mittels Loopback auf eine andere device zu kopieren.
Das ganze funktioniert teilweise, nur habe ich auf der Ziel-device keinen sauberen audiostream, es tönt zwar - aber nicht schön.Das Initialisieren der stream-devices, GetBuffer usw. scheint also zu funktionieren, nur das kopieren des Stream's scheint nicht ganz hinzuhauen. Ich kopiere den Stream in einem zyklischen Thread mit ThreadPriority::Highest dennoch kriege ich kein schönes Audiosignal...
Stream-Copy:
HRESULT ChannelDeviceHandler::CopyStream(){ HRESULT hr; BYTE *pSrcData; BYTE *pDstData; UINT32 availableFrames; DWORD flags; UINT32 numFramesPadding; UINT32 numFramesAvailable; UINT32 bufSize; //Copy Stream //------------- for(UINT channel = 1; channel <= CHANNELNUM; channel++){ if (this->channelVar[channel].pAudioClient != NULL){ hr = this->channelVar[channel].pAudioClient->GetCurrentPadding(&numFramesPadding); numFramesAvailable = this->channelVar[channel].bufferFrameCount - numFramesPadding; //Size Outstream hr = this->pSrcCaptureClient->GetNextPacketSize(&availableFrames); //Size Instream if (numFramesAvailable>availableFrames){ //Output > Input bufSize = availableFrames; } else{ bufSize = numFramesAvailable; } if (bufSize > 0) { //Get Buffers //----------- pDstData = NULL; pSrcData = NULL; hr = this->channelVar[channel].pRenderClient->GetBuffer(bufSize, &pDstData); hr = this->pSrcCaptureClient->GetBuffer(&pSrcData, &availableFrames, &flags, NULL, NULL); //Copy Datastream for(UINT32 i = 0; i < (bufSize*8); i++){ *pDstData++ = *pSrcData++; } hr = this->channelVar[channel].pRenderClient->ReleaseBuffer(bufSize, flags); hr = this->pSrcCaptureClient->ReleaseBuffer(bufSize); } } } //free(pBuffer); return 0; };Thread:
CyclicThread::CyclicThread(ChannelDeviceHandler *chHandler){ HRESULT hr; //Copy Object reference to member this->chHandler = chHandler; } void CyclicThread::CyclicProc(){ while(true){ this->chHandler->CyclicCall(1, 0.01); //Thread::Sleep(); } } private: System::Void Form1_Load(System::Object^ sender, System::EventArgs^ e) { DWORD dwRet; HRESULT hr; LPWSTR devName = (LPWSTR) malloc(200); //Create Object channelDevice = new ChannelDeviceHandler(); cycle = gcnew CyclicThread(channelDevice); dwRet = GetPrivateProfileString(TEXT("Devices"),TEXT("DevName1"),TEXT(""),devName,200, TEXT("c:\\myFile.ini")); if(wcscmp(devName,TEXT(""))){ comboBox1->Items->Add(gcnew String(devName)); comboBox1->SelectedItem = gcnew String(devName); } //Start Capture hr= channelDevice->StartLoopBackCapture(); //start thread cycThread = gcnew Thread( gcnew ThreadStart(cycle, &CyclicThread::CyclicProc ) ); cycThread->Priority = ThreadPriority::Highest; cycThread->Start(); //free PTR free(devName); }Wenn ich den Thread langsamer mache (mittels Sleep(5)), wird das Signal schlechter, daher denke ich dass es ein Timing-Problem sein könnte, aber was soll ich machen wenn ein eigener Thread mit ThreadPriority::Highest nicht reicht?
PS:
-Die Pufferzeit der Soundkarte ist HnsRequestedDuration = 100000 -> 10ms
-Framesize = 8 Byte sollte auch stimmen (2 Kanäle, 32Bit auflösung)
-Das ganze läuft unter VC++ Express 2010 - CLR FORM's-Projekt
-
PS: CyclicCall() ruft CopyStream() auf...