📄 pa_mac_core.c
字号:
OSStatus err = noErr; UInt32 count; int i; AudioDeviceID tempDeviceID = kAudioDeviceUnknown; PaDeviceID defaultDeviceID = paNoDevice; // get the default output device for the HAL // it is required to pass the size of the data to be returned count = sizeof(tempDeviceID); err = AudioHardwareGetProperty( kAudioHardwarePropertyDefaultInputDevice, &count, (void *) &tempDeviceID); if (err != noErr) goto error; // scan input devices to see which one matches this device defaultDeviceID = paNoDevice; for( i=LOWEST_INPUT_DEVID; i<=HIGHEST_INPUT_DEVID; i++ ) { DBUG(("PaOSX_QueryDefaultInputDevice: i = %d, aDevId = %ld\n", i, sDeviceInfos[i].audioDeviceID )); if( sDeviceInfos[i].audioDeviceID == tempDeviceID ) { defaultDeviceID = i; break; } }error: return defaultDeviceID;}/************************************************************************/static PaDeviceID PaOSX_QueryDefaultOutputDevice( void ){ OSStatus err = noErr; UInt32 count; int i; AudioDeviceID tempDeviceID = kAudioDeviceUnknown; PaDeviceID defaultDeviceID = paNoDevice; // get the default output device for the HAL // it is required to pass the size of the data to be returned count = sizeof(tempDeviceID); err = AudioHardwareGetProperty( kAudioHardwarePropertyDefaultOutputDevice, &count, (void *) &tempDeviceID); if (err != noErr) goto error; // scan output devices to see which one matches this device defaultDeviceID = paNoDevice; for( i=LOWEST_OUTPUT_DEVID; i<=HIGHEST_OUTPUT_DEVID; i++ ) { DBUG(("PaOSX_QueryDefaultOutputDevice: i = %d, aDevId = %ld\n", i, sDeviceInfos[i].audioDeviceID )); if( sDeviceInfos[i].audioDeviceID == tempDeviceID ) { defaultDeviceID = i; break; } }error: return defaultDeviceID;}/******************************************************************/static PaError PaOSX_QueryDevices( void ){ OSStatus err = noErr; UInt32 outSize; Boolean outWritable; int numBytes; // find out how many Core Audio devices there are, if any outSize = sizeof(outWritable); err = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &outSize, &outWritable); if (err != noErr) { PRINT_ERR("Couldn't get info about list of audio devices", err); sSavedHostError = err; return paHostError; } // calculate the number of device available sNumCoreDevices = outSize / sizeof(AudioDeviceID); // Bail if there aren't any devices if (sNumCoreDevices < 1) { PRINT(("No Devices Available")); return paHostError; } // make space for the devices we are about to get sCoreDeviceIDs = (AudioDeviceID *)malloc(outSize); // get an array of AudioDeviceIDs err = AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &outSize, (void *)sCoreDeviceIDs); if (err != noErr) { PRINT_ERR("Couldn't get list of audio device IDs", err); sSavedHostError = err; return paHostError; } // Allocate structures to hold device info pointers. // There will be a maximum of two Pa devices per Core Audio device, input and/or output. numBytes = sNumCoreDevices * 2 * sizeof(PaHostDeviceInfo); sDeviceInfos = (PaHostDeviceInfo *) PaHost_AllocateFastMemory( numBytes ); if( sDeviceInfos == NULL ) return paInsufficientMemory; // Scan all the Core Audio devices to see which support input and allocate a // PaHostDeviceInfo structure for each one. DBUG(("PaOSX_QueryDevices: scan for input ======================\n")); PaOSX_ScanDevices( IS_INPUT ); sNumInputDevices = sNumPaDevices; // Now scan all the output devices. DBUG(("PaOSX_QueryDevices: scan for output ======================\n")); PaOSX_ScanDevices( IS_OUTPUT ); sNumOutputDevices = sNumPaDevices - sNumInputDevices; // Figure out which of the devices that we scanned is the default device. sDefaultInputDeviceID = PaOSX_QueryDefaultInputDevice(); sDefaultOutputDeviceID = PaOSX_QueryDefaultOutputDevice(); return paNoError;}/*************************************************************************//* Query a device for its sample rate. * @return positive rate or 0.0 on error. */static Float64 PaOSX_GetDeviceSampleRate( AudioDeviceID deviceID, Boolean isInput ){ OSStatus err = noErr; AudioStreamBasicDescription formatDesc; UInt32 dataSize; dataSize = sizeof(formatDesc); err = AudioDeviceGetProperty( deviceID, 0, isInput, kAudioDevicePropertyStreamFormat, &dataSize, &formatDesc); if( err != noErr ) return 0.0; else return formatDesc.mSampleRate;}/*************************************************************************//* Allocate a string containing the device name. */static char *PaOSX_DeviceNameFromID(AudioDeviceID deviceID, Boolean isInput ){ OSStatus err = noErr; UInt32 outSize; Boolean outWritable; char *deviceName = nil; // query size of name err = AudioDeviceGetPropertyInfo(deviceID, 0, isInput, kAudioDevicePropertyDeviceName, &outSize, &outWritable); if (err == noErr) { deviceName = (char*)malloc( outSize + 1); if( deviceName ) { err = AudioDeviceGetProperty(deviceID, 0, isInput, kAudioDevicePropertyDeviceName, &outSize, deviceName); if (err != noErr) PRINT_ERR("Couldn't get audio device name", err); } } return deviceName;}/*************************************************************************** Scan all of the Core Audio devices to see which support selected** input or output mode.** Changes sNumDevices, and fills in sDeviceInfos.*/static int PaOSX_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 = PaOSX_QueryDeviceInfo( hostDeviceInfo, coreDeviceIndex, isInput ); DBUG(("PaOSX_ScanDevices: paDevId = %d, coreDevId = %d\n", sNumPaDevices, coreDeviceIndex )); 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 PaOSX_QueryDeviceInfo( PaHostDeviceInfo *hostDeviceInfo, int coreDeviceIndex, Boolean isInput ){ AudioStreamBasicDescription *allStreamFormats; AudioStreamBasicDescription formatDesc; OSStatus err; UInt32 outSize; Boolean outWritable; AudioDeviceID devID; int numStreamFormats; int maxChannels; int i; PaDeviceInfo *deviceInfo = &hostDeviceInfo->paInfo; deviceInfo->structVersion = 1; deviceInfo->maxInputChannels = 0; deviceInfo->maxOutputChannels = 0; deviceInfo->sampleRates = supportedSampleRateRange; // because we use sample rate converter to get continuous rates deviceInfo->numSampleRates = -1; devID = sCoreDeviceIDs[ coreDeviceIndex ]; hostDeviceInfo->audioDeviceID = devID; DBUG(("PaOSX_QueryDeviceInfo: name = %s\n", PaOSX_DeviceNameFromID( devID, isInput ))); DBUG(("PaOSX_QueryDeviceInfo: coreDeviceIndex = %d, devID = %d, isInput = %d\n", coreDeviceIndex, devID, isInput )); // Get data format info from the device. outSize = sizeof(formatDesc); err = AudioDeviceGetProperty(devID, 0, isInput, kAudioDevicePropertyStreamFormat, &outSize, &formatDesc); // This just may not be an appropriate device for input or output so leave quietly. if( (err != noErr) || (formatDesc.mChannelsPerFrame == 0) ) goto error; DBUG(("PaOSX_QueryDeviceInfo: mFormatID = %4s\n", &formatDesc.mFormatID)); DBUG(("PaOSX_QueryDeviceInfo: mFormatFlags = 0x%x\n", formatDesc.mFormatFlags)); DBUG(("PaOSX_QueryDeviceInfo: kLinearPCMFormatFlagIsFloat = 0x%x\n", kLinearPCMFormatFlagIsFloat)); // dmazzoni: all OS X devices support the float32 format. When we open the // device, if it isn't in this format, we will change it at that point. deviceInfo->nativeSampleFormats = paFloat32; // Determine maximum number of channels supported by looping through // all possible supported stream formats outSize = 0; err = AudioDeviceGetPropertyInfo( devID, 0, isInput, kAudioDevicePropertyStreamFormats, &outSize, &outWritable ); allStreamFormats = (AudioStreamBasicDescription *)malloc(outSize); numStreamFormats = outSize / sizeof(AudioStreamBasicDescription); err = AudioDeviceGetProperty( devID, 0, isInput, kAudioDevicePropertyStreamFormats, &outSize, allStreamFormats); DBUG(("%d supported formats!\n", numStreamFormats)); maxChannels = 0; for(i=0; i<numStreamFormats; i++) { DBUG(("Format %d: formatID=%4s flags=0x%x channels=%d rate=%.0f\n", i, &allStreamFormats[i].mFormatID, allStreamFormats[i].mFormatFlags, allStreamFormats[i].mChannelsPerFrame, allStreamFormats[i].mSampleRate)); if (allStreamFormats[i].mChannelsPerFrame > maxChannels) maxChannels = allStreamFormats[i].mChannelsPerFrame; } free(allStreamFormats); #if 0 memset( &formatDesc, 0, sizeof(formatDesc)); formatDesc.mChannelsPerFrame = 256; // FIXME - what about device with > 256 channels formatDesc.mFormatID = kAudioFormatLinearPCM; formatDesc.mFormatFlags = kAudioFormatFlagIsFloat | kAudioFormatFlagIsBigEndian | kAudioFormatFlagIsPacked; outSize = sizeof(formatDesc); err = AudioDeviceGetProperty( devID, 0, isInput, kAudioDevicePropertyStreamFormatMatch, &outSize, &formatDesc); if( err != noErr ) { PRINT_ERR("PaOSX_QueryDeviceInfo: Could not get device format match", err); sSavedHostError = err; return paHostError; } #endif if( isInput ) { deviceInfo->maxInputChannels = maxChannels; } else { deviceInfo->maxOutputChannels = maxChannels; } // Get the device name deviceInfo->name = PaOSX_DeviceNameFromID( devID, isInput ); return 1; DBUG(("\n"));error: return 0;}/**********************************************************************/static PaError PaOSX_MaybeQueryDevices( void ){ if( sNumPaDevices == 0 ) { return PaOSX_QueryDevices(); } return 0;}static char zeroPad[256] = { 0 };/************************************************************************ This is the proc that supplies the data to the AudioConverterFillBuffer call.** We can pass back arbitrarily sized blocks so if the FIFO region is split** just pass back the first half.*/static OSStatus PaOSX_InputConverterCallbackProc (AudioConverterRef inAudioConverter, UInt32* outDataSize, void** outData, void* inUserData){ internalPortAudioStream *past = (internalPortAudioStream *) inUserData; PaHostSoundControl *pahsc = (PaHostSoundControl *) past->past_DeviceData; void *dataPtr1; long size1; void *dataPtr2; long size2; /* Pass contiguous region from FIFO directly to converter. */ RingBuffer_GetReadRegions( &pahsc->ringBuffer, *outDataSize, &dataPtr1, &size1, &dataPtr2, &size2 );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -