Search code examples
c#-4.0xaudio2

XAudio2 Source/Master Voice SetVolume parameters


I'm trying to build a volume slider for my WPF app to apply to the WAV files I'm outputting via XAudio2.

I've got it all string together and can play sounds. Great!

I just can't make sense of the argument for the SetVolume method.

Can anyone explain what the appropriate values for a volume slider?

I'm sure I am missing something incredibly obvious and I;m just not used to playing with audio files so I'm pretty clueless to boot.

I expect I'd really want to end up with two sliders, one for the mastering voice and one for the source voice.


Solution

  • Generally you'd just use the volume control on the 'mastering voice' to control the overall volume level of your application's output. The per-source-voice volume is available for controlling the premix individual sounds, but that's not a particular intuitive way for a user to control the overall 'loudness' of an app.

    As to what the volume parameter means, it's defined as follows on Microsoft Docs:

    Volume levels are expressed as floating-point amplitude multipliers between -XAUDIO2_MAX_VOLUME_LEVEL and XAUDIO2_MAX_VOLUME_LEVEL (-2²⁴ to 2²⁴), with a maximum gain of 144.5 dB. A volume level of 1.0 means there is no attenuation or gain and 0 means silence. Negative levels can be used to invert the audio's phase. See XAudio2 Volume and Pitch Control for additional information on volume control.

    In practical terms, you set it to 0.0 to have no sound, and 1.0 to have it be 'full volume' of your originally mastered mix so 0.0 to 1.0 is a reasonable place to start. Depending on the volume of your individual sounds, the effects you are running, and in particular any reverb or 3D spatial positioning you may find that setting the overall volume to greater than 1.0 results in 'clipping'.

    Even with a mastering volume of 1.0, clipping can happen in complex mixes. A solution here is to use the FXMasteringLimiter APO on your mastering voice. For example, here's the code that adds the mastering limiter in DirectX Tool Kit for Audio.

        FXMASTERINGLIMITER_PARAMETERS params = {};
        params.Release = FXMASTERINGLIMITER_DEFAULT_RELEASE;
        params.Loudness = FXMASTERINGLIMITER_DEFAULT_LOUDNESS;
    
    #if (_WIN32_WINNT >= _WIN32_WINNT_WIN8)
        hr = CreateFX( __uuidof(FXMasteringLimiter),
        mVolumeLimiter.ReleaseAndGetAddressOf(),
        &params, sizeof(params) );
    #else
        hr = CreateFX( __uuidof(FXMasteringLimiter),
        mVolumeLimiter.ReleaseAndGetAddressOf() );
    #endif
        if ( FAILED(hr) )
            // error
    
        XAUDIO2_EFFECT_DESCRIPTOR desc = {};
        desc.InitialState = TRUE;
        desc.OutputChannels = masterChannels;
        desc.pEffect = mVolumeLimiter.Get();
    
        XAUDIO2_EFFECT_CHAIN chain = { 1, &desc };
        hr = mMasterVoice->SetEffectChain( &chain );
        if ( FAILED(hr) )
            // error
    
    #if (_WIN32_WINNT < _WIN32_WINNT_WIN8)
        hr = mMasterVoice->SetEffectParameters( 0, &params, sizeof(params) );
        if ( FAILED(hr) )
            // error
    #endif
    

    The conditional codepaths above are to handle XAudio 2.8 vs. XAudio 2.7 API differences. See this blog post.

    UPDATE:: Note that DirectX Tool Kit for Audio no longer support XAudio 2.7. Instead, it supports using XAudio 2.9 on Windows 7 SP1, Windows 8.0, Windows 8.1, and Windows 10 via XAudio2Redist.