The way it decides that is kind of primitive, but it works fairly well: the PIC counts the number of 0-to-1 transitions in a 0.1-second time period and remembers it. Then, if the counts from the last four periods are within 10% of each other, and they're within a set frequency range, it decides that it's hearing a whistle and activates the relay. The idea is that it only responds to a whistle, and not other noises, because of the frequency range requirement and the requirement that the frequency is steady.
Controlling the ceiling light
The device controls the AC power to my ceiling lights using a relay wired in parallel with my light switch, as shown below.
With the relay in parallel with the normal light switch, the light will be on if either one is on. The relay is open when the coil isn't being powered. That means, if I turn off my circuit, the relay stays open and the light is controlled with just the light switch.
I turned off my apartment's circuit breaker and connected the relay in the switch box beside the switch, and I left the wires that power the relay coil trailing out of the box. You shouldn't do this sort of thing unless you really know what you're doing; if the relay isn't rated for enough current/voltage, or if you wire things wrong, you could start a fire. Even though I'm an electrical engineer of supreme skill, I still made sure to wire the project and leave the light on at a time when I would be home and awake for a few hours, just in case Radio Shack had lied about the breaker ratings.
Whistle detection circuit
Below is the circuit that receives the audio. The first op-amp is amplifying the audio, and the second is acting as a comparator and outputting a digital '1' if the audio is above the reference, and a '0' if it's below it. (As a side note, the amplifier circuit shown below is the proper way to amplify audio; the simpler amplifier circuit that I use on my Starburst Turret page loses the bottom half of the audio wave, which is OK for the Starburst Turret but not necessarily OK for other uses.) The microcontroller counts the number of 1's in a 0.1-second time period, and if it's within a certain range, that means the whistle is within a certain frequency range. It's not a completely robust method, but it works decently well.
The frequency range I used was 900 to 2700Hz, which (according to a microphone hooked up to my oscilloscope) is roughly the range I can whistle, but doesn't include most background noise. Unfortunately, my vacuum cleaner apparently also makes a noise in this range, so I have to unplug the whistle-switch when I vacuum. If my circuit were more advanced, and could tell the difference between a sine wave (whistle) and a non-sine wave (vacuum) that have the same period, it wouldn't have that problem. That would add complexity, though.
If I were better at whistling, I could probably set different devices to different frequency ranges, which would be kind of cool. (The number of devices would be limited by the fact that the microphone doesn't pick up things perfectly, so you have to allow some fuzziness in your frequency requirements or you'll never be able to activate it.)
Here is my code for the PIC 18F1320 microcontroller that is the center of this project. It's C code for the free Microchip MPLAB C18 compiler: tonedetect.c