0
$\begingroup$

I'm working on porting Opus IMDCT/FFT to a fixed point 16-bit DSP with a 48-bit accumulator. I'm trying to do that with 32-bit fixed point numbers to keep the highest possible quality. I'm basing my implementation on Xiph's reference implementation which can be compiled to use fixed points.

Looking at the macros used to implement complex numbers operations, for instance C_ADD and C_SUB:

#define  C_ADD( res, a,b)\
    do {(res).r=ADD32_ovflw((a).r,(b).r);  (res).i=ADD32_ovflw((a).i,(b).i); \
    }while(0)
#define  C_SUB( res, a,b)\
    do {(res).r=SUB32_ovflw((a).r,(b).r);  (res).i=SUB32_ovflw((a).i,(b).i); \
    }while(0)

the underlying macros being used to add fixed point integers are called ADD32_ovflw and SUB32_ovflw. In turn, these macros are defined as:

/** Add two 32-bit values, ignore any overflows */
#define ADD32_ovflw(a,b) ((opus_val32)((opus_uint32)(a)+(opus_uint32)(b)))
/** Subtract two 32-bit values, ignore any overflows */
#define SUB32_ovflw(a,b) ((opus_val32)((opus_uint32)(a)-(opus_uint32)(b)))

I'm confused by the meaning of the "ignore any overflows" part. The DSP I'm working on natively support saturating adds and subs; to make an overflowing operation, I need to manually play with the carry flag, which requires many more opcodes.

To the best of my (little) understanding of signal processing, I would say that a well formed FFT part of a IMDCT should never cause any overflow. If an overflow happens, I would say that the fixed point precision is not enough, and scaling should be performed on the input (at the beginning, or after each step).

So probably the real meaning of ADD32_ovflw is "this will not overflow, do whatever add is more performant on your DSP", rather than "this must absolutely be implemented as an overflowing 32-bit addition". Is this correct?

$\endgroup$
1
  • $\begingroup$ This is an interesting question that I have just skimmed through. 35 years ago, i did an FFT on the Mot 56K and later on the 56002, that had a data growth bit that supported Block Floating Point. Do you have that? $\endgroup$ Aug 28 at 17:25

1 Answer 1

1
$\begingroup$

rather than "this must absolutely be implemented as an overflowing 32-bit addition". Is this correct?

That sounds right. The comment specifically states /** Add two 32-bit values, ignore any overflows */ . I would interpret this as "we are not going to handle overflows, whatever happens naturally will happen" . What "naturally" means depends on the processor on how its configured. Many processors can be configured to either "wrap around" or "saturate" on overflow. This is often implemented in hardware, so you don't incur any extra cost for either option.

If an overflow happens, I would say that the fixed point precision is not enough, and scaling should be performed on the input (at the beginning, or after each step).

That's always a trade-off between dealing with occasional clipping vs incurring a small amount of extra noise and each and every operation. Typically a bit of statistical analysis looking at a "normal" range of crest factors of the signal can help here, but unfortunately the FFT has high probability of extreme cases actually occurring in the real world.

Consider a linear sweep and a single sine wave: they have the same crest factor (about 3dB) and RMS in the time domain. However the spectral look completely different: the sweep spectrum also has a crest factor of about 3 dB but the crest factor of if the sine wave spectrum is $\sqrt{N}$ where $N$ is the FFT length. To avoid potential clipping you need to add a lot of guard bits which eats into your general Signal to Noise Ratio.

$\endgroup$

Your Answer

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

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