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

📄 pa_mac_core.c

📁 Audacity是一款用於錄音和編輯聲音的、免費的開放源碼軟體。它可以執行於Mac OS X、Microsoft Windows、GNU/Linux和其它作業系統
💻 C
📖 第 1 页 / 共 3 页
字号:
    return result;error:    return result;}/*******************************************************************/PaError PaHost_OpenOutputStream( internalPortAudioStream   *past ){    PaHostSoundControl *pahsc;    const PaHostDeviceInfo *hostDeviceInfo;    PaError          result = paNoError;    UInt32           bytesPerHostBuffer;    UInt32           dataSize;    OSStatus         err = noErr;    int              bytesPerOutputFrame;        pahsc = (PaHostSoundControl *) past->past_DeviceData;        DBUG(("PaHost_OpenStream: deviceID = 0x%x\n", past->past_OutputDeviceID));    if( (past->past_OutputDeviceID < LOWEST_OUTPUT_DEVID) ||        (past->past_OutputDeviceID > HIGHEST_OUTPUT_DEVID) )    {        return paInvalidDeviceId;    }    hostDeviceInfo = &sDeviceInfos[past->past_OutputDeviceID];    /* Try to set sample rate. */    result = PaHost_SetSampleRate( hostDeviceInfo->audioDeviceID, IS_OUTPUT, past->past_SampleRate );	if( result != paNoError ) return result;    if( past->past_NumOutputChannels != hostDeviceInfo->paInfo.maxOutputChannels )    {#if 1        return paInvalidChannelCount; // FIXME - how support mono?#else    /* Attempt to set number of channels. */         AudioStreamBasicDescription formatDesc;        OSStatus err;        memset( &formatDesc, 0, sizeof(AudioStreamBasicDescription) );        formatDesc.mChannelsPerFrame = past->past_NumOutputChannels;        err = AudioDeviceSetProperty( hostDeviceInfo->audioDeviceID, 0, 0,            IS_OUTPUT, kAudioDevicePropertyStreamFormat, sizeof(formatDesc), &formatDesc);        if (err != kAudioHardwareNoError)        {            result = paInvalidChannelCount;            goto error;        }#endif    }    // calculate buffer sizes in bytes    bytesPerOutputFrame = Pa_GetSampleSize(paFloat32) * past->past_NumOutputChannels;    pahsc->pahsc_BytesPerUserNativeOutputBuffer = past->past_FramesPerUserBuffer * bytesPerOutputFrame;    bytesPerHostBuffer = pahsc->pahsc_FramesPerHostBuffer * bytesPerOutputFrame;    // Change the bufferSize of the device! Is this per device or just for our stream?    dataSize = sizeof(bytesPerHostBuffer);    err = AudioDeviceSetProperty( hostDeviceInfo->audioDeviceID, 0, 0, IS_OUTPUT,                                  kAudioDevicePropertyBufferSize, dataSize, &bytesPerHostBuffer);    if( err != noErr )    {        ERR_RPT(("Could not force buffer size!"));        result = paHostError;        goto error;    }        // setup conversion procedure    result = PaConvert_SetupOutput( past, paFloat32 );        return result;error:    return result;}/*******************************************************************/PaError PaHost_GetTotalBufferFrames( internalPortAudioStream   *past ){    PaHostSoundControl *pahsc = (PaHostSoundControl *) past->past_DeviceData;    return pahsc->pahsc_FramesPerHostBuffer;}/******************************************************************** Determine how many User Buffers we can put into our CoreAudio stream buffer.* Uses:*    past->past_FramesPerUserBuffer, etc.* Sets:*    past->past_NumUserBuffers*    pahsc->pahsc_UserBuffersPerHostBuffer*    pahsc->pahsc_FramesPerHostBuffer*/static void PaHost_CalcHostBufferSize( internalPortAudioStream *past ){    PaHostSoundControl *pahsc = ( PaHostSoundControl *)past->past_DeviceData;    unsigned int  minNumUserBuffers;    // Determine number of user buffers based on minimum latency.    minNumUserBuffers = Pa_GetMinNumBuffers( past->past_FramesPerUserBuffer, past->past_SampleRate );    // Compare to user requested number in user wants more than the minimum.    past->past_NumUserBuffers = ( minNumUserBuffers > past->past_NumUserBuffers ) ?                                minNumUserBuffers : past->past_NumUserBuffers;    DBUG(("PaHost_CalcNumHostBuffers: min past_NumUserBuffers = %d\n", past->past_NumUserBuffers ));    // For CoreAudio, we only have one Host buffer, so...    pahsc->pahsc_UserBuffersPerHostBuffer = past->past_NumUserBuffers;    // Calculate size of CoreAudio buffer.    pahsc->pahsc_FramesPerHostBuffer = past->past_FramesPerUserBuffer * past->past_NumUserBuffers;    DBUG(("PaHost_CalcNumHostBuffers: pahsc_UserBuffersPerHostBuffer = %d\n", pahsc->pahsc_UserBuffersPerHostBuffer ));    DBUG(("PaHost_CalcNumHostBuffers: pahsc_FramesPerHostBuffer = %d\n", pahsc->pahsc_FramesPerHostBuffer ));}/*******************************************************************/PaError PaHost_OpenStream( internalPortAudioStream   *past ){    PaError             result = paNoError;    PaHostSoundControl *pahsc;    /* Allocate and initialize host data. */    pahsc = (PaHostSoundControl *) malloc(sizeof(PaHostSoundControl));    if( pahsc == NULL )    {        result = paInsufficientMemory;        goto error;    }    memset( pahsc, 0, sizeof(PaHostSoundControl) );    past->past_DeviceData = (void *) pahsc;    // If we are using both input and out, then they must be on the same CoreAudio device,    // until we implement a FIFO between two devices.    if( (past->past_OutputDeviceID != paNoDevice) && (past->past_InputDeviceID != paNoDevice) )    {        AudioDeviceID inputID = sDeviceInfos[past->past_InputDeviceID].audioDeviceID;        AudioDeviceID outputID = sDeviceInfos[past->past_OutputDeviceID].audioDeviceID;        if( inputID != outputID )        {            ERR_RPT(("PortAudio: input and output must use same CoreAudio device!\n"));            return paInvalidDeviceId;        }    }    PaHost_CalcHostBufferSize( past );    {        int msecLatency = (int) ((PaHost_GetTotalBufferFrames(past) * 1000) / past->past_SampleRate);        PRINT(("PortAudio on OS X - Latency = %d frames, %d msec\n", PaHost_GetTotalBufferFrames(past), msecLatency ));    }        /* Setup constants for CPU load measurement. */    pahsc->pahsc_InverseMicrosPerHostBuffer = past->past_SampleRate / (1000000.0 * 	pahsc->pahsc_FramesPerHostBuffer);    /* ------------------ OUTPUT */    if( (past->past_OutputDeviceID != paNoDevice) && (past->past_NumOutputChannels > 0) )    {        pahsc->pahsc_AudioDeviceID = sDeviceInfos[past->past_OutputDeviceID].audioDeviceID;        result = PaHost_OpenOutputStream( past );        if( result < 0 ) goto error;    }    /* ------------------ INPUT */    if( (past->past_InputDeviceID != paNoDevice) && (past->past_NumInputChannels > 0) )    {        pahsc->pahsc_AudioDeviceID = sDeviceInfos[past->past_InputDeviceID].audioDeviceID;        result = PaHost_OpenInputStream( past );        if( result < 0 ) goto error;    }    return result;error:    PaHost_CloseStream( past );    return result;}/*************************************************************************/PaError PaHost_StartOutput( internalPortAudioStream *past ){    return 0;}/*************************************************************************/PaError PaHost_StartInput( internalPortAudioStream *past ){    return 0;}/*************************************************************************/PaError PaHost_StartEngine( internalPortAudioStream *past ){    OSStatus            err = noErr;    PaError             result = paNoError;    PaHostSoundControl *pahsc = (PaHostSoundControl *) past->past_DeviceData;    past->past_StopSoon = 0;    past->past_StopNow = 0;    past->past_IsActive = 1;        // Associate an IO proc with the device and pass a pointer to the audio data context    err = AudioDeviceAddIOProc(pahsc->pahsc_AudioDeviceID, (AudioDeviceIOProc)appIOProc, past);    if (err != noErr) goto error;    // start playing sound through the device    err = AudioDeviceStart(pahsc->pahsc_AudioDeviceID, (AudioDeviceIOProc)appIOProc);    if (err != noErr) goto error;    return result;#if PA_TRACE_START_STOP    AddTraceMessage( "PaHost_StartEngine: TimeSlice() returned ", result );#endiferror:    return paHostError; // FIXME - save host error}/*************************************************************************/PaError PaHost_StopEngine( internalPortAudioStream *past, int abort ){    OSStatus  err = noErr;    PaHostSoundControl *pahsc = (PaHostSoundControl *) past->past_DeviceData;    if( pahsc == NULL ) return paNoError;    (void) abort;    /* Tell background thread to stop generating more data and to let current data play out. */    past->past_StopSoon = 1;    /* If aborting, tell background thread to stop NOW! */    if( abort ) past->past_StopNow = 1;    past->past_IsActive = 0;#if PA_TRACE_START_STOP    AddTraceMessage( "PaHost_StopOutput: pahsc_HWaveOut ", (int) pahsc->pahsc_HWaveOut );#endif    // FIXME - we should ask proc to stop instead of stopping abruptly    err = AudioDeviceStop(pahsc->pahsc_AudioDeviceID, (AudioDeviceIOProc)appIOProc);    if (err != noErr) goto Bail;    err = AudioDeviceRemoveIOProc(pahsc->pahsc_AudioDeviceID, (AudioDeviceIOProc)appIOProc);    if (err != noErr) goto Bail;    return paNoError;Bail:    return paHostError; // FIXME - save err}/*************************************************************************/PaError PaHost_StopInput( internalPortAudioStream *past, int abort ){    return paNoError;}/*************************************************************************/PaError PaHost_StopOutput( internalPortAudioStream *past, int abort ){    return paNoError;}/*******************************************************************/PaError PaHost_CloseStream( internalPortAudioStream   *past ){    PaHostSoundControl *pahsc;    if( past == NULL ) return paBadStreamPtr;    pahsc = (PaHostSoundControl *) past->past_DeviceData;    if( pahsc == NULL ) return paNoError;#if PA_TRACE_START_STOP    AddTraceMessage( "PaHost_CloseStream: pahsc_HWaveOut ", (int) pahsc->pahsc_HWaveOut );#endif    free( pahsc );    past->past_DeviceData = NULL;    return paNoError;}/*************************************************************************** Determine minimum number of buffers required for this host based** on minimum latency. Latency can be optionally set by user by setting** an environment variable. For example, to set latency to 200 msec, put:****    set PA_MIN_LATENCY_MSEC=200**** in the cshrc file.*/#define PA_LATENCY_ENV_NAME  ("PA_MIN_LATENCY_MSEC")#if 1int Pa_GetMinNumBuffers( int framesPerBuffer, double framesPerSecond ){    int minBuffers;    int denominator;    int minLatencyMsec = PA_MIN_LATENCY_MSEC;    char *minLatencyText = getenv(PA_LATENCY_ENV_NAME);    if( minLatencyText != NULL )    {        PRINT(("PA_MIN_LATENCY_MSEC = %s\n", minLatencyText ));        minLatencyMsec = atoi( minLatencyText );        if( minLatencyMsec < 1 ) minLatencyMsec = 1;        else if( minLatencyMsec > 5000 ) minLatencyMsec = 5000;    }    denominator =  1000.0 * framesPerBuffer;    minBuffers = (int) (((minLatencyMsec * framesPerSecond) + denominator - 1) / denominator );    if( minBuffers < 1 ) minBuffers = 1;    return minBuffers;}#else/*************************************************************************** Determine minimum number of buffers required for this host based** on minimum latency. */int Pa_GetMinNumBuffers( int framesPerUserBuffer, double sampleRate ){    int   minUserBuffers;    int   minFramesPerHostBuffer;    // Calculate minimum and maximum sizes based on timing and sample rate.    minFramesPerHostBuffer = (int) (PA_MIN_LATENCY_MSEC * sampleRate / 1000.0);    // round up to nearest multiple of 8    minFramesPerHostBuffer = (minFramesPerHostBuffer + 7) & ~7;    DBUG(("Pa_GetMinNumBuffers: minFramesPerHostBuffer = %d\n", minFramesPerHostBuffer ));    minUserBuffers = (minFramesPerHostBuffer + framesPerUserBuffer - 1) / framesPerUserBuffer;    if( minUserBuffers < 1 ) minUserBuffers = 1;    return minUserBuffers;}#endif/*************************************************************************** Cleanup device info.*/PaError PaHost_Term( void ){    int i;    if( sDeviceInfos != NULL )    {        for( i=0; i<sNumPaDevices; i++ )        {            if( sDeviceInfos[i].paInfo.name != NULL ) free( (char*)sDeviceInfos[i].paInfo.name );            if( sDeviceInfos[i].paInfo.sampleRates != NULL ) free( (void*)sDeviceInfos[i].paInfo.sampleRates );        }        free( sDeviceInfos );        sDeviceInfos = NULL;    }    sNumPaDevices = 0;    return paNoError;}/*************************************************************************/void Pa_Sleep( long msec ){#if 0    struct timeval timeout;    timeout.tv_sec = msec / 1000;	timeout.tv_usec = (msec % 1000) * 1000;	select( 0, NULL, NULL, NULL, &timeout );#else    usleep( msec * 1000 );#endif}/************************************************************************* * 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 = malloc( numBytes ); /* FIXME - do we need physical memory? */    if( addr != NULL ) memset( addr, 0, numBytes );    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 ) free( addr );}/***********************************************************************/PaError PaHost_StreamActive( internalPortAudioStream   *past ){    PaHostSoundControl *pahsc;    if( past == NULL ) return paBadStreamPtr;    pahsc = (PaHostSoundControl *) past->past_DeviceData;    if( pahsc == NULL ) return paInternalError;    return (PaError) past->past_IsActive;}/*************************************************************************/PaTimestamp Pa_StreamTime( PortAudioStream *stream ){    AudioTimeStamp timeStamp;    PaTimestamp streamTime;    PaHostSoundControl *pahsc;    internalPortAudioStream   *past = (internalPortAudioStream *) stream;    if( past == NULL ) return paBadStreamPtr;    pahsc = (PaHostSoundControl *) past->past_DeviceData;      AudioDeviceGetCurrentTime(pahsc->pahsc_AudioDeviceID, &timeStamp);      streamTime = ( timeStamp.mFlags & kAudioTimeStampSampleTimeValid) ?            timeStamp.mSampleTime : past->past_FrameCount;    return streamTime;}

⌨️ 快捷键说明

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