Files
wdsp/comm.h
T
Uladzimir Karpenka 9960a1d0e3 resample: vectorize the polyphase tap loop
The tap loop wrapped the ring with a test on every tap:

    if ((idx_out = idx_in + j) >= ringsize) idx_out -= ringsize;

which made the address non-affine and stopped the vectorizer. Split the
walk at the wrap point instead, so both halves are unit-stride, and split
the complex ring into separate I/Q arrays so the taps load contiguously
rather than through a de-interleaving ld2.

The dot product also could not be vectorized as written: reassociating an
fp reduction needs -ffast-math, which this library must not enable (it
relies on IEEE semantics for 0/0 = NaN and x/0 = Inf, see linux_port.h).
Carry four independent accumulator pairs instead, which both breaks the
FMA dependency chain and lets the vectorizer in on any compiler.

Measured on an Apple M1 Pro, 512-sample DSP buffers, best of 5:

  xresample, decimation to 48 kHz     before      after    speedup
    192k -> 48k  (561 taps)          342.0 us    84.2 us     4.06x
    384k -> 48k  (1121 taps)         708.9 us   175.1 us     4.05x
    576k -> 48k  (1681 taps)        1074.4 us   266.9 us     4.03x
    768k -> 48k  (2241 taps)        1438.9 us   360.0 us     4.00x

  full xrxa() chain, 576k input      1148.2 us   337.6 us     3.40x
                                     10.76%       3.16%   of one core

  xresampleF (float, host audio)                          2.6x - 3.4x

Summation order changes, so the double path is not bit-identical: over
400 buffers of the full RX chain the worst deviation is 1.1e-12, an SNR
of 251 dB. The float path is bit-identical, as the cast to float absorbs
the difference. With the resampler bypassed (48k in, 48k out) the chain
is unchanged bit-for-bit.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-09 22:44:08 +03:00

159 lines
4.4 KiB
C

/* comm.h
This file is part of a program that implements a Software-Defined Radio.
Copyright (C) 2013, 2024, 2025 Warren Pratt, NR0V
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
The author can be reached by email at
warren@wpratt.com
*/
#if defined(linux) || defined(__APPLE__)
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <string.h>
#include "linux_port.h"
#endif
#ifdef _WIN32
#include <Windows.h>
#include <process.h>
#include <intrin.h>
#endif
#include <math.h>
#include <stdint.h>
#include <time.h>
#ifdef _WIN32
#include <avrt.h>
#endif
#include "fftw3.h"
#include "amd.h"
#include "ammod.h"
#include "amsq.h"
#include "analyzer.h"
#include "anf.h"
#include "anr.h"
#include "apfshadow.h"
#include "bandpass.h"
#include "calcc.h"
#include "cblock.h"
#include "cfcomp.h"
#include "cfir.h"
#include "channel.h"
#include "cmath.h"
#include "compress.h"
#include "delay.h"
#include "dexp.h"
#include "div.h"
#include "doublepole.h"
#include "eer.h"
#include "emnr.h"
#include "rnnr.h" // NR3 + NR4 support
#include "sbnr.h" // NR3 + NR4 support
#include "emph.h"
#include "eq.h"
#include "fcurve.h"
#include "fir.h"
#include "firmin.h"
#include "fmd.h"
#include "fmmod.h"
#include "fmsq.h"
#include "gain.h"
#include "gaussian.h"
#include "gen.h"
#include "icfir.h"
#include "iir.h"
#include "impulse_cache.h"
#include "iobuffs.h"
#include "iqc.h"
#include "lmath.h"
#include "main.h"
#include "matchedCW.h"
#include "meter.h"
#include "meterlog10.h"
#include "nbp.h"
#include "nob.h"
#include "nobII.h"
#include "osctrl.h"
#include "patchpanel.h"
#include "resample.h"
#include "rmatch.h"
#include "RXA.h"
#include "sender.h"
#include "shift.h"
#include "siphon.h"
#include "slew.h"
#include "snb.h"
#include "ssql.h"
#include "syncbuffs.h"
#include "TXA.h"
#include "utilities.h"
#include "varsamp.h"
#include "wcpAGC.h"
// manage differences among consoles
#define _Thetis
// channel definitions
#define MAX_CHANNELS 32 // maximum number of supported channels
#define DSP_MULT 2 // number of dsp_buffsizes that are held in an iobuff pseudo-ring
#define INREAL float // data type for channel input buffer
#define OUTREAL float // data type for channel output buffer
// display definitions
#define dMAX_DISPLAYS 72 // maximum number of displays = max instances
#define dMAX_STITCH 4 // maximum number of sub-spans to stitch together
#define dMAX_NUM_FFT 1 // maximum number of ffts for an elimination
#define dMAX_PIXELS 16384 // maximum number of pixels that can be requested
#define dMAX_AVERAGE 60 // maximum number of pixel frames that will be window-averaged
#ifdef _Thetis
#define dINREAL double
#else
#define dINREAL float
#endif
#define dOUTREAL float
#define dSAMP_BUFF_MULT 2 // ratio of input sample buffer size to fft size (for overlap)
#define dNUM_PIXEL_BUFFS 3 // number of pixel output buffers
#define dMAX_M 1 // number of variables to calibrate
#define dMAX_N 100 // maximum number of frequencies at which to calibrate
#define dMAX_CAL_SETS 2 // maximum number of calibration data sets
#define dMAX_PIXOUTS 4 // maximum number of det/avg/outputs per display instance
// wisdom definitions
#define MAX_WISDOM_SIZE_DISPLAY 262144
#define MAX_WISDOM_SIZE_FILTER 262144 // was 32769
// math definitions
#define PI 3.1415926535897932
#define TWOPI 6.2831853071795864
// Non-aliasing qualifier for DSP buffers. Spelled __restrict rather than
// restrict because the JNI translation unit is compiled as -std=gnu89.
#if defined(__GNUC__) || defined(__clang__) || defined(_MSC_VER)
#define WDSP_RESTRICT __restrict
#else
#define WDSP_RESTRICT
#endif
// miscellaneous
typedef double complex[2];
#define PORT __declspec( dllexport )