pa_mac_core_blocking.c
字号:
/* * Implementation of the PortAudio API for Apple AUHAL * * 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 hostaip_src This file contains the implementation required for blocking I/O. It is separated from pa_mac_core.c simply to ease development.*/#include "pa_mac_core_blocking.h"#include "pa_mac_core_internal.h"#include <assert.h>#ifdef MOSX_USE_NON_ATOMIC_FLAG_BITS# define OSAtomicOr32( a, b ) ( (*(b)) |= (a) )# define OSAtomicAnd32( a, b ) ( (*(b)) &= (a) )#else# include <libkern/OSAtomic.h>#endif/* * This fnuction determines the size of a particular sample format. * if the format is not recognized, this returns zero. */static size_t computeSampleSizeFromFormat( PaSampleFormat format ){ switch( format ) { case paFloat32: return 4; case paInt32: return 4; case paInt24: return 3; case paInt16: return 2; case paInt8: case paUInt8: return 1; default: return 0; }}/* * Functions for initializing, resetting, and destroying BLIO structures. * *//* This should be called with the relevant info when initializing a stream for callback. */PaError initializeBlioRingBuffers( PaMacBlio *blio, PaSampleFormat inputSampleFormat, PaSampleFormat outputSampleFormat, size_t framesPerBuffer, long ringBufferSize, int inChan, int outChan ){ void *data; int result; /* zeroify things */ bzero( blio, sizeof( PaMacBlio ) ); /* this is redundant, but the buffers are used to check if the bufffers have been initialized, so we do it explicitly. */ blio->inputRingBuffer.buffer = NULL; blio->outputRingBuffer.buffer = NULL; /* initialize simple data */ blio->inputSampleFormat = inputSampleFormat; blio->inputSampleSize = computeSampleSizeFromFormat(inputSampleFormat); blio->outputSampleFormat = outputSampleFormat; blio->outputSampleSize = computeSampleSizeFromFormat(outputSampleFormat); blio->framesPerBuffer = framesPerBuffer; blio->inChan = inChan; blio->outChan = outChan; blio->statusFlags = 0; blio->errors = paNoError;#ifdef PA_MAC_BLIO_MUTEX blio->isInputEmpty = false; blio->isOutputFull = false;#endif /* setup ring buffers */#ifdef PA_MAC_BLIO_MUTEX result = PaMacCore_SetUnixError( pthread_mutex_init(&(blio->inputMutex),NULL), 0 ); if( result ) goto error; result = UNIX_ERR( pthread_cond_init( &(blio->inputCond), NULL ) ); if( result ) goto error; result = UNIX_ERR( pthread_mutex_init(&(blio->outputMutex),NULL) ); if( result ) goto error; result = UNIX_ERR( pthread_cond_init( &(blio->outputCond), NULL ) );#endif if( inChan ) { data = calloc( ringBufferSize, blio->inputSampleSize ); if( !data ) { result = paInsufficientMemory; goto error; } assert( 0 == RingBuffer_Init( &blio->inputRingBuffer, ringBufferSize*blio->inputSampleSize, data ) ); } if( outChan ) { data = calloc( ringBufferSize, blio->outputSampleSize ); if( !data ) { result = paInsufficientMemory; goto error; } assert( 0 == RingBuffer_Init( &blio->outputRingBuffer, ringBufferSize*blio->outputSampleSize, data ) ); } result = resetBlioRingBuffers( blio ); if( result ) goto error; return 0; error: destroyBlioRingBuffers( blio ); return result;}#ifdef PA_MAC_BLIO_MUTEXPaError blioSetIsInputEmpty( PaMacBlio *blio, bool isEmpty ){ PaError result = paNoError; if( isEmpty == blio->isInputEmpty ) goto done; /* we need to update the value. Here's what we do: * - Lock the mutex, so noone else can write. * - update the value. * - unlock. * - broadcast to all listeners. */ result = UNIX_ERR( pthread_mutex_lock( &blio->inputMutex ) ); if( result ) goto done; blio->isInputEmpty = isEmpty; result = UNIX_ERR( pthread_mutex_unlock( &blio->inputMutex ) ); if( result ) goto done; result = UNIX_ERR( pthread_cond_broadcast( &blio->inputCond ) ); if( result ) goto done; done: return result;}PaError blioSetIsOutputFull( PaMacBlio *blio, bool isFull ){ PaError result = paNoError; if( isFull == blio->isOutputFull ) goto done; /* we need to update the value. Here's what we do: * - Lock the mutex, so noone else can write. * - update the value. * - unlock. * - broadcast to all listeners. */ result = UNIX_ERR( pthread_mutex_lock( &blio->outputMutex ) ); if( result ) goto done; blio->isOutputFull = isFull; result = UNIX_ERR( pthread_mutex_unlock( &blio->outputMutex ) ); if( result ) goto done; result = UNIX_ERR( pthread_cond_broadcast( &blio->outputCond ) ); if( result ) goto done; done: return result;}#endif/* This should be called after stopping or aborting the stream, so that on next start, the buffers will be ready. */PaError resetBlioRingBuffers( PaMacBlio *blio ){#ifdef PA_MAC__BLIO_MUTEX int result;#endif blio->statusFlags = 0; if( blio->outputRingBuffer.buffer ) { RingBuffer_Flush( &blio->outputRingBuffer ); bzero( blio->outputRingBuffer.buffer, blio->outputRingBuffer.bufferSize ); /* Advance buffer */ RingBuffer_AdvanceWriteIndex( &blio->outputRingBuffer, blio->outputRingBuffer.bufferSize ); /* Update isOutputFull. */#ifdef PA_MAC__BLIO_MUTEX result = blioSetIsOutputFull( blio, toAdvance == blio->outputRingBuffer.bufferSize ); if( result ) goto error;#endif/* printf( "------%d\n" , blio->framesPerBuffer ); printf( "------%d\n" , blio->outChan ); printf( "------%d\n" , blio->outputSampleSize ); printf( "------%d\n" , blio->framesPerBuffer*blio->outChan*blio->outputSampleSize );*/ } if( blio->inputRingBuffer.buffer ) { RingBuffer_Flush( &blio->inputRingBuffer ); bzero( blio->inputRingBuffer.buffer, blio->inputRingBuffer.bufferSize ); /* Update isInputEmpty. */#ifdef PA_MAC__BLIO_MUTEX result = blioSetIsInputEmpty( blio, true ); if( result ) goto error;#endif } return paNoError;#ifdef PA_MAC__BLIO_MUTEX error: return result;#endif}/*This should be called when you are done with the blio. It can safely be called
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -