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

📄 pa_mac_core.c

📁 Audacity是一款用於錄音和編輯聲音的、免費的開放源碼軟體。它可以執行於Mac OS X、Microsoft Windows、GNU/Linux和其它作業系統
💻 C
📖 第 1 页 / 共 3 页
字号:
static int PaHost_ScanDevices( Boolean isInput ){    int coreDeviceIndex;    int result;    PaHostDeviceInfo  *hostDeviceInfo;    int numAdded = 0;    for(  coreDeviceIndex=0; coreDeviceIndex<sNumCoreDevices; coreDeviceIndex++ )    {        // try to fill in next PaHostDeviceInfo        hostDeviceInfo = &sDeviceInfos[sNumPaDevices];        result = PaHost_QueryDeviceInfo( hostDeviceInfo, coreDeviceIndex, isInput );        DBUG(("PaHost_ScanDevices: paDevId = %d, coreDevId = %d\n", sNumPaDevices, hostDeviceInfo->audioDeviceID ));        if( result > 0 )        {            sNumPaDevices += 1;  // bump global counter if we got one            numAdded += 1;        }        else if( result < 0 ) return result;    }    return numAdded;}/*************************************************************************** Try to fill in the device info for this device.** Return 1 if a good device that PA can use.** Return 0 if not appropriate** or return negative error.***/static int PaHost_QueryDeviceInfo( PaHostDeviceInfo *hostDeviceInfo, int coreDeviceIndex, Boolean isInput ){    OSErr   err;    int index;    UInt32  outSize;    AudioStreamBasicDescription formatDesc;    Boolean result;    AudioDeviceID    devID;    double *sampleRates = NULL; /* non-const ptr */    PaDeviceInfo *deviceInfo = &hostDeviceInfo->paInfo;    double possibleSampleRates[] = {8000.0, 11025.0, 22050.0, 44100.0, 48000.0, 88200.0, 96000.0};    int maxNumSampleRates = sizeof( possibleSampleRates ) / sizeof( double );    deviceInfo->structVersion = 1;    deviceInfo->maxInputChannels = 0;    deviceInfo->maxOutputChannels = 0;    deviceInfo->numSampleRates = -1;    devID = sCoreDeviceIDs[ coreDeviceIndex ];    hostDeviceInfo->audioDeviceID = devID;    // Figure out supported sample rates    // Make room in case device supports all rates.    sampleRates = (double*)PaHost_AllocateFastMemory( maxNumSampleRates * sizeof(double) );    if( sampleRates == NULL ) return paInsufficientMemory;    deviceInfo->sampleRates = sampleRates;    deviceInfo->numSampleRates = 0;    // Loop through the possible sampling rates and check each to see if the device supports it.    for (index = 0; index < maxNumSampleRates; index ++)    {        memset( &formatDesc, 0, sizeof(AudioStreamBasicDescription) );        formatDesc.mSampleRate = possibleSampleRates[index];        result = deviceDoesSupportFormat( devID, &formatDesc, isInput );        if (result == true)        {            deviceInfo->numSampleRates += 1;            *sampleRates = possibleSampleRates[index];            sampleRates++;        }    }    // If no sample rates supported, then not a very good device.    if( deviceInfo->numSampleRates == 0 ) goto error;    // Get data format info from the device.    outSize = sizeof(formatDesc);    err = AudioDeviceGetProperty(devID, 0, isInput, kAudioDevicePropertyStreamFormat, &outSize, &formatDesc);    // If no channels supported, then not a very good device.    if( (err != noErr) || (formatDesc.mChannelsPerFrame == 0) ) goto error;    if( isInput )    {        deviceInfo->maxInputChannels = formatDesc.mChannelsPerFrame;    }    else    {        deviceInfo->maxOutputChannels = formatDesc.mChannelsPerFrame;    }    // FIXME - where to put current sample rate?:  formatDesc.mSampleRate    // Right now the Core Audio headers only define one formatID: LinearPCM    // Apparently LinearPCM must be Float32 for now.    switch (formatDesc.mFormatID)    {    case kAudioFormatLinearPCM:        deviceInfo->nativeSampleFormats = paFloat32;        // FIXME - details about the format are in these flags.        // formatDesc.mFormatFlags        // here are the possibilities        // kLinearPCMFormatFlagIsFloat   // set for floating point, clear for integer        // kLinearPCMFormatFlagIsBigEndian  // set for big endian, clear for little        // kLinearPCMFormatFlagIsSignedInteger // set for signed integer, clear for unsigned integer,        //    only valid if kLinearPCMFormatFlagIsFloat is clear        // kLinearPCMFormatFlagIsPacked   // set if the sample bits are packed as closely together as possible,        //    clear if they are high or low aligned within the channel        // kLinearPCMFormatFlagIsAlignedHigh  // set if the sample bits are placed        break;    default:        deviceInfo->nativeSampleFormats = paFloat32;  // FIXME        break;    }    // Get the device name    deviceInfo->name = PaHost_DeviceNameFromID( devID, isInput );    return 1;error:    if( sampleRates != NULL ) free( sampleRates );    return 0;}/*************************************************************************** Returns recommended device ID.** On the PC, the recommended device can be specified by the user by** setting an environment variable. For example, to use device #1.****    set PA_RECOMMENDED_OUTPUT_DEVICE=1**** The user should first determine the available device ID by using** the supplied application "pa_devs".*/#define PA_ENV_BUF_SIZE  (32)#define PA_REC_IN_DEV_ENV_NAME  ("PA_RECOMMENDED_INPUT_DEVICE")#define PA_REC_OUT_DEV_ENV_NAME  ("PA_RECOMMENDED_OUTPUT_DEVICE")static PaDeviceID PaHost_GetEnvDefaultDeviceID( char *envName ){#if 0    UInt32   hresult;    char    envbuf[PA_ENV_BUF_SIZE];    PaDeviceID recommendedID = paNoDevice;    /* Let user determine default device by setting environment variable. */    hresult = GetEnvironmentVariable( envName, envbuf, PA_ENV_BUF_SIZE );    if( (hresult > 0) && (hresult < PA_ENV_BUF_SIZE) )    {        recommendedID = atoi( envbuf );    }    return recommendedID;#endif    return paNoDevice;}static PaError Pa_MaybeQueryDevices( void ){    if( sNumPaDevices == 0 )    {        return Pa_QueryDevices();    }    return 0;}/************************************************************************ Check for environment variable, else query devices and use result.*/PaDeviceID Pa_GetDefaultInputDeviceID( void ){    PaError result;    result = PaHost_GetEnvDefaultDeviceID( PA_REC_IN_DEV_ENV_NAME );    if( result < 0 )    {        result = Pa_MaybeQueryDevices();        if( result < 0 ) return result;        result = sDefaultInputDeviceID;    }    return result;}PaDeviceID Pa_GetDefaultOutputDeviceID( void ){    PaError result;    result = PaHost_GetEnvDefaultDeviceID( PA_REC_OUT_DEV_ENV_NAME );    if( result < 0 )    {        result = Pa_MaybeQueryDevices();        if( result < 0 ) return result;        result = sDefaultOutputDeviceID;    }    return result;}/************************************************************************ Initialize Host dependant part of API.*/PaError PaHost_Init( void ){    return Pa_MaybeQueryDevices();}/************************************************************************ Fill any available output buffers and use any available** input buffers by calling user callback.*/static PaError Pa_TimeSlice( internalPortAudioStream   *past, const AudioBufferList*  inInputData,                             AudioBufferList*  outOutputData ){    PaError           result = 0;    char             *inputNativeBufferfPtr = NULL;    char             *outputNativeBufferfPtr = NULL;    int               i;    int               buffersProcessed = 0;    int               done = 0;    PaHostSoundControl *pahsc = (PaHostSoundControl *) past->past_DeviceData;    if( pahsc == NULL ) return paInternalError;    past->past_NumCallbacks += 1;#if PA_TRACE_RUN    AddTraceMessage("Pa_TimeSlice: past_NumCallbacks ", past->past_NumCallbacks );#endif    Pa_StartUsageCalculation( past );    /* If we are using output, then we need an empty output buffer. */    if( past->past_NumOutputChannels > 0 )    {        outputNativeBufferfPtr =  (char*)outOutputData->mBuffers[0].mData;    }    /* If we are using input, then we need a full input buffer. */    if(  past->past_NumInputChannels > 0  )    {        inputNativeBufferfPtr = (char*)inInputData->mBuffers[0].mData;    }    buffersProcessed += 1;    /* Each host buffer contains multiple user buffers so do them all now. */    for( i=0; i<pahsc->pahsc_UserBuffersPerHostBuffer; i++ )    {        if( done )        {            if( outputNativeBufferfPtr )            {                /* Clear remainder of wave buffer if we are waiting for stop. */                AddTraceMessage("Pa_TimeSlice: zero rest of wave buffer ", i );                memset( outputNativeBufferfPtr, 0, pahsc->pahsc_BytesPerUserNativeOutputBuffer );            }        }        else        {            /* Convert 32 bit native data to user data and call user routine. */            result = PaConvert_Process( past, inputNativeBufferfPtr, outputNativeBufferfPtr );            if( result != 0) done = 1;        }        if( inputNativeBufferfPtr ) inputNativeBufferfPtr += pahsc->pahsc_BytesPerUserNativeInputBuffer;        if( outputNativeBufferfPtr) outputNativeBufferfPtr += pahsc->pahsc_BytesPerUserNativeOutputBuffer;    }    Pa_EndUsageCalculation( past );#if PA_TRACE_RUN    AddTraceMessage("Pa_TimeSlice: buffersProcessed ", buffersProcessed );#endif    return (result != 0) ? result : done;}OSStatus appIOProc (AudioDeviceID  inDevice, const AudioTimeStamp*  inNow,                    const AudioBufferList*  inInputData, const AudioTimeStamp*  inInputTime,                    AudioBufferList*  outOutputData, const AudioTimeStamp* inOutputTime,                    void* contextPtr){    PaError      result = 0;    internalPortAudioStream *past;    PaHostSoundControl *pahsc;    past = (internalPortAudioStream *) contextPtr;    pahsc = (PaHostSoundControl *) past->past_DeviceData;// printf("Num input Buffers: %d; Num output Buffers: %d.\n", inInputData->mNumberBuffers,	outOutputData->mNumberBuffers);    /* Has someone asked us to abort by calling Pa_AbortStream()? */    if( past->past_StopNow )    {        past->past_IsActive = 0; /* Will cause thread to return. */    }    /* 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 )    {        // FIXME - pretend all done        past->past_IsActive = 0; /* Will cause thread to return. */    }    else    {        /* use time stamp from CoreAudio if valid */        if( inOutputTime->mFlags & kAudioTimeStampSampleTimeValid)         {            past->past_FrameCount = inOutputTime->mSampleTime;        }                /* Process full input buffer and fill up empty output buffers. */        if( (result = Pa_TimeSlice( past, inInputData, outOutputData )) != 0)        {            /* User callback has asked us to stop. */#if PA_TRACE_START_STOP            AddTraceMessage( "Pa_OutputThreadProc: TimeSlice() returned ", result );#endif            past->past_StopSoon = 1; /* Request that audio play out then stop. */            result = paNoError;        }    }    // FIXME PaHost_UpdateStreamTime( pahsc );    return result;}#if 0static int PaHost_CalcTimeOut( internalPortAudioStream *past ){    /* Calculate timeOut longer than longest time it could take to play all buffers. */    int timeOut = (UInt32) (1500.0 * PaHost_GetTotalBufferFrames( past ) / past->past_SampleRate);    if( timeOut < MIN_TIMEOUT_MSEC ) timeOut = MIN_TIMEOUT_MSEC;    return timeOut;}#endif/*******************************************************************//* Attempt to set device sample rate. */static PaError PaHost_SetSampleRate( AudioDeviceID devID, Boolean isInput, double sampleRate ){    AudioStreamBasicDescription formatDesc;    OSStatus err;    memset( &formatDesc, 0, sizeof(AudioStreamBasicDescription) );    formatDesc.mSampleRate = sampleRate;    err = AudioDeviceSetProperty( devID, 0, 0,        isInput, kAudioDevicePropertyStreamFormat, sizeof(formatDesc), &formatDesc);    if (err != kAudioHardwareNoError) return paInvalidSampleRate;   	else return paNoError;}/*******************************************************************/PaError PaHost_OpenInputStream( internalPortAudioStream   *past ){    PaHostSoundControl *pahsc;    const PaHostDeviceInfo *hostDeviceInfo;    PaError          result = paNoError;    UInt32           bytesPerHostBuffer;    UInt32           dataSize;    OSStatus         err = noErr;    int              bytesPerInputFrame;    pahsc = (PaHostSoundControl *) past->past_DeviceData;        DBUG(("PaHost_OpenStream: deviceID = 0x%x\n", past->past_InputDeviceID));    if( (past->past_InputDeviceID < LOWEST_INPUT_DEVID) ||        (past->past_InputDeviceID > HIGHEST_INPUT_DEVID) )    {        return paInvalidDeviceId;    }    hostDeviceInfo = &sDeviceInfos[past->past_InputDeviceID];    /* Try to set sample rate. */    result = PaHost_SetSampleRate( hostDeviceInfo->audioDeviceID, IS_INPUT, past->past_SampleRate );	if( result != paNoError ) return result;    if( past->past_NumInputChannels != hostDeviceInfo->paInfo.maxInputChannels )    {#if 1        return paInvalidChannelCount; // FIXME - how support mono?#elseFIXME - should this be set on a stream basis? Is it possible to change?    /* Attempt to set number of channels. */         AudioStreamBasicDescription formatDesc;        OSStatus err;        memset( &formatDesc, 0, sizeof(AudioStreamBasicDescription) );        formatDesc.mChannelsPerFrame = past->past_NumInputChannels;                err = AudioDeviceSetProperty( hostDeviceInfo->audioDeviceID, 0, 0,            IS_INPUT, kAudioDevicePropertyStreamFormat, sizeof(formatDesc), &formatDesc);        if (err != kAudioHardwareNoError)        {            result = paInvalidChannelCount;            goto error;        }#endif    }    // calculate native buffer sizes in bytes    bytesPerInputFrame = Pa_GetSampleSize(paFloat32) * past->past_NumInputChannels;    pahsc->pahsc_BytesPerUserNativeInputBuffer = past->past_FramesPerUserBuffer * bytesPerInputFrame;    bytesPerHostBuffer = pahsc->pahsc_FramesPerHostBuffer * bytesPerInputFrame;    // Change the bufferSize of the device! Is this per device or just for our stream?    dataSize = sizeof(UInt32);    err = AudioDeviceSetProperty( hostDeviceInfo->audioDeviceID, 0, 0, IS_INPUT,                                  kAudioDevicePropertyBufferSize, dataSize, &bytesPerHostBuffer);    if( err != noErr )    {        ERR_RPT(("Could not force buffer size!"));        result = paHostError;        goto error;    }    // setup conversion procedure    result = PaConvert_SetupInput( past, paFloat32 );

⌨️ 快捷键说明

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