1

I'm trying to use C++ to recreate the spectrogram function used by Matlab. The function uses a Short Time Fourier Transform (STFT). I found some C++ code here that performs a STFT. The code seems to work perfectly for all frequencies but I only want a few. I found this post for a similar question with the following answer:

Just take the inner product of your data with a complex exponential at the frequency of interest. If g is your data, then just substitute for f the value of the frequency you want (e.g., 1, 3, 10, ...)

Having no background in mathematics, I can't figure out how to do this. The inner product part seems simple enough from the Wikipedia page but I have absolutely no idea what he means by (with regard to the formula for a DFT)

a complex exponential at frequency of interest

Could someone explain how I might be able to do this? My data structure after the STFT is a matrix filled with complex numbers. I just don't know how to extract my desired frequencies.

Relevant function, where window is Hamming, and vector of desired frequencies isn't yet an input because I don't know what to do with them:

Matrix<complex<double>> ShortTimeFourierTransform::Calculate(const vector<double> &signal,
    const vector<double> &window, int windowSize, int hopSize)
{
    int signalLength = signal.size();
    int nOverlap = hopSize;
    int cols = (signal.size() - nOverlap) / (windowSize - nOverlap);
    Matrix<complex<double>> results(window.size(), cols);

    int chunkPosition = 0;
    int readIndex;
    // Should we stop reading in chunks? 
    bool shouldStop = false;
    int numChunksCompleted = 0;
    int i;
    // Process each chunk of the signal
    while (chunkPosition < signalLength && !shouldStop)
    {
        // Copy the chunk into our buffer
        for (i = 0; i < windowSize; i++)
        {
            readIndex = chunkPosition + i;
            if (readIndex < signalLength)
            {
                // Note the windowing! 
                data[i][0] = signal[readIndex] * window[i];
                data[i][1] = 0.0;
            }
            else
            {
                // we have read beyond the signal, so zero-pad it!
                data[i][0] = 0.0;
                data[i][1] = 0.0;
                shouldStop = true;
            }
        }
        // Perform the FFT on our chunk
        fftw_execute(plan_forward);

        // Copy the first (windowSize/2 + 1) data points into your spectrogram.
        // We do this because the FFT output is mirrored about the nyquist 
        // frequency, so the second half of the data is redundant. This is how
        // Matlab's spectrogram routine works.
        for (i = 0; i < windowSize / 2 + 1; i++)
        {               
            double real = fft_result[i][0];
            double imaginary = fft_result[i][1];
            results(i, numChunksCompleted) = complex<double>(real, imaginary);
        }
        chunkPosition += hopSize;
        numChunksCompleted++;
    } // Excuse the formatting, the while ends here.
    return results;
}
Community
  • 1
  • 1
Phlox Midas
  • 4,093
  • 4
  • 35
  • 56
  • 1
    What is not clear from [Wikipedia description](https://en.wikipedia.org/wiki/Short-time_Fourier_transform#Discrete-time_STFT) and why you can't just code it? – Petr Jul 17 '15 at 12:34
  • If I understand your question right, I believe I've already coded the Discrete Time STFT. I'm now just trying to get the values at certain frequencies. – Phlox Midas Jul 17 '15 at 12:38
  • You can just code the formula exactly as it is written in Wikipedia. Just loop over frequencies and apply the formula for each frequence separately. – Petr Jul 17 '15 at 12:41
  • I'm sorry. I don't understand classical math notation. Which symbol is the desired frequency? Which portion of the formula would I have to apply to get the desired value? – Phlox Midas Jul 17 '15 at 12:45
  • 1
    `X(m,omega) = sum_n x[n]w[n-m]exp(-j*omega*n)`, with `omega` beging the frequency, `m` the shift, `x` your signal, `w` the window, and `j` the imaginary unit. – Petr Jul 17 '15 at 12:48
  • Thanks. I'm still a bit confused. Are there operators between x[n] and w[n-m] and exp(-j*omega*n)? And is n constant? Do [] still mean subscript, e.g. x[n] means the last item in the x vector? – Phlox Midas Jul 17 '15 at 12:53
  • I clicked chat by accident and can't delete this comment. – Phlox Midas Jul 17 '15 at 12:57
  • I suggest you read more or finally find someone who can explain the basics of math to you. – Petr Jul 17 '15 at 13:14
  • What you're looking for is [Euler's Formula](https://en.wikipedia.org/wiki/Euler%27s_formula). DSP without a thorough understanding of pure mathematics just isn't happening. I recommend finding and consuming some free undergraduate courseware - first and second year Elec. Eng and Engineering Maths. – marko Jul 17 '15 at 22:07

1 Answers1

1

Look up the Goertzel algorithm or filter for example code that uses the computational equivalent of an inner product against a complex exponential to measure the presence or magnitude of a specific stationary sinusoidal frequency in a signal. Performance or resolution will depend on the length of the filter and your signal.

Community
  • 1
  • 1
hotpaw2
  • 70,107
  • 14
  • 90
  • 153