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

📄 pa_mac.c

📁 ppciaxclient softphone
💻 C
📖 第 1 页 / 共 5 页
字号:
static double * PaMac_GetSampleRatesFromHandle ( int numRates, Handle h )
{
    OSErr   err = noErr;
    SInt8   hState;
    int     i;
    UnsignedFixed *fixedRates;
    double *rates = (double *) malloc( numRates * sizeof(double) ); /* MEM_011 */
    if( rates == NULL ) return NULL;
    /* Save and restore handle state as suggested by TechNote at:
            http://developer.apple.com/technotes/tn/tn1122.html
    */
    hState = HGetState (h);
    if (!(err = MemError ()))
    {
        HLock (h);
        if (!(err = MemError ( )))
        {
            fixedRates = (UInt32 *) *h;
            for( i=0; i<numRates; i++ )
            {
                rates[i] = UnsignedFixedToDouble(fixedRates[i]);
            }

            HSetState (h,hState);
            err = MemError ( );
        }
    }
    if( err )
    {
        free( rates );
        ERR_RPT(("Error in PaMac_GetSampleRatesFromHandle = %d\n", err ));
    }
    return rates;
}

/*************************************************************************/
int Pa_CountDevices()
{
    PaError err;
    DBUG(("Pa_CountDevices()\n"));
    /* If no devices, go find some. */
    if( sNumDevices <= 0 )
    {
        err = PaMac_ScanOutputDevices();
        if( err != paNoError ) goto error;
        err = PaMac_ScanInputDevices();
        if( err != paNoError ) goto error;
    }
    return sNumDevices;

error:
    PaHost_Term();
    DBUG(("Pa_CountDevices: returns %d\n", err ));
    return err;

}

/*************************************************************************/
const PaDeviceInfo* Pa_GetDeviceInfo( PaDeviceID id )
{
    if( (id < 0) || ( id >= Pa_CountDevices()) ) return NULL;
    return &sDevices[id].pad_Info;
}
/*************************************************************************/
PaDeviceID Pa_GetDefaultInputDeviceID( void )
{
    return sDefaultInputDeviceID;
}

/*************************************************************************/
PaDeviceID Pa_GetDefaultOutputDeviceID( void )
{
    return sDefaultOutputDeviceID;
}

/********************************* BEGIN CPU UTILIZATION MEASUREMENT ****/
static void PaMac_StartLoadCalculation( internalPortAudioStream   *past )
{
    PaHostSoundControl *pahsc = (PaHostSoundControl *) past->past_DeviceData;
    UnsignedWide widePad;
    if( pahsc == NULL ) return;
    /* Query system timer for usage analysis and to prevent overuse of CPU. */
    Microseconds( &widePad );
    pahsc->pahsc_EntryCount = UnsignedWideToUInt64( widePad );
}

/******************************************************************************
** Measure fractional CPU load based on real-time it took to calculate
** buffers worth of output.
*/
/**************************************************************************/
static void PaMac_EndLoadCalculation( internalPortAudioStream   *past )
{
    UnsignedWide widePad;
    UInt64    currentCount;
    long      usecsElapsed;
    double    newUsage;
    PaHostSoundControl *pahsc = (PaHostSoundControl *) past->past_DeviceData;
    if( pahsc == NULL ) return;
    
    /* Measure CPU utilization during this callback. Note that this calculation
    ** assumes that we had the processor the whole time.
    */
#define LOWPASS_COEFFICIENT_0   (0.95)
#define LOWPASS_COEFFICIENT_1   (0.99999 - LOWPASS_COEFFICIENT_0)
    Microseconds( &widePad );
    currentCount = UnsignedWideToUInt64( widePad );

	usecsElapsed = (long) U64Subtract(currentCount, pahsc->pahsc_EntryCount);
	
        /* Use inverse because it is faster than the divide. */
	newUsage =  usecsElapsed * pahsc->pahsc_InverseMicrosPerHostBuffer;
	
	past->past_Usage = (LOWPASS_COEFFICIENT_0 * past->past_Usage) +
                           (LOWPASS_COEFFICIENT_1 * newUsage);
 
}

/***********************************************************************
** Called by Pa_StartStream()
*/
PaError PaHost_StartInput( internalPortAudioStream   *past )
{
    PaHostSoundControl *pahsc = (PaHostSoundControl *) past->past_DeviceData;
    pahsc->pahsc_IsRecording = 0;
    pahsc->pahsc_StopRecording = 0;
    pahsc->pahsc_InputMultiBuffer.nextWrite = 0;
    pahsc->pahsc_InputMultiBuffer.nextRead = 0;
    return PaMac_RecordNext( past );
}

/***********************************************************************
** Called by Pa_StopStream().
** May be called during error recovery or cleanup code
** so protect against NULL pointers.
*/
PaError PaHost_StopInput( internalPortAudioStream   *past, int abort )
{
    int32   timeOutMsec;
    PaError result = paNoError;
    OSErr   err = 0;
    long    mRefNum;
    PaHostSoundControl *pahsc = (PaHostSoundControl *) past->past_DeviceData;
    if( pahsc == NULL ) return paNoError;

    (void) abort;

    mRefNum = pahsc->pahsc_InputRefNum;

    DBUG(("PaHost_StopInput: mRefNum = %d\n", mRefNum ));
    if( mRefNum )
    {
        DBUG(("PaHost_StopInput: pahsc_IsRecording = %d\n", pahsc->pahsc_IsRecording ));
        if( pahsc->pahsc_IsRecording )
        {
            /* PLB20010420 - Fix TIMEOUT in record mode. */
            pahsc->pahsc_StopRecording = 1; /* Request that we stop recording. */
            err = SPBStopRecording(mRefNum);
            DBUG(("PaHost_StopInput: then pahsc_IsRecording = %d\n", pahsc->pahsc_IsRecording ));

            /* Calculate timeOut longer than longest time it could take to play one buffer. */
            timeOutMsec = (int32) ((1500.0 * pahsc->pahsc_FramesPerHostBuffer) / past->past_SampleRate);
            /* Keep querying sound channel until it is no longer busy playing. */
            while( !err && pahsc->pahsc_IsRecording && (timeOutMsec > 0))
            {
                Pa_Sleep(20);
                timeOutMsec -= 20;
            }
            if( timeOutMsec <= 0 )
            {
                ERR_RPT(("PaHost_StopInput: timed out!\n"));
                return paTimedOut;
            }
        }
    }
    if( err )
    {
        sPaHostError = err;
        result = paHostError;
    }

    DBUG(("PaHost_StopInput: finished.\n", mRefNum ));
    return result;
}

/***********************************************************************/
static void PaMac_InitSoundHeader( internalPortAudioStream   *past, CmpSoundHeader *sndHeader )
{
    sndHeader->numChannels = past->past_NumOutputChannels;
    sndHeader->sampleRate = DoubleToUnsignedFixed(past->past_SampleRate);
    sndHeader->loopStart = 0;
    sndHeader->loopEnd = 0;
    sndHeader->encode = cmpSH;
    sndHeader->baseFrequency = kMiddleC;
    sndHeader->markerChunk = nil;
    sndHeader->futureUse2 = nil;
    sndHeader->stateVars = nil;
    sndHeader->leftOverSamples = nil;
    sndHeader->compressionID = 0;
    sndHeader->packetSize = 0;
    sndHeader->snthID = 0;
    sndHeader->sampleSize = 8 * sizeof(int16); // FIXME - might be 24 or 32 bits some day;
    sndHeader->sampleArea[0] = 0;
    sndHeader->format = kSoundNotCompressed;
}

static void SetFramesDone( PaHostSoundControl *pahsc, PaTimestamp framesDone )
{
	UnsignedWide     now;
 	Microseconds( &now );
 	pahsc->pahsc_NumFramesDone = framesDone;
 	pahsc->pahsc_WhenFramesDoneIncremented = UnsignedWideToUInt64( now );
}

/***********************************************************************/
PaError PaHost_StartOutput( internalPortAudioStream   *past )
{
    SndCommand  pauseCommand;
    SndCommand  resumeCommand;
    int          i;
    OSErr         error;
    PaHostSoundControl *pahsc = (PaHostSoundControl *) past->past_DeviceData;
    if( pahsc == NULL ) return paInternalError;
    if( pahsc->pahsc_Channel == NULL ) return paInternalError;

    past->past_StopSoon = 0;
    past->past_IsActive = 1;
    pahsc->pahsc_NumOutsQueued = 0;
    pahsc->pahsc_NumOutsPlayed = 0;
    
    SetFramesDone( pahsc, 0.0 );

    /* Pause channel so it does not do back ground processing while we are still filling the queue. */
    pauseCommand.cmd = pauseCmd;
    pauseCommand.param1 = pauseCommand.param2 = 0;
    error = SndDoCommand (pahsc->pahsc_Channel, &pauseCommand, true);
    if (noErr != error) goto exit;

    /* Queue all of the buffers so we start off full. */
    for (i = 0; i<pahsc->pahsc_NumHostBuffers; i++)
    {
        PaMac_PlayNext( past, i );
    }
    
    /* Resume channel now that the queue is full. */
    resumeCommand.cmd = resumeCmd;
    resumeCommand.param1 = resumeCommand.param2 = 0;
    error = SndDoImmediate( pahsc->pahsc_Channel, &resumeCommand );
    if (noErr != error) goto exit;

    return paNoError;
exit:
    past->past_IsActive = 0;
    sPaHostError = error;
    ERR_RPT(("Error in PaHost_StartOutput: SndDoCommand returned %d\n", error ));
    return paHostError;
}

/*******************************************************************/
long PaHost_GetTotalBufferFrames( internalPortAudioStream   *past )
{
    PaHostSoundControl *pahsc = (PaHostSoundControl *) past->past_DeviceData;
    return (long) (pahsc->pahsc_NumHostBuffers * pahsc->pahsc_FramesPerHostBuffer);
}

/***********************************************************************
** Called by Pa_StopStream().
** May be called during error recovery or cleanup code
** so protect against NULL pointers.
*/
PaError PaHost_StopOutput( internalPortAudioStream   *past, int abort )
{
    int32 timeOutMsec;
    PaHostSoundControl *pahsc = (PaHostSoundControl *) past->past_DeviceData;
    if( pahsc == NULL ) return paNoError;
    if( pahsc->pahsc_Channel == NULL ) return paNoError;

    DBUG(("PaHost_StopOutput()\n"));
    if( past->past_IsActive == 0 ) return paNoError;

    /* Set flags for callback function to see. */
    if( abort ) past->past_StopNow = 1;
    past->past_StopSoon = 1;
    /* Calculate timeOut longer than longest time it could take to play all buffers. */
    timeOutMsec = (int32) ((1500.0 * PaHost_GetTotalBufferFrames( past )) / past->past_SampleRate);
    /* Keep querying sound channel until it is no longer busy playing. */
    while( past->past_IsActive && (timeOutMsec > 0))
    {
        Pa_Sleep(20);
        timeOutMsec -= 20;
    }
    if( timeOutMsec <= 0 )
    {
        ERR_RPT(("PaHost_StopOutput: timed out!\n"));
        return paTimedOut;
    }
    else return paNoError;
}

/***********************************************************************/
PaError PaHost_StartEngine( internalPortAudioStream   *past )
{
    (void) past; /* Prevent unused variable warnings. */
    return paNoError;
}

/***********************************************************************/
PaError PaHost_StopEngine( internalPortAudioStream   *past, int abort )
{
    (void) past; /* Prevent unused variable warnings. */
    (void) abort; /* Prevent unused variable warnings. */
    return paNoError;
}
/***********************************************************************/
PaError PaHost_StreamActive( internalPortAudioStream   *past )
{
    PaHostSoundControl *pahsc = (PaHostSoundControl *) past->past_DeviceData;
    return (PaError) ( past->past_IsActive + pahsc->pahsc_IsRecording );
}
int Mac_IsVirtualMemoryOn( void )
{
    long  attr;
    OSErr result = Gestalt( gestaltVMAttr, &attr );
    DBUG(("gestaltVMAttr : 0x%x\n", attr ));
    return ((attr >> gestaltVMHasPagingControl ) & 1);
}

/*******************************************************************
* Determine number of host Buffers
* and how many User Buffers we can put into each host buffer.
*/
static void PaHost_CalcNumHostBuffers( internalPortAudioStream *past )
{
    PaHostSoundControl *pahsc = (PaHostSoundControl *) past->past_DeviceData;
    int32  minNumBuffers;
    int32  minFramesPerHostBuffer;
    int32  minTotalFrames;
    int32  userBuffersPerHostBuffer;

⌨️ 快捷键说明

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