jremington, that is the best de-bouncing guide on the planet. I've attempted to tackle those scenarios here, but haven't tested them all yet.
chewiesmissus, note that jitter is increased by use of delays. The last delay(20) in itself adds 20 ms of jitter to all readings.
So, for example , if duration = 100 ms, the last delay represents 20% jitter.
If you use pulseIn to get 10 readings so duration becomes 1000 ms, then the last delay will now represent 2% jitter.
Replacing the delays with a method like shown in the blink without delay example would greatly reduce jitter and improve response.