Would anyone notice if a referee's whistle transmitted a secret data burst?
I do really follow the game. But every time the pea whistle sounds to start the jam I can't help but think of the possibility of embedding data in the frequency fluctuation. I'm sure it's alternating between two distinct frequencies. Is it really that binary? How random is the fluctuation? Could it be synthesized to contain data, and could that be read back?
I found a staggeringly detailed Wikipedia article about the physics of whistles – but not a single word there about the effects of adding a pea inside, which is obviously the cause of the frequency modulation.
To investigate this I bought a metallic pea whistle, the Acme Thunderer 60.5, pictured here. Recording its sound wasn't straightforward; The laptop microphone couldn't handle the 103 dB sound level indoors, and there was too much background noise to record it outdoors. Later I did find a better mic and got this spectrogram of a 500-millisecond whistle.
The whistle seems to contain a sliding beginning phase, a long steady phase with frequency shifts, and a short sliding end phase. The "tail" after the end slide is just a room reverb and I'm not going to need it just yet. A slight amplitude modulation can be seen in the oscillogram. There's also noise on somewhat narrow bands around the harmonics.
The FM content is most clearly visible in the second and third harmonics. And seems like it could very well fit FSK data!
Making it sound right
I'm no expert on synthesizers, so I decided to write everything from scratch (whistle-encode.pl). It's simple to write the fundamental tone as a simple FSK modulator; at every sample point, a data-dependent increment is added to a phase accumulator, and the signal is a cosine of the accumulator. I used a low-pass IIR filter before frequency modulation to make the transitions smoother and more "natural". Adding the harmonics is just a matter of measuring their relative powers from the spectrogram, multiplying the fundamental phase by the index of the harmonic, and then multiplying the cosine of that phase angle by the relative power of that harmonic.
Getting the noise to sound right was trickier. I ended up generating white noise (a simple
rand()), lowpass filtering it, and then mixing a copy of it around every harmonic frequency. I gave the noise harmonics a different set of relative powers than for the cosine harmonics. It still sounds a bit too much like digital quantization noise.
There's a limit to the amount of bits that can be sent before the result starts to sound unnatural; nobody has lungs that big. A data rate of 100 bps sounded similar to the Acme Thunderer, which is pretty much nevertheless. I preceded the burst with two bytes for bit and byte sync (
0xAA 0xA7), and one byte for the packet size. Here's "OHAI!":
Sounds legit to me!
Writing a receiver is left as an exercise, but it should be as simple as receiving FSK. The frequency can be determined using
atan2, a zero-crossing detector, or FFT, for instance. The synchronization bytes are meant to help decode such a short burst; the alternating 0s and 1s of
0xAA probably give us enough transitions to get a bit lock, and the
0xA7 serves as a recognizable pattern to lock the byte boundaries on.