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

📄 pa_mac.c

📁 Audacity是一款用於錄音和編輯聲音的、免費的開放源碼軟體。它可以執行於Mac OS X、Microsoft Windows、GNU/Linux和其它作業系統
💻 C
📖 第 1 页 / 共 5 页
字号:
    int32  framesPerHostBuffer;    int32  numHostBuffers;        minFramesPerHostBuffer = pahsc->pahsc_MinFramesPerHostBuffer;    minFramesPerHostBuffer = (minFramesPerHostBuffer + 7) & ~7;    DBUG(("PaHost_CalcNumHostBuffers: minFramesPerHostBuffer = %d\n", minFramesPerHostBuffer ));        /* Determine number of user buffers based on minimum latency. */	/* PLB20020417 I used to call Pa_GetMinNumBuffers() which doesn't take into account the	**    variable minFramesPerHostBuffer. Now I call PaMac_GetMinNumBuffers() which will	**    gove lower latency when virtual memory is turned off. */    /* minNumBuffers = Pa_GetMinNumBuffers( past->past_FramesPerUserBuffer, past->past_SampleRate ); WRONG */    minNumBuffers = PaMac_GetMinNumBuffers( minFramesPerHostBuffer, past->past_FramesPerUserBuffer, past->past_SampleRate );        past->past_NumUserBuffers = ( minNumBuffers > past->past_NumUserBuffers ) ? minNumBuffers : past->past_NumUserBuffers;    DBUG(("PaHost_CalcNumHostBuffers: min past_NumUserBuffers = %d\n", past->past_NumUserBuffers ));    minTotalFrames = past->past_NumUserBuffers * past->past_FramesPerUserBuffer;        /* We cannot make the buffers too small because they may not get serviced quickly enough. */    if( (int32) past->past_FramesPerUserBuffer < minFramesPerHostBuffer )    {        userBuffersPerHostBuffer =            (minFramesPerHostBuffer + past->past_FramesPerUserBuffer - 1) /            past->past_FramesPerUserBuffer;    }    else    {        userBuffersPerHostBuffer = 1;    }    framesPerHostBuffer = past->past_FramesPerUserBuffer * userBuffersPerHostBuffer;        /* Calculate number of host buffers needed. Round up to cover minTotalFrames. */    numHostBuffers = (minTotalFrames + framesPerHostBuffer - 1) / framesPerHostBuffer;    /* Make sure we have enough host buffers. */    if( numHostBuffers < PA_MIN_NUM_HOST_BUFFERS)    {        numHostBuffers = PA_MIN_NUM_HOST_BUFFERS;    }    else    {        /* If we have too many host buffers, try to put more user buffers in a host buffer. */        while(numHostBuffers > PA_MAX_NUM_HOST_BUFFERS)        {            userBuffersPerHostBuffer += 1;            framesPerHostBuffer = past->past_FramesPerUserBuffer * userBuffersPerHostBuffer;            numHostBuffers = (minTotalFrames + framesPerHostBuffer - 1) / framesPerHostBuffer;        }    }    pahsc->pahsc_UserBuffersPerHostBuffer = userBuffersPerHostBuffer;    pahsc->pahsc_FramesPerHostBuffer = framesPerHostBuffer;    pahsc->pahsc_NumHostBuffers = numHostBuffers;    DBUG(("PaHost_CalcNumHostBuffers: pahsc_UserBuffersPerHostBuffer = %d\n", pahsc->pahsc_UserBuffersPerHostBuffer ));    DBUG(("PaHost_CalcNumHostBuffers: pahsc_NumHostBuffers = %d\n", pahsc->pahsc_NumHostBuffers ));    DBUG(("PaHost_CalcNumHostBuffers: pahsc_FramesPerHostBuffer = %d\n", pahsc->pahsc_FramesPerHostBuffer ));    DBUG(("PaHost_CalcNumHostBuffers: past_NumUserBuffers = %d\n", past->past_NumUserBuffers ));}/*******************************************************************/PaError PaHost_OpenStream( internalPortAudioStream   *past ){    OSErr             err;    PaError             result = paHostError;    PaHostSoundControl *pahsc;    int                 i;    /* Allocate and initialize host data. */    pahsc = (PaHostSoundControl *) PaHost_AllocateFastMemory(sizeof(PaHostSoundControl));    if( pahsc == NULL )    {        return paInsufficientMemory;    }    past->past_DeviceData = (void *) pahsc;    /* If recording, and virtual memory is turned on, then use bigger buffers to prevent glitches. */    if( (past->past_NumInputChannels > 0)  && Mac_IsVirtualMemoryOn() )    {        pahsc->pahsc_MinFramesPerHostBuffer = MAC_VIRTUAL_FRAMES_PER_BUFFER;    }    else    {        pahsc->pahsc_MinFramesPerHostBuffer = MAC_PHYSICAL_FRAMES_PER_BUFFER;    }    PaHost_CalcNumHostBuffers( past );        /* Setup constants for CPU load measurement. */    pahsc->pahsc_InverseMicrosPerHostBuffer = past->past_SampleRate / (1000000.0 * 	pahsc->pahsc_FramesPerHostBuffer);    /* ------------------ OUTPUT */    if( past->past_NumOutputChannels > 0 )    {        /* Create sound channel to which we can send commands. */        pahsc->pahsc_Channel = 0L;        err = SndNewChannel(&pahsc->pahsc_Channel, sampledSynth, 0, nil); /* FIXME - use kUseOptionalOutputDevice if not default. */        if(err != 0)        {            ERR_RPT(("Error in PaHost_OpenStream: SndNewChannel returned 0x%x\n", err ));            goto error;        }        /* Install our callback function pointer straight into the sound channel structure */        /* Use new CARBON name for callback procedure. */#if TARGET_API_MAC_CARBON        pahsc->pahsc_OutputCompletionProc = NewSndCallBackUPP(PaMac_OutputCompletionProc);#else        pahsc->pahsc_OutputCompletionProc = NewSndCallBackProc(PaMac_OutputCompletionProc);#endif        pahsc->pahsc_Channel->callBack = pahsc->pahsc_OutputCompletionProc;        pahsc->pahsc_BytesPerOutputHostBuffer = pahsc->pahsc_FramesPerHostBuffer * past->past_NumOutputChannels * sizeof(int16);        for (i = 0; i<pahsc->pahsc_NumHostBuffers; i++)        {            char *buf = (char *)PaHost_AllocateFastMemory(pahsc->pahsc_BytesPerOutputHostBuffer);            if (buf == NULL)            {                ERR_RPT(("Error in PaHost_OpenStream: could not allocate output buffer. Size = \n", pahsc->pahsc_BytesPerOutputHostBuffer ));                goto memerror;            }            PaMac_InitSoundHeader( past, &pahsc->pahsc_SoundHeaders[i] );            pahsc->pahsc_SoundHeaders[i].samplePtr = buf;            pahsc->pahsc_SoundHeaders[i].numFrames = (unsigned long) pahsc->pahsc_FramesPerHostBuffer;        }    }#ifdef SUPPORT_AUDIO_CAPTURE    /* ------------------ INPUT */    /* Use double buffer scheme that matches output. */    if( past->past_NumInputChannels > 0 )    {        int16   tempS;        long    tempL;        Fixed   tempF;        long    mRefNum;        Str255 namePString;#if TARGET_API_MAC_CARBON        pahsc->pahsc_InputCompletionProc = NewSICompletionUPP((SICompletionProcPtr)PaMac_InputCompletionProc);#else        pahsc->pahsc_InputCompletionProc = NewSICompletionProc((ProcPtr)PaMac_InputCompletionProc);#endif        pahsc->pahsc_BytesPerInputHostBuffer = pahsc->pahsc_FramesPerHostBuffer * past->past_NumInputChannels * sizeof(int16);        for (i = 0; i<pahsc->pahsc_NumHostBuffers; i++)        {            char *buf = (char *) PaHost_AllocateFastMemory(pahsc->pahsc_BytesPerInputHostBuffer);            if ( buf == NULL )            {                ERR_RPT(("PaHost_OpenStream: could not allocate input  buffer. Size = \n", pahsc->pahsc_BytesPerInputHostBuffer ));                goto memerror;            }            pahsc->pahsc_InputMultiBuffer.buffers[i] = buf;        }        pahsc->pahsc_InputMultiBuffer.numBuffers = pahsc->pahsc_NumHostBuffers;        // err = SPBOpenDevice( (const unsigned char *) &noname, siWritePermission, &mRefNum);        CToPString((char *)sDevices[past->past_InputDeviceID].pad_Info.name, namePString);        err = SPBOpenDevice(namePString, siWritePermission, &mRefNum);        if (err) goto error;        pahsc->pahsc_InputRefNum = mRefNum;        DBUG(("PaHost_OpenStream: mRefNum = %d\n", mRefNum ));        /* Set input device characteristics. */        tempS = 1;        err = SPBSetDeviceInfo(mRefNum, siContinuous, (Ptr) &tempS);        if (err)        {            ERR_RPT(("Error in PaHost_OpenStream: SPBSetDeviceInfo siContinuous returned %d\n", err ));            goto error;        }        tempL = 0x03;        err = SPBSetDeviceInfo(mRefNum, siActiveChannels, (Ptr) &tempL);        if (err)        {            DBUG(("PaHost_OpenStream: setting siActiveChannels returned 0x%x. Error ignored.\n", err ));        }        /* PLB20010908 - Use requested number of input channels. Thanks Dominic Mazzoni. */        tempS = past->past_NumInputChannels;        err = SPBSetDeviceInfo(mRefNum, siNumberChannels, (Ptr) &tempS);        if (err)        {            ERR_RPT(("Error in PaHost_OpenStream: SPBSetDeviceInfo siNumberChannels returned %d\n", err ));            goto error;        }        tempF = ((unsigned long)past->past_SampleRate) << 16;        err = SPBSetDeviceInfo(mRefNum, siSampleRate, (Ptr) &tempF);        if (err)        {            ERR_RPT(("Error in PaHost_OpenStream: SPBSetDeviceInfo siSampleRate returned %d\n", err ));            goto error;        }        /* Setup record-parameter block */        pahsc->pahsc_InputParams.inRefNum          = mRefNum;        pahsc->pahsc_InputParams.milliseconds      = 0;   // not used        pahsc->pahsc_InputParams.completionRoutine = pahsc->pahsc_InputCompletionProc;        pahsc->pahsc_InputParams.interruptRoutine  = 0;        pahsc->pahsc_InputParams.userLong          = (long) past;        pahsc->pahsc_InputParams.unused1           = 0;    }#endif /* SUPPORT_AUDIO_CAPTURE */    DBUG(("PaHost_OpenStream: complete.\n"));    return paNoError;error:    PaHost_CloseStream( past );    ERR_RPT(("PaHost_OpenStream: sPaHostError =  0x%x.\n", err ));    sPaHostError = err;    return paHostError;memerror:    PaHost_CloseStream( past );    return paInsufficientMemory;}/************************************************************************* Called by Pa_CloseStream().** May be called during error recovery or cleanup code** so protect against NULL pointers.*/PaError PaHost_CloseStream( internalPortAudioStream   *past ){    PaError result = paNoError;    OSErr   err = 0;    int     i;    PaHostSoundControl *pahsc;    DBUG(("PaHost_CloseStream( 0x%x )\n", past ));    if( past == NULL ) return paBadStreamPtr;    pahsc = (PaHostSoundControl *) past->past_DeviceData;    if( pahsc == NULL ) return paNoError;    if( past->past_NumOutputChannels > 0 )    {        /* TRUE means flush now instead of waiting for quietCmd to be processed. */        if( pahsc->pahsc_Channel != NULL ) SndDisposeChannel(pahsc->pahsc_Channel, TRUE);        {            for (i = 0; i<pahsc->pahsc_NumHostBuffers; i++)            {                Ptr p = (Ptr) pahsc->pahsc_SoundHeaders[i].samplePtr;                if( p != NULL ) PaHost_FreeFastMemory( p, pahsc->pahsc_BytesPerOutputHostBuffer );            }        }    }    if( past->past_NumInputChannels > 0 )    {        if( pahsc->pahsc_InputRefNum )        {            err = SPBCloseDevice(pahsc->pahsc_InputRefNum);            pahsc->pahsc_InputRefNum = 0;            if( err )            {                sPaHostError = err;                result = paHostError;            }        }        {            for (i = 0; i<pahsc->pahsc_InputMultiBuffer.numBuffers; i++)            {                Ptr p = (Ptr) pahsc->pahsc_InputMultiBuffer.buffers[i];                if( p != NULL ) PaHost_FreeFastMemory( p, pahsc->pahsc_BytesPerInputHostBuffer );            }        }    }    past->past_DeviceData = NULL;    PaHost_FreeFastMemory( pahsc, sizeof(PaHostSoundControl) );    DBUG(("PaHost_CloseStream: complete.\n", past ));    return result;}/*************************************************************************/int Pa_GetMinNumBuffers( int framesPerUserBuffer, double sampleRate ){/* We use the MAC_VIRTUAL_FRAMES_PER_BUFFER because we might be recording.** This routine doesn't have enough information to determine the best value** and is being depracated. */    return PaMac_GetMinNumBuffers( MAC_VIRTUAL_FRAMES_PER_BUFFER, framesPerUserBuffer, sampleRate );}/*************************************************************************/static int PaMac_GetMinNumBuffers( int minFramesPerHostBuffer, int framesPerUserBuffer, double sampleRate ){    int minUserPerHost = ( minFramesPerHostBuffer + framesPerUserBuffer - 1) / framesPerUserBuffer;    int numBufs = PA_MIN_NUM_HOST_BUFFERS * minUserPerHost;    if( numBufs < PA_MIN_NUM_HOST_BUFFERS ) numBufs = PA_MIN_NUM_HOST_BUFFERS;    (void) sampleRate;    return numBufs;}/*************************************************************************/void Pa_Sleep( int32 msec ){    EventRecord   event;    int32 sleepTime, endTime;    /* Convert to ticks. Round up so we sleep a MINIMUM of msec time. */    sleepTime = ((msec * 60) + 999) / 1000;    if( sleepTime < 1 ) sleepTime = 1;    endTime = TickCount() + sleepTime;    do    {        DBUGX(("Sleep for %d ticks.\n", sleepTime ));        /* Use WaitNextEvent() to sleep without getting events. */        /* PLB20010907 - Pass unused event to WaitNextEvent instead of NULL to prevent         * Mac OSX crash. Thanks Dominic Mazzoni. */        WaitNextEvent( 0, &event, sleepTime, NULL );        sleepTime = endTime - TickCount();    }    while( sleepTime > 0 );}/*************************************************************************/int32 Pa_GetHostError( void ){    int32 err = sPaHostError;    sPaHostError = 0;    return err;}/************************************************************************* * Allocate memory that can be accessed in real-time. * This may need to be held in physical memory so that it is not * paged to virtual memory. * This call MUST be balanced with a call to PaHost_FreeFastMemory(). */void *PaHost_AllocateFastMemory( long numBytes ){    void *addr = NewPtrClear( numBytes );    if( (addr == NULL) || (MemError () != 0) ) return NULL;#if (TARGET_API_MAC_CARBON == 0)    if( HoldMemory( addr, numBytes ) != noErr )    {        DisposePtr( (Ptr) addr );

⌨️ 快捷键说明

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