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

📄 pa_mac_core.c

📁 IAX client库, 一个VOIP的库. 支持H.323和SIP, PBX就是采用的它
💻 C
📖 第 1 页 / 共 5 页
字号:
            UInt32 size = pahsc->input.bytesPerUserNativeBuffer;            err = AudioConverterFillBuffer(                pahsc->input.converter,                PaOSX_InputConverterCallbackProc,                past,                &size,                pahsc->input.converterBuffer);            if( err != noErr ) return err;            inputBuffer = pahsc->input.converterBuffer;        }                /* Fill part of audio converter buffer by converting input to user format,        * calling user callback, then converting output to native format. */        if( PaConvert_Process( past, inputBuffer, outputBuffer ))        {            past->past_StopSoon = 1;        }    }    return err;}/******************************************************************************* This is the proc that supplies the data to the AudioConverterFillBuffer call*/static OSStatus PaOSX_OutputConverterCallbackProc (AudioConverterRef			inAudioConverter,								UInt32*						outDataSize,								void**						outData,								void*						inUserData){    internalPortAudioStream   *past = (internalPortAudioStream *) inUserData;    PaHostSoundControl *pahsc = (PaHostSoundControl *) past->past_DeviceData;    	*outData = pahsc->output.converterBuffer;	*outDataSize = pahsc->output.bytesPerUserNativeBuffer;    	return PaOSX_LoadAndProcess ( past, pahsc->input.converterBuffer, pahsc->output.converterBuffer );}/************************************************************************ Fill any available output buffers and use any available** input buffers by calling user callback.** Will set past->past_StopSoon if user callback indicates that it is finished.*/static OSStatus PaOSX_HandleInputOutput( internalPortAudioStream   *past,        const AudioBufferList*  inInputData,        AudioBufferList*  outOutputData ){    OSStatus            err = noErr;    char               *inputNativeBufferfPtr = NULL;    char               *outputNativeBufferfPtr = NULL;    PaHostSoundControl *pahsc = (PaHostSoundControl *) past->past_DeviceData;    /* If we are using output, then we need an empty output buffer. */    if( outOutputData->mNumberBuffers > 0 )    {        outputNativeBufferfPtr =  (char*)outOutputData->mBuffers[0].mData;    }    if(  inInputData->mNumberBuffers > 0  )    {        inputNativeBufferfPtr = (char*)inInputData->mBuffers[0].mData;            /* Write to FIFO here if we are only using this callback. */        if( (pahsc->mode == PA_MODE_INPUT_ONLY) || (pahsc->mode == PA_MODE_IO_ONE_DEVICE) )        {            long writeRoom = RingBuffer_GetWriteAvailable( &pahsc->ringBuffer );            long numBytes = inInputData->mBuffers[0].mDataByteSize;            if( numBytes <= writeRoom )            {                RingBuffer_Write(  &pahsc->ringBuffer, inputNativeBufferfPtr, numBytes );                DBUGBACK(("PaOSX_HandleInputOutput: wrote %ld bytes to FIFO.\n", inInputData->mBuffers[0].mDataByteSize));            } // FIXME else drop samples on floor, remember overflow???                    }    }    if( pahsc->mode == PA_MODE_INPUT_ONLY )    {        /* Generate user buffers as long as we have a half full input FIFO. */        long halfSize = pahsc->ringBuffer.bufferSize / 2;        while( (RingBuffer_GetReadAvailable( &pahsc->ringBuffer ) >= halfSize) &&            (past->past_StopSoon == 0) )        {            err = PaOSX_LoadAndProcess ( past, NULL, NULL );            if( err != noErr ) goto error;        }    }    else    {        UInt32 size = outOutputData->mBuffers[0].mDataByteSize;        err = AudioConverterFillBuffer(            pahsc->output.converter,            PaOSX_OutputConverterCallbackProc,            past,            &size,            outputNativeBufferfPtr);        if( err != noErr )        {            PRINT_ERR("PaOSX_HandleInputOutput: AudioConverterFillBuffer failed", err);            goto error;        }    }    error:    return err;}/****************************************************************** * This callback is used when two separate devices are used for input and output. * This often happens when using USB devices which present as two devices: input and output. * It just writes its data to a FIFO so that it can be read by the main callback * proc PaOSX_CoreAudioIOCallback(). */static OSStatus PaOSX_CoreAudioInputCallback (AudioDeviceID  inDevice, const AudioTimeStamp*  inNow,                    const AudioBufferList*  inInputData, const AudioTimeStamp*  inInputTime,                    AudioBufferList*  outOutputData, const AudioTimeStamp* inOutputTime,                    void* contextPtr){    internalPortAudioStream *past = (internalPortAudioStream *) contextPtr;    PaHostSoundControl *pahsc;    pahsc = (PaHostSoundControl *) past->past_DeviceData;       /* If there is a FIFO for input then write to it. */    if( pahsc->ringBufferData != NULL )    {        long writeRoom = RingBuffer_GetWriteAvailable( &pahsc->ringBuffer );        long numBytes = inInputData->mBuffers[0].mDataByteSize;        if( numBytes <= writeRoom )        {            RingBuffer_Write(  &pahsc->ringBuffer, inInputData->mBuffers[0].mData, inInputData->mBuffers[0].mDataByteSize );        }        else        {            DBUGBACK(("PaOSX_CoreAudioInputCallback: FIFO too full to write!\n"));        }                }        return noErr;}/****************************************************************** * This is the primary callback for CoreAudio. * It can handle input and/or output for a single device. * It takes input from CoreAudio, converts it and passes it to the * PortAudio user callback. Then takes the PA results and passes it * back to CoreAudio. */static OSStatus PaOSX_CoreAudioIOCallback (AudioDeviceID  inDevice, const AudioTimeStamp*  inNow,                    const AudioBufferList*  inInputData, const AudioTimeStamp*  inInputTime,                    AudioBufferList*  outOutputData, const AudioTimeStamp* inOutputTime,                    void* contextPtr){    OSStatus      err = noErr;    internalPortAudioStream *past;    PaHostSoundControl *pahsc;    past = (internalPortAudioStream *) contextPtr;    pahsc = (PaHostSoundControl *) past->past_DeviceData;    /* Has someone asked us to abort by calling Pa_AbortStream()? */    if( past->past_StopNow )    {        past->past_IsActive = 0; /* Will cause thread to return. */    }    /* Has someone asked us to stop by calling Pa_StopStream()     * OR has a user callback returned '1' to indicate finished.     */    else if( past->past_StopSoon )    {        // FIXME - Pretend all done. Should wait for audio to play out but CoreAudio latency very low.        past->past_IsActive = 0; /* Will cause thread to return. */    }    else    {        /* use time stamp from CoreAudio if valid */        /* dmazzoni: this is unreliable!        if( inOutputTime->mFlags & kAudioTimeStampSampleTimeValid)         {            past->past_FrameCount = inOutputTime->mSampleTime;        }        else if( inInputTime->mFlags & kAudioTimeStampSampleTimeValid)         {            past->past_FrameCount = inInputTime->mSampleTime;        }        */                /* Measure CPU load. */        Pa_StartUsageCalculation( past );        past->past_NumCallbacks += 1;                /* Process full input buffer and fill up empty output buffers. */        err = PaOSX_HandleInputOutput( past, inInputData, outOutputData );                Pa_EndUsageCalculation( past );    }    if( err != 0 ) DBUG(("PaOSX_CoreAudioIOCallback: returns %ld.\n", err ));    return err;}/*******************************************************************//** Attempt to set device sample rate. * This is not critical because we use an AudioConverter but we may * get better fidelity if we can avoid resampling. * * Only set format once because some devices take time to settle. * Return flag indicating whether format changed so we know whether to wait * for DevicePropertyListener to get called. * * @return negative error, zero if no change, or one if changed successfully. */static PaError PaOSX_SetFormat( AudioDeviceID devID, Boolean isInput,        double desiredRate, int desiredNumChannels ){    AudioStreamBasicDescription origDesc;    AudioStreamBasicDescription formatDesc;    AudioStreamID *streams;    PaError  result = 0;    OSStatus err;    Boolean  outWritable;    UInt32   outSize;    UInt32   dataSize;    UInt32   supportsMixing;    Float64  originalRate;    int      originalChannels;    int      numStreams;    pid_t    hog_pid;    pid_t    this_pid = getpid();    int      did_set_hog_mode = 0;    int      i;    /* Get current device format. This is critical because if we pass     * zeros for unspecified fields then the iMic device gets switched to a 16 bit     * integer format!!! I don't know if this is a Mac bug or not. But it only     * started happening when I upgraded from OS X V10.1 to V10.2 (Jaguar).     */    dataSize = sizeof(formatDesc);    err = AudioDeviceGetProperty( devID, 0, isInput,                                  kAudioDevicePropertyStreamFormat, &dataSize, &formatDesc);    if( err != noErr )        {            PRINT_ERR("PaOSX_SetFormat: Could not get format.", err);            sSavedHostError = err;            return paHostError;        }    origDesc = formatDesc;    originalRate = origDesc.mSampleRate;    originalChannels = origDesc.mChannelsPerFrame;            // Is it already set to the correct format?    if( (originalRate != desiredRate) ||        (originalChannels != desiredNumChannels) ||        (origDesc.mFormatID != kAudioFormatLinearPCM) ||        (origDesc.mFormatFlags & kLinearPCMFormatFlagIsFloat)==0 )        {            if (originalRate != desiredRate)                DBUG(("PaOSX_SetFormat: try to change sample rate to %f.\n", desiredRate ));            if (originalChannels != desiredNumChannels)                DBUG(("PaOSX_SetFormat: try to set number of channels to %d\n", desiredNumChannels));            if (formatDesc.mFormatID != kAudioFormatLinearPCM)                DBUG(("PaOSX_SetFormat: try to set formatID to linear PCM\n"));            if ((formatDesc.mFormatFlags & kLinearPCMFormatFlagIsFloat)==0)                DBUG(("PaOSX_SetFormat: try to set formatFlags to float32\n"));            // First we try to grab hog mode on the device, because otherwise it won't let            // us change the format. -dmazzoni            DBUG(("Checking hog mode\n"));            outSize = sizeof(hog_pid);            err = AudioDeviceGetProperty(devID, 0, isInput,                                         kAudioDevicePropertyHogMode, &outSize, &hog_pid);            if (!err) {                DBUG(("Current status of hog mode: pid=%d this_pid=%d\n", (int)hog_pid, (int)this_pid));                if (hog_pid != this_pid) {                    hog_pid = this_pid;                    err = AudioDeviceSetProperty( devID, 0, 0, isInput,                                                  kAudioDevicePropertyHogMode, sizeof(hog_pid), &hog_pid);                    if (!err) {                        DBUG(("Successfully set hog mode - new pid=%d!\n", (int)hog_pid));                               err = AudioDeviceGetProperty(devID, 0, isInput,                                                     kAudioDevicePropertyHogMode, &outSize, &hog_pid);                        if (!err) {                            DBUG(("Checking new status of hog mode: pid=%d this_pid=%d\n",                                  (int)hog_pid, (int)this_pid));                            did_set_hog_mode = 1;                        }                    }                }            }            // Get a list of the device's streams            err = AudioDeviceGetPropertyInfo( devID, 0, isInput,                                              kAudioDevicePropertyStreams, &outSize, &outWritable );                    streams = (AudioStreamID *)malloc(outSize);                    err = AudioDeviceGetProperty( devID, 0, isInput,                                          kAudioDevicePropertyStreams, &outSize, streams);            // If that was successful, loop through each stream and set its format to            // linear PCM float.            if (err) {                DBUG(("Couldn't get device's streams!  err=%d\n", err));            }            else {                numStreams = outSize / sizeof(AudioStreamID);                for(i=0; i<numStreams; i++) {                    memset(&formatDesc, 0, sizeof(AudioStreamBasicDescription));                                   formatDesc.mFormatID = kAudioFormatLinearPCM;                    outSize = sizeof(AudioStreamBasicDescription);                    err = AudioDeviceGetProperty(devID, 0, isInput, kAudioStreamPropertyPhysicalFormatMatch,                                                 &outSize, &formatDesc);                    DBUG(("Asked for stream physical format match, got "                          "err=%d, rate=%1f, formatID=%s, flags=%d channels=%d\n",                          err,                           formatDesc.mSampleRate, FourCharCode2Str(formatDesc.mFormatID),                          formatDesc.mFormatFlags, formatDesc.mChannelsPerFrame));                    if (formatDesc.mFormatID != kAudioFormatLinearPCM) {                        DBUG(("Couldn't even get linear PCM!\n"));                    }                    else {                        err = AudioDeviceSetProperty( devID, 0, 0,                                                      isInput, kAudioStreamPropertyPhysicalFormat,                                                      sizeof(formatDesc), &formatDesc);

⌨️ 快捷键说明

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