📄 pa_asio.cpp
字号:
void *buffer = stream->asioBufferInfos[ i + stream->inputChannelCount ].buffers[index]; int bytesPerSample = BytesPerAsioSample( stream->asioChannelInfos[ i + stream->inputChannelCount ].type ); memset( buffer, 0, stream->framesPerHostCallback * bytesPerSample ); }}static unsigned long SelectHostBufferSize( unsigned long suggestedLatencyFrames, PaAsioDriverInfo *driverInfo ){ unsigned long result; if( suggestedLatencyFrames == 0 ) { result = driverInfo->bufferPreferredSize; } else{ if( suggestedLatencyFrames <= (unsigned long)driverInfo->bufferMinSize ) { result = driverInfo->bufferMinSize; } else if( suggestedLatencyFrames >= (unsigned long)driverInfo->bufferMaxSize ) { result = driverInfo->bufferMaxSize; } else { if( driverInfo->bufferGranularity == -1 ) { /* power-of-two */ result = 2; while( result < suggestedLatencyFrames ) result *= 2; if( result < (unsigned long)driverInfo->bufferMinSize ) result = driverInfo->bufferMinSize; if( result > (unsigned long)driverInfo->bufferMaxSize ) result = driverInfo->bufferMaxSize; } else if( driverInfo->bufferGranularity == 0 ) { /* the documentation states that bufferGranularity should be zero when bufferMinSize, bufferMaxSize and bufferPreferredSize are the same. We assume that is the case. */ result = driverInfo->bufferPreferredSize; } else { /* modulo granularity */ unsigned long remainder = suggestedLatencyFrames % driverInfo->bufferGranularity; if( remainder == 0 ) { result = suggestedLatencyFrames; } else { result = suggestedLatencyFrames + (driverInfo->bufferGranularity - remainder); if( result > (unsigned long)driverInfo->bufferMaxSize ) result = driverInfo->bufferMaxSize; } } } } return result;}/* returns channelSelectors if present */static PaError ValidateAsioSpecificStreamInfo( const PaStreamParameters *streamParameters, const PaAsioStreamInfo *streamInfo, int deviceChannelCount, int **channelSelectors ){ if( streamInfo ) { if( streamInfo->size != sizeof( PaAsioStreamInfo ) || streamInfo->version != 1 ) { return paIncompatibleHostApiSpecificStreamInfo; } if( streamInfo->flags & paAsioUseChannelSelectors ) *channelSelectors = streamInfo->channelSelectors; if( !(*channelSelectors) ) return paIncompatibleHostApiSpecificStreamInfo; for( int i=0; i < streamParameters->channelCount; ++i ){ if( (*channelSelectors)[i] < 0 || (*channelSelectors)[i] >= deviceChannelCount ){ return paInvalidChannelCount; } } } return paNoError;}/* see pa_hostapi.h for a list of validity guarantees made about OpenStream parameters */static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi, PaStream** s, const PaStreamParameters *inputParameters, const PaStreamParameters *outputParameters, double sampleRate, unsigned long framesPerBuffer, PaStreamFlags streamFlags, PaStreamCallback *streamCallback, void *userData ){ PaError result = paNoError; PaAsioHostApiRepresentation *asioHostApi = (PaAsioHostApiRepresentation*)hostApi; PaAsioStream *stream = 0; PaAsioStreamInfo *inputStreamInfo, *outputStreamInfo; unsigned long framesPerHostBuffer; int inputChannelCount, outputChannelCount; PaSampleFormat inputSampleFormat, outputSampleFormat; PaSampleFormat hostInputSampleFormat, hostOutputSampleFormat; unsigned long suggestedInputLatencyFrames; unsigned long suggestedOutputLatencyFrames; PaDeviceIndex asioDeviceIndex; ASIOError asioError; int asioIsInitialized = 0; int asioBuffersCreated = 0; int completedBuffersPlayedEventInited = 0; int i; PaAsioDriverInfo *driverInfo; int *inputChannelSelectors = 0; int *outputChannelSelectors = 0; /* unless we move to using lower level ASIO calls, we can only have one device open at a time */ if( asioHostApi->openAsioDeviceIndex != paNoDevice ){ PA_DEBUG(("OpenStream paDeviceUnavailable\n")); return paDeviceUnavailable; } if( inputParameters && outputParameters ) { /* full duplex ASIO stream must use the same device for input and output */ if( inputParameters->device != outputParameters->device ){ PA_DEBUG(("OpenStream paBadIODeviceCombination\n")); return paBadIODeviceCombination; } } if( inputParameters ) { inputChannelCount = inputParameters->channelCount; inputSampleFormat = inputParameters->sampleFormat; suggestedInputLatencyFrames = (unsigned long)((inputParameters->suggestedLatency * sampleRate)+0.5f); /* unless alternate device specification is supported, reject the use of paUseHostApiSpecificDeviceSpecification */ if( inputParameters->device == paUseHostApiSpecificDeviceSpecification ) return paInvalidDevice; asioDeviceIndex = inputParameters->device; PaAsioDeviceInfo *asioDeviceInfo = (PaAsioDeviceInfo*)hostApi->deviceInfos[asioDeviceIndex]; /* validate hostApiSpecificStreamInfo */ inputStreamInfo = (PaAsioStreamInfo*)inputParameters->hostApiSpecificStreamInfo; result = ValidateAsioSpecificStreamInfo( inputParameters, inputStreamInfo, asioDeviceInfo->commonDeviceInfo.maxInputChannels, &inputChannelSelectors ); if( result != paNoError ) return result; } else { inputChannelCount = 0; inputSampleFormat = 0; suggestedInputLatencyFrames = 0; } if( outputParameters ) { outputChannelCount = outputParameters->channelCount; outputSampleFormat = outputParameters->sampleFormat; suggestedOutputLatencyFrames = (unsigned long)((outputParameters->suggestedLatency * sampleRate)+0.5f); /* unless alternate device specification is supported, reject the use of paUseHostApiSpecificDeviceSpecification */ if( outputParameters->device == paUseHostApiSpecificDeviceSpecification ) return paInvalidDevice; asioDeviceIndex = outputParameters->device; PaAsioDeviceInfo *asioDeviceInfo = (PaAsioDeviceInfo*)hostApi->deviceInfos[asioDeviceIndex]; /* validate hostApiSpecificStreamInfo */ outputStreamInfo = (PaAsioStreamInfo*)outputParameters->hostApiSpecificStreamInfo; result = ValidateAsioSpecificStreamInfo( outputParameters, outputStreamInfo, asioDeviceInfo->commonDeviceInfo.maxOutputChannels, &outputChannelSelectors ); if( result != paNoError ) return result; } else { outputChannelCount = 0; outputSampleFormat = 0; suggestedOutputLatencyFrames = 0; } driverInfo = &asioHostApi->openAsioDriverInfo; /* NOTE: we load the driver and use its current settings rather than the ones in our device info structure which may be stale */ result = LoadAsioDriver( asioHostApi->inheritedHostApiRep.deviceInfos[ asioDeviceIndex ]->name, driverInfo, asioHostApi->systemSpecific ); if( result == paNoError ) asioIsInitialized = 1; else{ PA_DEBUG(("OpenStream ERROR1\n")); goto error; } /* check that input device can support inputChannelCount */ if( inputChannelCount > 0 ) { if( inputChannelCount > driverInfo->inputChannelCount ) { result = paInvalidChannelCount; PA_DEBUG(("OpenStream ERROR2\n")); goto error; } } /* check that output device can support outputChannelCount */ if( outputChannelCount ) { if( outputChannelCount > driverInfo->outputChannelCount ) { result = paInvalidChannelCount; PA_DEBUG(("OpenStream ERROR3\n")); goto error; } } // check that the device supports the requested sample rate asioError = ASIOCanSampleRate( sampleRate ); PA_DEBUG(("ASIOCanSampleRate(%f):%d\n",sampleRate, asioError )); if( asioError != ASE_OK ) { result = paInvalidSampleRate; PA_DEBUG(("ERROR: ASIOCanSampleRate: %s\n", PaAsio_GetAsioErrorText(asioError) )); goto error; } // retrieve the current sample rate, we only change to the requested // sample rate if the device is not already in that rate. ASIOSampleRate oldRate; asioError = ASIOGetSampleRate(&oldRate); if( asioError != ASE_OK ) { result = paInvalidSampleRate; PA_DEBUG(("ERROR: ASIOGetSampleRate: %s\n", PaAsio_GetAsioErrorText(asioError) )); goto error; } PA_DEBUG(("ASIOGetSampleRate:%f\n",oldRate)); if (oldRate != sampleRate){ PA_DEBUG(("before ASIOSetSampleRate(%f)\n",sampleRate)); asioError = ASIOSetSampleRate( sampleRate ); /* Set sample rate */ if( asioError != ASE_OK ) { result = paInvalidSampleRate; PA_DEBUG(("ERROR: ASIOSetSampleRate: %s\n", PaAsio_GetAsioErrorText(asioError) )); goto error; } PA_DEBUG(("after ASIOSetSampleRate(%f)\n",sampleRate)); } else { PA_DEBUG(("No Need to change SR\n")); } /* IMPLEMENT ME: - if a full duplex stream is requested, check that the combination of input and output parameters is supported */ /* validate platform specific flags */ if( (streamFlags & paPlatformSpecificFlags) != 0 ){ PA_DEBUG(("OpenStream invalid flags!!\n")); return paInvalidFlag; /* unexpected platform specific flag */ } stream = (PaAsioStream*)PaUtil_AllocateMemory( sizeof(PaAsioStream) ); if( !stream ) { result = paInsufficientMemory; PA_DEBUG(("OpenStream ERROR5\n")); goto error; } stream->completedBuffersPlayedEvent = CreateEvent( NULL, TRUE, FALSE, NULL ); if( stream->completedBuffersPlayedEvent == NULL ) { result = paUnanticipatedHostError; PA_ASIO_SET_LAST_SYSTEM_ERROR( GetLastError() ); PA_DEBUG(("OpenStream ERROR6\n")); goto error; } completedBuffersPlayedEventInited = 1; stream->asioBufferInfos = 0; /* for deallocation in error */ stream->asioChannelInfos = 0; /* for deallocation in error */ stream->bufferPtrs = 0; /* for deallocation in error */ if( streamCallback ) { PaUtil_InitializeStreamRepresentation( &stream->streamRepresentation, &asioHostApi->callbackStreamInterface, streamCallback, userData ); } else { PaUtil_InitializeStreamRepresentation( &stream->streamRepresentation, &asioHostApi->blockingStreamInterface, streamCallback, userData ); } PaUtil_InitializeCpuLoadMeasurer( &stream->cpuLoadMeasurer, sampleRate ); stream->asioBufferInfos = (ASIOBufferInfo*)PaUtil_AllocateMemory( sizeof(ASIOBufferInfo) * (inputChannelCount + outputChannelCount) ); if( !stream->asioBufferInfos ) { result = paInsufficientMemory; PA_DEBUG(("OpenStream ERROR7\n")); goto error; } for( i=0; i < inputChannelCount; ++i ) { ASIOBufferInfo *info = &stream->asioBufferInfos[i]; info->isInput = ASIOTrue; if( inputChannelSelectors ){ // inputChannelSelectors values have already been validated in // ValidateAsioSpecificStreamInfo() above info->channelNum = inputChannelSelectors[i]; }else{ info
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -