📄 pa_mac_core.c
字号:
if (err) { DBUG(("Could not set stream %d to linear PCM: %s (%d)\n", i, FourCharCode2Str(err), err)); } else { DBUG(("Successfully set stream %d to linear PCM\n", i)); } if (formatDesc.mSampleRate != desiredRate) { /* Let's also try to get the sample rate to match */ double origRate = formatDesc.mSampleRate; formatDesc.mSampleRate = desiredRate; err = AudioDeviceGetProperty(devID, 0, isInput, kAudioStreamPropertyPhysicalFormatMatch, &outSize, &formatDesc); if (!err && formatDesc.mFormatID == kAudioFormatLinearPCM && formatDesc.mSampleRate != origRate) { err = AudioDeviceSetProperty( devID, 0, 0, isInput, kAudioStreamPropertyPhysicalFormat, sizeof(formatDesc), &formatDesc); if (!err) { DBUG(("We were able to set the sample rate to %.1f, too!\n", formatDesc.mSampleRate)); } } } } } } free(streams); // Find the closest match to the stream format that we want. memset(&formatDesc, 0, sizeof(AudioStreamBasicDescription)); formatDesc.mFormatID = kAudioFormatLinearPCM; /* formatDesc.mSampleRate = desiredRate; Since we already set the physical format, we'll definitely get the sample rate we wanted if possible. And if not, then our converter will do the sample rate conversion anyway. Either way, it doesn't help to ask for the rate we want, and it could hurt (because some devices will switch into a non-linear-PCM mode to give you the rate you want). */ /* Should this be in here? I'm not sure... (Yes, if not many devices will default to mono instead of stereo...) */ formatDesc.mChannelsPerFrame = desiredNumChannels; /* These probably don't matter... formatDesc.mBytesPerFrame = formatDesc.mChannelsPerFrame * sizeof(float); formatDesc.mBytesPerPacket = formatDesc.mBytesPerFrame * formatDesc.mFramesPerPacket; */ outSize = sizeof(AudioStreamBasicDescription); err = AudioDeviceGetProperty(devID, 0, isInput, kAudioDevicePropertyStreamFormatMatch, &outSize, &formatDesc); DBUG(("Asked for stream format match, got err=%d, rate=%1f, formatID=%s, flags=%d channels=%d\n", err, formatDesc.mSampleRate, FourCharCode2Str(formatDesc.mFormatID), formatDesc.mFormatFlags, formatDesc.mChannelsPerFrame)); // It's absolutely necessary that we get linear PCM. If not, // we must fail. if (formatDesc.mFormatID != kAudioFormatLinearPCM) { DBUG(("Couldn't even get any linear PCM format!!!\n")); result = paSampleFormatNotSupported; } else { if( formatDesc.mSampleRate == origDesc.mSampleRate && formatDesc.mChannelsPerFrame == origDesc.mChannelsPerFrame && formatDesc.mFormatID == origDesc.mFormatID && formatDesc.mFormatFlags == origDesc.mFormatFlags) { DBUG(("No need to change the device, it's already in an acceptable format\n")); result = 0; } else { DBUG(("Changing device format\n")); DBUG(("Orig: rate=%1f, formatID=%s, flags=%d channels=%d\n", origDesc.mSampleRate, FourCharCode2Str(origDesc.mFormatID), origDesc.mFormatFlags, origDesc.mChannelsPerFrame)); DBUG((" New: rate=%1f, formatID=%s, flags=%d channels=%d\n", formatDesc.mSampleRate, FourCharCode2Str(formatDesc.mFormatID), formatDesc.mFormatFlags, formatDesc.mChannelsPerFrame)); err = AudioDeviceSetProperty( devID, 0, 0, isInput, kAudioDevicePropertyStreamFormat, sizeof(formatDesc), &formatDesc); if (err) { DBUG(("Error trying to change device format: %d\n", err)); if (did_set_hog_mode) result = paSampleFormatNotSupported; else result = paDeviceUnavailable; } else { DBUG(("Success!\n")); result = 1; } } } // Try to turn on mixing if possible (lets other programs play // sounds, too) if (result == 1) { supportsMixing = 1; err = AudioDeviceSetProperty( devID, 0, 0, isInput, kAudioDevicePropertySupportsMixing, sizeof(UInt32), &supportsMixing); if (err) { DBUG(("Unable to turn on mixing\n")); } else { DBUG(("Turned on mixing!\n")); } } // Release hog mode if necessary if (did_set_hog_mode) { DBUG(("Releasing hog mode.\n")); hog_pid = -1; err = AudioDeviceSetProperty( devID, 0, 0, isInput, kAudioDevicePropertyHogMode, sizeof(hog_pid), &hog_pid); if (!err) DBUG(("Hog release successful.\n")); } } return result;}/******************************************************************* * Check volume level of device. If below threshold, then set to newLevel. * Using volume instead of decibels because decibel range varies by device. */static void PaOSX_FixVolumeScalars( AudioDeviceID devID, Boolean isInput, int numChannels, double threshold, double newLevel ){ OSStatus err = noErr; UInt32 dataSize; int iChannel; /* The master channel is 0. Left and right are channels 1 and 2. */ /* Fix volume. */ for( iChannel = 0; iChannel<=numChannels; iChannel++ ) { Float32 fdata32; dataSize = sizeof( fdata32 ); err = AudioDeviceGetProperty( devID, iChannel, isInput, kAudioDevicePropertyVolumeScalar, &dataSize, &fdata32 ); printf("devID=%d\n", devID); printf("Channel=%d input=%d volume=%f\n", iChannel, (int)isInput, fdata32); if( err == noErr ) { DBUG(("kAudioDevicePropertyVolumeScalar for channel %d = %f\n", iChannel, fdata32)); if( fdata32 <= (Float32) threshold ) { dataSize = sizeof( fdata32 ); fdata32 = (Float32) newLevel; printf("Channel=%d input=%d new volume=%f\n", iChannel, (int)isInput, fdata32); err = AudioDeviceSetProperty( devID, 0, iChannel, isInput, kAudioDevicePropertyVolumeScalar, dataSize, &fdata32 ); if( err != noErr ) { PRINT(("Warning: audio volume is very low and could not be turned up.\n")); } else { PRINT(("Volume for audio channel %d was <= %4.2f so set to %4.2f by PortAudio!\n", iChannel, threshold, newLevel )); } } } }/* Unmute if muted. */ for( iChannel = 0; iChannel<=numChannels; iChannel++ ) { UInt32 uidata32; dataSize = sizeof( uidata32 ); err = AudioDeviceGetProperty( devID, iChannel, isInput, kAudioDevicePropertyMute, &dataSize, &uidata32 ); if( err == noErr ) { DBUG(("uidata32 for channel %d = %ld\n", iChannel, uidata32)); if( uidata32 == 1 ) // muted? { dataSize = sizeof( uidata32 ); uidata32 = 0; // unmute err = AudioDeviceSetProperty( devID, 0, iChannel, isInput, kAudioDevicePropertyMute, dataSize, &uidata32 ); if( err != noErr ) { PRINT(("Warning: audio is muted and could not be unmuted!\n")); } else { PRINT(("Audio channel %d was unmuted by PortAudio!\n", iChannel )); } } } }}#if 0static void PaOSX_DumpDeviceInfo( AudioDeviceID devID, Boolean isInput ){ OSStatus err = noErr; UInt32 dataSize; UInt32 uidata32; Float32 fdata32; AudioValueRange audioRange; dataSize = sizeof( uidata32 ); err = AudioDeviceGetProperty( devID, 0, isInput, kAudioDevicePropertyLatency, &dataSize, &uidata32 ); if( err != noErr ) { PRINT_ERR("Error reading kAudioDevicePropertyLatency", err); return; } PRINT(("kAudioDevicePropertyLatency = %d\n", (int)uidata32 )); dataSize = sizeof( fdata32 ); err = AudioDeviceGetProperty( devID, 1, isInput, kAudioDevicePropertyVolumeScalar, &dataSize, &fdata32 ); if( err != noErr ) { PRINT_ERR("Error reading kAudioDevicePropertyVolumeScalar", err); return; } PRINT(("kAudioDevicePropertyVolumeScalar = %f\n", fdata32 )); dataSize = sizeof( uidata32 ); err = AudioDeviceGetProperty( devID, 0, isInput, kAudioDevicePropertyBufferSize, &dataSize, &uidata32 ); if( err != noErr ) { PRINT_ERR("Error reading buffer size", err); return; } PRINT(("kAudioDevicePropertyBufferSize = %d bytes\n", (int)uidata32 )); dataSize = sizeof( audioRange ); err = AudioDeviceGetProperty( devID, 0, isInput, kAudioDevicePropertyBufferSizeRange, &dataSize, &audioRange ); if( err != noErr ) { PRINT_ERR("Error reading buffer size range", err); return; } PRINT(("kAudioDevicePropertyBufferSizeRange = %g to %g bytes\n", audioRange.mMinimum, audioRange.mMaximum )); dataSize = sizeof( uidata32 ); err = AudioDeviceGetProperty( devID, 0, isInput, kAudioDevicePropertyBufferFrameSize, &dataSize, &uidata32 ); if( err != noErr ) { PRINT_ERR("Error reading buffer size", err); return; } PRINT(("kAudioDevicePropertyBufferFrameSize = %d frames\n", (int)uidata32 )); dataSize = sizeof( audioRange ); err = AudioDeviceGetProperty( devID, 0, isInput, kAudioDevicePropertyBufferFrameSizeRange, &dataSize, &audioRange ); if( err != noErr ) { PRINT_ERR("Error reading buffer size range", err); return; } PRINT(("kAudioDevicePropertyBufferFrameSizeRange = %g to %g frames\n", audioRange.mMinimum, audioRange.mMaximum )); return;}#endif/*******************************************************************/static OSStatus PAOSX_DevicePropertyListener (AudioDeviceID inDevice, UInt32 inChannel, Boolean isInput, AudioDevicePropertyID inPropertyID, void* inClientData){ PaHostSoundControl *pahsc; internalPortAudioStream *past; UInt32 dataSize; OSStatus err = noErr; AudioStreamBasicDescription userStreamFormat, hardwareStreamFormat; Boolean updateInverseMicros; Boolean updateConverter; past = (internalPortAudioStream *) inClientData; pahsc = (PaHostSoundControl *) past->past_DeviceData; DBUG(("PAOSX_DevicePropertyListener: called with propertyID = 0x%0X\n", (unsigned int) inPropertyID )); updateInverseMicros = (inDevice == pahsc->primaryDeviceID) && ((inPropertyID == kAudioDevicePropertyStreamFormat) || (inPropertyID == kAudioDevicePropertyBufferFrameSize)); updateConverter = (inPropertyID == kAudioDevicePropertyStreamFormat); // Sample rate needed for both. if( updateConverter || updateInverseMicros ) { /* Get target device format */ dataSize = sizeof(hardwareStreamFormat); err = AudioDeviceGetProperty(inDevice, 0, isInput, kAudioDevicePropertyStreamFormat, &dataSize, &hardwareStreamFormat); if( err != noErr ) { PRINT_ERR("PAOSX_DevicePropertyListener: Could not get device format", err);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -