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

📄 pa_mac_core.c

📁 一个开源SIP协议栈
💻 C
📖 第 1 页 / 共 5 页
字号:
                             srConverter ) );
          /* Set quality */
          ERR_WRAP( AudioConverterSetProperty(
                             *srConverter,
                             kAudioConverterSampleRateConverterQuality,
                             sizeof( value ),
                             &value ) );
       }
    }
    /* -- set IOProc (callback) -- */
    callbackKey = outStreamParams ? kAudioUnitProperty_SetRenderCallback
                                  : kAudioOutputUnitProperty_SetInputCallback ;
    rcbs.inputProc = AudioIOProc;
    rcbs.inputProcRefCon = refCon;
    ERR_WRAP( AudioUnitSetProperty(
                               *audioUnit,
                               callbackKey,
                               kAudioUnitScope_Output,
                               outStreamParams ? OUTPUT_ELEMENT : INPUT_ELEMENT,
                               &rcbs,
                               sizeof(rcbs)) );

    if( inStreamParams && outStreamParams && *srConverter )
           ERR_WRAP( AudioUnitSetProperty(
                               *audioUnit,
                               kAudioOutputUnitProperty_SetInputCallback,
                               kAudioUnitScope_Output,
                               INPUT_ELEMENT,
                               &rcbs,
                               sizeof(rcbs)) );

    /*IMPLEMENTME: may need to worry about channel mapping.*/

    /* initialize the audio unit */
    ERR_WRAP( AudioUnitInitialize(*audioUnit) );

    if( inStreamParams && outStreamParams )
       VDBUG( ("Opened device %ld for input and output.\n", *audioDevice ) );
    else if( inStreamParams )
       VDBUG( ("Opened device %ld for input.\n", *audioDevice ) );
    else if( outStreamParams )
       VDBUG( ("Opened device %ld for output.\n", *audioDevice ) );
    return paNoError;
#undef ERR_WRAP

    error:
       CloseComponent( *audioUnit );
       *audioUnit = NULL;
       if( result )
          return PaMacCore_SetError( result, line, 1 );
       return paResult;
}

/* 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;
    PaMacAUHAL *auhalHostApi = (PaMacAUHAL*)hostApi;
    PaMacCoreStream *stream = 0;
    int inputChannelCount, outputChannelCount;
    PaSampleFormat inputSampleFormat, outputSampleFormat;
    PaSampleFormat hostInputSampleFormat, hostOutputSampleFormat;
    VVDBUG(("OpenStream(): in chan=%d, in fmt=%ld, out chan=%d, out fmt=%ld SR=%g, FPB=%ld\n",
                inputParameters  ? inputParameters->channelCount  : -1,
                inputParameters  ? inputParameters->sampleFormat  : -1,
                outputParameters ? outputParameters->channelCount : -1,
                outputParameters ? outputParameters->sampleFormat : -1,
                (float) sampleRate,
                framesPerBuffer ));
    VDBUG( ("Opening Stream.\n") );

    /*These first few bits of code are from paSkeleton with few modifications.*/
    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;

        /* Host supports interleaved float32 */
        hostInputSampleFormat = paFloat32;
    }
    else
    {
        inputChannelCount = 0;
        inputSampleFormat = hostInputSampleFormat = paFloat32; /* Surpress 'uninitialised var' warnings. */
    }

    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;

        /* Host supports interleaved float32 */
        hostOutputSampleFormat = paFloat32;
    }
    else
    {
        outputChannelCount = 0;
        outputSampleFormat = hostOutputSampleFormat = paFloat32; /* Surpress 'uninitialized var' warnings. */
    }

    /* validate platform specific flags */
    if( (streamFlags & paPlatformSpecificFlags) != 0 )
        return paInvalidFlag; /* unexpected platform specific flag */

    stream = (PaMacCoreStream*)PaUtil_AllocateMemory( sizeof(PaMacCoreStream) );
    if( !stream )
    {
        result = paInsufficientMemory;
        goto error;
    }

    /* If we fail after this point, we my be left in a bad state, with
       some data structures setup and others not. So, first thing we
       do is initialize everything so that if we fail, we know what hasn't
       been touched.
     */

    stream->inputAudioBufferList.mBuffers[0].mData = NULL;
    stream->inputRingBuffer.buffer = NULL;
    bzero( &stream->blio, sizeof( PaMacBlio ) );
/*
    stream->blio.inputRingBuffer.buffer = NULL;
    stream->blio.outputRingBuffer.buffer = NULL;
    stream->blio.inputSampleFormat = inputParameters?inputParameters->sampleFormat:0;
    stream->blio.inputSampleSize = computeSampleSizeFromFormat(stream->blio.inputSampleFormat);
    stream->blio.outputSampleFormat=outputParameters?outputParameters->sampleFormat:0;
    stream->blio.outputSampleSize = computeSampleSizeFromFormat(stream->blio.outputSampleFormat);
*/
    stream->inputSRConverter = NULL;
    stream->inputUnit = NULL;
    stream->outputUnit = NULL;
    stream->inputFramesPerBuffer = 0;
    stream->outputFramesPerBuffer = 0;
    stream->bufferProcessorIsInitialized = FALSE;

    /* assert( streamCallback ) ; */ /* only callback mode is implemented */
    if( streamCallback )
    {
        PaUtil_InitializeStreamRepresentation( &stream->streamRepresentation,
                                        &auhalHostApi->callbackStreamInterface,
                                        streamCallback, userData );
    }
    else
    {
        PaUtil_InitializeStreamRepresentation( &stream->streamRepresentation,
                                        &auhalHostApi->blockingStreamInterface,
					BlioCallback, &stream->blio );
    }

    PaUtil_InitializeCpuLoadMeasurer( &stream->cpuLoadMeasurer, sampleRate );

    /* -- handle paFramesPerBufferUnspecified -- */
    if( framesPerBuffer == paFramesPerBufferUnspecified ) {
       long requested = 64;
       if( inputParameters )
          requested = MAX( requested, inputParameters->suggestedLatency * sampleRate / 2 );
       if( outputParameters )
          requested = MAX( requested, outputParameters->suggestedLatency *sampleRate / 2 );
       VDBUG( ("Block Size unspecified. Based on Latency, the user wants a Block Size near: %ld.\n",
              requested ) );
       if( requested <= 64 ) {
          /*requested a realtively low latency. make sure this is in range of devices */
          /*try to get the device's min natural buffer size and use that (but no smaller than 64).*/
          AudioValueRange audioRange;
          size_t size = sizeof( audioRange );
          if( inputParameters ) {
             WARNING( result = AudioDeviceGetProperty( auhalHostApi->devIds[inputParameters->device],
                                          0,
                                          false,
                                          kAudioDevicePropertyBufferFrameSizeRange,
                                          &size, &audioRange ) );
             if( result )
                requested = MAX( requested, audioRange.mMinimum );
          }
          if( outputParameters ) {
             WARNING( result = AudioDeviceGetProperty( auhalHostApi->devIds[outputParameters->device],
                                          0,
                                          false,
                                          kAudioDevicePropertyBufferFrameSizeRange,
                                          &size, &audioRange ) );
             if( result )
                requested = MAX( requested, audioRange.mMinimum );
          }
       } else {
          /* requested a realtively high latency. make sure this is in range of devices */
          /*try to get the device's max natural buffer size and use that (but no larger than 1024).*/
          AudioValueRange audioRange;
          size_t size = sizeof( audioRange );
          requested = MIN( requested, 1024 );
          if( inputParameters ) {
             WARNING( result = AudioDeviceGetProperty( auhalHostApi->devIds[inputParameters->device],
                                          0,
                                          false,
                                          kAudioDevicePropertyBufferFrameSizeRange,
                                          &size, &audioRange ) );
             if( result )
                requested = MIN( requested, audioRange.mMaximum );
          }
          if( outputParameters ) {
             WARNING( result = AudioDeviceGetProperty( auhalHostApi->devIds[outputParameters->device],
                                          0,
                                          false,
                                          kAudioDevicePropertyBufferFrameSizeRange,
                                          &size, &audioRange ) );
             if( result )
                requested = MIN( requested, audioRange.mMaximum );
          }
       }
       /* -- double check ranges -- */
       if( requested > 1024 ) requested = 1024;
       if( requested < 64 ) requested = 64;
       VDBUG(("After querying hardware, setting block size to %ld.\n", requested));
       framesPerBuffer = requested;
    }

    /* -- Now we actually open and setup streams. -- */
    if( inputParameters && outputParameters && outputParameters->device == inputParameters->device )
    { /* full duplex. One device. */
       result = OpenAndSetupOneAudioUnit( inputParameters,
                                          outputParameters,
                                          framesPerBuffer,
                                          &(stream->inputFramesPerBuffer),
                                          &(stream->outputFramesPerBuffer),
                                          auhalHostApi,
                                          &(stream->inputUnit),
                                          &(stream->inputSRConverter),
                                          &(stream->inputDevice),
                                          sampleRate,
                                          stream );
       stream->outputUnit = stream->inputUnit;
       stream->outputDevice = stream->inputDevice;
       if( result != paNoError )
           goto error;
    }
    else
    { /* full duplex, different devices OR simplex */
       result = OpenAndSetupOneAudioUnit( NULL,
                                          outputParameters,
                                          framesPerBuffer,
                                          NULL,
                                          &(stream->outputFramesPerBuffer),
                                          auhalHostApi,
                                          &(stream->outputUnit),
                                          NULL,
                                          &(stream->outputDevice),
                                          sampleRate,
                                          stream );
       if( result != paNoError )
           goto error;
       result = OpenAndSetupOneAudioUnit( inputParameters,
                                          NULL,
                                          framesPerBuffer,
                                          &(stream->inputFramesPerBuffer),
                                          NULL,
                                          auhalHostApi,
                                          &(stream->inputUnit),
                                          &(stream->inputSRConverter),
                                          &(stream->inputDevice),
                                          sampleRate,
                                          stream );
       if( result != paNoError )
           goto error;
    }

    if( stream->inputUnit ) {
       const size_t szfl = sizeof(float);
       /* setup the AudioBufferList used for input */
       bzero( &stream->inputAudioBufferList, sizeof( AudioBufferList ) );
       stream->inputAudioBufferList.mNumberBuffers = 1;
       stream->inputAudioBufferList.mBuffers[0].mNumberChannels
                 = inputChannelCount;
       stream->inputAudioBufferList.mBuffers[0].mDataByteSize
                 = stream->inputFramesPerBuffer*inputChannelCount*szfl;
       stream->inputAudioBufferList.mBuffers[0].mData
                 = (float *) calloc(
                               stream->inputFramesPerBuffer*inputChannelCount,
                               szfl );
       if( !stream->inputAudioBufferList.mBuffers[0].mData )
       {
          result = paInsufficientMemory;
          goto error;
       }
        
       /*

⌨️ 快捷键说明

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