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

📄 pa_mac_core.c

📁 IAX client库, 一个VOIP的库. 支持H.323和SIP, PBX就是采用的它
💻 C
📖 第 1 页 / 共 5 页
字号:
            sSavedHostError = err;            goto error;        }    }        if( updateConverter )    {        DBUG(("PAOSX_DevicePropertyListener: HW rate = %f\n", hardwareStreamFormat.mSampleRate ));        DBUG(("PAOSX_DevicePropertyListener: user rate = %f\n", past->past_SampleRate ));                /* Set source user format. */        memset(&userStreamFormat, 0, sizeof(AudioStreamBasicDescription));	userStreamFormat.mFormatID = kAudioFormatLinearPCM;	userStreamFormat.mFormatFlags =	  kAudioFormatFlagIsFloat |	  kAudioFormatFlagIsBigEndian |	  kAudioFormatFlagIsPacked;	userStreamFormat.mBitsPerChannel = 32;        userStreamFormat.mSampleRate = past->past_SampleRate;	// sample rate of the user synthesis code        userStreamFormat.mChannelsPerFrame = (isInput) ? past->past_NumInputChannels : past->past_NumOutputChannels;	//	the number of channels in each frame            userStreamFormat.mBytesPerFrame = userStreamFormat.mChannelsPerFrame * sizeof(float);	userStreamFormat.mFramesPerPacket = 1;        userStreamFormat.mBytesPerPacket = userStreamFormat.mBytesPerFrame * userStreamFormat.mFramesPerPacket;        if( isInput )        {            if( pahsc->input.converter != NULL )            {                verify_noerr(AudioConverterDispose (pahsc->input.converter));            }                        // Convert from hardware format to user format.            err = AudioConverterNew (                &hardwareStreamFormat,                 &userStreamFormat,                 &pahsc->input.converter );            if( err != noErr )            {                PRINT_ERR("Could not create input format converter", err);                sSavedHostError = err;                goto error;            }        }        else        {            if( pahsc->output.converter != NULL )            {                verify_noerr(AudioConverterDispose (pahsc->output.converter));            }                        // Convert from user format to hardware format.            err = AudioConverterNew (                &userStreamFormat,                 &hardwareStreamFormat,                 &pahsc->output.converter );            if( err != noErr )            {                PRINT_ERR("Could not create output format converter", err);                sSavedHostError = err;                goto error;            }        }    }        if( updateInverseMicros )    {        // Update coefficient used to calculate CPU Load based on sampleRate and bufferSize.        UInt32 ioBufferSize;        dataSize = sizeof(ioBufferSize);        err = AudioDeviceGetProperty( inDevice, 0, isInput,                        kAudioDevicePropertyBufferFrameSize, &dataSize,                        &ioBufferSize);        if( err == noErr )        {            pahsc->inverseMicrosPerHostBuffer = hardwareStreamFormat.mSampleRate /                (1000000.0 * ioBufferSize);        }    }error:    pahsc->formatListenerCalled = true;    return err;}/* Allocate FIFO between Device callback and Converter callback so that device can push data* and converter can pull data.*/static PaError PaOSX_CreateInputRingBuffer( internalPortAudioStream   *past ){    PaHostSoundControl *pahsc = (PaHostSoundControl *) past->past_DeviceData;    OSStatus  err = noErr;    UInt32    dataSize;    double    sampleRateRatio;    long      numBytes;    UInt32    framesPerHostBuffer;    UInt32    bytesForDevice;    UInt32    bytesForUser;    AudioStreamBasicDescription formatDesc;        dataSize = sizeof(formatDesc);    err = AudioDeviceGetProperty( pahsc->input.audioDeviceID, 0, IS_INPUT,        kAudioDevicePropertyStreamFormat, &dataSize, &formatDesc);    if( err != noErr )    {        PRINT_ERR("PaOSX_CreateInputRingBuffer: Could not get I/O buffer size.\n", err);        sSavedHostError = err;        return paHostError;    }    // If device is delivering audio faster than being consumed then buffer must be bigger.    sampleRateRatio = formatDesc.mSampleRate / past->past_SampleRate;        // Get size of CoreAudio IO buffers.    dataSize = sizeof(framesPerHostBuffer);    err = AudioDeviceGetProperty( pahsc->input.audioDeviceID, 0, IS_INPUT,                                kAudioDevicePropertyBufferFrameSize, &dataSize,                                &framesPerHostBuffer);    if( err != noErr )    {        PRINT_ERR("PaOSX_CreateInputRingBuffer: Could not get I/O buffer size.\n", err);        sSavedHostError = err;        return paHostError;    }        bytesForDevice = framesPerHostBuffer * formatDesc.mChannelsPerFrame * sizeof(Float32) * 2;        bytesForUser = past->past_FramesPerUserBuffer * past->past_NumInputChannels *        sizeof(Float32) * 3 * sampleRateRatio;            // Ring buffer should be large enough to consume audio input from device,    // and to deliver a complete user buffer.    numBytes = (bytesForDevice > bytesForUser) ? bytesForDevice : bytesForUser;                numBytes = RoundUpToNextPowerOf2( numBytes );    DBUG(("PaOSX_CreateInputRingBuffer: FIFO numBytes = %ld\n", numBytes));    pahsc->ringBufferData = PaHost_AllocateFastMemory( numBytes );    if( pahsc->ringBufferData == NULL )    {        return paInsufficientMemory;    }    RingBuffer_Init( &pahsc->ringBuffer, numBytes, pahsc->ringBufferData );    // make it look full at beginning    RingBuffer_AdvanceWriteIndex( &pahsc->ringBuffer, numBytes );        return paNoError;}/****************************************************************** * Try to set the I/O bufferSize of the device. * Scale the size by the ratio of the sample rates so that the converter will have * enough data to operate on. */static OSStatus PaOSX_SetDeviceBufferSize( AudioDeviceID devID, Boolean isInput, int framesPerUserBuffer, Float64 sampleRateRatio ){    UInt32    dataSize;    UInt32    ioBufferSize;    int       scaler;        	scaler = (int) sampleRateRatio;    if( sampleRateRatio > (Float64) scaler ) scaler += 1;    DBUG(("PaOSX_SetDeviceBufferSize: buffer size scaler = %d\n", scaler ));    ioBufferSize = framesPerUserBuffer * scaler;        // Limit buffer size to reasonable value.    if( ioBufferSize < 128 ) ioBufferSize = 128;    dataSize = sizeof(ioBufferSize);    return AudioDeviceSetProperty( devID, 0, 0, isInput,                            kAudioDevicePropertyBufferFrameSize, dataSize,                            &ioBufferSize);}/*******************************************************************/static PaError PaOSX_OpenCommonDevice( internalPortAudioStream   *past,        PaHostInOut *inOut, Boolean isInput ){    PaHostSoundControl *pahsc = (PaHostSoundControl *) past->past_DeviceData;    PaError          result = paNoError;    OSStatus         err = noErr;    Float64          deviceRate;    /* dmazzoni: this is not needed because we use PortMixer    PaOSX_FixVolumeScalars( inOut->audioDeviceID, isInput,        inOut->numChannels, -0.1, 0.9 );    */    pahsc->formatListenerCalled = false;    // Add listener for when format changed by other apps.    DBUG(("PaOSX_OpenCommonDevice: call AudioDeviceAddPropertyListener()\n" ));    err = AudioDeviceAddPropertyListener( inOut->audioDeviceID, 0, isInput,                                          kAudioDevicePropertyStreamFormat,                                          (AudioDevicePropertyListenerProc) PAOSX_DevicePropertyListener, past );    if (err != noErr)    {        return -1; // FIXME    }    // Only change format if current HW format is different.    // Don't bother to check result because we are going to use an AudioConverter anyway.    result = PaOSX_SetFormat( inOut->audioDeviceID, isInput, past->past_SampleRate, inOut->numChannels );    // Synchronize with device because format changes put some devices into unusable mode.    if( result == 1 )    {        const int sleepDurMsec = 10;        int spinCount = MIN_TIMEOUT_MSEC / sleepDurMsec;        while( !pahsc->formatListenerCalled && (spinCount > 0) )        {	    DBUG(("Sleeping: %d\n", spinCount));            Pa_Sleep( sleepDurMsec ); // FIXME - use a semaphore or signal            spinCount--;        }        if( !pahsc->formatListenerCalled )        {            PRINT(("PaOSX_OpenCommonDevice: timed out waiting for device format to settle.\n"));        }        result = 0;    }    // The HW device format changes are asynchronous.  If the DevicePropertyListener    // still hasn't been called, we call it manually here.    if( inOut->converter == NULL )    {        err = PAOSX_DevicePropertyListener (inOut->audioDeviceID,                                            0, isInput, kAudioDevicePropertyStreamFormat, past);        if (err != kAudioHardwareNoError)        {            PRINT_ERR("PaOSX_OpenCommonDevice: PAOSX_DevicePropertyListener failed.\n", err);            sSavedHostError = err;            return paHostError;        }    }#if SET_DEVICE_BUFFER_SIZE    // Try to set the I/O bufferSize of the device.    {        Float64   ratio;        deviceRate = PaOSX_GetDeviceSampleRate( inOut->audioDeviceID, isInput );        if( deviceRate <= 0.0 ) deviceRate =  past->past_SampleRate;        ratio = deviceRate / past->past_SampleRate ;        err = PaOSX_SetDeviceBufferSize( inOut->audioDeviceID, isInput,            past->past_FramesPerUserBuffer, ratio );        if( err != noErr )        {            DBUG(("PaOSX_OpenCommonDevice: Could not set I/O buffer size.\n"));        }    }#endif    /* Allocate an input buffer because we need it between the user callback and the converter. */    inOut->converterBuffer = PaHost_AllocateFastMemory( inOut->bytesPerUserNativeBuffer );    if( inOut->converterBuffer == NULL )    {        return paInsufficientMemory;    }    return result;}/*******************************************************************/static PaError PaOSX_OpenInputDevice( internalPortAudioStream   *past ){    PaHostSoundControl *pahsc = (PaHostSoundControl *) past->past_DeviceData;    const PaHostDeviceInfo *hostDeviceInfo;    PaError          result = paNoError;            DBUG(("PaOSX_OpenInputDevice: -------------\n"));        if( (past->past_InputDeviceID < LOWEST_INPUT_DEVID) ||        (past->past_InputDeviceID > HIGHEST_INPUT_DEVID) )    {        return paInvalidDeviceId;    }    hostDeviceInfo = &sDeviceInfos[past->past_InputDeviceID];    if( past->past_NumInputChannels > hostDeviceInfo->paInfo.maxInputChannels )    {        return paInvalidChannelCount; /* Too many channels! */    }    pahsc->input.numChannels = past->past_NumInputChannels;    // setup PA conversion procedure    result = PaConvert_SetupInput( past, paFloat32 );    result = PaOSX_OpenCommonDevice( past, &pahsc->input, IS_INPUT );    if( result != paNoError ) goto error;        // Allocate a ring buffer so we can push in data from device, and pull through AudioConverter.    result = PaOSX_CreateInputRingBuffer( past );    if( result != paNoError ) goto error;            error:    return result;}/*******************************************************************/static PaError PaOSX_OpenOutputDevice( internalPortAudioStream *past ){    PaHostSoundControl *pahsc;    const PaHostDeviceInfo *hostDeviceInfo;    PaError          result = paNoError;    DBUG(("PaOSX_OpenOutputDevice: -------------\n"));    pahsc = (PaHostSoundControl *) past->past_DeviceData;        // Validate DeviceID    DBUG(("PaOSX_OpenOutputDevice: deviceID = 0x%x\n", past->past_OutputDeviceID));    if( (past->past_OutputDeviceID < LOWEST_OUTPUT_DEVID) ||        (past->past_OutputDeviceID > HIGHEST_OUTPUT_DEVID) )    {        return paInvalidDeviceId;    }    hostDeviceInfo = &sDeviceInfos[past->past_OutputDeviceID];        // Validate number of channels.    if( past->past_NumOutputChannels > hostDeviceInfo->paInfo.maxOutputChannels )    {        return paInvalidChannelCount; /* Too many channels! */    }    pahsc->output.numChannels = past->past_NumOutputChannels;        // setup conversion procedure    result = PaConvert_SetupOutput( past, paFloat32 );	if( result != paNoError ) goto error;            result = PaOSX_OpenCommonDevice( past, &pahsc->output, IS_OUTPUT );    if( result != paNoError ) goto error;    error:    return result;}/******************************************************************** Determine how many User Buffers we can put into our CoreAudio stream buffer.* Uses:*    past->past_FramesPerUser

⌨️ 快捷键说明

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