📄 pa_mac_core_utilities.c
字号:
/* * 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 + -