📄 pa_linux_asihpi.c
字号:
PaSampleFormat hostSampleFormat = 0; HW16 hpiError = 0; /* Unless alternate device specification is supported, reject the use of paUseHostApiSpecificDeviceSpecification */ if( parameters->device == paUseHostApiSpecificDeviceSpecification ) return paInvalidDevice; else { assert( parameters->device < hostApi->info.deviceCount ); *hpiDevice = (PaAsiHpiDeviceInfo*) hostApi->deviceInfos[ parameters->device ]; } /* Validate streamInfo - this implementation doesn't use custom stream info */ if( parameters->hostApiSpecificStreamInfo ) return paIncompatibleHostApiSpecificStreamInfo; /* Check that device can support channel count */ if( (*hpiDevice)->streamIsOutput ) { maxChannelCount = (*hpiDevice)->baseDeviceInfo.maxOutputChannels; } else { maxChannelCount = (*hpiDevice)->baseDeviceInfo.maxInputChannels; } if( (maxChannelCount == 0) || (parameters->channelCount > maxChannelCount) ) return paInvalidChannelCount; /* All standard sample formats are supported by the buffer adapter, and this implementation doesn't support any custom sample formats */ if( parameters->sampleFormat & paCustomFormat ) return paSampleFormatNotSupported; /* Switch to closest HPI native format */ hostSampleFormat = PaUtil_SelectClosestAvailableFormat(PA_ASIHPI_AVAILABLE_FORMATS_, parameters->sampleFormat ); /* Setup format + info objects */ hpiError = HPI_FormatCreate( hpiFormat, (HW16)parameters->channelCount, PaAsiHpi_PaToHpiFormat( hostSampleFormat ), (HW32)sampleRate, 0, 0 ); if( hpiError ) { PA_ASIHPI_REPORT_ERROR_( hpiError ); switch( hpiError ) { case HPI_ERROR_INVALID_FORMAT: return paSampleFormatNotSupported; case HPI_ERROR_INVALID_SAMPLERATE: case HPI_ERROR_INCOMPATIBLE_SAMPLERATE: return paInvalidSampleRate; case HPI_ERROR_INVALID_CHANNELS: return paInvalidChannelCount; } } return paNoError;}/** Open HPI input stream with given format. This attempts to open HPI input stream with desired format. If the format is not supported or the device is unavailable, the stream is closed and a PortAudio error code is returned. @param hostApi Pointer to host API struct @param hpiDevice Pointer to HPI device struct @param hpiFormat Pointer to HPI format struct @return PortAudio error code (typically indicating a problem with stream format or device)*/static PaError PaAsiHpi_OpenInput( struct PaUtilHostApiRepresentation *hostApi, const PaAsiHpiDeviceInfo *hpiDevice, const HPI_FORMAT *hpiFormat, HPI_HISTREAM *hpiStream ){ PaAsiHpiHostApiRepresentation *hpiHostApi = (PaAsiHpiHostApiRepresentation*)hostApi; PaError result = paNoError; HW16 hpiError = 0; /* Catch misplaced output devices, as they typically have 0 input channels */ PA_UNLESS_( !hpiDevice->streamIsOutput, paInvalidChannelCount ); /* Try to open input stream */ PA_ASIHPI_UNLESS_( HPI_InStreamOpen( hpiHostApi->subSys, hpiDevice->adapterIndex, hpiDevice->streamIndex, hpiStream ), paDeviceUnavailable ); /* Set input format (checking it in the process) */ /* Could also use HPI_InStreamQueryFormat, but this economizes the process */ hpiError = HPI_InStreamSetFormat( hpiHostApi->subSys, *hpiStream, (HPI_FORMAT*)hpiFormat ); if( hpiError ) { PA_ASIHPI_REPORT_ERROR_( hpiError ); PA_ASIHPI_UNLESS_( HPI_InStreamClose( hpiHostApi->subSys, *hpiStream ), paNoError ); switch( hpiError ) { case HPI_ERROR_INVALID_FORMAT: return paSampleFormatNotSupported; case HPI_ERROR_INVALID_SAMPLERATE: case HPI_ERROR_INCOMPATIBLE_SAMPLERATE: return paInvalidSampleRate; case HPI_ERROR_INVALID_CHANNELS: return paInvalidChannelCount; default: /* In case anything else went wrong */ return paInvalidDevice; } }error: return result;}/** Open HPI output stream with given format. This attempts to open HPI output stream with desired format. If the format is not supported or the device is unavailable, the stream is closed and a PortAudio error code is returned. @param hostApi Pointer to host API struct @param hpiDevice Pointer to HPI device struct @param hpiFormat Pointer to HPI format struct @return PortAudio error code (typically indicating a problem with stream format or device)*/static PaError PaAsiHpi_OpenOutput( struct PaUtilHostApiRepresentation *hostApi, const PaAsiHpiDeviceInfo *hpiDevice, const HPI_FORMAT *hpiFormat, HPI_HOSTREAM *hpiStream ){ PaAsiHpiHostApiRepresentation *hpiHostApi = (PaAsiHpiHostApiRepresentation*)hostApi; PaError result = paNoError; HW16 hpiError = 0; /* Catch misplaced input devices, as they typically have 0 output channels */ PA_UNLESS_( hpiDevice->streamIsOutput, paInvalidChannelCount ); /* Try to open output stream */ PA_ASIHPI_UNLESS_( HPI_OutStreamOpen( hpiHostApi->subSys, hpiDevice->adapterIndex, hpiDevice->streamIndex, hpiStream ), paDeviceUnavailable ); /* Check output format (format is set on first write to output stream) */ hpiError = HPI_OutStreamQueryFormat( hpiHostApi->subSys, *hpiStream, (HPI_FORMAT*)hpiFormat ); if( hpiError ) { PA_ASIHPI_REPORT_ERROR_( hpiError ); PA_ASIHPI_UNLESS_( HPI_OutStreamClose( hpiHostApi->subSys, *hpiStream ), paNoError ); switch( hpiError ) { case HPI_ERROR_INVALID_FORMAT: return paSampleFormatNotSupported; case HPI_ERROR_INVALID_SAMPLERATE: case HPI_ERROR_INCOMPATIBLE_SAMPLERATE: return paInvalidSampleRate; case HPI_ERROR_INVALID_CHANNELS: return paInvalidChannelCount; default: /* In case anything else went wrong */ return paInvalidDevice; } }error: return result;}/** Checks whether the desired stream formats and devices are supported (for both input and output). This is done by actually opening the appropriate HPI streams and closing them again. @param hostApi Pointer to host API struct @param inputParameters Pointer to stream parameter struct for input side of stream @param outputParameters Pointer to stream parameter struct for output side of stream @param sampleRate Desired sample rate @return PortAudio error code (paFormatIsSupported on success) */static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi, const PaStreamParameters *inputParameters, const PaStreamParameters *outputParameters, double sampleRate ){ PaError result = paFormatIsSupported; PaAsiHpiHostApiRepresentation *hpiHostApi = (PaAsiHpiHostApiRepresentation*)hostApi; PaAsiHpiDeviceInfo *hpiDevice = NULL; HPI_FORMAT hpiFormat; /* Input stream */ if( inputParameters ) { HPI_HISTREAM hpiStream; PA_DEBUG(( "%s: Checking input params: dev=%d, sr=%d, chans=%d, fmt=%d\n", __FUNCTION__, inputParameters->device, (int)sampleRate, inputParameters->channelCount, inputParameters->sampleFormat )); /* Create and validate format */ PA_ENSURE_( PaAsiHpi_CreateFormat( hostApi, inputParameters, sampleRate, &hpiDevice, &hpiFormat ) ); /* Open stream to further check format */ PA_ENSURE_( PaAsiHpi_OpenInput( hostApi, hpiDevice, &hpiFormat, &hpiStream ) ); /* Close stream again */ PA_ASIHPI_UNLESS_( HPI_InStreamClose( hpiHostApi->subSys, hpiStream ), paNoError ); } /* Output stream */ if( outputParameters ) { HPI_HOSTREAM hpiStream; PA_DEBUG(( "%s: Checking output params: dev=%d, sr=%d, chans=%d, fmt=%d\n", __FUNCTION__, outputParameters->device, (int)sampleRate, outputParameters->channelCount, outputParameters->sampleFormat )); /* Create and validate format */ PA_ENSURE_( PaAsiHpi_CreateFormat( hostApi, outputParameters, sampleRate, &hpiDevice, &hpiFormat ) ); /* Open stream to further check format */ PA_ENSURE_( PaAsiHpi_OpenOutput( hostApi, hpiDevice, &hpiFormat, &hpiStream ) ); /* Close stream again */ PA_ASIHPI_UNLESS_( HPI_OutStreamClose( hpiHostApi->subSys, hpiStream ), paNoError ); }error: return result;}/* ---------------------------- Stream Interface ---------------------------- *//** Obtain HPI stream information. This obtains info such as stream state and available data/space in buffers. It also estimates whether an underflow or overflow occurred. @param streamComp Pointer to stream component (input or output) to query @param info Pointer to stream info struct that will contain result @return PortAudio error code (either paNoError, paDeviceUnavailable or paUnanticipatedHostError) */static PaError PaAsiHpi_GetStreamInfo( PaAsiHpiStreamComponent *streamComp, PaAsiHpiStreamInfo *info ){ PaError result = paDeviceUnavailable; HW16 state; HW32 bufferSize, dataSize, frameCounter, auxDataSize, threshold; HW32 hwBufferSize, hwDataSize; assert( streamComp ); assert( info ); /* First blank the stream info struct, in case something goes wrong below. This saves the caller from initializing the struct. */ info->state = 0; info->bufferSize = 0; info->dataSize = 0; info->frameCounter = 0; info->auxDataSize = 0; info->totalBufferedData = 0; info->availableFrames = 0; info->underflow = 0; info->overflow = 0; if( streamComp->hpiDevice && streamComp->hpiStream ) { /* Obtain detailed stream info (either input or output) */ if( streamComp->hpiDevice->streamIsOutput ) { PA_ASIHPI_UNLESS_( HPI_OutStreamGetInfoEx( streamComp->hpiDevice->subSys, streamComp->hpiStream, &state, &bufferSize, &dataSize, &frameCounter, &auxDataSize ), paUnanticipatedHostError ); } else { PA_ASIHPI_UNLESS_( HPI_InStreamGetInfoEx( streamComp->hpiDevice->subSys, streamComp->hpiStream, &state, &bufferSize, &dataSize, &frameCounter, &auxDataSize ), paUnanticipatedHostError ); } /* Load stream info */ info->state = state; info->bufferSize = bufferSize; info->dataSize = dataSize; info->frameCounter = frameCounter; info->auxDataSize = auxDataSize; /* Determine total buffered data */ info->totalBufferedData = dataSize; if( streamComp->hostBufferSize > 0 ) info->totalBufferedData += auxDataSize; info->totalBufferedData /= streamComp->bytesPerFrame; /* Determine immediately available frames */ info->availableFrames = streamComp->hpiDevice->streamIsOutput ? bufferSize - dataSize : dataSize; info->availableFrames /= streamComp->bytesPerFrame; /* Minimum space/data required in buffers */ threshold = PA_MIN( streamComp->tempBufferSize, streamComp->bytesPerFrame * PA_ASIHPI_MIN_FRAMES_ ); /* Obtain hardware buffer stats first, to simplify things */ hwBufferSize = streamComp->hardwareBufferSize; hwDataSize = streamComp->hostBufferSize > 0 ? auxDataSize : dataSize; /* Underflow is a bit tricky */ info->underflow = streamComp->hpiDevice->streamIsOutput ? /* Stream seems to start in drained state sometimes, so ignore initial underflow */ (frameCounter > 0) && ( (state == HPI_STATE_DRAINED) || (hwDataSize == 0) ) : /* Input streams check the first-level (host) buffer for underflow */ (state != HPI_STATE_STOPPED) && (dataSize < threshold); /* Check for overflow in second-level (hardware) buffer for both input and output */ info->overflow = (state != HPI_STATE_STOPPED) && (hwBufferSize - hwDataSize < threshold); return paNoError;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -