Linearity of Windows volume APIs – IAudioMeterInformation and full-scale signals

We have talked about some of the volume APIs Windows exposes. We have also talked about what it means for a volume control to be linear in magnitude, linear in power, or linear in dB.

The attachment to this blog post contains:

  • An app I wrote to exercise the IAudioStreamVolume, ISimpleAudioVolume, IChannelAudioVolume, and IAudioEndpointVolume APIs
  • An Excel spreadsheet with the analysis of the output of the app

Let's start by looking at what the app does.

volume-linearity.exe --signal | --stream | --session | --channel |
--endpoint-db | --capture
--signal varies the amplitude of the generated signal from 0 to 1
--stream varies the IAudioStreamVolume from 0 to 1
--session varies the ISimpleAudioVolume from 0 to 1
--channel varies the IChannelAudioVolume from 0 to 1
--endpoint-db varies the IAudioEndpointVolume from X dB to Y dB
where X and Y are the min and max values supported
--capture varies session, channel, and endpoint-db volumes
on the default capture device

Let's look at --signal mode first. The app plays a square wave at amplitudes from 0 (silence) to 1 (full-scale), varying in a linearly in magnitude. It takes periodic readings using IAudioMeterInformation to see what the peak values on the other side of the audio engine are. The IAudioMeterInformation API returns readings that are also linear in magnitude, so the response graph looks nice and linear:

Well... wait a second. What happened at full scale? Let's get a closer look:

When we attempt to play a square wave of amplitude greater than about 0.985, the meter reveals that what we get out of the audio engine is not quite what we put in. The volume has been capped. What's going on?

If we look at the list of WASAPI Audio Processing objects, notice that one of them is called CAudioLimiter. The job of this APO is to take its input and produce output that is limited to the range (-1, 1). When it sees that signals are getting too close to the edge, it steps in and pulls the signal closer to the center.

For this reason, the other modes of volume-linearity.exe use a half-scale (-1/2, 1/2) square wave rather than a full-scale square wave.

UPDATE June 1 2011: added --capture mode

UPDATE September 28 2015: moved source to

Comments (6)

  1. tongy says:

    I have a question, does this applicable to capture stream also?

  2. Good question; I don't know.

  3. ferongr says:

    Somewhat late, but a discussion at HydrogenAudio about null-testing digital signals brought me here. What were the justifications for deciding to limit output signal amplitude? Was it something done to prevent hard clipping (though in that case the limiter could presumably operate at -0dBFS) or another reason?

    This is more like idle curiosity on my part. I understand that a limiter operating at ≈ -0,1313 dBFS will definitely not be audible.

  4. The limiter is there to simplify mixing, and playback of sources which are outside of the (-1, 1) range.

    It doesn't really serve any purpose if there is only one stream playing and the source is already in the (-1, 1) range.

  5. ferongr says:

    That means it doesn't limit at all with a single source playing audio (e.g. WMP) then, right? If this is true then this sets a large misunderstanding about what it does straight.

  6. If you give WMP a file containing audio outside of the [-1, 1] range, WMP will happily hand the out-of-range data to its IAudioClient, so a limiter is necessary sometimes even in the single-source case.

    The limiter is almost always in effect, even when it doesn't serve any real purpose (single-source with in-range data.)

    There are a few exceptions though, e.g., streaming Dolby Digital audio to a receiver with a hardware decoder.

Skip to main content