以dB为单位确定音量

时间:2012-03-30 19:33:47

标签: macos core-audio

这应该是一个简单的问题。在我的Macbook Pro上,内置输出设备不支持kAudioDevicePropertyVolumeScalar属性,因此我必须使用kAudioHardwareServiceDeviceProperty_VirtualMasterVolume来获取和设置音量。

我的问题是,如何将此标量值转换为我在音频MIDI设置和HALLAB等实用程序中看到的分贝值?像kAudioDevicePropertyVolumeScalarToDecibels这样的明显答案不起作用,因为标量音量属性不可用。

2 个答案:

答案 0 :(得分:0)

一般来说,你只是这样做; db值= 10 * log(标量值),如果标量值代表功率,或者如果标量值代表电压,则dB值= 20 * log(标量值)。

答案 1 :(得分:0)

这对我有用。它适用于立体声音频设备,但如果需要,可以轻松地针对多声道设备进行调整。有些设备使用联合“零”通道,有些需要设置左/右 (1/2) 通道。该行为似乎也取决于 MacOS 版本。

-(AudioDeviceID)defaultOutputDeviceID {
    AudioDeviceID   outputDeviceID = kAudioObjectUnknown;
    UInt32 propertySize = 0;
    OSStatus status = noErr;
    AudioObjectPropertyAddress propertyAOPA;
    propertyAOPA.mScope = kAudioObjectPropertyScopeGlobal;
    propertyAOPA.mElement = kAudioObjectPropertyElementMaster;
    propertyAOPA.mSelector = kAudioHardwarePropertyDefaultOutputDevice;
    propertySize = sizeof(AudioDeviceID);
    
    status = AudioObjectGetPropertyData(kAudioObjectSystemObject, &propertyAOPA, 0, NULL, &propertySize, &outputDeviceID);
    
    if(status)
    {
        NSLog(@"Cannot find default output device!");
    }
    return outputDeviceID;
}

-(Float32)volumeDb {
    OSStatus status = noErr;
    AudioDeviceID outputDeviceID = [AppDelegate defaultOutputDeviceID];
    
    if (outputDeviceID == kAudioObjectUnknown) {
        return NAN;
    }
    
    Float32 volumeDB = 0;
    UInt32 propSize = sizeof(volumeDB);
    AudioObjectPropertyAddress  propertyAddress;

    //Catalina
    propertyAddress.mElement = kAudioObjectPropertyElementMaster;
    propertyAddress.mSelector = kAudioDevicePropertyVolumeDecibels;
    propertyAddress.mScope = kAudioDevicePropertyScopeOutput;

    status = AudioObjectGetPropertyData(outputDeviceID, &propertyAddress, 0, NULL, &propSize, &volumeDB);

    if (status != noErr) {
        //Mojave , use 1st channel instead=
        propertyAddress.mElement = 1;
        propSize = sizeof(volumeDB);
        status = AudioObjectGetPropertyData(outputDeviceID, &propertyAddress, 0, NULL, &propSize, &volumeDB);
        if (status)
        {
            NSLog(@"No volumeDb returned for device 0x%0x", outputDeviceID);
            return 0.0;
        }
    }
    return volumeDB;
}

-(void)setVolumeDb:(Float32)volumeDb {
    AudioDeviceID outputDeviceID = [AppDelegate defaultOutputDeviceID];
    if (outputDeviceID == kAudioObjectUnknown) {
        NSLog(@"Unknown device");
    }
    UInt32 propSize = sizeof(Float32);
    AudioObjectPropertyAddress  propertyAddress;

    propertyAddress.mSelector = kAudioDevicePropertyVolumeDecibels;
    propertyAddress.mScope = kAudioDevicePropertyScopeOutput;
    propertyAddress.mElement = kAudioObjectPropertyElementMaster;
    AudioObjectSetPropertyData(outputDeviceID, &propertyAddress, 0, NULL, propSize, &volumeDb);
    propertyAddress.mElement = 1;
    AudioObjectSetPropertyData(outputDeviceID, &propertyAddress, 0, NULL, propSize, &volumeDb);
    propertyAddress.mElement = 2;
    AudioObjectSetPropertyData(outputDeviceID, &propertyAddress, 0, NULL, propSize, &volumeDb);
}