Sorry, how does the dsp_vector_rms() function work? Topic is solved

Technical questions regarding the XTC tools and programming with XMOS.
Post Reply
User avatar
notDilbert
Member
Posts: 14
Joined: Mon Feb 25, 2019 3:05 pm

Sorry, how does the dsp_vector_rms() function work?

Post by notDilbert »

Please help, do not understand whats up with this function.

Why is the result not as expected 2000?

Code: Select all

#include <stdio.h>
#include <stdint.h>
#include <dsp.h>

#define INPUT_LENGTH 4

#define FCONV(a, q1, q2) (((q2)>(q1)) ? (a)<<((q2)-(q1)) : (a)>>((q1)-(q2)))

int32_t input_i[INPUT_LENGTH];

int main()
{
    #define Q_N 12

    for (int i = 0; i < INPUT_LENGTH; i++)
    {
        input_i[i] = 2000;
    }

    int32_t rms = dsp_vector_rms(input_i, INPUT_LENGTH, Q_N);

    printf("RMS %d\n", rms);  // RMS 128028 ???

    return 0;
}


View Solution
User avatar
CousinItt
Respected Member
Posts: 360
Joined: Wed May 31, 2017 6:55 pm

Post by CousinItt »

It's a bug.

Take a peek at the innards of dsp_vector_rms()

Code: Select all

int32_t dsp_vector_rms
(
    const int32_t* input_vector_X,
    int32_t        vector_length,
    const int32_t  q_format
) {
    int32_t vectort_pwr = dsp_vector_power   ( input_vector_X, vector_length, q_format );
    int32_t mean_square = dsp_math_divide  ( vectort_pwr, (vector_length << q_format),      q_format );
    int32_t rt_mean_sqr = dsp_math_sqrt( mean_square); 
    return rt_mean_sqr;
}
dsp_math_sqrt() does not care which Q format you've specified - it's fixed at Q24 format. The documentation for dsp_vector_rms mentions it using dsp_math_sqrt but doesn't explain this limitation. It refers to a "final value" but this appears to relate to the value of mean_square above. Because of this problem the result of the function is left-shifted by 6 bits in your case - i.e. half the difference between Q24 and your format.

If you try your example using Q24 format and initialise your input vector elements to, say Q24(0.1) you'll get the right answer.
User avatar
notDilbert
Member
Posts: 14
Joined: Mon Feb 25, 2019 3:05 pm

Post by notDilbert »

Thank you, Revised as advised.

Code: Select all

#include <stdio.h>
#include <stdint.h>
#include <dsp.h>

#define INPUT_LENGTH 64

int32_t input_i[INPUT_LENGTH];

int main()
{
    #define Q_N 24

    for (int i = 0; i < INPUT_LENGTH; i++)
    {
        input_i[i] = Q24(0.1);
    }

    printf("%d\n", input_i[0]);

    int rms = dsp_vector_rms(input_i, INPUT_LENGTH, Q_N);

    printf("RMS %d\n", rms);  // RMS 1677720 ???

    return 0;
}
Much better.

Note I changed the INPUT_LENGTH define size, So this places another hard limit on the input vector size and it's values, correct?
User avatar
CousinItt
Respected Member
Posts: 360
Joined: Wed May 31, 2017 6:55 pm

Post by CousinItt »

The result of dsp_vector_power will overflow if the combination of length and element magnitude is too large. For Q24, this would be if the length of the vector is greater than 127, assuming the elements are limited to magnitude Q24(1.0). Also, the second parameter to dsp_math_divide (vector_length << q_format) is close to causing a divide by an incorrect value (possibly zero) if the length is too large.

Hence if you need to use dsp_vector_rms for a longer vector, the only solution is to use a lower Q format and then correct the result for the sqrt problem. For example, you could use a 256 element vector with Q22 format, a maximum magnitude of Q22(1.0) for all of its elements, and get a result that you need to shift right once, with rounding if it matters.
Post Reply