0
$\begingroup$

I'm trying to get an LPC magnitude spectrum to match to an FFT magnitude spectrum. Basically I want the peak height in the LPC Spectrum to match the peak height in the FFT Spectrum.

Thanks to numerical recipes I have some code that produces me an LPC spectrum with what looks like the correct shape.

bool CLPC::BuildMagitudeSpectrumFromLPC( float* pOutSpec, unsigned int outSpecSize )
{
    int spec    = 0;
    while( spec < outSpecSize )
    {
        const float theta = (M_PI * 2.0f) * ((1.0f / (outSpecSize * 2)) * spec);
        const float wpr   = cosf( theta );
        const float wpi   = sinf( theta );

        float sumR  = 1.0f;
        float sumI  = 0.0f;

        float wR    = 1.0f;
        float wI    = 0.0f;
        int i   = 0;
        while( i < mNumLPC )
        {
            const float wTemp = wR;
            wR      = wR * wpr - wI     * wpi;
            wI      = wI * wpr + wTemp  * wpi;

            sumR    -= mLPCs[i] * wR;
            sumI    -= mLPCs[i] * wI;
            i++;
        }

        pOutSpec[spec] = mMeanSquareError / (sumR * sumR + sumI * sumI);
        spec++;
    }
}

Its worth noting that I manually re-scale it to a dB scale elsewhere.

My problem appears to be that I can't figure out the scaling on this spectrum. The above code returns values of greater than 1 (at seemingly the correct peak locations) for values that are not greater than 0dBFS on the FFT magnitude spectrum. When I overlay the 2 the toughs also appear to be too high as well.

Has anyone any idea how to get the peak heights and troughs to correspond between the 2?

I'm NOT windowing before passing to the LPC. Should I be?

Aso, Am I right in thinking that this line is a bit odd:

 pOutSpec[spec] = mMeanSquareError / (sumR * sumR + sumI * sumI);

I would have thought I'm taking the absoloute of the complex number represented by sumR and sumI. Wouldn't this mean calling sqrt on it? ie.

 pOutSpec[spec] = mMeanSquareError / std::sqrt( sumR * sumR + sumI * sumI );

Doing the above doesn't help my problem all it does is squash up the LPC spectrum somewhat ...

$\endgroup$

2 Answers 2

1
$\begingroup$

I have a similar function to compute the Spectrum from the predicator coefficients, but instead of your code that I do not understand, I have the following :

pOutSpec[spec] = mMeanSquareError / (sumR * sumR + sumI * sumI);

I have something that computes the real and imaginary parts into my buffer :

data[2 * spec] = sumR / (sumR * sumR + sumI * sumI);
data[(2 * spec) + 1] = -sumI / (sumR * sumR + sumI * sumI);

Then I use different functions to display the spectrum according to the chosen format (Real, Magnitude, Square Magnitude or Log).

I also have some problems with scaling, both for the FFT Spectrum and the LPC Spectrum. I have chosen to scale them based on my display area, but as a result, their scale is not exactly the same on the display.

$\endgroup$
1
0
$\begingroup$

I found this at http://web.science.mq.edu.au/~cassidy/comp449/html/comp449.html 6.3. Decibels

We commonly transform a spectrum as calculated by the fft into a decibel spectrum to better reflect the response of the human ear. The units of amplitude in the raw spectrum shown above are the same as those of the sampled acoustic signal. The decibel scale is a logarithmic scale of relative amplitude where we first devide by a reference amplitude (which corresponds to 0dB) and then take the naturnal logarithm. Finaly we multiply by 20:

AdB = 20*log(A / Aref)

where AdB is the amplitude in decibels, A is the raw amplitude and Aref is the (raw) reference amplitude. There are five basic choices for Aref:

1) Choose a known standard reference value. This requires calibration of your recording and digitising equipment against some standard. 2) Take Aref to be the average amplitude in the utterance you took your window from. 3) Make Aref the peak amplitude value in the spectrum, this makes the peak always have an amplitude of 0dB. 4) Make Aref the amplitude at a fixed frequency, say 1000Hz, for this spectrum. The spectrum will always now pass through 0dB at 1000Hz. 5) Make Aref zero, that is just take the log of the raw amplitude value.

The choice of value for Aref depends on the needs of your application. The big question is whether you want to preserve differences in amplitude between spectra or between utterances. For example, if you think that amplitude is going to be a useful cue then you need to preserve the relative amplitude of your spectra, so you can't use either method 3 or 4 above. If you want to factor out the overall loudness of a recording then method 2 might be useful. If you want to get precise relative amplitude measures then you need to use a calibrated system (method 1).

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.