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

📄 pa_mac_core_utilities.c

📁 一个开源SIP协议栈
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 * Helper and utility functions for pa_mac_core.c (Apple AUHAL implementation)
 *
 * PortAudio Portable Real-Time Audio Library
 * Latest Version at: http://www.portaudio.com
 *
 * Written by Bjorn Roche of XO Audio LLC, from PA skeleton code.
 * Portions copied from code by Dominic Mazzoni (who wrote a HAL implementation)
 *
 * Dominic's code was based on code by Phil Burk, Darren Gibbs,
 * Gord Peters, Stephane Letz, and Greg Pfiel.
 *
 * The following people also deserve acknowledgements:
 *
 * Olivier Tristan for feedback and testing
 * Glenn Zelniker and Z-Systems engineering for sponsoring the Blocking I/O
 * interface.
 * 
 *
 * Based on the Open Source API proposed by Ross Bencina
 * Copyright (c) 1999-2002 Ross Bencina, Phil Burk
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files
 * (the "Software"), to deal in the Software without restriction,
 * including without limitation the rights to use, copy, modify, merge,
 * publish, distribute, sublicense, and/or sell copies of the Software,
 * and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

/*
 * The text above constitutes the entire PortAudio license; however, 
 * the PortAudio community also makes the following non-binding requests:
 *
 * Any person wishing to distribute modifications to the Software is
 * requested to send the modifications to the original developer so that
 * they can be incorporated into the canonical version. It is also 
 * requested that these non-binding requests be included along with the 
 * license above.
 */

/**
 @file
 @ingroup hostapi_src
*/

#include "pa_mac_core_utilities.h"


PaError PaMacCore_SetUnixError( int err, int line )
{
   PaError ret;
   const char *errorText;

   if( err == 0 )
   {
      return paNoError;
   }

   ret = paNoError;
   errorText = strerror( err );

   /** Map Unix error to PaError. Pretty much the only one that maps
       is ENOMEM. */
   if( err == ENOMEM )
      ret = paInsufficientMemory;
   else
      ret = paInternalError;

   DBUG(("%d on line %d: msg='%s'\n", err, line, errorText));
   PaUtil_SetLastHostErrorInfo( paCoreAudio, err, errorText );

   return ret;
}

/*
 * Translates MacOS generated errors into PaErrors
 */
PaError PaMacCore_SetError(OSStatus error, int line, int isError)
{
    /*FIXME: still need to handle possible ComponentResult values.*/
    /*       unfortunately, they don't seem to be documented anywhere.*/
    PaError result;
    const char *errorType; 
    const char *errorText;
    
    switch (error) {
    case kAudioHardwareNoError:
        return paNoError;
    case kAudioHardwareNotRunningError:
        errorText = "Audio Hardware Not Running";
        result = paInternalError; break;
    case kAudioHardwareUnspecifiedError: 
        errorText = "Unspecified Audio Hardware Error";
        result = paInternalError; break;
    case kAudioHardwareUnknownPropertyError:
        errorText = "Audio Hardware: Unknown Property";
        result = paInternalError; break;
    case kAudioHardwareBadPropertySizeError:
        errorText = "Audio Hardware: Bad Property Size";
        result = paInternalError; break;
    case kAudioHardwareIllegalOperationError: 
        errorText = "Audio Hardware: Illegal Operation";
        result = paInternalError; break;
    case kAudioHardwareBadDeviceError:
        errorText = "Audio Hardware: Bad Device";
        result = paInvalidDevice; break;
    case kAudioHardwareBadStreamError:
        errorText = "Audio Hardware: BadStream";
        result = paBadStreamPtr; break;
    case kAudioHardwareUnsupportedOperationError:
        errorText = "Audio Hardware: Unsupported Operation";
        result = paInternalError; break;
    case kAudioDeviceUnsupportedFormatError:
        errorText = "Audio Device: Unsupported Format";
        result = paSampleFormatNotSupported; break;
    case kAudioDevicePermissionsError:
        errorText = "Audio Device: Permissions Error";
        result = paDeviceUnavailable; break;
    /* Audio Unit Errors: http://developer.apple.com/documentation/MusicAudio/Reference/CoreAudio/audio_units/chapter_5_section_3.html */
    case kAudioUnitErr_InvalidProperty:
        errorText = "Audio Unit: Invalid Property";
        result = paInternalError; break;
    case kAudioUnitErr_InvalidParameter:
        errorText = "Audio Unit: Invalid Parameter";
        result = paInternalError; break;
    case kAudioUnitErr_NoConnection:
        errorText = "Audio Unit: No Connection";
        result = paInternalError; break;
    case kAudioUnitErr_FailedInitialization:
        errorText = "Audio Unit: Initialization Failed";
        result = paInternalError; break;
    case kAudioUnitErr_TooManyFramesToProcess:
        errorText = "Audio Unit: Too Many Frames";
        result = paInternalError; break;
    case kAudioUnitErr_IllegalInstrument:
        errorText = "Audio Unit: Illegal Instrument";
        result = paInternalError; break;
    case kAudioUnitErr_InstrumentTypeNotFound:
        errorText = "Audio Unit: Instrument Type Not Found";
        result = paInternalError; break;
    case kAudioUnitErr_InvalidFile:
        errorText = "Audio Unit: Invalid File";
        result = paInternalError; break;
    case kAudioUnitErr_UnknownFileType:
        errorText = "Audio Unit: Unknown File Type";
        result = paInternalError; break;
    case kAudioUnitErr_FileNotSpecified:
        errorText = "Audio Unit: File Not Specified";
        result = paInternalError; break;
    case kAudioUnitErr_FormatNotSupported:
        errorText = "Audio Unit: Format Not Supported";
        result = paInternalError; break;
    case kAudioUnitErr_Uninitialized:
        errorText = "Audio Unit: Unitialized";
        result = paInternalError; break;
    case kAudioUnitErr_InvalidScope:
        errorText = "Audio Unit: Invalid Scope";
        result = paInternalError; break;
    case kAudioUnitErr_PropertyNotWritable:
        errorText = "Audio Unit: PropertyNotWritable";
        result = paInternalError; break;
    case kAudioUnitErr_InvalidPropertyValue:
        errorText = "Audio Unit: Invalid Property Value";
        result = paInternalError; break;
    case kAudioUnitErr_PropertyNotInUse:
        errorText = "Audio Unit: Property Not In Use";
        result = paInternalError; break;
    case kAudioUnitErr_Initialized:
        errorText = "Audio Unit: Initialized";
        result = paInternalError; break;
    case kAudioUnitErr_InvalidOfflineRender:
        errorText = "Audio Unit: Invalid Offline Render";
        result = paInternalError; break;
    case kAudioUnitErr_Unauthorized:
        errorText = "Audio Unit: Unauthorized";
        result = paInternalError; break;
    case kAudioUnitErr_CannotDoInCurrentContext:
        errorText = "Audio Unit: cannot do in current context";
        result = paInternalError; break;
    default:
        errorText = "Unknown Error";
        result = paInternalError;
    }

    if (isError)
        errorType = "Error";
    else
        errorType = "Warning";

    if ((int)error < -99999 || (int)error > 99999)
        DBUG(("%s on line %d: err='%4s', msg='%s'\n", errorType, line, (const char *)&error, errorText));
    else
        DBUG(("%s on line %d: err=%d, 0x%x, msg='%s'\n", errorType, line, (int)error, (unsigned)error, errorText));

    PaUtil_SetLastHostErrorInfo( paCoreAudio, error, errorText );

    return result;
}

/*
 * This function computes an appropriate ring buffer size given
 * a requested latency (in seconds), sample rate and framesPerBuffer.
 *
 * The returned ringBufferSize is computed using the following
 * constraints:
 *   - it must be at least 4.
 *   - it must be at least 3x framesPerBuffer.
 *   - it must be at least 2x the suggestedLatency.
 *   - it must be a power of 2.
 * This function attempts to compute the minimum such size.
 *
 * FEEDBACK: too liberal/conservative/another way?
 */
long computeRingBufferSize( const PaStreamParameters *inputParameters,
                                   const PaStreamParameters *outputParameters,
                                   long inputFramesPerBuffer,
                                   long outputFramesPerBuffer,
                                   double sampleRate )
{
   long ringSize;
   int index;
   int i;
   double latencyTimesChannelCount ;
   long framesPerBufferTimesChannelCount ;

   VVDBUG(( "computeRingBufferSize()\n" ));

   assert( inputParameters || outputParameters );

   if( outputParameters && inputParameters )
   {
      latencyTimesChannelCount = MAX(
           inputParameters->suggestedLatency * inputParameters->channelCount,
           outputParameters->suggestedLatency * outputParameters->channelCount );
      framesPerBufferTimesChannelCount = MAX(
           inputFramesPerBuffer * inputParameters->channelCount,
           outputFramesPerBuffer * outputParameters->channelCount );
   } 
   else if( outputParameters )
   {
      latencyTimesChannelCount
                = outputParameters->suggestedLatency * outputParameters->channelCount;
      framesPerBufferTimesChannelCount
                = outputFramesPerBuffer * outputParameters->channelCount;
   }
   else /* we have inputParameters  */
   {
      latencyTimesChannelCount
                = inputParameters->suggestedLatency * inputParameters->channelCount;
      framesPerBufferTimesChannelCount
                = inputFramesPerBuffer * inputParameters->channelCount;
   }

   ringSize = (long) ( latencyTimesChannelCount * sampleRate * 2 + .5);
   VDBUG( ( "suggested latency * channelCount: %d\n", (int) (latencyTimesChannelCount*sampleRate) ) );
   if( ringSize < framesPerBufferTimesChannelCount * 3 )
      ringSize = framesPerBufferTimesChannelCount * 3 ;
   VDBUG(("framesPerBuffer*channelCount:%d\n",(int)framesPerBufferTimesChannelCount));
   VDBUG(("Ringbuffer size (1): %d\n", (int)ringSize ));

   /* make sure it's at least 4 */
   ringSize = MAX( ringSize, 4 );

   /* round up to the next power of 2 */
   index = -1;
   for( i=0; i<sizeof(long)*8; ++i )
      if( ringSize >> i & 0x01 )
         index = i;
   assert( index > 0 );
   if( ringSize <= ( 0x01 << index ) )
      ringSize = 0x01 << index ;
   else
      ringSize = 0x01 << ( index + 1 );

   VDBUG(( "Final Ringbuffer size (2): %d\n", (int)ringSize ));
   return ringSize;
}


/*
 * Durring testing of core audio, I found that serious crashes could occur
 * if properties such as sample rate were changed multiple times in rapid
 * succession. The function below has some fancy logic to make sure that changes
 * are acknowledged before another is requested. That seems to help a lot.
 */

OSStatus propertyProc(
    AudioDeviceID inDevice, 
    UInt32 inChannel, 
    Boolean isInput, 
    AudioDevicePropertyID inPropertyID, 
    void* inClientData )
{
   MutexAndBool *mab = (MutexAndBool *) inClientData;

⌨️ 快捷键说明

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