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

📄 pa_mac_core_blocking.c

📁 一个开源的sip源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 * 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 == PaUtil_InitializeRingBuffer(
            &blio->inputRingBuffer,
            ringBufferSize*blio->inputSampleSize,
            data ) );
   }
   if( outChan ) {
      data = calloc( ringBufferSize, blio->outputSampleSize );
      if( !data )
      {
         result = paInsufficientMemory;
         goto error;
      }

      assert( 0 == PaUtil_InitializeRingBuffer(
            &blio->outputRingBuffer,
            ringBufferSize*blio->outputSampleSize,
            data ) );
   }

   result = resetBlioRingBuffers( blio );
   if( result )
      goto error;

   return 0;

 error:
   destroyBlioRingBuffers( blio );
   return result;
}

#ifdef PA_MAC_BLIO_MUTEX
PaError 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 ) {
      PaUtil_FlushRingBuffer( &blio->outputRingBuffer );
      bzero( blio->outputRingBuffer.buffer,
             blio->outputRingBuffer.bufferSize );
      /* Advance buffer */
      PaUtil_AdvanceRingBufferWriteIndex( &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 ) {
      PaUtil_FlushRingBuffer( &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 + -