I'm working with an SDR that has a 12-bit signed ADC/DAC that stores in 16-bit IQ samples. I want to ensure that after all the DSP is done the samples saturate at 12 bits instead of getting truncated by the SDR.
This is the equivalent c++ code:
for (int i = 0; i < block_size_with_header; i++) {
if (floatSamples[i].real() > 2047)
floatSamples[i].real(2047);
if (floatSamples[i].imag() > 2047)
floatSamples[i].imag(2047);
if (floatSamples[i].real() < -2048)
floatSamples[i].real(-2048);
if (floatSamples[i].imag() < -2048)
floatSamples[i].imag(-2048);
}
Is there a faster way to do this using SIMD or Assembly? I've seen questions on here saturating at 16 bits or 8 bits, but not 12.
Thanks.
One interesting property of clamping, applying it twice doesn’t change the output, i.e.
clamp( clamp( x ) ) == clamp( x )
for allx
. This greatly simplifies handling of remainder. Here’s AVX2 example, untested.The input pointer doesn’t need to be aligned. Still, when it is aligned by 32 bytes, the function will run slightly faster.