From: robiwan Date: Thu, 23 Feb 2012 15:29:24 +0000 (+0000) Subject: ASIO: X-Git-Tag: pa_stable_v19_20140130_r1919~81 X-Git-Url: https://andrewgundersen.net/repos?a=commitdiff_plain;h=32e0080310e79d621b1da63901cb91d74dcc4d5d;p=portaudio ASIO: - Certain drivers write over the available memory of PaAsioDriverInfo, now a padding area makes sure the stack doesn't get corrupted. WDM-KS: - Corrected capture event handling --- diff --git a/src/hostapi/asio/pa_asio.cpp b/src/hostapi/asio/pa_asio.cpp index 2f90c28..5735e16 100644 --- a/src/hostapi/asio/pa_asio.cpp +++ b/src/hostapi/asio/pa_asio.cpp @@ -1031,8 +1031,6 @@ PaError PaAsio_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex PaAsioHostApiRepresentation *asioHostApi; PaAsioDeviceInfo *deviceInfoArray; char **names; - PaAsioDriverInfo paAsioDriverInfo; - asioHostApi = (PaAsioHostApiRepresentation*)PaUtil_AllocateMemory( sizeof(PaAsioHostApiRepresentation) ); if( !asioHostApi ) { @@ -1142,6 +1140,13 @@ PaError PaAsio_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex for( i=0; i < driverCount; ++i ) { + /* Due to the headless design of the ASIO API, drivers are free to write over data given to them (like M-Audio + drivers f.i.). This is an attempt to overcome that. */ + union _tag_local { + PaAsioDriverInfo info; + char _padding[4096]; + } paAsioDriver; + PA_DEBUG(("ASIO names[%d]:%s\n",i,names[i])); @@ -1176,7 +1181,7 @@ PaError PaAsio_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex /* Attempt to load the asio driver... */ - if( LoadAsioDriver( asioHostApi, names[i], &paAsioDriverInfo, asioHostApi->systemSpecific ) == paNoError ) + if( LoadAsioDriver( asioHostApi, names[i], &paAsioDriver.info, asioHostApi->systemSpecific ) == paNoError ) { PaAsioDeviceInfo *asioDeviceInfo = &deviceInfoArray[ (*hostApi)->info.deviceCount ]; PaDeviceInfo *deviceInfo = &asioDeviceInfo->commonDeviceInfo; @@ -1186,15 +1191,15 @@ PaError PaAsio_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex deviceInfo->name = names[i]; PA_DEBUG(("PaAsio_Initialize: drv:%d name = %s\n", i,deviceInfo->name)); - PA_DEBUG(("PaAsio_Initialize: drv:%d inputChannels = %d\n", i, paAsioDriverInfo.inputChannelCount)); - PA_DEBUG(("PaAsio_Initialize: drv:%d outputChannels = %d\n", i, paAsioDriverInfo.outputChannelCount)); - PA_DEBUG(("PaAsio_Initialize: drv:%d bufferMinSize = %d\n", i, paAsioDriverInfo.bufferMinSize)); - PA_DEBUG(("PaAsio_Initialize: drv:%d bufferMaxSize = %d\n", i, paAsioDriverInfo.bufferMaxSize)); - PA_DEBUG(("PaAsio_Initialize: drv:%d bufferPreferredSize = %d\n", i, paAsioDriverInfo.bufferPreferredSize)); - PA_DEBUG(("PaAsio_Initialize: drv:%d bufferGranularity = %d\n", i, paAsioDriverInfo.bufferGranularity)); + PA_DEBUG(("PaAsio_Initialize: drv:%d inputChannels = %d\n", i, paAsioDriver.info.inputChannelCount)); + PA_DEBUG(("PaAsio_Initialize: drv:%d outputChannels = %d\n", i, paAsioDriver.info.outputChannelCount)); + PA_DEBUG(("PaAsio_Initialize: drv:%d bufferMinSize = %d\n", i, paAsioDriver.info.bufferMinSize)); + PA_DEBUG(("PaAsio_Initialize: drv:%d bufferMaxSize = %d\n", i, paAsioDriver.info.bufferMaxSize)); + PA_DEBUG(("PaAsio_Initialize: drv:%d bufferPreferredSize = %d\n", i, paAsioDriver.info.bufferPreferredSize)); + PA_DEBUG(("PaAsio_Initialize: drv:%d bufferGranularity = %d\n", i, paAsioDriver.info.bufferGranularity)); - deviceInfo->maxInputChannels = paAsioDriverInfo.inputChannelCount; - deviceInfo->maxOutputChannels = paAsioDriverInfo.outputChannelCount; + deviceInfo->maxInputChannels = paAsioDriver.info.inputChannelCount; + deviceInfo->maxOutputChannels = paAsioDriver.info.outputChannelCount; deviceInfo->defaultSampleRate = 0.; bool foundDefaultSampleRate = false; @@ -1222,13 +1227,13 @@ PaError PaAsio_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex */ double defaultLowLatency = - paAsioDriverInfo.bufferPreferredSize / deviceInfo->defaultSampleRate; + paAsioDriver.info.bufferPreferredSize / deviceInfo->defaultSampleRate; deviceInfo->defaultLowInputLatency = defaultLowLatency; deviceInfo->defaultLowOutputLatency = defaultLowLatency; double defaultHighLatency = - paAsioDriverInfo.bufferMaxSize / deviceInfo->defaultSampleRate; + paAsioDriver.info.bufferMaxSize / deviceInfo->defaultSampleRate; if( defaultHighLatency < defaultLowLatency ) defaultHighLatency = defaultLowLatency; /* just in case the driver returns something strange */ @@ -1249,10 +1254,10 @@ PaError PaAsio_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex PA_DEBUG(("PaAsio_Initialize: drv:%d defaultHighInputLatency = %f\n", i, deviceInfo->defaultHighInputLatency)); PA_DEBUG(("PaAsio_Initialize: drv:%d defaultHighOutputLatency = %f\n", i, deviceInfo->defaultHighOutputLatency)); - asioDeviceInfo->minBufferSize = paAsioDriverInfo.bufferMinSize; - asioDeviceInfo->maxBufferSize = paAsioDriverInfo.bufferMaxSize; - asioDeviceInfo->preferredBufferSize = paAsioDriverInfo.bufferPreferredSize; - asioDeviceInfo->bufferGranularity = paAsioDriverInfo.bufferGranularity; + asioDeviceInfo->minBufferSize = paAsioDriver.info.bufferMinSize; + asioDeviceInfo->maxBufferSize = paAsioDriver.info.bufferMaxSize; + asioDeviceInfo->preferredBufferSize = paAsioDriver.info.bufferPreferredSize; + asioDeviceInfo->bufferGranularity = paAsioDriver.info.bufferGranularity; asioDeviceInfo->asioChannelInfos = (ASIOChannelInfo*)PaUtil_GroupAllocateMemory( diff --git a/src/hostapi/wdmks/pa_win_wdmks.c b/src/hostapi/wdmks/pa_win_wdmks.c index 515e790..ba5ae55 100644 --- a/src/hostapi/wdmks/pa_win_wdmks.c +++ b/src/hostapi/wdmks/pa_win_wdmks.c @@ -1532,6 +1532,8 @@ static PaWinWdmPin* PinNew(PaWinWdmFilter* parentFilter, unsigned long pinId, Pa { ULONG topoPinId = GetConnectedPin(pinId, (pin->dataFlow == KSPIN_DATAFLOW_IN), parentFilter, -1, NULL, NULL); + const wchar_t kInputName[] = L"Input"; + const wchar_t kOutputName[] = L"Output"; if (topoPinId != KSFILTER_NODE) { @@ -1580,7 +1582,7 @@ static PaWinWdmPin* PinNew(PaWinWdmFilter* parentFilter, unsigned long pinId, Pa /* Make sure pin gets a name here... */ if (wcslen(pin->friendlyName) == 0) { - wcscpy(pin->friendlyName, (pin->dataFlow == KSPIN_DATAFLOW_IN) ? L"Output" : L"Input"); + wcscpy(pin->friendlyName, (pin->dataFlow == KSPIN_DATAFLOW_IN) ? kOutputName : kInputName); #ifdef UNICODE PA_DEBUG(("PinNew: Setting pin friendly name to '%s'\n", pin->friendlyName)); #else @@ -1798,7 +1800,7 @@ static PaWinWdmPin* PinNew(PaWinWdmFilter* parentFilter, unsigned long pinId, Pa /* Make sure we get a name for the pin */ if (wcslen(pin->friendlyName) == 0) { - wcscpy(pin->friendlyName, L"Input"); + wcscpy(pin->friendlyName, kInputName); } #ifdef UNICODE PA_DEBUG(("PinNew: Input friendly name '%s'\n", pin->friendlyName)); @@ -1875,7 +1877,8 @@ static PaWinWdmPin* PinNew(PaWinWdmFilter* parentFilter, unsigned long pinId, Pa result = GetNameFromCategory(&category, TRUE, pin->inputs[i]->friendlyName, MAX_PATH); if (result != paNoError) { - _snwprintf(pin->inputs[i]->friendlyName, MAX_PATH, L"Input %d", i + 1); + /* Only specify name, let name hash in ScanDeviceInfos fix postfix enumerators */ + wcscpy(pin->inputs[i]->friendlyName, kInputName); } } #ifdef UNICODE @@ -1903,14 +1906,7 @@ static PaWinWdmPin* PinNew(PaWinWdmFilter* parentFilter, unsigned long pinId, Pa { PA_DEBUG(("PinNew: No topology pin id found. Bad...\n")); /* No TOPO pin id ??? This is bad. Ok, so we just say it is an input or output... */ - if (pin->dataFlow == KSPIN_DATAFLOW_IN) - { - wcscpy(pin->friendlyName, L"Line Out"); - } - else - { - wcscpy(pin->friendlyName, L"Line In"); - } + wcscpy(pin->friendlyName, (pin->dataFlow == KSPIN_DATAFLOW_IN) ? kOutputName : kInputName); } } @@ -5422,8 +5418,6 @@ static PaError PreparePinsForStart(PaProcessThreadInfo* pInfo) { goto error; } - /* Reset the events as some devices SET the event on PinRead */ - ResetEvent(pInfo->stream->capture.packets[i].Signal.hEvent); ++pInfo->pending; } } @@ -5903,24 +5897,27 @@ PA_THREAD_FUNC ProcessingThread(void* pParam) { if (eventSignalled < captureEvents) { - timeStamp[0] = dwCurrentTime; - info.stream->capture.pPin->fnEventHandler(&info, eventSignalled); - /* Since we use the ring buffer, we can submit the buffers directly */ - if (!info.stream->streamStop) + if (info.stream->capture.pPin->fnEventHandler(&info, eventSignalled) == paNoError) { - result = info.stream->capture.pPin->fnSubmitHandler(&info, info.captureTail); - if (result != paNoError) + timeStamp[0] = dwCurrentTime; + + /* Since we use the ring buffer, we can submit the buffers directly */ + if (!info.stream->streamStop) { - PA_HP_TRACE((info.stream->hLog, "Capture submit handler failed with result %d", result)); - break; + result = info.stream->capture.pPin->fnSubmitHandler(&info, info.captureTail); + if (result != paNoError) + { + PA_HP_TRACE((info.stream->hLog, "Capture submit handler failed with result %d", result)); + break; + } + } + ++info.captureTail; + /* If full-duplex, let _only_ render event trigger processing. We still need the stream stop + handling working, so let that be processed anyways... */ + if (info.stream->userOutputChannels > 0) + { + doProcessing = 0; } - } - ++info.captureTail; - /* If full-duplex, let _only_ render event trigger processing. We still need the stream stop - handling working, so let that be processed anyways... */ - if (info.stream->userOutputChannels > 0) - { - doProcessing = 0; } } else if (eventSignalled < renderEvents) @@ -6317,6 +6314,16 @@ static PaError PaPinCaptureEventHandler_WaveCyclic(PaProcessThreadInfo* pInfo, u assert( eventIndex < pInfo->stream->capture.noOfPackets ); + if (packet->Header.DataUsed == 0) + { + PA_HP_TRACE((pInfo->stream->hLog, ">>> Capture bogus event: idx=%u (DataUsed=%u)", eventIndex, packet->Header.DataUsed)); + + /* Bogus event, reset! This is to handle the behavior of this USB mic: http://shop.xtz.se/measurement-system/microphone-to-dirac-live-room-correction-suite + on startup of streaming, where it erroneously sets the event without the corresponding buffer being filled (DataUsed == 0) */ + ResetEvent(packet->Signal.hEvent); + return -1; + } + pInfo->capturePackets[pInfo->captureHead & cPacketsArrayMask].packet = packet; frameCount = PaUtil_WriteRingBuffer(&pInfo->stream->ringBuffer, packet->Header.Data, pInfo->stream->capture.framesPerBuffer); @@ -6335,9 +6342,8 @@ static PaError PaPinCaptureSubmitHandler_WaveCyclic(PaProcessThreadInfo* pInfo, assert(packet != 0); PA_HP_TRACE((pInfo->stream->hLog, "Capture submit: %u", eventIndex)); packet->Header.DataUsed = 0; /* Reset for reuse */ - result = PinRead(pInfo->stream->capture.pPin->handle, packet); - /* Reset event, as some drivers might not do so (or even set the event!!), resulting in a 100% CPU capture loop */ ResetEvent(packet->Signal.hEvent); + result = PinRead(pInfo->stream->capture.pPin->handle, packet); ++pInfo->pending; return result; }