Help needed with SINE2TINTERP function


#1

I hope i got the section right.
I'm investigating the axoloti function SINE2TINTERP(phase,output destination).
From what i have understood phase is the actual argument of the function, the one in which the sine will be calculated. Output destination is a variable in which the result will be stored.

Soo, if i do

int32_t r;
SINE2TINTERP( some number here,r);

the value sin(some other number) will be stored inside the r variable.

But what is the range of the function? I tried dissecting the math/cos object and aside from the uberweird bitwise shifts there's not a lot of magic happening.

Is there some way to port the function to a normal mathematical range? sin(+/-pi)=0 sin(pi/2)=1, sin(-pi/2)=-1 ?


#2

Hi Sputnki

I guess with fixpoint arithmetics, you allways have to fight with the bit-shifts. I found this wikipedia article very helpful: Fixed-point arithmetic

I used the functions arm_sin_q31 and arm_cos_q31 in in my filter objects (see my contributions). These functions are well documented on the Keil homepage.

The following fragment is from function f_filter_biquad_A in unit axoloti_filters.c:

  int32_t sinW0; // = arm_sin_q31(filter_W0);
  int32_t cosW0; // = arm_cos_q31(filter_W0);
  int a = filter_W0;
  int b = filter_W0 + (1 << 30);

  SINE2TINTERP(a, sinW0)
  SINE2TINTERP(b, cosW0)

So it seems to me that SINE2TINTERP is a replacement (maybe faster) for arm_sin_q31, using the same ranges. cos(w0) was replaced with sin(w0+pi/2), which is the same. So (1<<30) stands for pi/2. The Keil homepage says:
the fixed-point Q15 and Q31 have a scaled input with the range [0 +0.9999] mapping to [0 2pi).*
We're in Q31, so this seems right to me (the fixed-point range is chosen so that a value of 2*pi wraps around to 0).


#3

Id be interested in @johannes thoughts on this too.

a quick look at the SINE2TINTERP code, it seems to be doing something very similar to arm_sin_q31().
then I remembered a discussion a while back, talking about using the q31 functions, and @johannes said he was concerned that many of these were not inlined, so they have a function call overhead.

Id be interested to know if this is the sole reason or if there are differences/other reasons.

personally, I'm a little in two minds, obviously if you have lots of function calls, then the overhead could become significant, but with careful programming (and depending on use-case), it may be 'acceptable' - and of course saves 'code' space, which with all this inlining, on complex patches can become an issue.
(there are always trade-offs in programming , especially when limited resources are available)


#4

By the way, all the factory filter objects (except the vcf-objects) are using arm_sin_q31 and arm_cos_q31, not SINE2TINTERP.


#5

Ive just had a look.... nothing is using arm_sin_q31/arm_cos_q31 that I can see?
but I can see the eq objects are using arm_biquad_cascade_df1_q31 and similar the fir are using the arm_fir, and the rfft is using arm_rfft (etc)

unless of course I'm missing something...


#6

Sorry, I didn't mean calling directly. But biquad_lp_coefs, biquad_bp_coefs and biquad_hp_coefs (see axoloti_filters.h) are actually calling arm_sin_q31 and arm_cos_q31. And the following factory objects are using one of these functions:

axoloti-factory\objects\filter\lp m.axo
axoloti-factory\objects\filter\lp.axo
axoloti-factory\objects\filter\bp m.axo
axoloti-factory\objects\filter\bp.axo
axoloti-factory\objects\filter\hp m.axo
axoloti-factory\objects\filter\hp.axo
axoloti-factory\objects\spectral\analyzer 24.axo


#7

ah, yeah... I see now... in fact its only the state variable filters using SINE2INTERP, and as you say the vcf ... (via f_filter_biquad_A)

hmm, that makes it even more interesting as to why SINE2INTERP is sometimes used, and sometimes not.