Problem about dsp_lib dsp_adaptive_nlms() Topic is solved

Voice related projects and technical discussions
link0513
Member++
Posts: 26
Joined: Tue Jul 02, 2019 8:38 am

Problem about dsp_lib dsp_adaptive_nlms()

Post by link0513 »

When I use function dsp_lib dsp_adaptive_nlms() to operate the voice sample, it will output below problem when it run (building is ok). and use same parameter in function dsp_lib dsp_adaptive_lms() is good.

return_sample = dsp_adaptive_nlms(sample0, sample1, (int32_t)&error_sample, coeff, state, 100, Q28(0.01), 28);

xrun: Program received signal ET_ARITHMETIC, Arithmetic exception.
[Switching to tile[1] core[4] (dual issue)]
0x00047c24 in dsp_math_divide ()
View Solution
link0513
Member++
Posts: 26
Joined: Tue Jul 02, 2019 8:38 am

Post by link0513 »

Anybody know that ? please help.
User avatar
CousinItt
Respected Member
Posts: 367
Joined: Wed May 31, 2017 6:55 pm

Post by CousinItt »

dsp_math_divide uses the ldivu instrution. According to the xCORE-200 architecture manual, the ET_ARITHMETIC exception is raised if the divisor is zero, or if the result of the division will not fit into a 32-bit word.
link0513
Member++
Posts: 26
Joined: Tue Jul 02, 2019 8:38 am

Post by link0513 »

CousinItt wrote: Fri Jul 05, 2019 12:22 pm dsp_math_divide uses the ldivu instrution. According to the xCORE-200 architecture manual, the ET_ARITHMETIC exception is raised if the divisor is zero, or if the result of the division will not fit into a 32-bit word.
Hi, in official example code(AN00209), the parameter source_sample and reference_sample is use Q31 format data to test. And if I use Q31(0.01) instead of the 32-bit parameters, there is also not any error when running.But I2S data is use 32-bit to operate not Q31 data. There is a other strange thing is that dsp_math_divide in dsp_adaptive_nlms does not use these two parameter( source_sample and reference_sample).
link0513
Member++
Posts: 26
Joined: Tue Jul 02, 2019 8:38 am

Post by link0513 »

CousinItt wrote: Fri Jul 05, 2019 12:22 pm dsp_math_divide uses the ldivu instrution. According to the xCORE-200 architecture manual, the ET_ARITHMETIC exception is raised if the divisor is zero, or if the result of the division will not fit into a 32-bit word.
Hi, you are right, the error is because the divisor is zero when beginning. And another question is what is your mean about"if the result of the division will not fit into a 32-bit word". I found that even thought I filter the zero sample data , the function sometimes is still output ET_ARITHMETIC. It maybe is because the second cause what you said. Look forward to your reply, thank you very much.
User avatar
CousinItt
Respected Member
Posts: 367
Joined: Wed May 31, 2017 6:55 pm

Post by CousinItt »

But I2S data is use 32-bit to operate not Q31 data
Q31 is a 32-bit data format, at least in the dsp_lib convention: 31 bits to represent the fraction after the fixed point, plus the sign bit. The I2S specification doesn't specify the format for data.
User avatar
CousinItt
Respected Member
Posts: 367
Joined: Wed May 31, 2017 6:55 pm

Post by CousinItt »

Regarding ET_ARITHMETIC, see the description for ldivu in the xmos document xCORE-200: The XMOS XS2 Architecture.
link0513
Member++
Posts: 26
Joined: Tue Jul 02, 2019 8:38 am

Post by link0513 »

CousinItt wrote: Mon Jul 08, 2019 5:57 pm Regarding ET_ARITHMETIC, see the description for ldivu in the xmos document xCORE-200: The XMOS XS2 Architecture.
Thank you. And back to the first question. if I input a voice data to the dsp_adaptive_nlms,the energy is maybe zero sometimes, so that it still will cause the ET_ARITHMETIC error. How to solve this?
In this code " if( energy < (1 << (31-(31-qq)*2)) ) energy = (1 << (31-(31-qq)*2)) + 0", if when "qq" is less than 16, (31-(31-qq)*2) will output a negative and then energy will be zero or negative. right?

Code: Select all

 
 int32_t dsp_adaptive_nlms
(
    int32_t  source_sample,
    int32_t  reference_sample,
    int32_t* error_sample,
    const int32_t* filter_coeffs,
    int32_t* state_data,
    const int32_t num_taps,
   const int32_t mu,
    const int32_t q_format
) {
    int32_t output_sample, energy, adjustment, ee, qq;
     output_sample = dsp_filters_fir( source_sample, filter_coeffs, state_data, num_taps, q_format );
    
    // Error equals difference between reference and filter output:
    // e[n] = d[n] - y[n]

    *error_sample = reference_sample - output_sample;
     energy = dsp_vector_power( state_data, num_taps, q_format );
         // Adjust energy q_format to account for range of reciprocal
    for( qq = q_format, ee = energy; qq >= 0 && !(ee & 0x80000000); --qq ) ee <<= 1;
    energy = energy >> (q_format - qq);
    // Saturate the reciprocal value to max value for the given q_format
    [highlight=yellow]if( energy < (1 << (31-(31-qq)*2)) ) energy = (1 << (31-(31-qq)*2)) + 0;[/highlight]
    
    energy = dsp_math_divide( (1 << qq), energy, qq );
    
    adjustment = dsp_math_multiply( *error_sample, mu, q_format );
    adjustment = dsp_math_multiply( energy, adjustment, qq + q_format - q_format );
    
    dsp_vector_muls_addv( state_data, adjustment, (int32_t*) filter_coeffs, (int32_t*) filter_coeffs, num_taps, q_format );
        
    return output_sample;
 }
 
 
User avatar
CousinItt
Respected Member
Posts: 367
Joined: Wed May 31, 2017 6:55 pm

Post by CousinItt »

I don't know enough about the algorithm to comment in much detail, but it looks like the saturation operation...

Code: Select all

// Saturate the reciprocal value to max value for the given q_format
    if( energy < (1 << (31-(31-qq)*2)) ) energy = (1 << (31-(31-qq)*2)) + 0;
... is supposed to ensure that if the energy is too small a minimum value is used instead. It should never be negative because it's the sum of squares of the state_data vector elements.
link0513
Member++
Posts: 26
Joined: Tue Jul 02, 2019 8:38 am

Post by link0513 »

CousinItt wrote: Fri Jul 12, 2019 2:00 pm I don't know enough about the algorithm to comment in much detail, but it looks like the saturation operation...

Code: Select all

// Saturate the reciprocal value to max value for the given q_format
    if( energy < (1 << (31-(31-qq)*2)) ) energy = (1 << (31-(31-qq)*2)) + 0;
... is supposed to ensure that if the energy is too small a minimum value is used instead. It should never be negative because it's the sum of squares of the state_data vector elements.
Thank you. I don't know enough about algorithm too. It is the function in the dsp lib, maybe only XMOS's algorithm engineer can solve it..