⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pa_linux_alsa.c

📁 Audacity是一款用於錄音和編輯聲音的、免費的開放源碼軟體。它可以執行於Mac OS X、Microsoft Windows、GNU/Linux和其它作業系統
💻 C
📖 第 1 页 / 共 5 页
字号:
    ENSURE( snd_pcm_hw_params_set_buffer_size_near( pcm, hwParams, &highLatency ), paUnanticipatedHostError );    *defaultLowLatency = (double) lowLatency / *defaultSampleRate;    *defaultHighLatency = (double) highLatency / *defaultSampleRate;end:    snd_pcm_close( pcm );    return result;error:    *channels = 0;    goto end;}/* Build PaDeviceInfo list, ignore devices for which we cannot determine capabilities (possibly busy, sigh) */static PaError BuildDeviceList( PaAlsaHostApiRepresentation *alsaApi ){    PaUtilHostApiRepresentation *commonApi = &alsaApi->commonHostApiRep;    PaAlsaDeviceInfo *deviceInfoArray;    int deviceCount = 0;    int card_idx;    int device_idx;    snd_ctl_t *ctl;    snd_ctl_card_info_t *card_info;    PaError result = paNoError;    int blocking = SND_PCM_NONBLOCK;    if( getenv( "PA_ALSA_INITIALIZE_BLOCK" ) && atoi( getenv( "PA_ALSA_INITIALIZE_BLOCK" ) ) )        blocking = 0;    /* These two will be set to the first working input and output device, respectively */    commonApi->info.defaultInputDevice = paNoDevice;    commonApi->info.defaultOutputDevice = paNoDevice;    /* count the devices by enumerating all the card numbers */    /* snd_card_next() modifies the integer passed to it to be:     *      the index of the first card if the parameter is -1     *      the index of the next card if the parameter is the index of a card     *      -1 if there are no more cards     *     * The function itself returns 0 if it succeeded. */    card_idx = -1;    while( snd_card_next( &card_idx ) == 0 && card_idx >= 0 )    {        ++deviceCount;    }    /* allocate deviceInfo memory based on the number of devices */    UNLESS( commonApi->deviceInfos = (PaDeviceInfo**)PaUtil_GroupAllocateMemory(            alsaApi->allocations, sizeof(PaDeviceInfo*) * deviceCount ), paInsufficientMemory );    /* allocate all device info structs in a contiguous block */    UNLESS( deviceInfoArray = (PaAlsaDeviceInfo*)PaUtil_GroupAllocateMemory(            alsaApi->allocations, sizeof(PaAlsaDeviceInfo) * deviceCount ), paInsufficientMemory );    /* now loop over the list of devices again, filling in the deviceInfo for each     * A: If a device is deemed unavailable (can't get name), its not added to list of devices.     */    card_idx = -1;    device_idx = 0;    snd_ctl_card_info_alloca( &card_info );    while( snd_card_next( &card_idx ) == 0 && card_idx >= 0 )    {        PaAlsaDeviceInfo *deviceInfo = &deviceInfoArray[device_idx];        PaDeviceInfo *commonDeviceInfo = &deviceInfo->commonDeviceInfo;        snd_pcm_t *pcm;        char *deviceName;        char alsaDeviceName[50];        const char *cardName;        /* First of all, get name of card */        snprintf( alsaDeviceName, 50, "hw:%d", card_idx );        if( snd_ctl_open( &ctl, alsaDeviceName, 0 ) < 0 )            continue;   /* Unable to open card :( */        snd_ctl_card_info( ctl, card_info );        snd_ctl_close( ctl );        cardName = snd_ctl_card_info_get_name( card_info );        /* Zero fields */        memset( commonDeviceInfo, 0, sizeof (PaDeviceInfo) );        UNLESS( deviceName = (char*)PaUtil_GroupAllocateMemory( alsaApi->allocations,                                                        strlen(cardName) + 1 ), paInsufficientMemory );        strcpy( deviceName, cardName );        commonDeviceInfo->name = deviceName;        deviceInfo->deviceNumber = card_idx;    /* ALSA device number */        commonDeviceInfo->structVersion = 2;        commonDeviceInfo->hostApi = alsaApi->hostApiIndex;        /* to determine device capabilities, we must open the device and query the         * hardware parameter configuration space */        /* Query capture */        if( snd_pcm_open( &pcm, alsaDeviceName, SND_PCM_STREAM_CAPTURE, blocking ) >= 0 )        {            if( GropeDevice( pcm, &commonDeviceInfo->maxInputChannels,                        &commonDeviceInfo->defaultLowInputLatency, &commonDeviceInfo->defaultHighInputLatency,                        &commonDeviceInfo->defaultSampleRate ) != paNoError )                continue;   /* Error */        }                        /* Query playback */        if( snd_pcm_open( &pcm, alsaDeviceName, SND_PCM_STREAM_PLAYBACK, blocking ) >= 0 )        {            if( GropeDevice( pcm, &commonDeviceInfo->maxOutputChannels,                        &commonDeviceInfo->defaultLowOutputLatency, &commonDeviceInfo->defaultHighOutputLatency,                        &commonDeviceInfo->defaultSampleRate ) != paNoError )                continue;   /* Error */        }        /* A: Storing pointer to PaAlsaDeviceInfo object as pointer to PaDeviceInfo object.         * Should now be safe to add device info, unless the device supports neither capture nor playback         */        if( commonDeviceInfo->maxInputChannels || commonDeviceInfo->maxOutputChannels )        {            if( commonApi->info.defaultInputDevice == paNoDevice )                commonApi->info.defaultInputDevice = device_idx;            if( commonApi->info.defaultOutputDevice == paNoDevice )                commonApi->info.defaultOutputDevice = device_idx;            commonApi->deviceInfos[ device_idx++ ] = (PaDeviceInfo *) deviceInfo;        }    }    commonApi->info.deviceCount = device_idx;   /* Number of successfully queried devices */end:    return result;error:    goto end;   /* No particular action */}static void Terminate( struct PaUtilHostApiRepresentation *hostApi ){    PaAlsaHostApiRepresentation *alsaHostApi = (PaAlsaHostApiRepresentation*)hostApi;    assert( hostApi );    if( alsaHostApi->allocations )    {        PaUtil_FreeAllAllocations( alsaHostApi->allocations );        PaUtil_DestroyAllocationGroup( alsaHostApi->allocations );    }    PaUtil_FreeMemory( alsaHostApi );    pthread_mutex_destroy( &gmtx );}/* Check against known device capabilities */static PaError ValidateParameters( const PaStreamParameters *parameters, const PaAlsaDeviceInfo *deviceInfo, StreamIO io,        const PaAlsaStreamInfo *streamInfo ){    int maxChans;    assert( parameters );    if( streamInfo )    {        if( streamInfo->size != sizeof (PaAlsaStreamInfo) || streamInfo->version != 1 )            return paIncompatibleHostApiSpecificStreamInfo;        if( parameters->device != paUseHostApiSpecificDeviceSpecification )            return paInvalidDevice;    }    if( parameters->device == paUseHostApiSpecificDeviceSpecification )    {        if( streamInfo )            return paNoError;   /* Skip further checking */        return paInvalidDevice;    }    maxChans = (io == streamIn ? deviceInfo->commonDeviceInfo.maxInputChannels :        deviceInfo->commonDeviceInfo.maxOutputChannels);    if( parameters->channelCount > maxChans )    {        return paInvalidChannelCount;    }    return paNoError;}/* Given an open stream, what sample formats are available? */static PaSampleFormat GetAvailableFormats( snd_pcm_t *pcm ){    PaSampleFormat available = 0;    snd_pcm_hw_params_t *hwParams;    snd_pcm_hw_params_alloca( &hwParams );    snd_pcm_hw_params_any( pcm, hwParams );    if( snd_pcm_hw_params_test_format( pcm, hwParams, SND_PCM_FORMAT_FLOAT ) >= 0)        available |= paFloat32;    if( snd_pcm_hw_params_test_format( pcm, hwParams, SND_PCM_FORMAT_S32 ) >= 0)        available |= paInt32;    if( snd_pcm_hw_params_test_format( pcm, hwParams, SND_PCM_FORMAT_S24 ) >= 0)        available |= paInt24;    if( snd_pcm_hw_params_test_format( pcm, hwParams, SND_PCM_FORMAT_S16 ) >= 0)        available |= paInt16;    if( snd_pcm_hw_params_test_format( pcm, hwParams, SND_PCM_FORMAT_U8 ) >= 0)        available |= paUInt8;    if( snd_pcm_hw_params_test_format( pcm, hwParams, SND_PCM_FORMAT_S8 ) >= 0)        available |= paInt8;    return available;}static snd_pcm_format_t Pa2AlsaFormat( PaSampleFormat paFormat ){    switch( paFormat )    {        case paFloat32:            return SND_PCM_FORMAT_FLOAT;        case paInt16:            return SND_PCM_FORMAT_S16;        case paInt24:            return SND_PCM_FORMAT_S24;        case paInt32:            return SND_PCM_FORMAT_S32;        case paInt8:            return SND_PCM_FORMAT_S8;        case paUInt8:            return SND_PCM_FORMAT_U8;        default:            return SND_PCM_FORMAT_UNKNOWN;    }}/* \brief Open an ALSA pcm handle *  * The device to be open can be specified in a custom PaAlsaStreamInfo struct, or it will be a device number. In case of a * device number, it maybe specified through an env variable (PA_ALSA_PLUGHW) that we should open the corresponding plugin * device. */static PaError AlsaOpen(snd_pcm_t **pcm, const PaAlsaDeviceInfo *deviceInfo, const PaAlsaStreamInfo        *streamInfo, snd_pcm_stream_t streamType ){    PaError result = paNoError;    int ret;    char *deviceName = alloca( 50 );    if( !streamInfo )    {        int usePlug = 0;        char *prefix;                if( getenv( "PA_ALSA_PLUGHW" ) )            usePlug = atoi( getenv( "PA_ALSA_PLUGHW" ) );        prefix = usePlug ? "plughw" : "hw";        snprintf( deviceName, 50, "%s:%d", prefix, deviceInfo->deviceNumber );    }    else        deviceName = (char *) streamInfo->deviceString;    if( (ret = snd_pcm_open( pcm, deviceName, streamType, SND_PCM_NONBLOCK )) < 0 )    {        *pcm = NULL;     /* Not to be closed */        ENSURE( ret, ret == -EBUSY ? paDeviceUnavailable : paBadIODeviceCombination );    }    ENSURE( snd_pcm_nonblock( *pcm, 0 ), paUnanticipatedHostError );end:    return result;error:    goto end;}static PaError TestParameters( const PaStreamParameters *parameters, const PaAlsaDeviceInfo *deviceInfo, const PaAlsaStreamInfo        *streamInfo, double sampleRate, snd_pcm_stream_t streamType ){    PaError result = paNoError;    snd_pcm_t *pcm = NULL;    PaSampleFormat availableFormats;    PaSampleFormat paFormat;    snd_pcm_hw_params_t *params;    snd_pcm_hw_params_alloca( &params );    PA_ENSURE( AlsaOpen( &pcm, deviceInfo, streamInfo, streamType ) );    snd_pcm_hw_params_any( pcm, params );    ENSURE( SetApproximateSampleRate( pcm, params, sampleRate ), paInvalidSampleRate );    ENSURE( snd_pcm_hw_params_set_channels( pcm, params, parameters->channelCount ), paInvalidChannelCount );    /* See if we can find a best possible match */    availableFormats = GetAvailableFormats( pcm );    PA_ENSURE( paFormat = PaUtil_SelectClosestAvailableFormat( availableFormats, parameters->sampleFormat ) );end:    if( pcm )        snd_pcm_close( pcm );    return result;error:    goto end;}static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi,                                  const PaStreamParameters *inputParameters,                                  const PaStreamParameters *outputParameters,                                  double sampleRate ){    int inputChannelCount = 0, outputChannelCount = 0;    PaSampleFormat inputSampleFormat, outputSampleFormat;    PaError result = paFormatIsSupported;    const PaAlsaDeviceInfo *inputDeviceInfo = NULL, *outputDeviceInfo = NULL;    const PaAlsaStreamInfo *inputStreamInfo = NULL, *outputStreamInfo = NULL;    if( inputParameters )    {        if( inputParameters->device != paUseHostApiSpecificDeviceSpecification )        {            assert( inputParameters->device < hostApi->info.deviceCount );            inputDeviceInfo = (PaAlsaDeviceInfo *)hostApi->deviceInfos[ inputParameters->device ];        }        else            inputStreamInfo = inputParameters->hostApiSpecificStreamInfo;        PA_ENSURE( ValidateParameters( inputParameters, inputDeviceInfo, streamIn, inputStreamInfo ) );        inputChannelCount = inputParameters->channelCount;        inputSampleFormat = inputParameters->sampleFormat;    }    if( outputParameters )

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -