Matthew van Eerde's web log

  • Matthew van Eerde's web log

    UI text flow of various languages

    • 1 Comments

    This point came up today in a spec review. The text had language like "put the choices 1-N in rows of three, starting with 1 in the top left corner of the screen, and in rows of three to four going down the screen."

    Western Europeans and 'mericans (like me) are accustomed to text layout that looks like this, so the text makes sense to us.

    Left-to-right, top-down:

    But there's a significant number of people in the world (some of whom would use a product designed to the spec) that read right-to-left.  They would be much more comfortable with a text layout like this:

    Right-to-left, top-down:

    These people include those who read Arabic or Hebrew, for example.

    There's also a third text layout that needs a little introduction.  There are two different layouts for Japanese.

    The traditional way to write Japanese is in vertical columns, each of which is read/written top down, and the columns are themselves read right-to-left.  A Japanese would expect a product with a "traditional feel" to be laid out like this:

    Top-down, right-to-left:

    To digress a little...

    If vertical space is constrained (for example, for the sign above a storefront) there might only be room for one character per column:

    Top-down, right-to-left, columns are one character high:

    To the casual viewer, this is easily confused with right-to-left / top-down.  Japanese is sometimes incorrectly thought of as an RTL language.  There's a similar effect in Western European languages on some hotel signs that have lots of vertical space but only enough horizontal room for one column.

    Finally, I should mention that Japanese also has a modern text layout.  For products that are aiming for a modern feel as opposed to a traditional feel, it is usual to write the Japanese characters in left-to-right / top-down layout.

    (Footnote: note that single-row-high Japanese text can be read either left-to-right, or right-to-left, depending on context.  There are often clues available to allow a reader to know which way to read; for example, I believe some characters are written differently depending on which layout is in effect.  Also, the font or the setting may give hints as to whether a "traditional" or "modern" feel is intended.)

  • Matthew van Eerde's web log

    Troubleshooting: how to install the Microsoft HD Audio class driver

    • 1 Comments

    Most on-the-motherboard audio devices support the Intel High Definition Audio standard.  Windows Vista (and later) includes a "class driver", hdaudio.sys, which should work with any such audio device.

    Usually systems come with a vendor-supplied driver installed.  This driver is designed specifically for the hardware it runs on (as opposed to being designed to the standard) and so it comes with additional functionality.

    Occasionally, for troubleshooting purposes, it is useful to switch from one driver to the other... either to get the additional functionality provided by the vendor-supplied driver, or to see what happens if the class driver is installed.

    Here's how to switch back and forth.

    Click "Start".

    Type "devmgmt.msc" (without the quotes) to launch Device Manager.

    Expand the "Sound, video and game controllers" node and note the list of audio devices.  In this case, I have one audio device, and by the "High Definition Audio Device" name I deduce that I have the class driver installed.  (If the device name included a company name, I would infer that I had a vendor driver installed.)

    Right-click the device you want to change the software on.

    Windows offers to automatically detect the driver that should be installed.  No thanks, we want to pick a particular driver:

    Windows asks where we want to look - do we have a set of driver files, or is the driver already in the list of installed drivers?  In this case, we want to look at the list of drivers for this hardware that are already installed.

    Windows shows us a list of drivers that are already installed and usable for this hardware.  At this point you would expect to see two drivers listed: the vendor driver, and "High Definition Audio Device."  (When I made this blog post, I was lazy, so I didn't bother to make a screenshot that showed two drivers.)

    To install the class driver, pick "High Definition Audio Device" and click "Next."

    "High Definition Audio Device" is a class driver, so you get this warning.  Click "Yes."

    Windows does its thing...

    ... and eventually tells you that it's done.  If your audio device was in use, you may get the "you have to restart" message.  Regardless, click "Close".

    If you got the "you will need to restart" message, Windows helpfully offers to restart right away.

    Make sure you're ready for a restart (no unsaved documents or anything) and restart either by clicking "Yes" or by using the Start menu.

    When you're done experimenting, you can go back to the vendor-supplied driver by going through the same steps and choosing the vendor-supplied driver in the list of drivers.

  • Matthew van Eerde's web log

    How to enumerate WASAPI Audio Processing Objects (APOs) on your system

    • 0 Comments

    Source and binaries (amd64 and x86) attached.

    Pseudocode:

    main() {
        UINT32 nCount;
        EnumerateAPOs(myCallback, &nCount);
        print nCount;
    }

    ...

    // called once for each APO
    myCallback(PAPO_REG_PROPERTIES props, PVOID pnCount) {
        print props;
        (*pnCount)++;
    }

    Gotcha: the APO_REG_PROPERTIES structure is variable-size.  If you want to store the structure for later use, you need to make the copy before the callback function exits, and make sure add on the size of any additional interface IDs beyond the first (the first is included in the structure) if you want to store them too.

    Output on my system:

    >apoenum.exe
    -- APO properties for CAudioVolume --
        clsid: {06587E71-F043-403A-BF49-CB591BA6E103}
        Flags: 0x0000000f
            APO_FLAG_INPLACE
            APO_FLAG_SAMPLESPERFRAME_MUST_MATCH
            APO_FLAG_FRAMESPERSECOND_MUST_MATCH
            APO_FLAG_BITSPERSAMPLE_MUST_MATCH
        szFriendlyName: "CAudioVolume"
        szCopyrightInfo: "copyright (c) 2003 microsoft corporation"
        u32MajorVersion: 1
        u32MinorVersion: 0
        u32MinInputConnections: 1
        u32MaxInputConnections: 1
        u32MinOutputConnections: 1
        u32MaxOutputConnections: 1
        u32MaxInstances: 4294967295
        u32NumAPOInterfaces: 1
        #1: {D81229B1-5A43-480C-92F7-BE0F7F4EAB60}

    -- APO properties for CAudioConstrictor --
        clsid: {07252659-BB6B-4B79-B78B-623F6699A579}
        Flags: 0x0000000f
            APO_FLAG_INPLACE
            APO_FLAG_SAMPLESPERFRAME_MUST_MATCH
            APO_FLAG_FRAMESPERSECOND_MUST_MATCH
            APO_FLAG_BITSPERSAMPLE_MUST_MATCH
        szFriendlyName: "CAudioConstrictor"
        szCopyrightInfo: "Copyright (c) 2003 Microsoft Corporation"
        u32MajorVersion: 1
        u32MinorVersion: 0
        u32MinInputConnections: 1
        u32MaxInputConnections: 1
        u32MinOutputConnections: 1
        u32MaxOutputConnections: 1
        u32MaxInstances: 4294967295
        u32NumAPOInterfaces: 1
        #1: {6B54B2B5-45EE-4F11-9935-9EC3183AD534}

    -- APO properties for caudiomixer --
        clsid: {12DD4DBB-532B-4FCE-8653-74CDB9C8FE5A}
        Flags: 0x0000000e
            APO_FLAG_SAMPLESPERFRAME_MUST_MATCH
            APO_FLAG_FRAMESPERSECOND_MUST_MATCH
            APO_FLAG_BITSPERSAMPLE_MUST_MATCH
        szFriendlyName: "caudiomixer"
        szCopyrightInfo: "Copyright (C) 2003 Microsoft Corporation"
        u32MajorVersion: 1
        u32MinorVersion: 0
        u32MinInputConnections: 1
        u32MaxInputConnections: 1
        u32MinOutputConnections: 1
        u32MaxOutputConnections: 1
        u32MaxInstances: 4294967295
        u32NumAPOInterfaces: 1
        #1: {C23BDC7A-47F8-49A1-B750-692C35B532C3}

    -- APO properties for CAudioRateConvertCMPT --
        clsid: {27C98999-2895-4829-B080-5A8B65BD3DB0}
        Flags: 0x0000000a
            APO_FLAG_SAMPLESPERFRAME_MUST_MATCH
            APO_FLAG_BITSPERSAMPLE_MUST_MATCH
        szFriendlyName: "CAudioRateConvertCMPT"
        szCopyrightInfo: "Copyright (c) 2005 Microsoft Corporation"
        u32MajorVersion: 1
        u32MinorVersion: 0
        u32MinInputConnections: 1
        u32MaxInputConnections: 1
        u32MinOutputConnections: 1
        u32MaxOutputConnections: 1
        u32MaxInstances: 4294967295
        u32NumAPOInterfaces: 3
        #1: {788F7BE2-9C40-41C0-AF05-4393FBF409F9}
        #2: {C78841EF-516F-4516-B591-F04FA93783A9}
        #3: {7BA1DB8F-78AD-49CD-9591-F79D80A17C81}

    -- APO properties for caudiometer --
        clsid: {3DC09436-7D83-4BA0-ADDC-CD47F996C5BA}
        Flags: 0x0000000f
            APO_FLAG_INPLACE
            APO_FLAG_SAMPLESPERFRAME_MUST_MATCH
            APO_FLAG_FRAMESPERSECOND_MUST_MATCH
            APO_FLAG_BITSPERSAMPLE_MUST_MATCH
        szFriendlyName: "caudiometer"
        szCopyrightInfo: "copyright (c) 2003 microsoft corporation"
        u32MajorVersion: 1
        u32MinorVersion: 0
        u32MinInputConnections: 1
        u32MaxInputConnections: 1
        u32MinOutputConnections: 0
        u32MaxOutputConnections: 1
        u32MaxInstances: 4294967295
        u32NumAPOInterfaces: 1
        #1: {419B26E3-FA99-4408-83DE-CC1276EFA489}

    -- APO properties for caudioformatconvert --
        clsid: {3FD7F233-A716-472E-8F2F-C25954F34E96}
        Flags: 0x00000006
            APO_FLAG_SAMPLESPERFRAME_MUST_MATCH
            APO_FLAG_FRAMESPERSECOND_MUST_MATCH
        szFriendlyName: "caudioformatconvert"
        szCopyrightInfo: "copyright (c) 2003 microsoft corporation"
        u32MajorVersion: 1
        u32MinorVersion: 0
        u32MinInputConnections: 1
        u32MaxInputConnections: 1
        u32MinOutputConnections: 1
        u32MaxOutputConnections: 1
        u32MaxInstances: 4294967295
        u32NumAPOInterfaces: 2
        #1: {FC7DFF56-6B8D-45A9-B4CA-266F9AC21693}
        #2: {6BB6A944-7352-4327-AB91-D92607B25656}

    -- APO properties for caudiomatrix --
        clsid: {541987EE-0E02-411E-9A85-1FC6156E7F4B}
        Flags: 0x0000000c
            APO_FLAG_FRAMESPERSECOND_MUST_MATCH
            APO_FLAG_BITSPERSAMPLE_MUST_MATCH
        szFriendlyName: "caudiomatrix"
        szCopyrightInfo: "copyright (c) 2003 microsoft corporation"
        u32MajorVersion: 1
        u32MinorVersion: 0
        u32MinInputConnections: 1
        u32MaxInputConnections: 1
        u32MinOutputConnections: 1
        u32MaxOutputConnections: 1
        u32MaxInstances: 4294967295
        u32NumAPOInterfaces: 1
        #1: {BB8B2F5D-2AF0-473F-BD94-F55A77587D3F}

    -- APO properties for WM audio LFX APO --
        clsid: {62DC1A93-AE24-464C-A43E-452F824C4250}
        Flags: 0x0000000d
            APO_FLAG_INPLACE
            APO_FLAG_FRAMESPERSECOND_MUST_MATCH
            APO_FLAG_BITSPERSAMPLE_MUST_MATCH
        szFriendlyName: "WM audio LFX APO"
        szCopyrightInfo: "Copyright Microsoft"
        u32MajorVersion: 1
        u32MinorVersion: 1
        u32MinInputConnections: 1
        u32MaxInputConnections: 1
        u32MinOutputConnections: 1
        u32MaxOutputConnections: 1
        u32MaxInstances: 4294967295
        u32NumAPOInterfaces: 1
        #1: {FD7F2B29-24D0-4B5C-B177-592C39F9CA10}

    -- APO properties for WM audio GFX APO --
        clsid: {637C490D-EEE3-4C0A-973F-371958802DA2}
        Flags: 0x0000000d
            APO_FLAG_INPLACE
            APO_FLAG_FRAMESPERSECOND_MUST_MATCH
            APO_FLAG_BITSPERSAMPLE_MUST_MATCH
        szFriendlyName: "WM audio GFX APO"
        szCopyrightInfo: "Copyright Microsoft"
        u32MajorVersion: 1
        u32MinorVersion: 1
        u32MinInputConnections: 1
        u32MaxInputConnections: 1
        u32MinOutputConnections: 1
        u32MaxOutputConnections: 1
        u32MaxInstances: 4294967295
        u32NumAPOInterfaces: 1
        #1: {FD7F2B29-24D0-4B5C-B177-592C39F9CA10}

    -- APO properties for caudiorateconvert --
        clsid: {C58BD103-E87F-4B78-A0FA-7A5C95970EE2}
        Flags: 0x0000000a
            APO_FLAG_SAMPLESPERFRAME_MUST_MATCH
            APO_FLAG_BITSPERSAMPLE_MUST_MATCH
        szFriendlyName: "caudiorateconvert"
        szCopyrightInfo: "copyright (c) 2003 microsoft corporation"
        u32MajorVersion: 1
        u32MinorVersion: 0
        u32MinInputConnections: 1
        u32MaxInputConnections: 1
        u32MinOutputConnections: 1
        u32MaxOutputConnections: 1
        u32MaxInstances: 4294967295
        u32NumAPOInterfaces: 3
        #1: {788F7BE2-9C40-41C0-AF05-4393FBF409F9}
        #2: {C78841EF-516F-4516-B591-F04FA93783A9}
        #3: {7BA1DB8F-78AD-49CD-9591-F79D80A17C81}

    -- APO properties for CAudioLimiter --
        clsid: {D69E0717-DD4B-4B25-997A-DA813833B8AC}
        Flags: 0x0000000e
            APO_FLAG_SAMPLESPERFRAME_MUST_MATCH
            APO_FLAG_FRAMESPERSECOND_MUST_MATCH
            APO_FLAG_BITSPERSAMPLE_MUST_MATCH
        szFriendlyName: "CAudioLimiter"
        szCopyrightInfo: "Copyright (c) 2003 Microsoft Corporation"
        u32MajorVersion: 1
        u32MinorVersion: 0
        u32MinInputConnections: 1
        u32MaxInputConnections: 1
        u32MinOutputConnections: 1
        u32MaxOutputConnections: 1
        u32MaxInstances: 4294967295
        u32NumAPOInterfaces: 1
        #1: {7DF8824C-AEC7-4119-9425-E6979172A8AE}

    -- APO properties for caudiocopy --
        clsid: {E916B6B2-22BD-4AFC-B337-D3D9FB27670E}
        Flags: 0x0000000e
            APO_FLAG_SAMPLESPERFRAME_MUST_MATCH
            APO_FLAG_FRAMESPERSECOND_MUST_MATCH
            APO_FLAG_BITSPERSAMPLE_MUST_MATCH
        szFriendlyName: "caudiocopy"
        szCopyrightInfo: "copyright (c) 2003 microsoft corporation"
        u32MajorVersion: 1
        u32MinorVersion: 0
        u32MinInputConnections: 1
        u32MaxInputConnections: 1
        u32MinOutputConnections: 1
        u32MaxOutputConnections: 1
        u32MaxInstances: 4294967295
        u32NumAPOInterfaces: 1
        #1: {ADF7583D-F947-4311-83FB-066AD4E5E7C2}

    APOs found: 12
  • Matthew van Eerde's web log

    How to enumerate Audio Compression Manager (ACM) drivers on your system (spot the bug!)

    • 0 Comments

    Source and binaries (amd64 and x86) attached.

    Pseudocode:

    list acm_drivers;
    acmDriverEnum( myCallbackFunction, &acm_drivers, ...);
        // myCallbackFunction(driver, pacm_drivers) { pacm_drivers->add(driver); }
    for each driver in (acm_drivers) {
        details = acmDriverDetails(driver);
        print details;
    }

    Output on my system - spot the bug!

    >acmenum.exe
    ACM Drivers found: 6
    -- ACM Driver Details: Microsoft IMA ADPCM --
        cbStruct: 1804
        fccType: 0x63647561 (audc)
        fccComp: 0x00000000 (    )
        wMid: 1
        wPid: 34
        vdwACM: 0x03320000 (3.50.12800)
        vdwDriver: 0x04000000 (4.0.0)
        fdwSupport: 0x00000001
            ACMDRIVERDETAILS_SUPPORTF_CODEC
        cFormatTags: 2
        cFilterTags: 0
        hicon: 0x0000000000000000
        szShortName: "Microsoft IMA ADPCM"
        szLongName: "Microsoft IMA ADPCM CODEC"
        szCopyright: "Copyright (C) 1992-1996 Microsoft Corporation"
        szLicensing: ""
        szFeatures: "Compresses and decompresses IMA ADPCM audio data."

    -- ACM Driver Details: Microsoft CCITT G.711 --
        cbStruct: 1804
        fccType: 0x63647561 (audc)
        fccComp: 0x00000000 (    )
        wMid: 1
        wPid: 37
        vdwACM: 0x03320000 (3.50.12800)
        vdwDriver: 0x04000000 (4.0.0)
        fdwSupport: 0x00000001
            ACMDRIVERDETAILS_SUPPORTF_CODEC
        cFormatTags: 3
        cFilterTags: 0
        hicon: 0x0000000000000000
        szShortName: "Microsoft CCITT G.711"
        szLongName: "Microsoft CCITT G.711 A-Law and u-Law CODEC"
        szCopyright: "Copyright (c) 1993-1996 Microsoft Corporation"
        szLicensing: ""
        szFeatures: "Compresses and decompresses CCITT G.711 A-Law and u-Law audio data."

    -- ACM Driver Details: Microsoft GSM 6.10 --
        cbStruct: 1804
        fccType: 0x63647561 (audc)
        fccComp: 0x00000000 (    )
        wMid: 1
        wPid: 36
        vdwACM: 0x03320000 (3.50.12800)
        vdwDriver: 0x04000000 (4.0.0)
        fdwSupport: 0x00000001
            ACMDRIVERDETAILS_SUPPORTF_CODEC
        cFormatTags: 2
        cFilterTags: 0
        hicon: 0x0000000000000000
        szShortName: "Microsoft GSM 6.10"
        szLongName: "Microsoft GSM 6.10 Audio CODEC"
        szCopyright: "Copyright (C) 1993-1996 Microsoft Corporation"
        szLicensing: ""
        szFeatures: "Compresses and decompresses audio data conforming to the ETSI-GSM (European Telecommunications Standards Institute-Groupe Special Mobile) recommendation 6.10."

    -- ACM Driver Details: MS-ADPCM --
        cbStruct: 1804
        fccType: 0x63647561 (audc)
        fccComp: 0x00000000 (    )
        wMid: 1
        wPid: 33
        vdwACM: 0x03320000 (3.50.12800)
        vdwDriver: 0x04000000 (4.0.0)
        fdwSupport: 0x00000001
            ACMDRIVERDETAILS_SUPPORTF_CODEC
        cFormatTags: 2
        cFilterTags: 0
        hicon: 0x0000000000000000
        szShortName: "MS-ADPCM"
        szLongName: "Microsoft ADPCM CODEC"
        szCopyright: "Copyright (C) 1992-1996 Microsoft Corporation"
        szLicensing: ""
        szFeatures: "Compresses and decompresses Microsoft ADPCM audio data."

    -- ACM Driver Details: MPEG Layer-3 Codec  --
        cbStruct: 1804
        fccType: 0x63647561 (audc)
        fccComp: 0x00000000 (    )
        wMid: 172
        wPid: 9
        vdwACM: 0x03320000 (3.50.12800)
        vdwDriver: 0x01090191 (1.9.2305)
        fdwSupport: 0x00000001
            ACMDRIVERDETAILS_SUPPORTF_CODEC
        cFormatTags: 2
        cFilterTags: 0
        hicon: 0x0000000067C507A5
        szShortName: "MPEG Layer-3 Codec "
        szLongName: "Fraunhofer IIS MPEG Layer-3 Codec (decode only)"
        szCopyright: "Copyright ⌐ 1996-1999 Fraunhofer Institut Integrierte Schaltungen IIS"
        szLicensing: ""
        szFeatures: "decoder only version"

    -- ACM Driver Details: MS-PCM --
        cbStruct: 1804
        fccType: 0x63647561 (audc)
        fccComp: 0x00000000 (    )
        wMid: 1
        wPid: 38
        vdwACM: 0x03320000 (3.50.12800)
        vdwDriver: 0x05000000 (5.0.0)
        fdwSupport: 0x00000002
            ACMDRIVERDETAILS_SUPPORTF_CONVERTER
        cFormatTags: 1
        cFilterTags: 0
        hicon: 0x0000000000000000
        szShortName: "MS-PCM"
        szLongName: "Microsoft PCM Converter"
        szCopyright: "Copyright (C) 1992-1996 Microsoft Corporation"
        szLicensing: ""
        szFeatures: "Converts frequency and bits per sample of PCM audio data."

  • Matthew van Eerde's web log

    How to enumerate DirectSound DirectX Media Objects (DMOs) on your system

    • 0 Comments

    Source and binaries (amd64 and x86) attached.

    Pseudocode:

    GUID dmo_categories[] = { ... }
    for (each guid in dmo_categories) {
        IEnumDMO = DMOEnum(guid, DMO_ENUMF_INCLUDE_KEYED, ...);
        while (0 != items fetched by IEnumDMO::Next(&iid, &szName...)) {
           print iid, szName
        }
    }

    Output on my system:

    >dmoenum.exe
    -- Audio decoders ({57F2DB8B-E6BB-4513-9D43-DCD2A6593125}) --
    WMAudio Decoder DMO ({2EEB4ADF-4578-4D10-BCA7-BB955F56320A})
    WMAPro over S/PDIF DMO ({5210F8E4-B0BB-47C3-A8D9-7B2282CC79ED})
    WMSpeech Decoder DMO ({874131CB-4ECC-443B-8948-746B89595D20})
    MP3 Decoder DMO ({BBEEA841-0A63-4F52-A7AB-A9B3A84ED38A})

    -- Audio effects ({F3602B3F-0592-48DF-A4CD-674721E7EBEB}) --
    ParamEq ({120CED89-3BF4-4173-A132-3CB406CF3231})
    AEC ({745057C7-F353-4F2D-A7EE-58434477730E})
    WavesReverb ({87FC0268-9A55-4360-95AA-004A1D9DE26C})
    Gargle ({DAFD8210-5711-4B91-9FE3-F75B7AE279BF})
    Compressor ({EF011F79-4000-406D-87AF-BFFB3FC39D57})
    Distortion ({EF114C90-CD1D-484E-96E5-09CFAF912A21})
    Echo ({EF3E932C-D40B-4F51-8CCF-3F98F1B29D5D})
    I3DL2Reverb ({EF985E71-D5C7-42D4-BA4D-2D073E2E96F4})
    Flanger ({EFCA3D92-DFD8-4672-A603-7420894BAD98})
    Chorus ({EFE6629C-81F7-4281-BD91-C9D604A95AF6})
    Resampler DMO ({F447B69E-1884-4A7E-8055-346F74D6EDB3})

    -- Audio encoders ({33D9A761-90C8-11D0-BD43-00A0C911CE86}) --
    WM Speech Encoder DMO ({1F1F4E1A-2252-4063-84BB-EEE75F8856D5})
    WMAudio Encoder DMO ({70F598E9-F4AB-495A-99E2-A7C4D3D89ABF})

    -- Video decoders ({4A69B442-28BE-4991-969C-B500ADF5D8A8}) --
    Mpeg4s Decoder DMO ({2A11BAE2-FE6E-4249-864B-9E9ED6E8DBC2})
    WMV Screen decoder DMO ({7BAFB3B1-D8F4-4279-9253-27DA423108DE})
    WMVideo Decoder DMO ({82D353DF-90BD-4382-8BC2-3F6192B76E34})
    Mpeg43 Decoder DMO ({CBA9E78B-49A3-49EA-93D4-6BCBA8C4DE07})
    MS ATC Screen Decoder 1 ({F1931D8E-51D3-496F-BE8A-3D08AEE9C9DB})
    Mpeg4 Decoder DMO ({F371728A-6052-4D47-827C-D039335DFE0A})

    -- Video effects ({D990EE14-776C-4723-BE46-3DA2F56F10B9}) --
    Frame Rate Converter ({01F36CE2-0907-4D8B-979D-F151BE91C883})
    Resizer DMO ({1EA1EA14-48F4-4054-AD1A-E8AEE10AC805})
    TOC Generator ({4DDA1941-77A0-4FB1-A518-E2185041D70C})
    Thumbnail Generator ({559C6BAD-1EA8-4963-A087-8A6810F9218B})
    Color Control ({798059F0-89CA-4160-B325-AEB48EFE4F9A})
    Color Converter DMO ({98230571-0087-4204-B020-3282538E57D3})

    -- Video encoders ({33D9A760-90C8-11D0-BD43-00A0C911CE86}) --
    WMVideo8 Encoder DMO ({7E320092-596A-41B2-BBEB-175D10504EB6})
    WMVideo9 Encoder DMO ({D23B90D0-144F-46BD-841D-59E4EB19DC59})
    MSScreen 9 encoder DMO ({F7FFE0A0-A4F5-44B5-949E-15ED2BC66F9D})

    -- Audio capture effects ({F665AABA-3E09-4920-AA5F-219811148F09}) --

     

  • Matthew van Eerde's web log

    How to enumerate DirectShow filters on your system

    • 3 Comments

    Last time I showed how to enumerate Media Foundation transforms.  This time, DirectShow filters.  Source and binaries attached.

    In pseudocode:

    GUID directshow_categories[] = { ... }; // static list
    ICreateDevEnum = CoCreate(...);
    for (each category in directshow_categories) {
        display the category name and GUID

        IEnumMoniker = ICreateDevEnum::CreateClassEnumerator(category);

        for (each IMoniker that IEnumMoniker finds) {
            IBindCtx = CreateBindCtx(...);
            IPropertyBag = IMoniker::BindToStorage(IBindCtx);

            pull the friendly name from the IPropertyBag and display it
        }
    }

    Output of the tool on my system:

    >devenum.exe
    -- Audio Capture Sources ({33D9A762-90C8-11D0-BD43-00A0C911CE86}) --
        Front Microphone (High Definiti
        Line In (High Definition Audio
        Rear Microphone (High Definitio

    -- Audio Compressors ({33D9A761-90C8-11D0-BD43-00A0C911CE86}) --
        WM Speech Encoder DMO
        WMAudio Encoder DMO
        IMA ADPCM
        PCM
        Microsoft ADPCM
        GSM 6.10
        CCITT A-Law
        CCITT u-Law
        MPEG Layer-3

    -- Audio Renderers ({E0F158E1-CB04-11D0-BD4E-00A0C911CE86}) --
        Speakers (High Definition Audio
        Default DirectSound Device
        Default WaveOut Device
        DirectSound: Speakers (High Definition Audio Device)

    -- Device Control Filters ({CC7BFB46-F175-11D1-A392-00E0291F3959}) --

    -- DirectShow Filters ({083863F1-70DE-11D0-BD40-00A0C911CE86}) --
        WMAudio Decoder DMO
        WMAPro over S/PDIF DMO
        WMSpeech Decoder DMO
        MP3 Decoder DMO
        Mpeg4s Decoder DMO
        WMV Screen decoder DMO
        WMVideo Decoder DMO
        Mpeg43 Decoder DMO
        Mpeg4 Decoder DMO
        DV Muxer
        Color Space Converter
        WM ASF Reader
        AVI Splitter
        VGA 16 Color Ditherer
        SBE2MediaTypeProfile
        Microsoft DTV-DVD Video Decoder
        AC3 Parser Filter
        StreamBufferSink
        Microsoft TV Captions Decoder
        MJPEG Decompressor
        CBVA DMO wrapper filter
        MPEG-I Stream Splitter
        SAMI (CC) Parser
        VBI Codec
        MPEG-2 Splitter
        Closed Captions Analysis Filter
        SBE2FileScan
        Microsoft MPEG-2 Video Encoder
        Internal Script Command Renderer
        MPEG Audio Decoder
        DV Splitter
        Video Mixing Renderer 9
        Microsoft MPEG-2 Encoder
        ACM Wrapper
        Video Renderer
        MPEG-2 Video Stream Analyzer
        Line 21 Decoder
        Video Port Manager
        Video Renderer
        VPS Decoder
        WM ASF Writer
        VBI Surface Allocator
        File writer
        iTV Data Sink
        iTV Data Capture filter
        DVD Navigator
        Microsoft TV Subtitles Decoder
        Overlay Mixer2
        AVI Draw
        RDP DShow Redirection Filter
        Microsoft MPEG-2 Audio Encoder
        WST Pager
        MPEG-2 Demultiplexer
        DV Video Decoder
        SampleGrabber
        Null Renderer
        MPEG-2 Sections and Tables
        Microsoft AC3 Encoder
        StreamBufferSource
        Smart Tee
        Overlay Mixer
        AVI Decompressor
        NetBridge
        AVI/WAV File Source
        Wave Parser
        MIDI Parser
        Multi-file Parser
        File stream renderer
        Microsoft DTV-DVD Audio Decoder
        StreamBufferSink2
        AVI Mux
        Line 21 Decoder 2
        File Source (Async.)
        File Source (URL)
        Media Center Extender Encryption Filter
        AudioRecorder WAV Dest
        AudioRecorder Wave Form
        SoundRecorder Null Renderer
        Infinite Pin Tee Filter
        Enhanced Video Renderer
        BDA MPEG2 Transport Information Filter
        MPEG Video Decoder

    -- External Renderers ({CC7BFB41-F175-11D1-A392-00E0291F3959}) --

    -- Midi Renderers ({4EFE2452-168A-11D1-BC76-00C04FB9453B}) --
        Default MidiOut Device
        Microsoft GS Wavetable Synth

    -- Video Capture Sources ({860BB310-5D01-11D0-BD3B-00A0C911CE86}) --

    -- Video Compressors ({33D9A760-90C8-11D0-BD43-00A0C911CE86}) --
        WMVideo8 Encoder DMO
        WMVideo9 Encoder DMO
        MSScreen 9 encoder DMO
        DV Video Encoder
        MJPEG Compressor
        Cinepak Codec by Radius
        Intel IYUV codec
        Intel IYUV codec
        Microsoft RLE
        Microsoft Video 1

    -- WDM Stream Decompression Devices ({2721AE20-7E70-11D0-A5D6-28DB04C10000}) --

    -- WDM Streaming Capture Devices ({65E8773D-8F56-11D0-A3B9-00A0C9223196}) --
        HD Audio Microphone
        HD Audio Muxed capture

    -- WDM Streaming Crossbar Devices ({A799A801-A46D-11D0-A18C-00A02401DCD4}) --

    -- WDM Streaming Rendering Devices ({65E8773E-8F56-11D0-A3B9-00A0C9223196}) --
        HD Audio Speaker

    -- WDM Streaming Tee/Splitter Devices ({0A4252A0-7E70-11D0-A5D6-28DB04C10000}) --
        Tee/Sink-to-Sink Converter

    -- WDM Streaming TV Audio Devices ({A799A802-A46D-11D0-A18C-00A02401DCD4}) --

    -- WDM Streaming TV Tuner Devices ({A799A800-A46D-11D0-A18C-00A02401DCD4}) --

    -- WDM Streaming VBI Codecs ({07DAD660-22F1-11D1-A9F4-00C04FBBDE8F}) --

    -- WDM Streaming Communication Transforms ({CF1DDA2C-9743-11D0-A3EE-00A0C9223196}) --
        Tee/Sink-to-Sink Converter

    -- WDM Streaming Data Transforms ({2EB07EA0-7E70-11D0-A5D6-28DB04C10000}) --

    -- WDM Streaming Interface Transforms ({CF1DDA2D-9743-11D0-A3EE-00A0C9223196}) --

    -- WDM Streaming Mixer Devices ({AD809C00-7B88-11D0-A5D6-28DB04C10000}) --

    -- BDA Network Providers ({71985F4B-1CA1-11D3-9CC8-00C04F7971E0}) --
        Microsoft ATSC Network Provider
        Microsoft DVBC Network Provider
        Microsoft DVBS Network Provider
        Microsoft DVBT Network Provider
        Microsoft Network Provider

    -- BDA Receiver Components ({FD0A5AF4-B41D-11D2-9C95-00C04F7971E0}) --

    -- BDA Rendering Filters ({71985F4A-1CA1-11D3-9CC8-00C04F7971E0}) --

    -- BDA Source Filters ({71985F48-1CA1-11D3-9CC8-00C04F7971E0}) --

    -- BDA Transport Information Renderers ({A2E3074F-6C3D-11D3-B653-00C04F79498E}) --
        BDA MPEG2 Transport Information Filter
        MPEG-2 Sections and Tables

    -- Video Effects (1 input) ({CC7BFB42-F175-11D1-A392-00E0291F3959}) --
        Fade
        BasicImage
        Convolution
        Chroma
        Matrix
        Pixelate
        DxtAlphaSetter Class
        Text Label Class
        Scale
        Blur
        Glow
        ICMFilter
        Alpha
        DropShadow
        Wave
        MotionBlur
        Shadow
        Emboss
        Engrave
        Light

    -- Video Effects (2 inputs) ({CC7BFB43-F175-11D1-A392-00E0291F3959}) --
        CrBlinds
        Iris
        RadialWipe
        Fade
        ZigZag
        RandomBars
        CrIris
        CrRadialWipe
        Spiral
        Pixelate
        Wheel
        Strips
        CrStretch
        Inset
        CrSlide
        CrInset
        Compositor
        Blinds
        CrSpiral
        Wipe
        CheckerBoard
        GradientWipe
        DxtCompositor Class
        CrBarn
        DxtKey Class
        Slide
        DxtJpeg Class
        CrZigzag
        Barn
        Stretch
        RandomDissolve

    -- EncAPI Encoders ({7D22E920-5CA9-4787-8C2B-A6779BD11781}) --
        Microsoft MPEG-2 Audio Encoder
        Microsoft MPEG-2 Video Encoder

    -- EncAPI Multiplexers ({236C9559-ADCE-4736-BF72-BAB34E392196}) --
        Microsoft MPEG-2 Encoder

     

  • Matthew van Eerde's web log

    Wheel of Fortune conundrum

    • 1 Comments
    What happens if Pat gets a Bankrupt on the Final Spin?
  • Matthew van Eerde's web log

    How to enumerate Media Foundation transforms on your system

    • 0 Comments

    This mini-application (source and binaries attached) uses MFTEnumEx to get a list of all the registered IMFTransform classes on the system.  If you're writing a Media Foundation app, you're likely going to use different flags than I used... see the documentation for sets of flags that match three different scenarios.

    In my case I wanted as exhaustive a list of transforms as possible - so I include asynchronous MFTs, disabled MFTs, etc:

    DWORD dwFlags = 0
        // enumerate all three kinds of data flow
        | MFT_ENUM_FLAG_SYNCMFT
        | MFT_ENUM_FLAG_ASYNCMFT
        | MFT_ENUM_FLAG_HARDWARE
           
        // include not-usually-included kinds of MFTs
        | MFT_ENUM_FLAG_FIELDOFUSE
        | MFT_ENUM_FLAG_LOCALMFT
        | MFT_ENUM_FLAG_TRANSCODE_ONLY
       
        // DO NOT filter or sort the results
        // we want to include even blocked MFTs in this list
        // EXPLICITLY NOT SETTING MFT_ENUM_FLAG_SORTANDFILTER
    ;

    Opportunities for later improvement - I only print out the friendly name and the CLSID for each found transform.  I could add things like the MF_TRANSFORM_FLAGS_Attribute, the MF_SUPPORT_DYNAMIC_FORMAT_CHANGE attribute, the supported input types and output types, etc.  But this is good enough for now.

    Output of the tool on my machine:

    > MFTEnum.exe

    -- Audio decoders ({9EA73FB4-EF7A-4559-8D5D-719D8F0426C7}) --
    WMAudio Decoder MFT ({2EEB4ADF-4578-4D10-BCA7-BB955F56320A})
    Microsoft AAC Audio Decoder MFT ({32D186A7-218F-4C75-8876-DD77273A8999})
    GSM ACM Wrapper MFT ({4A76B469-7B66-4DD4-BA2D-DDF244C766DC})
    WMAPro over S/PDIF MFT ({5210F8E4-B0BB-47C3-A8D9-7B2282CC79ED})
    WMSpeech Decoder DMO ({874131CB-4ECC-443B-8948-746B89595D20})
    G711 Wrapper MFT ({92B66080-5E2D-449E-90C4-C41F268E5514})
    IMA ADPCM ACM Wrapper MFT ({A16E1BFF-A80D-48AD-AECD-A35C005685FE})
    MP3 Decoder MFT ({BBEEA841-0A63-4F52-A7AB-A9B3A84ED38A})
    ADPCM ACM Wrapper MFT ({CA34FE0A-5722-43AD-AF23-05F7650257DD})

    -- Audio effects ({11064C48-3648-4ED0-932E-05CE8AC811B7}) --
    AEC ({745057C7-F353-4F2D-A7EE-58434477730E})
    Resampler MFT ({F447B69E-1884-4A7E-8055-346F74D6EDB3})

    -- Audio encoders ({91C64BD0-F91E-4D8C-9276-DB248279D975}) --
    WM Speech Encoder DMO ({1F1F4E1A-2252-4063-84BB-EEE75F8856D5})
    WMAudio Encoder MFT ({70F598E9-F4AB-495A-99E2-A7C4D3D89ABF})
    Microsoft AAC Audio Encoder MFT ({93AF0C51-2275-45D2-A35B-F2BA21CAED00})

    -- Demultiplexers ({A8700A7A-939B-44C5-99D7-76226B23B3F1}) --
    No IMFTransforms found.

    -- Multiplexers ({059C561E-05AE-4B61-B69D-55B61EE54A7B}) --
    No IMFTransforms found.

    -- Miscellaneous ({90175D57-B7EA-4901-AEB3-933A8747756F}) --
    No IMFTransforms found.

    -- Video decoders ({D6C02D4B-6833-45B4-971A-05A4B04BAB91}) --
    DV Decoder MFT ({404A6DE5-D4D6-4260-9BC7-5A6CBD882432})
    Mpeg4s Decoder MFT ({5686A0D9-FE39-409F-9DFF-3FDBC849F9F5})
    Microsoft H264 Video Decoder MFT ({62CE7E72-4C71-4D20-B15D-452831A87D9D})
    WMV Screen decoder MFT ({7BAFB3B1-D8F4-4279-9253-27DA423108DE})
    WMVideo Decoder MFT ({82D353DF-90BD-4382-8BC2-3F6192B76E34})
    NVIDIA Video Decoder MFT ({ACAE6A3C-3DB0-4F71-B783-CDBD2AC6FDE8})
    MJPEG Decoder MFT ({CB17E772-E1CC-4633-8450-5617AF577905})
    Mpeg43 Decoder MFT ({CBA9E78B-49A3-49EA-93D4-6BCBA8C4DE07})
    Mpeg4 Decoder MFT ({F371728A-6052-4D47-827C-D039335DFE0A})

    -- Video effects ({12E17C21-532C-4A6E-8A1C-40825A736397}) --
    Frame Rate Converter ({01F36CE2-0907-4D8B-979D-F151BE91C883})
    Resizer MFT ({1EA1EA14-48F4-4054-AD1A-E8AEE10AC805})
    Color Control ({798059F0-89CA-4160-B325-AEB48EFE4F9A})
    Color Converter MFT ({98230571-0087-4204-B020-3282538E57D3})

    -- Video encoders ({F79EAC7D-E545-4387-BDEE-D647D7BDE42A}) --
    NVIDIA Video Encoder MFT ({305AFD76-ADD0-417E-AA99-3AC4FDB22B21})
    H264 Encoder MFT ({6CA50344-051A-4DED-9779-A43305165E35})
    WMVideo8 Encoder MFT ({7E320092-596A-41B2-BBEB-175D10504EB6})
    WMVideo9 Encoder MFT ({D23B90D0-144F-46BD-841D-59E4EB19DC59})

    -- Video processors ({302EA3FC-AA5F-47F9-9F7A-C2188BB16302}) --
    NVIDIA Video Processor MFT ({6A8C0482-4A25-48A1-AFD1-0A7C1629352A})

    -- KS data compressors ({1E84C900-7E70-11D0-A5D6-28DB04C10000}) --
    No IMFTransforms found.

    -- KS data decompressors ({2721AE20-7E70-11D0-A5D6-28DB04C10000}) --
    No IMFTransforms found.

    EDIT: the IMFAttributes::GetAllocatedString call in this app is incorrect.  I pass a NULL for the "length" output parameter.  As it turns out, this must not be NULL because the call may be marshaled out-of-proc.

  • Matthew van Eerde's web log

    Jeopardy conundrum

    • 4 Comments

    What happens if Double Jeopardy ends and all contestants are in the red (or have no money?)

    Do they skip Final Jeopardy and pick three new people for the next show?

  • Matthew van Eerde's web log

    Pirates of Penzance puzzle - what year is it?

    • 1 Comments

    The setting of today's blog post is The Pirates of Penzance, Gilbert and Sullivan's musical about making sure you read the fine print.

    The scene opens with a birthday celebration for Frederic, who has just turned 21 and completed his pirate apprenticeship.

    SAM.    For today our pirate 'prentice
            Rises from indenture freed;
        Strong his arm, and keen his scent is
            He's a pirate now indeed!

    ALL.    Here's good luck to Frederic's ventures!
            Frederic's out of his indentures.

    SAM.    Two and twenty, now he's rising,
            And alone he's fit to fly,
        Which we're bent on signalizing
            With unusual revelry.
    ...
    KING.  Yes, Frederic, from to-day you rank as a full-blown member of our band.


    Frederic, however, is a fine upstanding young man with no taste for piracy; he served this long only because he was contractually obligated.

    FRED.  To-day I am out of my indentures, and to-day I leave you for ever.
    ...
    SAM.  We don't seem to make piracy pay.  I'm sure I don't know why, but we don't.
    FRED.  I know why, but, alas! I mustn't tell you; it wouldn't be right.
    KING.  Why not, my boy?  It's only half-past eleven, and you are one of us until the clock strikes twelve.


    Reinforcement of the fact that (as of today) Fred is now twenty-one:

    FRED.  Ruth, I will be quite candid with you.  You are very dear to me, as you know, but I must be circumspect. You see, you are considerably older than I. A lad of twenty-one usually looks for a wife of seventeen.


    Fred is well on his way to wiping out his former employers when they track him down and point out a technicality in the contract:

    KING.

    For some ridiculous reason, to which, however, I've no desire to be disloyal,
    Some person in authority, I don't know who, very likely the Astronomer Royal,
    Has decided that, although for such a beastly month as February, twenty-eight days as a rule are plenty,
    One year in every four his days shall be reckoned as nine and twenty.
    Through some singular coincidence -- I shouldn't be surprised if it were owing to the agency of an ill-natured fairy --
    You are the victim of this clumsy arrangement, having been born in leap-year, on the twenty-ninth of February;
    And so, by a simple arithmetical process, you'll easily discover,
    That though you've lived twenty-one years, yet, if we go by birthdays, you're only five and a little bit over!
    ...
    FRED.  (more amused than any)  How quaint the ways of Paradox!
        At common sense she gaily mocks!
        Though counting in the usual way,
            Years twenty-one I've been alive,
        Yet, reckoning by my natal day,
            I am a little boy of five!

    RUTH and KING.    He is a little boy of five! Ha! ha! ha!
    ...
    FRED.  Upon my word, this is most curious -- most absurdly whimsical. Five-and-a-quarter!  No one would think it to look at me!
    RUTH.  You are glad now, I'll be bound, that you spared us. You would never have forgiven yourself when you discovered that you had killed two of your comrades.
    FRED.  My comrades?
    KING.  (rises)  I'm afraid you don't appreciate the delicacy of your position:   You were apprenticed to us --
    FRED.  Until I reached my twenty-first year.
    KING.  No, until you reached your twenty-first birthday (producing document), and, going by birthdays, you are as yet only five-and-a-quarter.


    Shocked, Fred goes to confess to his sweetheart Mabel, portrayed in this picture by Marion Hood:

     http://blogs.msdn.com/photos/matthew_van_eerde/images/10004590/original.aspx

    FRED.    No, Mabel, no.  A terrible disclosure
        Has just been made. Mabel, my dearly-loved one,
        I bound myself to serve the pirate captain
        Until I reached my one-and-twentieth birthday --
    MABEL.    But you are twenty-one?
    FRED.        I've just discovered
        That I was born in leap-year, and that birthday
        Will not be reached by me till nineteen forty!

    MABEL.    Oh, horrible!  Catastrophe appalling!

    This brings us to the point.  Calculate the following:

    1. In what year was Frederic born?
    2. With as much accuracy as possible, specify the date and time of the opening scene.
  • Matthew van Eerde's web log

    Solution: baby boys and baby girls

    • 1 Comments

    Last week I posed an interview question about the ratio of baby boys to girls in a hypothetical country.

    In a country in which people only want boys, every family continues to have children until they have a boy. If they have a girl, they have another child. If they have a boy, they stop. What is the proportion of boys to girls in the country?

    The correct conclusion is "probably pretty close to 50-50," but the path to the conclusion is far more interesting and important than the conclusion itself.

    This question interests me (though I would never use it as an interview question) because there are many ways to get the answer.  There are many different kinds of assumptions that are entailed by the problem statement, and the mathematical rigor of the solution can vary tremendously.

    First, check out Business Insider's answer, which is perfectly adequate.  The approach is to solve the more specific problem "... when there are 10 families, and they all start at once."  (This is an excellent approach, recommended [among others] by the famous mathematician George Polya.)

    This one caused quite the debate, but we figured it out following these steps:

    • Imagine you have 10 couples who have 10 babies. 5 will be girls. 5 will be boys. (Total babies made: 10, with 5 boys and 5 girls)
    • The 5 couples who had girls will have 5 babies. Half (2.5) will be girls. Half (2.5) will be boys. Add 2.5 boys to the 5 already born and 2.5 girls to the 5 already born. (Total babies made: 15, with 7.5 boys and 7.5 girls.)
    • The 2.5 couples that had girls will have 2.5 babies. Half (1.25) will be boys and half (1.25) will be girls. Add 1.25 boys to the 7.5 boys already born and 1.25 girls to the 7.5 already born. (Total babies: 17.5 with 8.75 boys and 8.75 girls).
    • And so on, maintianing a 50/50 population.

    This is a good back-of-the-envelope calculation, but it talks about things like "2.5 babies" which is silly and "and so on, maintaining a 50/50 population" which begs the question.  Nevertheless, it's a good answer for a short interview.

    Before I get to my own solutions, a digression on another related problem:

    Two trains are heading toward each other on the same track.  They are 120 miles apart (as the track is laid) at time t = 0.  Each train is moving at 30 mph.

    At time t = 0 a fly takes off from the front of the first train and starts flying toward the second train, following the track, at 60 mph (yes, this fly is faster than the train.)  As soon as it reaches the second train it turns around (losing no time on the turnaround, and without being crushed on the windshield) and starts back toward the first train.  When it reaches the first train again it turns around and heads back toward the second train again, and so on, back and forth, until the trains collide and the poor creature's miserable existence is mercifully ended between them.

    The question is: how many miles did the fly's odometer advance between time t = 0 and the collision?  (I know, flies don't usually have odometers. This fly does.  He's a very peculiar fly.  But you knew that already.)

    There are two canonical ways to answer this question.  One way is to start calculating from the fly's point of view:

    Well, the fly F starts at x = -60 and heads toward train T2 at 60 mph... but the train is heading toward the origin at 30 mph... so I solve the system of two linear equations F(t) = -60 + 60t and T2(t) = 60 - 30t and I get the point of intersection is at x = 20 (t = 1 1/3 but this is less relevant.)  So the fly goes 60 + 20 = 80 miles on the first leg.  Then he turns around and heads back toward T1, which by this time is at x = -20... so I solve the new system of two linear equations and I get the point of intersection is at x = -6 2/3.  So the fly goes 26 2/3 miles on the second leg, or 80 + 26 2/3 so far.  Now I do the third leg... hmm, it looks like the distance he goes on each leg is 1/3 the distance of the leg before, that's interesting... I wonder if I can prove it... [proof elided]... OK, it boils down to:

    http://blogs.msdn.com/photos/matthew_van_eerde/images/10000339/original.aspx

    ... and I know the geometric series formula...

    http://blogs.msdn.com/photos/matthew_van_eerde/images/10000345/original.aspx

    for |r| < 1 (Geometric series theorem.)

    ... if I pull out the 80 and substitute r = 1/3 I get... 

    http://blogs.msdn.com/photos/matthew_van_eerde/images/10000340/original.aspx

    which comes out to... 120 miles!

    This is absolutely correct.  But the other way is to back off a step and look at it from the director's point of view.

    OK, the trains start at time t = 0 and they head toward each other at 30 miles per hour each.  So the distance between them is getting smaller at a rate of 60 miles per hour.  There's 120 miles between them at the start, so the crash will happen at time t = 2 hours.  The little fly is going at a constant 60 miles per hour throughout those two hours (poor little fella) so he'll have racked up exactly 120 miles of travel at the time of the collision.  I don't know how far he goes on any given leg (and I don't particularly care.)

    Legend has it that legendary mathematician John von Neumann was asked this question during class by a student eager to show him up.  Von Neumann thought for a few moments and came up with the correct answer.

    Student (somewhat embarrassed:) Darn... I was hoping you wouldn't see the shortcut, and you'd have to sum the series.

    Von Neumann (puzzled:) I did sum the series.

    Student: (awed silence)

    Heh.  Gets me every time.

    Anyway, back to boys and girls.  The "easy" way to solve this is to think of it from the point of view of the hospital maternity ward:

    Every day, women come in and give birth.  The midwife doesn't know (or care) how many siblings the newborn has, and nothing in the problem statement changes the assumption that the midwife is going to see a (roughly) equal number of boys and girls being delivered.  So the ratio of boys to girls is (roughly) 50-50.

    Changing the point of view from the family to the hospital reveals that almost all of the information in the problem statement was extraneous:

    In a country in which people only want boys, every family continues to have children until they have a boy. If they have a girl, they have another child. If they have a boy, they stop. What is the proportion of boys to girls in the country?

    All well and good.  But let's try the summing-the-series way (I'm a glutton for punishment.)  We'll start by figuring out how many boys there are, and then figure out how many girls there are, and then calculate the ratio directly.  This way we'll actually use all the information in the problem.

    -- How many boys are there? --

    Well, the number of families in the country is not given.  Let's call it F, and we'll only count families that actually have children.  About half of the families would have had a boy first... that's F / 2 boys.  The remainder would have tried again.  About half of these would have gotten a boy on the second try... that's F / 4 boys.  The remainder would have tried again.  About half of these would have gotten a boy on the third try... that's F / 8 boys.

    At this point we can use an inductive argument to say that for any n from 1 to infinity, there are F / 2n boys that result from the a family getting a boy on the nth try.  Key to this inductive argument are the perfectly natural assumptions that a family can support arbitrarily many children, and that a woman is capable of generating children arbitrarily quickly.

    The total number of boys B can then be calculated as:

    http://blogs.msdn.com/photos/matthew_van_eerde/images/10000341/original.aspx

    (Note the use of the geometric series formula again.)

    That is to say, there are precisely as many boys as there are families.  Which makes sense because each family has one boy.  Hmm, perhaps there was an easier way to solve this part...

    -- How many girls are there? --

    The F / 2 families that got a boy first shot out of the box have 0 girls: 0 * F / 2.

    The F / 4 families that got a boy on the second try have 1 girl each: 1 * F / 4.

    The F / 8 families that got a boy on the third try have 2 girls each: 2 * F / 8.

    ...

    The total number of girls G is thus:

    http://blogs.msdn.com/photos/matthew_van_eerde/images/10000342/original.aspx

    ... um...

    It's not immediately clear how to sum the series.  An elegant way is to use a trick worth remembering:

    Let:

    http://blogs.msdn.com/photos/matthew_van_eerde/images/10000348/original.aspx
    I am assuming both |x| < 1 (for convergence) and x ≠ 0 (for convenience.)

    Differentiate (this is the trick:)

    http://blogs.msdn.com/photos/matthew_van_eerde/images/10000350/original.aspx

    Multiply both sides by x:

    http://blogs.msdn.com/photos/matthew_van_eerde/images/10000349/original.aspx

    Now substitute x = 1/2:

    http://blogs.msdn.com/photos/matthew_van_eerde/images/10000346/original.aspx

    Back to the calculation:

    http://blogs.msdn.com/photos/matthew_van_eerde/images/10000343/original.aspx

    Heh.  The total number of girls is also equal to the total number of families... they're just distributed differently (F / 2 families have no girls; F / 4 have one; F / 8 have two; F / 16 have three, etc.)

    -- What is the ratio of boys to girls? --

    Since B = G = F, the ratio B / G = 1.

    QED

    All this beautiful analysis to the contrary, the answer is actually wrong.  More boys are born every year than girls (at a ratio of about 106 to 100), and this is countered gradually due to a higher mortality rate among boys than girls (there are fewer girls born every year but they have a higher life expectancy.)  The cutoff age is 36... below this age there are more men than women, above that age there are more women than men.

  • Matthew van Eerde's web log

    Interview question: baby boys and baby girls

    • 1 Comments

    Source:

    http://www.businessinsider.com/15-google-interview-questions-that-will-make-you-feel-stupid-2009-11#in-a-country-in-which-people-only-want-boys-3

    In a country in which people only want boys, every family continues to have children until they have a boy. If they have a girl, they have another child. If they have a boy, they stop. What is the proportion of boys to girls in the country?

    Answer next week.

    EDIT 4/26: Answer.

  • Matthew van Eerde's web log

    Spot the bug - Outlook "block sender" icon, solution

    • 2 Comments

    Last week I posed the question, what's wrong with this Outlook icon?

     http://blogs.msdn.com/photos/matthew_van_eerde/images/9995171/original.aspx

    The answer is simple - the slash in the "no" icon goes the wrong way.

    My personal keystone for this is a street sign in a certain panel of The Calculus Affair, but the direction of the slash is part of ISO-3864: top-left to bottom-right.

     http://blogs.msdn.com/photos/matthew_van_eerde/images/9995183/original.aspx

    Perhaps a better mnemonic is to think of the word "NO":

    http://blogs.msdn.com/photos/matthew_van_eerde/images/9995183/original.aspx=http://blogs.msdn.com/photos/matthew_van_eerde/images/9995921/original.aspx+http://blogs.msdn.com/photos/matthew_van_eerde/images/9995922/original.aspx

    The Outlook team isn't the only one to get this wrong, though:

     http://blogs.msdn.com/photos/matthew_van_eerde/images/9995182/original.aspx

  • Matthew van Eerde's web log

    Spot the bug - Outlook "block sender" icon

    • 4 Comments

    Back in Windows 7 I did a fair amount of UI testing for the Sound team.

    One of the problems with testing UI is it gives you an unconscious attention to detail that's difficult to unlearn.

    For example, this Outlook bug didn't bother me before... but now it does.

    http://blogs.msdn.com/photos/matthew_van_eerde/images/9995171/original.aspx

    Exercise: what is the bug?

    Answer next week.

    EDIT 4/19/201: Answer.

  • Matthew van Eerde's web log

    Blown movie lines - Torn Curtain

    • 1 Comments

    http://blogs.msdn.com/photos/matthew_van_eerde/images/9992536/original.aspx

    In the underrated movie Torn Curtain, American scientists Michael Armstrong (Paul Newman) and Sarah Louise Sherman (Julie Andrews) meet up with East German scientist Gustav Lindt (the excellent actor Ludwig Dorath) to pump him for a secret formula (the MacGuffin.)

    They're at an upscale party and a waltz is playing.  Lindt is a little tipsy and enjoying himself, and he says:

    Lindt: The Vienna Waltz. Did I tell you my sister Emily was knocked down by a tram in Vienna? (sings along to the good bit - about 0:54 in the link below.)

    Why is this a blown line?

    Because there is no such waltz. There are various waltzes with "Vienna" in the title, but the particular waltz in question is the Emperor Waltz.  It would indeed be unfortunate if poor Emily was knocked down by the Emperor...

    Hitchcock directed a film about Johann Strauss, Jr.: Waltzes from Vienna, and Ludwig Donath was himself Austrian, so this mistake is surprising.

    As an aside, it was this movie (in particular the blackboard scene) that stimulated my youthful interest in mathematics.  A couple of people arguing over weird chalk symbols and one of them says "it would blow up!" - that got my attention.
  • Matthew van Eerde's web log

    Famous Watch Story

    • 0 Comments

    Thanks to Gerry F. in Tampa for raising this interesting question.  Given: a perfect watch with three sweep hands (hour, minute and second).  (By "sweep", I mean that the hands move continuously and do not "jump" every hour, minute, or second.)

     http://blogs.msdn.com/photos/matthew_van_eerde/images/9955069/original.aspx

    Find: a list of all times at which the three hands divide the circle of the clock into three equal sections - that is to say, any pair of hands will form a 120° angle, or, in radians, an angle of 2π/3.  (For the rest of the post I will use radians.)

    The remainder of this post is my proof of the surprising result.  If you'd like to try solving the problem yourself, stop reading now...

    OK.  First, let's define some terms.

    Let t be the time.  I'm going to make a rather strange choice for the units.  I have the obvious choices of hours, minutes, or seconds - instead, I'm going to choose a unit of half-days.  So 12:00 corresponds to t = 0 or 1; 4:00 corresponds to t = 1/3; 9:00 corresponds to t = 3/4, etc.  Note the clock has periodic behavior with a period of 1 (in units of t.)

    Let H be the directed angle between 12 and the hour hand, increasing from 0 (at 12:00, t = 0) through π/2 (at 3:00) and all the way 'round to 2π at 12:00 again.  Note that at 9:00 H is defined to be 3π/2 and not merely π/2.  Note that H is also periodic with period 1.

    Let M be the directed angle between 12 and the minute hand similarly.  Note M is periodic with period 1/12: the minute hand goes all the way 'round in an hour, which is 1/12 of a half-day.

    Let S be the directed angle between 12 and the second hand.  Note S is periodic with period 1/720: the second hand goes 'round 720 times in a half-day.

    We can now write explicit formulas for H, M, and S in terms of t:

    http://blogs.msdn.com/photos/matthew_van_eerde/images/9955070/original.aspx

    Define θxy as the directed angle between hand x and hand y.  In particular:

    http://blogs.msdn.com/photos/matthew_van_eerde/images/9955071/original.aspx

    The key point is that the angles between the hands are periodic.  The angle between the minute and the hour hands cycles from 0 through 2π exactly 11 times every half-day; the angle between the minute and the hour hands, exactly 12*59 times; and the angle between the hour and the second hands, exactly (12*60 - 1) = 719 times.

    Now that we have formulas for the three relevant angles, we can answer the question "when are these angles 2π/3 or 4π/3?"  In particular, define {txy} as the set of times at which the x and y hands make either a 2π/3 angle or a 4π/3 angle.

    Let's consider the angle between the hour and minute hand first.

     http://blogs.msdn.com/photos/matthew_van_eerde/images/9955072/original.aspx

    So the angle is 2π/3 (or 4π/3) at multiples of t = 1/33 of a half-day, or every 12*60/33 = 21 and 9/11 minutes... except that at every third multiple of 21 and 9/11 minutes, the hands coincide, so those don't count.

    But rather than think of it as "21 and 9/11 minutes", I'd like to urge you to think of it as "1/(3*11) of a cycle."

    Now consider the angle between the minute and the second hand:

    http://blogs.msdn.com/photos/matthew_van_eerde/images/9955075/original.aspx

    The angle between the minute and the second hand is 2π/3 or 4π/3 at multiples of 1/(3*12*59) of a half-day (except that, as before, at every third multiple of 1/2124 the hands coincide instead of making a suitable angle.)

    The following is a demonstration that {tHM} and {tMS} have no elements in common.  This implies that the hour/minute angle and the minute/second angle are never 2π/3 or 4π/3 simultaneously.  As this is a necessary condition for the three hands to divide the clock evenly, the three hands never divide the clock evenly.

    Write {tHM} and {tMS} in lowest terms.  How many factors of 3 are there in the numerator of each fraction?  In the denominator?

    The numerator is easy.  The numerator is never a multiple of 3 to begin with, and cancelation of common terms in the numerator and denominator will never add a factor, so after cancelation there are (still) no factors of 3.

    The denominator for each tHM has exactly one factor of 3; the denominator for each tMS has exactly two factors of 3.

    Thus, the two sets have no elements in common, and the clock is never evenly divided.  QED.

    To illustrate the importance of the numerator being a nonmultiple of 3, let's calculate {tHS}:

     http://blogs.msdn.com/photos/matthew_van_eerde/images/9955073/original.aspx

    719 happens to be prime.

    It is tempting to put forth the following fallacious argument:

    Fallacious argument: "{tHS} consists of a bunch of fractions whose denominator contains the large prime factor 719.  Neither of the other sets {tHM} or {tMS} contain this large prime factor in their denominators... therefore {tHS} contains no elements in common with either {tHM} or {tMS}, QED."

    The problem with this argument is that it attempts to prove something that is false.  True, the intersection of {tHS} and {tMS} is empty, but the intersection of {tHS} and {tHM} is not empty - in fact, it consists of precisely the two elements { 1/3, 2/3 } (which correspond to 4:00:00 and 8:00:00 respectively.)

    What happened to the factor of 719 in the denominator?  It got canceled out by a multiple of 719 in the numerator.  In particular, 1/3 = (3*239 + 2)/(3*719), and 2/3 = (3*479 + 1)/(3*719).

  • Matthew van Eerde's web log

    Newton: combining celestial and terrestrial mechanics

    • 1 Comments

    For as long as there have been humans, we have looked at the skies - and around us on Earth as well.  Things move in the skies; things move on Earth.  The way things move in the skies is called "celestial mechanics"; the way things move on Earth is called "terrestrial mechanics."

    The ancient Greeks thought there were five elements, corresponding to the five regular (Platonic) solids: the four terrestrial elements (air, fire, earth, and water) and the fifth celestial element which the Romans called quintessence.

    All kinds of rules were discovered/proposed for how things move on Earth.  Galileo demonstrated that falling objects accelerate at the same rate regardless of their mass.  Similar rules were discovered/proposed for how things move in the heavens.  Kepler demonstrated that the planets move in ellipses around the sun, that they swept out equal areas in equal times, etc.  But everybody knew that things in the heavens were different than they were on Earth.

    Then Newton, building on Hooke, came up with the crazy idea that perhaps things fall on Earth for the same reason that heavenly objects go in ellipses... that all objects, celestial or terrestrial, act on each other from a distance in a uniform fashion.  (He himself wrote that this was such a crazy idea that no-one should take it seriously.)

    That one body may act upon another at a distance through a vacuum without the mediation of anything else, by and through which their action and force may be conveyed from one another, is to me so great an absurdity that, I believe, no man who has in philosophic matters a competent faculty of thinking could ever fall into it. -- Isaac Newton

    But he had done some calculations and it seemed to work out... specifically, he worked out how much acceleration you would expect the Earth to exert on an object as far away as the Moon, and how much acceleration the Moon would need to stay in its orbit (and not wander off or spiral down into the Earth.)

    I... compared the force requisite to keep the moon in her orb with the force of gravity at the surface of the earth and found them to answer pretty nearly. -- Isaac Newton

    Note Newton's use of the word "orb" to describe the motion of the moon, a direct reference to celestial mechanics.

    Let's see how compelling those calculations were, shall we?

    His first idea was that there was this thing called "force" which was equal to the mass of an object multiplied by the acceleration it was undergoing.  F = m a.  Fine.

    His second idea (which he stole, at least partially, from Hooke) was that any two objects have a force that attracts them, which is proportional to both of their masses, and inversely proportional to the square of the distance between them (that's the part he stole from Hooke.)  F = G m1 m2 / r2.  Fine.

    His third idea was that an object that goes around a circle of radius r at a constant speed v is undergoing a constant centripetal acceleration of a = v2 / rThis follows pretty quickly from the definitions with a little geometry, trigonometry, and a dash of calculus.  Fine.

    He also knew some facts.  I'm going to state them in metric because, hey, this is the twenty-first century.  He knew:

    • The distance from the center of the Earth to the surface (where the apple trees are) is 3,960 miles: 6370 km.
    • Falling objects on the surface of the Earth accelerate at 32.2 ft/s2: 9.81 m/s2.
    • The distance from the center of the Earth to the center of the Moon is 239,000 miles: 384,000 km.
    • The Moon takes 27.3 days to make a single sidereal orbit around the Earth: 236,000 s.

    http://blogs.msdn.com/photos/matthew_van_eerde/images/9952568/original.aspx

    Coarse estimate time...

    If the Moon is roughly 50 times further away from the center of the Earth than an apple is, and "gravitational" acceleration is inversely proportional to the square of the distance between two objects, then the Moon should be accelerated roughly 1/2500th as much as the apple is: 0.004 m/s2 instead of 10 m/s2,

    More precisely...

    Consider the apple case (mE is the mass of the Earth, mA the mass of the apple:)

    FA = mA aA = G mE mA / rA2
    a
    A rA2 = G mE
    9.81 m/s2 (6.37e6 m)2 = G mE
    G
    mE = 3.98e14 m3/s2

    Now consider the moon case:

    FM = mM aM = G mE mM / rM2
    aM = G mE / rM2
    aM = 3.98e14 m3/s2 / (3.84e5 m)2
    aM = 0.00269 m/s2

    So Newton's proposed formula predicts that the Earth's gravity causes the Moon to accelerate at 0.00269 m/s2.  This is, indeed, roughly 0.004 m/s2 so it jives with our coarse estimate.

    Let's see how that compares to the necessary centripetal acceleration to achieve a closed orbit: a = v2 / r.

    The distance the moon travels in its sidereal orbit is 2π * 3.84e5 m = 2.42e9 m, and it does so in 27.3 days; so its velocity is 2π * 3.84e5 m / (27.3 days * 24 (hours / day) * 60 (minutes / hour) * 60 (s / minute)) = 1020 m/s.  This is roughly Mach 3 in our atmosphere.

    The centripetal acceleration is thus measured to be (1020 m/s)2 / 3.84e8 m = 0.00273 m/s2. Newton's prediction is about 1.5% off, which isn't bad, considering.

    Note that although Newton knew the value of the product G mE, he didn't know either G or mE seperately.  It wasn't until Cavendish took two known masses and measured the gravitational pull between them directly that G was evaluated; we could then calculate the mass of the earth as G mE / G.

    Once G was known we could also evaluate the mass of the Sun based on Earth's orbit.  However, we still could not determine the mass of the Moon... in fact, back in the 1950s, American scientists were unable to determine the mass of Sputnik (which would have been very helpful) even though we could see its orbit.

    Which raises the question... how did we know the mass of the Moon?

  • Matthew van Eerde's web log

    Deriving the centripetal acceleration formula

    • 25 Comments

    A body that moves in a circular motion (of radius r) at constant speed (v) is always being accelerated.  The acceleration is at right angles to the direction of motion (towards the center of the circle) and of magnitude v2 / r.

    The direction of acceleration is deduced by symmetry arguments.  If the acceleration pointed out of the plane of the circle, then the body would leave the plane of the circle; it doesn't, so it isn't.  If the acceleration pointed in any direction other than perpendicular (left or right) then the body would speed up or slow down.  It doesn't.

    Now for the magnitude.  Consider the distance traveled by the body over a small time increment Δt:

    http://blogs.msdn.com/photos/matthew_van_eerde/images/9952566/original.aspx

    We can calculate the arc length s as both the distance traveled (distance = rate * time = v Δt) and using the definition of a radian (arc = radius * angle in radians = r Δθ:)

    http://blogs.msdn.com/photos/matthew_van_eerde/images/9952564/original.aspx

    The angular velocity of the object is thus v / r (in radians per unit of time.)

    The right half of the diagram is formed by putting the tails of the two v vectors together.  Note that Δθ is the same in both diagrams.

    http://blogs.msdn.com/photos/matthew_van_eerde/images/9952565/original.aspx

    Note the passing from sin to cos is via l'Hôpital's rule.

    QED.

  • Matthew van Eerde's web log

    Rules for making change

    • 0 Comments

    It happens a million times a day.  Somebody pays cash for something and gets change.  But there are rules, and Raymond's friend seems to like to break those rules.  Luckily for Raymond's friend, one of the rules is the customer is always right... or as Mr. Krabs would say, the money is always right.  This blog post is about a couple of the more mathematical rules.

    Rule for the cashier: you must give "canonical" change.

    Whether to honor requests for non-canonical change is a complicated morass I will not attempt to tackle in this blog post as too much depends on context.  But the initial offering must be canonical.

    By "canonical change", I mean the cashier must give change using the smallest possible number of canonical coins and bills.  For example, (one quarter + one nickel) is a rendering of $0.30 using only two coins, while (three dimes) is three coins, so a cashier must never give change that includes three dimes.

    By "canonical coins and bills" I mean (in the U.S.) this precise list:

    • penny
    • nickel
    • dime
    • quarter
    • $1 bill
    • $5 bill
    • $10 bill
    • $20 bill
    I discuss usage of non-canonical (unusual) coins and bills later.

    Rule 1 for the customer: "Tap, tap, no takebacks"

    The tender and canonical change cannot intersect.

    Don't give the cashier anything they would just hand back to you directly.

    This is the rule that Raymond's friend broke - it just wastes everyone's time to play musical chairs with the money.
    Actually, this rule is just a corollary of the more general rule:

    Rule 2 for the customer: "No side transactions."

    No subset of the tender can have the same value as any subset of canonical change for that tender.

    Don't give the cashier anything that they would just hand back to you in coalesced form.

    If you want to consolidate your change, go to a bank or use one of those big machines.

    Corollary 1: it is always OK to pay with a single large bill.
    Corollary 2: it is always OK to give exact change.

    Unusual denominations:

    The two-dollar bill, the dollar coin (in any of its forms), the half-dollar coin, and bills higher than $20 are "unusual" denominations that complicate the situation slightly.

    Rule for the cashier: Unusual denominations stay in the drawer.

    Accept them (unless there are security rules at your place of business) but they are explicitly not part of any canonical change.

    Rule for the customer: Go right ahead.

    You can pay with an unusual denomination provided that you do not break the "no side transactions" rule or any large-denomination security rule at the business in question.

    Examples:

    In the following examples, "total" is the amount owed; "tender" is the amount the customer gives to the cashier; and "change" is what the cashier gives back to the customer.

    Total Tender Change Notes
    $5.20 $5 bill + $2 bill $1 bill + three quarters + one nickel OK - cashier correctly accepted the $2
    $5.20

    $5 bill + $1 bill

    two quarters + three dimes Cashier gave out more coins than necessary
    $5.20 $5 bill + $1 bill half-dollar + one quarter + one nickel Cashier gave out non-canonical half-dollar
    $5.20 $5 bill + four quarters three quarters + one nickel Customer gave three "takeback" quarters
    $5.20 $5 bill + quarter + nickel dime OK
    $5.20 $5 bill + quarter + five pennies dime OK
    $5.20 $5 bill + quarter + ten pennies dime + nickel Customer got nickel for five pennies in "side transaction"

    In the last row, you can think of the "side transaction" as either five pennies for a nickel or ten pennies for a dime. I prefer the former.

  • Matthew van Eerde's web log

    How to turn on HDCP or SCMS in an audio playback app

    • 1 Comments

    There's an MSDN sample of how to turn on HDCP or SCMS in a playback app.  The sample is loosely based on a test app I wrote, but there are still some rough edges.  For example, the CMFAttributeImpl<T> template is not part of the SDK or the DDK.  Also, there's a leak in the GetDigitalAudioEndpoint implementation.  (Using the private template was my bug.  The leak was someone else's.)

    Exercise: find the leak.

    There are also rough edges in the test app.  For one thing, it doesn't play audio - the way to use the app is to

    1. Start playing audio using your favorite audio playback application, to the digital output on which want to turn on HDCP or SCMS.
    2. Run the trustedaudiodrivers2.exe command line to do what you want it to.

    Source and binaries (x86 and amd64) attached.

    >trustedaudiodrivers2
    trustedaudiodrivers2 --list-devices

    trustedaudiodrivers2
        --device [ communications | console | multimedia | <device-name>]
        --copy-ok [ 0 | 1 ]
        --digital-output-disable [ 0 | 1 ]
        --test-certificate-enable [ 0 | 1 ]
        --drm-level <drm-level>

    --list-devices: displays a list of output devices.

    Sets a Trusted Audio Drivers 2 output policy on a given audio endpoint.
    --device
        communications: set policy on default communications render endpoint.
        console: set policy on default console render endpoint.
        multimedia: set policy on default multimedia render endpoint.
        <device-name>: set policy on the endpoint with this long name.
    --copy-ok: 1 or 0. Set to 0 to turn on "copy protection" (SCMS or HDCP)
    --digital-output-disable: 1 or 0. Set to 1 to disable output (or turn on HDCP.) --test-certificate-enable: 1 or 0. Set to 1 to allow the test certificate.
    --drm-level: set to a number. 1100 is a good default.

    Here's a sample command line which should disable the digital out (or enable HDCP, if the driver supports it.)  This is line-wrapped for readability only.

    >trustedaudiodrivers2.exe
        --device "Acer H213H (High Definition Audio Device)"
        --copy-ok 1
        --digital-output-disable 1
        --test-certificate-enable 1
        --drm-level 1300

    If all goes well the output should look something like this:

    Output Trust Authorities on this endpoint: 2
    Processing Output Trust Authority #1 of 2
    OTA action is PEACTION_PLAY (1)
    GetOriginatorID() called
    GetOriginatorID() called
    GenerateRequiredSchemas() called
    dwAttributes: MFOUTPUTATTRIBUTE_DIGITAL (0x00000001)
    guidOutputSubType: MFCONNECTOR_HDMI ({57CD596D-CE47-11D9-92DB-000BDB28FF98})
    cProtectionSchemasSupported: 1
    MFPROTECTION_TRUSTEDAUDIODRIVERS ({65BDF3D2-0168-4816-A533-55D47B027101})
    MFPROTECTION_TRUSTEDAUDIODRIVERS supported.
    IMFOutputSchema::GetSchemaType called
    IMFOutputSchema::GetConfigurationData called
    IMFOutputTrustAuthority::SetPolicy returned 0x00000000
    Processing Output Trust Authority #2 of 2
    OTA action is PEACTION_EXTRACT (4)
    Skipping as the OTA action is not PEACTION_PLAY
    Policy successfully applied.  Press any key to release IMFTrustedOutput...

    At that point I pressed a key, which redacted the policy, and the music started playing again.

    Common causes of failures:

    1. No audio is playing to that device.  Setting protection requires an active audio stream.
    2. The audio device is not S/PDIF or HDMI.
    3. The audio driver is not capable of enforcing the protection.
    4. The audio driver is test-signed only; try --test-certificate-enable 1
    5. Kernel debugging is enabled.
    6. Driver verifier is enabled.

    This source should compile with just publically available headers and no special voodoo on the part of the developer.

    EDIT: 11/13/2009 10:05 AM

    A subtle problem was called to my attention.  This line triggers an ATL ASSERT:

    hr = pMFOutputTrustAuthority->SetPolicy(&pMFOutputPolicy, 1, &pbTicket, &cbTicket);

    The ASSERT is in CComPtr<IMFOutputPolicy>::operator& which ASSERTs if the pointer CComPtr<IMFOutputPolicy>::p is not NULL.

    My first instinct was to bypass the assertion like this:

    hr = pMFOutputTrustAuthority->SetPolicy(&pMFOutputPolicy.p, 1, &pbTicket, &cbTicket);

    But ASSERTs are there for a reason.  The fundamental problem here is that I'm trying to be too clever.

    Despite its name, IMFOutputTrustAuthority::SetPolicy takes, not an IMFOutputPolicy *, but an array of IMFOutputPolicy *s.  A little confusing, yes.  As this is effectively a sample, I should be emphasizing this behavior, not covering it up.

    So here's the fix I decided on.  Updated source and binaries attached.

    // we're only setting a single policy but the API allows setting multiple policies
    // (like WaitForMultipleObjects)
    IMFOutputPolicy *rMFOutputPolicies[1] = { pMFOutputPolicy };
    hr = pMFOutputTrustAuthority->SetPolicy(
        rMFOutputPolicies,
        ARRAYSIZE(rMFOutputPolicies),
        &pbTicket,
        &cbTicket
    );

     

  • Matthew van Eerde's web log

    Perl one-liner: approximate pi via Monte Carlo method

    • 0 Comments

    http://programmingpraxis.com/2009/10/09/calculating-pi/

    >perl -e"print 4/(map{$n+=rand()**2+rand()**2<1}1..pop)*$n" 5000
    3.1336

    59 characters, plus arguments.

  • Matthew van Eerde's web log

    Nitpicking László Polgár's Chess: ... #1071

    • 2 Comments

    I was reading László Polgár's excellent book Chess: 5334 Problems, Combinations, and Games and ran across #1071, White to move and mate in 2:

    The purported solution is...

    1. ♘xf6+ ♚xf6
    2. ♕f7#

    ... which, indeed, works - and there is no other mate in two that I can see - so why blog this?

    Because there's a mate in one.

  • Matthew van Eerde's web log

    Forcing Windows to install on a single partition

    • 1 Comments

    If you're installing Windows via a boot DVD, and you choose Custom, you have the option to rearrange partitions.  I like use this to have each drive be one big partition.

    Windows 7 wants to set aside a 100 MB partition for something-or-other.  I'm sure there's a very good reason for this but I am too lazy to look up the team that owns this space and ask them what it is.

    So I'm in the "Where do you want to install Windows?" stage, I've gone into "advanced drive setup", and I've deleted all the partitions.  Fine.  I then create a partition that fills the drive, and I get this popup:

    Install Windows
    To ensure that all Windows features work correctly, Windows might create additional partitions for system files.
    OK | Cancel

    After letting Windows finish installing, I jump into diskpart.exe and sure enough, Windows has created an additional partition.  A small one, to be sure... but an additional partition (horrors!)

    Not being one to let Windows push me around, I decided to experiment, and came up with the following dance to allow me to just have one big partition thankyouverymuch:

    1. Boot from the Windows DVD
    2. Choose Custom (advanced) as opposed to Upgrade
    3. Go into Drive options (advanced)
    4. Delete all partitions on the drive
    5. Create a new partition - you will get the prompt above
    6. Click OK
    7. There will now be two partitions - a small (System) one and a large (Primary) one.
    8. Delete the large one.
    9. Extend the new one to fill the drive.
    10. Install Windows.
    11. Open Windows Explorer
    12. Right-click the C: drive | Properties
    13. Delete the "System Reserved" partition name
    Et voilà, Windows installs perfectly happily on the single partition (confirmed with diskpart.exe post-installation.)
  • Matthew van Eerde's web log

    Tweaks I make every time I install Windows

    • 9 Comments

    As preparation for moving one of my machines from Vista to Windows 7, I'm compiling a list of all the little tweaks I like to make to machines that I use a lot:

    Boot from the Windows DVD.  Delete all partitions; make each hard drive one big partition.  (Hmm... apparently Windows 7 really wants a second 100 MB partition.  Do the partition dance to force it into installing on a single partition.)

    In the "password hint" box, type a misleading hint.

    In "Help protect your computer and improve Windows automatically", choose "Ask me later."

    Once I'm in, create a new limited user (not a member of the Administrators group) and use that as my primary account.

    Control Panel | Hardware and Sound | Mouse
        Pointers | Enable pointer shadow (uncheck)
        Pointer Options
            Enhance pointer precision (uncheck)
            Hide pointer while typing (uncheck)

    Right-click taskbar | Properties | Taskbar
        Use small icons (check)
        Taskbar location on screen (change to "Right")
        Taskbar buttons (change to "Never combine")
        Notification area | Customize
            Turn system icons on or off
                Clock | Off (select)
                Volume | Off (select)
                Network | Off (select)
                ... turn everything off, except sometimes.
                (for example, I might leave Power on for a laptop.)
            Always show all icons and notifications on the taskbar (check)
        Use Aero Peek to preview the desktop (uncheck)

    Windows Explorer | Organize
        Layout | Details pane (uncheck)
        Folder and search options | View | Advanced settings
            Always show icons, never thumbnails (check)
            Always show menus (check)
            Display file icon on thumbnails (uncheck)
            Display file size information in folder tips (uncheck)
            Display the full path in the title bar (Classic theme only) (check)
            Hidden files and folders | Show hidden files, folders, and drives (select)
            Hide empty drives in the Computer folder (uncheck)
            Hide extensions for known file types (uncheck)
            Hide protected operating system files (Recommended) (uncheck, Yes I'm sure)
            Show pop-up description for folder and desktop items (uncheck)

    Control Panel | System and Security | Windows Update | Change settings
        Download updates but let me choose whether to install them (select)
        Allow all users to install updates on this computer (check)

    Elevated command prompt | gpedit.msc | Local Computer Policy
        User Configuration | Administrative Templates | Windows Components
            Windows Explorer | Turn off numerical sorting in Windows Explorer (enable)
        Computer Configuration | Administrative Templates
            System
                Power Management | Video and Display Settings
                    Turn Off Adaptive Display Timeout (Plugged In) (enable)
                    Turn Off Adaptive Display Timeout (On Battery) (enable)
            Windows Components | Windows Update
                Do not display 'Install Updates and Shut Down' ... (enable)
                Do not adjust default option to 'Install Updates and Shut Down' ... (enable)

    Control Panel | View by: Small icons (select)
        AutoPlay | Use AutoPlay for all media and devices (uncheck)
        Indexing Options | Modify | Show all locations
            Offline Files (uncheck)
            C:\Users (uncheck)
            C:\ProgramData\Microsoft\Windows\Start Menu (uncheck)
        Troubleshooting | Change settings | Computer Maintenance | Off (select)
        Windows Defender | Tools
            Automatic scanning | Automatically scan my computer (uncheck)
            Real-time protection | Use real-time protection (recommended) (uncheck)
            Administrator | Use this program (uncheck)

    Right-click Start Menu | Properties
        Customize
            Computer | Don't display this item (select)
            Connect To (uncheck)
            Control Panel | Don't display this item (select)
            Default Programs (uncheck)
            Devices and Printers (uncheck)
            Documents | Don't display this item (select)
            Enable context menus and dragging and dropping (uncheck)
            Games | Don't display this item (select)
            Help (uncheck)
            Highlight newly installed programs (uncheck)
            Music | Don't display this item (select)
            Open submenus when I pause on them with the mouse pointer (uncheck)
            Personal folder | Don't display this item (select)
            Pictures | Don't display this item (select)
            Search other files and libraries | Don't search (select)
            Search programs and Control Panel (uncheck)
            Use large icons (uncheck)
            Number of recent programs to display (set to 20 to make the menu bigger)
            Number of recent items to display in Jump Lists (set to 20 to make the menu bigger)
        Store and display recently opened programs in the Start menu (uncheck)
        Store and display recently opened items in the Start menu and the taskbar (uncheck)

    Right-click everything that is pinned to the taskbar
        Unpin this program from taskbar

    Right-click Recycle Bin | Properties
        For each hard drive in turn (select)
            Don't move files to the Recycle Bin. Remove files immediately... (select)

    Control Panel | Appearance and Personalization
        Personalization | Change desktop icons | Recycle Bin (uncheck)
        Change desktop background
            Picture Location: Solid Colors (select, choose black)

    Control Panel | User Accounts | Change your account picture
        Browse for more pictures
            http://blogs.msdn.com/photos/matthew_van_eerde/images/6831850/thumb.aspx

    Control Panel | Ease of access
        Change how your mouse works
            Mouse pointers | Regular Black (select)
            Prevent windows from being automatically arranged when moved to the edge of the screen (check)
        Change how your keyboard works
            Set up Sticky Keys | Turn on Sticky Keys when SHIFT is pressed five times (uncheck)
        Optimize visual display
            Turn off all unnecessary animations (when possible) (check)

    Make a folder on the desktop named "_"
        Open the following folders simultaneously
            _
            C:\ProgramData\Microsoft\Windows\Start Menu
            C:\Users\%username%\AppData\Roaming\Microsoft\Windows\Start Menu
        Copy various shortcuts from Start Menu over to _
            Notepad
            Paint
            Command Prompt
            Calculator
            ... whatever else strikes my fancy
        ... as I install programs, consider adding them here if I use them a lot

    Right-click the taskbar | Toolbars | New toolbar... | Desktop | _ (Select Folder)
        Right-click the taskbar | Lock the taskbar (uncheck)
        Drag the thumb of the _ toolbar to the top of the taskbar
        Right-click _
            Show Text (uncheck)
            Show title (uncheck)
            View | Small Icons (check)
        Drag the taskbar to be a tiny bit wider so three small icons fit side-by-side
        Drag the view-active-tasks part of the taskbar to be big
        Right-click the taskbar | Lock the taskbar (check)

    Make a 1-pixel-by-1-pixel black .jpg and set it as the LogonUI background

    I'm sure I'm forgetting some other things.  I'll add them later when I run into them.

    I could probably make a series out of this.  Possible candidates for future posts: "Tweaks I make every time I install Office", "Tweaks I make every time I install Firefox"...

    Command Prompt | Alt-Space | Defaults | QuickEdit Mode (check)

  • Matthew van Eerde's web log

    How to calculate a sine sweep - the right way

    • 3 Comments

    Three quarters are better than a dollar because they make noise!
        -- Lilly, Lilly's Purple Plastic Purse

    Last time I talked about how to calculate a sine sweep mathematically.  There's a closed-form solution which is quite elegant but, alas, useless in a practical computer implementation due to the very big numbers that are being fed to the sin(...) function.

    A computer implementation will care only about the discrete samples that need to be generated.  The integral in the previous post turns out to be counterproductive - we're much more interested in the infinite sequence of φi, and more particularly in their residue mod 2π.

    Here are Matlab scripts that implement a sine sweep both ways:

    First, the naïve mathematical solution that just calculates the exponential:

    function signal = sinesweep_nostate( ...
        start, ...
        finish, ...
        seconds, ...
        sample_rate, ...
        amplitude, ...
        initial_phase, ...
        dc ...
    )
    % sinesweep_nostate returns a single-channel sine logarithmic sweep
    %     DO NOT USE THIS FUNCTION IN PRODUCTION
    %     THIS IS A PEDAGOGICAL EXERCISE ONLY
    %     THE SIGNAL THIS PRODUCES GRADUALLY DISTORTS
    %     INSTEAD USE sinesweep
    %    
    %     start: starting frequency in Hz
    %     finish: ending frequency in Hz
    %     seconds: duration of sweep in seconds
    %     samplerate: samples per second
    %     amplitude: amplitude
    %     initial_phase: starting phase
    %     dc: dc

    % echo these interesting intermediate values to the console
    R = (finish / start) ^ (1 / seconds)
    B = 2 * pi * start / log(R)
    A = initial_phase - B

    time = 0 : 1 / sample_rate : seconds;
    phase = A + B * R .^ time;
    signal = amplitude * sin(phase) + dc;

    end % sinesweep_nostate

    Now, the iterative version that adds up the little Δφs to calculate φi iteratively:

    function signal = sinesweep( ...
        start, ...
        finish, ...
        seconds, ...
        sample_rate, ...
        amplitude, ...
        initial_phase, ...
        dc ...
    )
    % sinesweep returns a single-channel sine logarithmic sweep
    %     start: starting frequency in Hz
    %     finish: ending frequency in Hz
    %     seconds: duration of sweep in seconds
    %     samplerate: samples per second
    %     amplitude: amplitude
    %     initial_phase: starting phase
    %     dc: dc

    time = 0 : 1 / sample_rate : seconds;
    frequency = exp( ...
        log(start) * (1 - time / seconds) + ...
        log(finish) * (time / seconds) ...
    );

    phase = 0 * time;
    phase(1) = initial_phase;
    for i = 2:length(phase)
        phase(i) = ...
            mod(phase(i - 1) + 2 * pi * frequency(i) / sample_rate, 2 * pi);
    end

    signal = amplitude * sin(phase) + dc;

    end % sinesweep

    If anything, one would expect the first to be more accurate, since it is mathematically precise, and the second is only an approximation.  But let's see how the signal produced by each of them holds up.

    I calculate, and plot, the same sweep both ways, with a slight dc offset to facilitate seeing the different sweeps on the same plot.  In particular this is a logarithmic sweep from 20 kHz to 21 kHz, over 30 seconds, using 44100 samples per second, an amplitude of 0.2, an initial phase of π, and a dc of 0.25 for one and 0.26 for the other:

    plot(...
        x, sinesweep(20000, 21000, 30, 44100, 0.2, pi, 0.25), 'd', ...
        x, sinesweep_nostate(20000, 21000, 30, 44100, 0.2, pi, 0.26), 's' ...
    )

    (x is just 1:30*44100 - necessary to allow a single plot statement.)

    Note that the approximate method is plotted in diamonds, and will be 0.01 lower on the resulting graph than the "exact" method, plotted in squares.

    (This takes a while to plot because there are a heckuva lot of points...)

    Ah, a nice solid mass of green and blue.  I won't show it here.

    OK, let's zoom in to a very early chunk of the signal - I expect these to match up closely, with only the dc offset separating the points:

    Yup.  Looks pretty good - give or take a pixel (quantization error in the display.)

    Now let's see what happens to the signal towards the end of the 30 seconds.

    Ick.  Something's rotten in the state of Denmark.  This distortion is so bad that it's visible - you don't even have to take an FFT to see it.

    Exercise: take an FFT and look at the distortion.

    Advanced Exercise: demonstrate that the distortion is, in fact, in the "exact" method and not in the iterative method... that is to say, show which clock is right.

    EDIT: On second glance it looks like the second picture is just showing a horizontal shift between the two signals, which is expected.  I'll need to dig deeper if I'm to prove my assertion that the iterative method produces less distortion than the "exact" method.

Page 4 of 6 (138 items) «23456