Matthew van Eerde's web log

  • Matthew van Eerde's web log

    Spot the bug - control flow macro


    Found this in a code review.

    Well, in all candor, I didn't find it; our automated code review tool found it.  But I'm taking credit for it because I read the output of the automated code review tool. :-)

    Code rewritten because I'm too lazy to look it up.

    // macros.h
    #define ENSURE_EQUAL(x, y) if (x != y) { bail(); }

    // implementation.cpp
    hr = foo();
    ENSURE_EQUAL( foo_supported() ? S_OK : E_FOO_NOT_SUPPORTED, hr );

  • Matthew van Eerde's web log

    Generating formulae for polygonal numbers (triangular, square, pentagonal...)


    The formula for square numbers is easy to remember:
    sn = n2
    There are also triangular numbers, pentagonal numbers, hexagonal numbers, and in general k-gonal numbers. These have formulae too... for example, triangular numbers:
    tn = n (n + 1) / 2
    ... but they can be hard to remember.

    If you see a fact, try to see it as intuitively as possible.

    Some formulae are not worth memorizing - it is more worthwhile to grasp the ideas behind the formulae and rederive them when you need them (or look them up.) This blog post shows how to derive the formulae for k-gonal numbers.

    Let's define a few terms. I've defined sn and tn above, and I'll define pn as the nth pentagonal number and hn as the nth hexagonal number, but let's generalize... let gk,n = g(k, n) be the nth k-gonal number. For example:
    g(3, n) = tn = n (n + 1) / 2
    g(4, n) = sn = n2
    The task, then, is to find a formula for g(k, n) for general k and n.

    Consider the nth k-gonal number. For simplicity of illustration, I will focus on a particular number, but the approach followed here should be followed while keeping the general case in mind. So, specifically, let's take a look at the 4th pentagonal number p4 = g(5, 4):

    The idea is to conceptually "cut" (n – 1) specific lines...

    ... and then "unroll" the structure to form a kind of "bar chart":

    The base of the chart is precisely one edge of the original diagram and so has length n = 4 (counting dots, not lines.) There are a couple of ways to find the height of the last bar - you can observe that each bar (not counting the bottom dot) adds (k – 2) = 3 over the bar before it (as marked below,) and there are (n – 1) = 3 nontrivial bars.
    Or you can note that each bar is the bottom dot, plus the sum of (k – 2) = 3 edges, each of which has (n – 1) = 3 unique dots, if we don't count the first dot as being part of the edge.
    Either way, you come up with the height being:
    h = 1 + (k – 2)(n – 1) = 1 + 3(3) = 10

    So we know the base and the height of the triangle. How do we find the area? Well, if we double the triangle, we get a rectangle:

    The base of the rectangle is n = 4, and the height is:
    h + 1 = 2 + (k – 2) (n – 1) = (k – 2) n + (4 – k) = (5 – 2) 4 + (4 – 5) = 11
    The area of the triangle is half of the area of the rectangle:
    g(k, n) = n ((k – 2) n + (4 – k)) / 2 = 4 ((5 – 2) 4 + (4 – 5)) / 2 = 22
    Counting dots confirms that there are, in fact, 22.

    So we have a general theorem - let's try it out on a few special cases. We can use the ones we know as a check.

    g(3, n) = n ((3 – 2) n + (4 – 3)) / 2 = n (n + 1) / 2 = tn
    g(4, n) = n ((4 – 2) n + (4 – 4)) / 2 = n2 = sn
    g(5, n) = n ((5 – 2) n + (4 – 5)) / 2 = n (3n – 1) / 2 = pn
    g(6, n) = n ((6 – 2) n + (4 – 6)) / 2 = n (2n – 1) = hn
    g(7, n) = n ((7 – 2) n + (4 – 7)) / 2 = n (5n – 3) / 2
    g(k, n) = n ((k – 2) n + (4 – k)) / 2

    Further checks: g(k, 1) should be 1 for all k, and g(k, 2) should be k for all k. These also check out.

  • Matthew van Eerde's web log

    Windows audio render volume settings, from local to global


    Windows has four different volume settings for any given piece of audio; they are all applied simultaneously. For example, if one of these settings is muted, you will not hear the audio, even if the others are turned up to "full". Here they are, from local to global:

    Stream volume

    The WASAPI API for this is IAudioStreamVolume.

    This most local volume control is used only in rather specialized situations. If a particular app wants to play multiple audio streams to the same audio device, and in the same session (see below), but wants to control the volumes for the streams independently, this is the volume control to use. For example:

    • A media playback app might want to cross fade songs n and n + 1 in a playlist; it could do this by playing the songs in different streams, gradually bringing the volume for song n down to zero, while simultaneously bringing the volume for song n + 1 up to full.
    • A game might offer distinct volume controls for:
      • The background music in the game
      • The sound effects (gunshots, explosions, and so on)
      • Voice chat in the game
      The first two would likely be in the same session and would thus use stream volume controls (exposed via the game UI - Windows does not offer UI for stream volume.) The third could very well be a different session, and even use a different device - the background music and sound effects might go to the default console device (e.g., speakers) while the voice chat might go to the default communications device (e.g., a headset.)

    Apps could also get these same effects by doing their own mixing and volume handling, and playing a single stream to the Windows audio engine, of course.

    Session volume

    By and large, this is the volume control that apps most commonly use. The WASAPI APIs for this are ISimpleAudioVolume and the more-rarely used IChannelAudioVolume.

    This is what people mean when they say "application volume" - a session is, by and large, an app (though there are exceptions in both directions.) This is the "S" in "WASAPI" - Windows Audio Session API.

    The session volume shows up in the Volume Mixer - each "Application" slider is a session volume control. This is also usually (but not always) tied to a volume control in the app.

    Endpoint volume

    The WASAPI API for this is IAudioEndpointVolume. Apps should generally prefer ISimpleAudioVolume to this because IAudioEndpointVolume will affect all apps on the system.

    This is what people mean when they say "system volume." It is exposed in the following three places in the UI. Note if you have multiple audio devices, each has its own setting.


    More about ducking

    When you get a phone call or start a voice chat, Windows (starting in Windows 7) will attenuate (or "duck") all of the audio on the system (except for phone calls and voice chats.) This is the "most global" because it affects all streams on all audio devices. Note that this volume control only has three settings (four if you count "mute".)


    Larry Osterman did a series of audio volume posts - one of them contains much of the information in this post, though the ducking feature was added after his post.

Page 1 of 1 (3 items)

April, 2011