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

📄 pa_mac.c

📁 Audacity是一款用於錄音和編輯聲音的、免費的開放源碼軟體。它可以執行於Mac OS X、Microsoft Windows、GNU/Linux和其它作業系統
💻 C
📖 第 1 页 / 共 5 页
字号:
        return NULL;    }#endif    return addr;}/************************************************************************* * Free memory that could be accessed in real-time. * This call MUST be balanced with a call to PaHost_AllocateFastMemory(). */void PaHost_FreeFastMemory( void *addr, long numBytes ){    if( addr == NULL ) return;#if TARGET_API_MAC_CARBON    (void) numBytes;#else    UnholdMemory( addr, numBytes );#endif    DisposePtr( (Ptr) addr );}/*************************************************************************/PaTimestamp Pa_StreamTime( PortAudioStream *stream ){	PaTimestamp   framesDone1;	PaTimestamp   framesDone2;	UInt64        whenIncremented;	UnsignedWide  now;	UInt64        now64;	long          microsElapsed;	long          framesElapsed;	    PaHostSoundControl *pahsc;    internalPortAudioStream   *past = (internalPortAudioStream *) stream;    if( past == NULL ) return paBadStreamPtr;    pahsc = (PaHostSoundControl *) past->past_DeviceData;    /* Capture information from audio thread. * We have to be careful that we don't get interrupted in the middle. * So we grab the pahsc_NumFramesDone twice and make sure it didn't change. */ 	do 	{ 		framesDone1 = pahsc->pahsc_NumFramesDone; 		whenIncremented = pahsc->pahsc_WhenFramesDoneIncremented; 		framesDone2 = pahsc->pahsc_NumFramesDone; 	} while( framesDone1 != framesDone2 ); 	 /* Calculate how many microseconds have elapsed and convert to frames. */ 	Microseconds( &now ); 	now64 = UnsignedWideToUInt64( now ); 	microsElapsed = U64Subtract( now64, whenIncremented ); 	framesElapsed = microsElapsed * past->past_SampleRate * 0.000001; 		return framesDone1 + framesElapsed;}/**************************************************************************** Callback for Input, SPBRecord()*/int gRecordCounter = 0;int gPlayCounter = 0;pascal void PaMac_InputCompletionProc(SPBPtr recParams){    PaError                    result = paNoError;    int                        finished = 1;    internalPortAudioStream   *past;    PaHostSoundControl        *pahsc;    gRecordCounter += 1; /* debug hack to see if engine running */    /* Get our PA data from Mac structure. */    past = (internalPortAudioStream *) recParams->userLong;    if( past == NULL ) return;    if( past->past_Magic != PA_MAGIC )    {        AddTraceMessage("PaMac_InputCompletionProc: bad MAGIC, past", (long) past );        AddTraceMessage("PaMac_InputCompletionProc: bad MAGIC, magic", (long) past->past_Magic );        goto error;    }    pahsc = (PaHostSoundControl *) past->past_DeviceData;    past->past_NumCallbacks += 1;    /* Have we been asked to stop recording? */    if( (recParams->error == abortErr) || pahsc->pahsc_StopRecording ) goto error;    /* If there are no output channels, then we need to call the user callback function from here.     * Otherwise we will call the user code during the output completion routine.     */    if(past->past_NumOutputChannels == 0)    {		SetFramesDone( pahsc,			pahsc->pahsc_NumFramesDone + pahsc->pahsc_FramesPerHostBuffer );        result = PaMac_CallUserLoop( past, NULL );    }    /* Did user code ask us to stop? If not, issue another recording request. */    if( (result == paNoError) && (pahsc->pahsc_StopRecording == 0) )    {        result = PaMac_RecordNext( past );        if( result != paNoError ) pahsc->pahsc_IsRecording = 0;    }    else goto error;    return;error:    pahsc->pahsc_IsRecording = 0;    pahsc->pahsc_StopRecording = 0;    return;}/************************************************************************* Called by either input or output completion proc.** Grabs input data if any present, and calls PA conversion code,** that in turn calls user code.*/static PaError PaMac_CallUserLoop( internalPortAudioStream   *past, int16 *outPtr ){    PaError             result = paNoError;    PaHostSoundControl *pahsc = (PaHostSoundControl *) past->past_DeviceData;    int16              *inPtr = NULL;    int                 i;        /* Advance read index for sound input FIFO here, independantly of record/write process. */    if(past->past_NumInputChannels > 0)    {        if( MultiBuffer_IsReadable( &pahsc->pahsc_InputMultiBuffer ) )        {            inPtr = (int16 *)  MultiBuffer_GetNextReadBuffer( &pahsc->pahsc_InputMultiBuffer );            MultiBuffer_AdvanceReadIndex( &pahsc->pahsc_InputMultiBuffer );        }    }    /* Call user code enough times to fill buffer. */    if( (inPtr != NULL) || (outPtr != NULL) )    {        PaMac_StartLoadCalculation( past ); /* CPU usage */#ifdef PA_MAX_USAGE_ALLOWED	/* If CPU usage exceeds limit, skip user callback to prevent hanging CPU. */		if( past->past_Usage > PA_MAX_USAGE_ALLOWED )	    {	    	past->past_FrameCount += (PaTimestamp) pahsc->pahsc_FramesPerHostBuffer;		}		else#endif		{			        for( i=0; i<pahsc->pahsc_UserBuffersPerHostBuffer; i++ )	        {	            result = (PaError) Pa_CallConvertInt16( past, inPtr, outPtr );	            if( result != 0)	            {	                /* Recording might be in another process, so tell it to stop with a flag. */	                pahsc->pahsc_StopRecording = pahsc->pahsc_IsRecording;	                break;	            }	            /* Advance sample pointers. */	            if(inPtr != NULL) inPtr += past->past_FramesPerUserBuffer * past->past_NumInputChannels;	            if(outPtr != NULL) outPtr += past->past_FramesPerUserBuffer * past->past_NumOutputChannels;	        }	    }		        PaMac_EndLoadCalculation( past );    }    return result;}/************************************************************************* Setup next recording buffer in FIFO and issue recording request to Snd Input Manager.*/static PaError PaMac_RecordNext( internalPortAudioStream   *past ){    PaError  result = paNoError;    OSErr     err;    PaHostSoundControl *pahsc = (PaHostSoundControl *) past->past_DeviceData;    /* Get pointer to next buffer to record into. */    pahsc->pahsc_InputParams.bufferPtr  = MultiBuffer_GetNextWriteBuffer( &pahsc->pahsc_InputMultiBuffer );    /* Advance write index if there is room. Otherwise keep writing same buffer. */    if( MultiBuffer_IsWriteable( &pahsc->pahsc_InputMultiBuffer ) )    {        MultiBuffer_AdvanceWriteIndex( &pahsc->pahsc_InputMultiBuffer );    }    AddTraceMessage("PaMac_RecordNext: bufferPtr", (long) pahsc->pahsc_InputParams.bufferPtr );    AddTraceMessage("PaMac_RecordNext: nextWrite", pahsc->pahsc_InputMultiBuffer.nextWrite );    /* Setup parameters and issue an asynchronous recording request. */    pahsc->pahsc_InputParams.bufferLength      = pahsc->pahsc_BytesPerInputHostBuffer;    pahsc->pahsc_InputParams.count             = pahsc->pahsc_BytesPerInputHostBuffer;    err = SPBRecord(&pahsc->pahsc_InputParams, true);    if( err )    {        AddTraceMessage("PaMac_RecordNext: SPBRecord error ", err );        sPaHostError = err;        result = paHostError;    }    else    {        pahsc->pahsc_IsRecording = 1;    }    return result;}/**************************************************************************** Callback for Output Playback()** Return negative error, 0 to continue, 1 to stop.*/long    PaMac_FillNextOutputBuffer( internalPortAudioStream   *past, int index ){    PaHostSoundControl  *pahsc;    long                 result = 0;    int                  finished = 1;    char                *outPtr;    gPlayCounter += 1; /* debug hack */    past->past_NumCallbacks += 1;    pahsc = (PaHostSoundControl *) past->past_DeviceData;    if( pahsc == NULL ) return -1;    /* Are we nested?! */    if( pahsc->pahsc_IfInsideCallback ) return 0;    pahsc->pahsc_IfInsideCallback = 1;    /* Get pointer to buffer to fill. */    outPtr = pahsc->pahsc_SoundHeaders[index].samplePtr;    /* Combine with any sound input, and call user callback. */    result = PaMac_CallUserLoop( past, (int16 *) outPtr );    pahsc->pahsc_IfInsideCallback = 0;    return result;}/*************************************************************************************** Called by SoundManager when ready for another buffer.*/static pascal void PaMac_OutputCompletionProc (SndChannelPtr theChannel, SndCommand * theCallBackCmd){    internalPortAudioStream *past;    PaHostSoundControl      *pahsc;    (void) theChannel;    (void) theCallBackCmd;    /* Get our data from Mac structure. */    past = (internalPortAudioStream *) theCallBackCmd->param2;    if( past == NULL ) return;    pahsc = (PaHostSoundControl *) past->past_DeviceData;    pahsc->pahsc_NumOutsPlayed += 1;	SetFramesDone( pahsc,			pahsc->pahsc_NumFramesDone + pahsc->pahsc_FramesPerHostBuffer );			    PaMac_BackgroundManager( past, theCallBackCmd->param1 );}/*******************************************************************/static PaError PaMac_BackgroundManager( internalPortAudioStream   *past, int index ){    PaError      result = paNoError;    PaHostSoundControl *pahsc = (PaHostSoundControl *) past->past_DeviceData;    /* Has someone asked us to abort by calling Pa_AbortStream()? */    if( past->past_StopNow )    {        SndCommand  command;        /* Clear the queue of any pending commands. */        command.cmd = flushCmd;        command.param1 = command.param2 = 0;        SndDoImmediate( pahsc->pahsc_Channel, &command );        /* Then stop currently playing buffer, if any. */        command.cmd = quietCmd;        SndDoImmediate( pahsc->pahsc_Channel, &command );        past->past_IsActive = 0;    }    /* Has someone asked us to stop by calling Pa_StopStream()     * OR has a user callback returned '1' to indicate finished.     */    else if( past->past_StopSoon )    {        if( (pahsc->pahsc_NumOutsQueued - pahsc->pahsc_NumOutsPlayed) <= 0 )        {            past->past_IsActive = 0; /* We're finally done. */        }    }    else    {        PaMac_PlayNext( past, index );    }    return result;}/*************************************************************************************** Fill next buffer with sound and queue it for playback.*/static void PaMac_PlayNext ( internalPortAudioStream *past, int index ){    OSErr                  error;    long                     result;    SndCommand               playCmd;    SndCommand           callbackCmd;    PaHostSoundControl      *pahsc = (PaHostSoundControl *) past->past_DeviceData;    /* If this was the last buffer, or abort requested, then just be done. */    if ( past->past_StopSoon ) goto done;        /* Load buffer with sound. */    result = PaMac_FillNextOutputBuffer ( past, index );    if( result > 0 ) past->past_StopSoon = 1; /* Stop generating audio but wait until buffers play. */    else if( result < 0 ) goto done;        /* Play the next buffer. */    playCmd.cmd = bufferCmd;    playCmd.param1 = 0;    playCmd.param2 = (long) &pahsc->pahsc_SoundHeaders[ index ];    error = SndDoCommand (pahsc->pahsc_Channel, &playCmd, true );    if( error != noErr ) goto gotError;        /* Ask for a callback when it is done. */    callbackCmd.cmd = callBackCmd;    callbackCmd.param1 = index;    callbackCmd.param2 = (long)past;    error = SndDoCommand (pahsc->pahsc_Channel, &callbackCmd, true );    if( error != noErr ) goto gotError;    pahsc->pahsc_NumOutsQueued += 1;    return;gotError:    sPaHostError = error;done:    return;}

⌨️ 快捷键说明

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