|Comments on Friday 8 February 2008:|
|A post for programmers who are being frustrated with bad documentation - Google didn't help me, but once it indexes this it might help someone else. In programming audio in the latest DirectX "hey it's Monday again, let's make everything work another new totally different way" upgrade to audio functionality, there is a function|
HRESULT IXACTWave::SetPitch(XACTPITCH pitch)About which the documentation says "The value of pitch may be between XACTPITCH_MIN (-1200) and XACTPITCH_MAX (1200), which is approximately one semitone."
Now the astute amongst you might realise that already this is annoying and ambiguous - what is approximately one semitone? The distance between -1200 and 1200, which is 2400, or a distance of 1200? Also, what the hell, when you're changing pitch by playing the sample at a different frequency you can easily go up and down by a whole octave by doubling or halving the frequency, why are you limiting me to a semitone? Well, thankfully, the answer to "which of these" is "no, it is neither of those things that could possibly be meant by that sentence."
Instead, a pitch of 1200 is approximately one octave above 0, and each 100 pitch is a semitone. So you can in fact go up and down by an octave, like you should be able to (though really there's no reason for it to disallow going two octaves if you want to, even though it'd sound crap) as well as pitching to nearby notes easily. It's a bit strange to have SetPitch operating on a linear scale like this since the change of frequency is an exponential scale, which conversion must presumably be going on behind the scenes in a manner that would be entirely unnecessary for my purposes since I could precalculate the desired frequencies, but oh well, at least it works and does what I need it to do.
Another malfunctioning function is
HRESULT IXACTWave::Stop(DWORD flags)which "returns S_OK if successful, otherwise an error code." Except no it doesn't - if you use IXACTWaveBank::Play to start a sound, and then call Stop on the output IXACTWave pointer immediately afterwards, it returns S_OK but the wave does not in fact stop, which is horrible if the wave was set to loop indefinitely. However, you can call Destroy on the output wave object which will reliably stop it. I have no idea what's going on behind the scenes there, or whether one needs to call Destroy on every output wave pointer out of a wavebank.Play call to avoid memory leaks, because the documentation is fucking awful. Hooray.
In other good design news, installing Linux Ubuntu, the "user-friendly" desktop Linux. Step 1: graphical installer. Very posh and Windows-like. Here's a dialog box, fill it in. Here's another one to select your timezone. Oh you don't want to be able to click 'next' do you? Well good luck with that, Mr "only 800x600 screen" (or less, as, say, on an Eee machine), because that button is way off the bottom of the screen where you can't get it unless you know some arcane key-mouse combinations to work around it. This has been a known and potentially-easily-fixed issue for about two years. Oh Lunix nerds, you are so good at user interfaces.
And further on the audio front, is there really no preexisting function to make a segment of a wave file loop smoothly? It's getting to the point that I'm considering writing my own command-line wave file editor to perform the following operations: