Friday 20 October 2017

An act of frequency folly

Working through some software problems today ended in some rather funny solutions this morning (why do programming breakthroughs always seem to happen when everyone else is asleep??).

It just so happens that both the Rubik's Cube Solver and the Solar Flare Detector are going to require me to become a pro at manipulating PC soundcards, both for sending and receiving signals.

Sending signals is fine:

    1. Find a nice stable interface library, 
    2. Bash together some sample values,
    3. Send them off to generic 'write' function,
    4. Play sweet sweet music,
    5. Become single most hated person in the lab for constantly playing annoyingly pitched sine tones...
Receiving signals is proving slightly trickier, or rather analysing the received signals in the frequency domain is proving rather mind bending. To illustrate, some nice graphs:
An arbitrary signal received through my PC's microphone (in the time domain). Ignore both axis for the moment.
The reported amplitude spectrum of the above signal. The fact that is is clearly just a copy of the original signal put through an 'magnitude' function rang many alarm bells. Another bell ringer was the fact that is not symmetrical around the Nyquist frequency (~22 kHz), a necessary outcome of an FFT. We can read the bottom axis as frequency directly.
An example of what I was expecting to see, a nicely prepared amplitude spectra of two superimposed sinusoids with a large DC offset. We can use the bottom axis as frequency again. Note that it ends at about 22 kHz, the magics of digital sampling mean that anything above this frequency is simply a reflection of the spectra below that point - it is easier to not show it.
What appeared to be happening was that the Fast Fourier Transform (FFT) function I was using seemed to like synthesised, simple, waveforms - but not horrible real life ones.

At this point it is probably a good idea to give some indication of the software I am using, as it turned out my interpretation of it was the cause of most of my errors. In general when programming on a PC or large computer I like to use Python 3, and for this particular task I deployed the potent Numpy/Matlibplot library combo. Initially I was using PyAudio to interact with sound related hardware, but I quickly realised that the sounds it was producing were awfully messy and did not correspond to the carefully crafted sine waves I was trying to generate. After digging around and seeing some other people complaining on various forums I switched to the SoundDevice library which promised to be more stable. It was, and I quickly progressed from producing signals to trying to receive them.

That was when I started producing graphs like those above. I dug around, maybe my received data needed to be in another format ... maybe I needed to change the sampling frequencies ... e.c.t. (That last 'solution' turned out to be an incredibly bad idea, I can only guess that the software  and hardware supporting the soundcard and Python interface is optimised for specific sampling rates, because who would want to change that? :) )

Several hours of digital sampling theory, frequent code double checking and desperate internet searches ended when I realised that I had misunderstood some documentation and got my rows and columns mixed up when feeding data to the FFT function.

As quickly as I realised my problem all anger at my poor computer subsided, I had been asking it to compute the frequency content of thousands of individual samples (which gives the amplitude of said samples at DC/0 Hz) and then plot the results. Instead of plotting a bunch of data points at x = 0, Python had plotted each individual result like a column graph which (unsurprisingly) produced a copy of the original signal with all negative results flipped to be positive. The reason the synthesised waveform had not had this problem was because it was stored differently and so did not have its rows and columns confused.

Once I started using the data correctly my issues quickly resolved and I began producing graphs like the one below, cheering and waking up all my flatmates...
A nicer frequency amplitude spectrum of the signal incorrectly processed above. It has had its spectra cut off around 22 kHz in the same manner as the spectra of the synthesised signal. I am fairly sure that everyone in my terrace of houses knows I was able to produce this graph. 
Sorry that this has been a bit of a dry post, I have to take the opportunity to write when something happens that is both applicable, and has shiny images!

Anyway, until next time....

No comments:

Post a Comment