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

📄 pa_jack.c

📁 一个开源的sip源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
        /* Unlock mutex and await signal from processing thread */        result = WaitCondition( stream->hostApi );    }    ASSERT_CALL( pthread_mutex_unlock( &hostApi->mtx ), 0 );    ENSURE_PA( result );error:    return result;}/* Add stream to processing queue */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;    PaJackHostApiRepresentation *jackHostApi = (PaJackHostApiRepresentation*)hostApi;    PaJackStream *stream = NULL;    char *port_string = PaUtil_GroupAllocateMemory( jackHostApi->deviceInfoMemory, jack_port_name_size() );    unsigned long regexSz = jack_client_name_size() + 3;    char *regex_pattern = PaUtil_GroupAllocateMemory( jackHostApi->deviceInfoMemory, regexSz );    const char **jack_ports = NULL;    /* int jack_max_buffer_size = jack_get_buffer_size( jackHostApi->jack_client ); */    int i;    int inputChannelCount, outputChannelCount;    const double jackSr = jack_get_sample_rate( jackHostApi->jack_client );    PaSampleFormat inputSampleFormat = 0, outputSampleFormat = 0;    int bpInitialized = 0, srInitialized = 0;   /* Initialized buffer processor and stream representation? */    unsigned long ofs;    /* validate platform specific flags */    if( (streamFlags & paPlatformSpecificFlags) != 0 )        return paInvalidFlag; /* unexpected platform specific flag */    if( (streamFlags & paPrimeOutputBuffersUsingStreamCallback) != 0 )    {        streamFlags &= ~paPrimeOutputBuffersUsingStreamCallback;        /*return paInvalidFlag;*/   /* This implementation does not support buffer priming */    }    if( framesPerBuffer != paFramesPerBufferUnspecified )    {        /* Jack operates with power of two buffers, and we don't support non-integer buffer adaption (yet) */        /*UNLESS( !(framesPerBuffer & (framesPerBuffer - 1)), paBufferTooBig );*/  /* TODO: Add descriptive error code? */    }    /* Preliminary checks */    if( inputParameters )    {        inputChannelCount = inputParameters->channelCount;        inputSampleFormat = inputParameters->sampleFormat;        /* unless alternate device specification is supported, reject the use of            paUseHostApiSpecificDeviceSpecification */        if( inputParameters->device == paUseHostApiSpecificDeviceSpecification )            return paInvalidDevice;        /* check that input device can support inputChannelCount */        if( inputChannelCount > hostApi->deviceInfos[ inputParameters->device ]->maxInputChannels )            return paInvalidChannelCount;        /* validate inputStreamInfo */        if( inputParameters->hostApiSpecificStreamInfo )            return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */    }    else    {        inputChannelCount = 0;    }    if( outputParameters )    {        outputChannelCount = outputParameters->channelCount;        outputSampleFormat = outputParameters->sampleFormat;        /* unless alternate device specification is supported, reject the use of            paUseHostApiSpecificDeviceSpecification */        if( outputParameters->device == paUseHostApiSpecificDeviceSpecification )            return paInvalidDevice;        /* check that output device can support inputChannelCount */        if( outputChannelCount > hostApi->deviceInfos[ outputParameters->device ]->maxOutputChannels )            return paInvalidChannelCount;        /* validate outputStreamInfo */        if( outputParameters->hostApiSpecificStreamInfo )            return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */    }    else    {        outputChannelCount = 0;    }    /* ... check that the sample rate exactly matches the ONE acceptable rate     * A: This rate isn't necessarily constant though? */#define ABS(x) ( (x) > 0 ? (x) : -(x) )    if( ABS(sampleRate - jackSr) > 1 )       return paInvalidSampleRate;#undef ABS    UNLESS( stream = (PaJackStream*)PaUtil_AllocateMemory( sizeof(PaJackStream) ), paInsufficientMemory );    ENSURE_PA( InitializeStream( stream, jackHostApi, inputChannelCount, outputChannelCount ) );    /* the blocking emulation, if necessary */    stream->isBlockingStream = !streamCallback;    if( stream->isBlockingStream )    {        float latency = 0.001; /* 1ms is the absolute minimum we support */        int   minimum_buffer_frames = 0;        if( inputParameters && inputParameters->suggestedLatency > latency )            latency = inputParameters->suggestedLatency;        else if( outputParameters && outputParameters->suggestedLatency > latency )            latency = outputParameters->suggestedLatency;        /* the latency the user asked for indicates the minimum buffer size in frames */        minimum_buffer_frames = (int) (latency * jack_get_sample_rate( jackHostApi->jack_client ));        /* we also need to be able to store at least three full jack buffers to avoid dropouts */        if( jackHostApi->jack_buffer_size * 3 > minimum_buffer_frames )            minimum_buffer_frames = jackHostApi->jack_buffer_size * 3;        /* setup blocking API data structures (FIXME: can fail) */	BlockingBegin( stream, minimum_buffer_frames );        /* install our own callback for the blocking API */        streamCallback = BlockingCallback;        userData = stream;        PaUtil_InitializeStreamRepresentation( &stream->streamRepresentation,                                               &jackHostApi->blockingStreamInterface, streamCallback, userData );    }    else    {        PaUtil_InitializeStreamRepresentation( &stream->streamRepresentation,                                               &jackHostApi->callbackStreamInterface, streamCallback, userData );    }    srInitialized = 1;    PaUtil_InitializeCpuLoadMeasurer( &stream->cpuLoadMeasurer, jackSr );    /* create the JACK ports.  We cannot connect them until audio     * processing begins */    /* Register a unique set of ports for this stream     * TODO: Robust allocation of new port names */    ofs = jackHostApi->inputBase;    for( i = 0; i < inputChannelCount; i++ )    {        snprintf( port_string, jack_port_name_size(), "in_%lu", ofs + i );        UNLESS( stream->local_input_ports[i] = jack_port_register(              jackHostApi->jack_client, port_string,              JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0 ), paInsufficientMemory );    }    jackHostApi->inputBase += inputChannelCount;    ofs = jackHostApi->outputBase;    for( i = 0; i < outputChannelCount; i++ )    {        snprintf( port_string, jack_port_name_size(), "out_%lu", ofs + i );        UNLESS( stream->local_output_ports[i] = jack_port_register(             jackHostApi->jack_client, port_string,             JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0 ), paInsufficientMemory );    }    jackHostApi->outputBase += outputChannelCount;    /* look up the jack_port_t's for the remote ports.  We could do     * this at stream start time, but doing it here ensures the     * name lookup only happens once. */    if( inputChannelCount > 0 )    {        int err = 0;                /* ... remote output ports (that we input from) */        snprintf( regex_pattern, regexSz, "%s:.*", hostApi->deviceInfos[ inputParameters->device ]->name );        UNLESS( jack_ports = jack_get_ports( jackHostApi->jack_client, regex_pattern,                                     NULL, JackPortIsOutput ), paUnanticipatedHostError );        for( i = 0; i < inputChannelCount && jack_ports[i]; i++ )        {            if( (stream->remote_output_ports[i] = jack_port_by_name(                 jackHostApi->jack_client, jack_ports[i] )) == NULL )             {                err = 1;                break;            }        }        free( jack_ports );        UNLESS( !err, paInsufficientMemory );        /* Fewer ports than expected? */        UNLESS( i == inputChannelCount, paInternalError );    }    if( outputChannelCount > 0 )    {        int err = 0;        /* ... remote input ports (that we output to) */        snprintf( regex_pattern, regexSz, "%s:.*", hostApi->deviceInfos[ outputParameters->device ]->name );        UNLESS( jack_ports = jack_get_ports( jackHostApi->jack_client, regex_pattern,                                     NULL, JackPortIsInput ), paUnanticipatedHostError );        for( i = 0; i < outputChannelCount && jack_ports[i]; i++ )        {            if( (stream->remote_input_ports[i] = jack_port_by_name(                 jackHostApi->jack_client, jack_ports[i] )) == 0 )            {                err = 1;                break;            }        }        free( jack_ports );        UNLESS( !err , paInsufficientMemory );        /* Fewer ports than expected? */        UNLESS( i == outputChannelCount, paInternalError );    }    ENSURE_PA( PaUtil_InitializeBufferProcessor(                  &stream->bufferProcessor,                  inputChannelCount,                  inputSampleFormat,                  paFloat32,            /* hostInputSampleFormat */                  outputChannelCount,                  outputSampleFormat,                  paFloat32,            /* hostOutputSampleFormat */                  jackSr,                  streamFlags,                  framesPerBuffer,                  0,                            /* Ignored */                  paUtilUnknownHostBufferSize,  /* Buffer size may vary on JACK's discretion */                  streamCallback,                  userData ) );    bpInitialized = 1;    if( stream->num_incoming_connections > 0 )        stream->streamRepresentation.streamInfo.inputLatency = (jack_port_get_latency( stream->remote_output_ports[0] )                - jack_get_buffer_size( jackHostApi->jack_client )  /* One buffer is not counted as latency */            + PaUtil_GetBufferProcessorInputLatency( &stream->bufferProcessor )) / sampleRate;    if( stream->num_outgoing_connections > 0 )        stream->streamRepresentation.streamInfo.outputLatency = (jack_port_get_latency( stream->remote_input_ports[0] )                - jack_get_buffer_size( jackHostApi->jack_client )  /* One buffer is not counted as latency */            + PaUtil_GetBufferProcessorOutputLatency( &stream->bufferProcessor )) / sampleRate;    stream->streamRepresentation.streamInfo.sampleRate = jackSr;    stream->t0 = jack_frame_time( jackHostApi->jack_client );   /* A: Time should run from Pa_OpenStream */    ENSURE_PA( AddStream( stream ) );  /* Add to queue over opened streams */        *s = (PaStream*)stream;    return result;error:    if( stream )        CleanUpStream( stream, srInitialized, bpInitialized );    return result;}/*    When CloseStream() is called, the multi-api layer ensures that    the stream has already been stopped or aborted.*/static PaError CloseStream( PaStream* s ){    PaError result = paNoError;    PaJackStream *stream = (PaJackStream*)s;    /* Remove this stream from the processing queue */    ENSURE_PA( RemoveStream( stream ) );error:    CleanUpStream( stream, 1, 1 );    return result;}static PaError RealProcess( PaJackStream *stream, jack_nframes_t frames ){    PaError result = paNoError;    PaStreamCallbackTimeInfo timeInfo = {0,0,0};    int chn;    int framesProcessed;    const double sr = jack_get_sample_rate( stream->jack_client );    /* Shouldn't change during the process callback */    PaStreamCallbackFlags cbFlags = 0;    /* If the user has returned !paContinue from the callback we'll want to flush the internal buffers,     * when these are empty we can finally mark the stream as inactive */    if( stream->callbackResult != paContinue &&            PaUtil_IsBufferProcessorOutputEmpty( &stream->bufferProcessor ) )    {        stream->is_active = 0;        if( stream->streamRepresentation.streamFinishedCallback )            stream->streamRepresentation.streamFinishedCallback( stream->streamRepresentation.userData );        PA_DEBUG(( "%s: Callback finished\n", __FUNCTION__ ));        goto end;    }    timeInfo.currentTime = (jack_frame_time( stream->jack_client ) - stream->t0) / sr;    if( stream->num_incoming_connections > 0 )        timeInfo.inputBufferAdcTime = timeInfo.currentTime - jack_port_get_latency( stream->remote_output_ports[0] )            / sr;    if( stream->num_outgoing_connections > 0 )        timeInfo.outputBufferDacTime = timeInfo.currentTime + jack_port_get_latency( stream->remote_input_ports[0] )            / sr;    PaUtil_BeginCpuLoadMeasurement( &stream->cpuLoadMeasurer );    if( stream->xrun )    {        /* XXX: Any way to tell which of these occurred? */        cbFlags = paOutputUnderflow | paInputOverflow;        stream->xrun = FALSE;    }    PaUtil_BeginBufferProcessing( &stream->bufferProcessor, &timeInfo,            cbFlags );    if( stream->num_incoming_connections > 0 )        PaUtil_SetInputFrameCount( &stream->bufferProcessor, frames );    if( stream->num_outgoing_connections > 0 )        PaUtil_SetOutputFrameCount( &stream->bufferProcessor, frames );    for( chn = 0; chn < stream->num_incoming_connections; chn++ )    {        jack_default_audio_sample_t *channel_buf = (jack_default_audio_sample_t*)            jack_port_get_buffer( stream->local_input_ports[chn],                    frames );        PaUtil_SetNonInterleavedInputChannel( &stream->bufferProcessor,                chn,                channel_buf );    }    for( chn = 0; chn < stream->num_outgoing_connections; chn++ )    {        jack_default_audio_sample_t *channel_buf = (jack_default_audio_sample_t*)            jack_port_get_buffer( stream->local_output_ports[chn],                    frames );

⌨️ 快捷键说明

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