When implementing your spectrogram algorithm, make the following assumptions:
- use a Hamming window
- the window length is N=256
- zero-pad by a factor of 2
- do not overlap
Here are some things to keep in mind:
- do not vectorize your code or use MATLAB-specific helper functions that are not available on the tablet (such as
zeros()
ornorm()
), as you want to make porting it to C as straightforward as possible. - Retain only half of the FFT output, as it is conjugate symmetric (make sure you know why!)
- If X = Xr + jXi is a complex number, the magnitude squared operation computes Xr^2 + Xi^2.
- Because power can vary by orders of magnitude, the Log computation is used to reduce the dynamic range of the spectrogram output; this is useful when visualizing the data.
If your input signal is 8192 samples long, then your spectrogram output can be thought of as a 256 x 32 real-valued matrix. Make sure to understand why. You can then use the
image()
or
imagesc()
functions in MATLAB to visualize the data.
Part 4: a c implementation of the spectrogram
Specifications
Your task is to implement a C version of the spectrogram algorithm that you wrote in Part 3. Here are some guidelines for how to proceed:
- Remember you are doing block-based processing. Every time
process()
is called,inBuf
hasN
samples available to be processed. - Read Section 2.1 of the FFTW tutorial to understand the data structures and function calls of the FFTW library.
- Remember that floating point is available on this processor.
- Use the test vector to verify that intermediate operations are being computed correctly (e.g., multiplication, zero-padding, log function, etc.).
- For
extra credit , implement a scheme that allows for arbitrary overlapping. This may require modifying code in
Lab4Activity.java
Scaling the output
The values of
outBuf
must be between 0.0 and 1.0. This is because the output values are directly mapped to RGB colors, with each color channel being 8 bits. As the spectrogram output is generally not in between 0.0 and 1.0, you will need to find an appropriate mapping.
One possible mapping is to linearly scale and saturate the spectrogram output; you must determine the scaling parameters experimentally by processing real audio data. Here is an outline of one way to do this:
- Start up the GDB debugger and
Resume
with all breakpoints disabled. - While playing a loud tone (i.e., generate in MATLAB and play out through headphones), set a breakpoint right before your
process()
function returns. - Export the
inBuf
array to a file. Review Part 2: Exporting Variables to a File if you don't remember how. - Repeat this process for noise-only input.
- Import the two files into MATLAB to determine a suitable dynamic range.
Quiz information
Be able to describe the effects of windowing and zero-padding on FFT spectral analysis. Know basic properties of the Fourier transform, DTFT, and DFT. What are the trade-offs between block-based and sample-by-sample processing? Although we did not require you to implement it, understand the effects of overlapping when computing the STFT. Understand the basic Android project structure and the relationship between Java and C programming for Android.