12dc701604bbb23e729717fbbc02bbadba6d5d08
Two pieces of pure overhead, neither of them doing any DSP.
The POSIX QueueUserWorkItem() shim spawned a thread and immediately joined
it. That is a synchronous call -- the parallelism the Windows thread pool
provides is absent here either way -- so it only bought a pthread_create()
and its stack mmap, ~15 us, for every FFT frame. Call the function directly.
(The Windows build is untouched and still gets its thread pool; a real pool
for POSIX would be a separate change, and only pays off for num_stitch > 1.)
The dispatcher thread ran `for (each ss, LO) {...} Sleep(1);`, and Sleep(1)
is usleep(1000), so it woke 1000 times a second to re-read the same flags.
That burned 0.63% of a core even with no samples arriving. Give it a
semaphore instead, signalled by the four Spectrum*() entry points when new
samples land, and by SetAnalyzer/DestroyAnalyzer after they raise
end_dispatcher so the blocking wait always has a way out. SetAnalyzer holds
SetAnalyzerSection while it waits for the dispatcher to quit, and the
dispatcher never takes that section, so signalling from under it is safe.
Measured on an Apple M1 Pro; 16384-point complex FFT, 1024-sample buffers,
~40 pixel frames/s, CPU of all threads via getrusage:
idle, no samples at all 0.63% of a core -> 0.00%
under load 3.54% -> 2.65%
Output pixels are bit-identical. Stressed with 3 create/destroy cycles and
24 on-the-fly SetAnalyzer reconfigurations while a second thread fed samples:
no deadlock.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
WDSP
DSP library for SDR (Software Defined Radio) applications.
Originally written for Windows by Warren Pratt, NR0V. Ported to Linux and Android by John Melton G0ORX/N6LYT.
Project structure
wdsp/
├── *.c / *.h — WDSP library sources
├── org_openhpsdr_dsp_Wdsp.c/.h — JNI bridge
├── Makefile — host build (Linux / macOS)
├── Makefile.android — Android cross-build
├── java/
│ └── org/openhpsdr/dsp/Wdsp.java
├── third_party/
│ ├── fftw/ — FFTW source (download manually, see below)
│ ├── rnnoise/ — RNNoise noise suppression
│ └── libspecbleach/ — spectral noise reduction
├── obj/ — object files (generated)
└── lib/ — built libraries (generated)
Host build (Linux / macOS)
Dependencies
Linux:
sudo apt install build-essential libfftw3-dev pkg-config default-jdk
macOS:
brew install fftw pkg-config
Build
# Full build: static + shared + JNI library + Java classes
make
# Individual targets
make static # lib/libwdsp.a
make shared # lib/libwdsp.so (or .dylib on macOS)
make java # lib/libwdspj.so + java/build/
Install
sudo make install # installs to /usr/local/lib and /usr/local/include
sudo make PREFIX=/opt/wdsp install # custom prefix
sudo make install_java # install libwdspj alongside libwdsp
Options
| Variable | Default | Description |
|---|---|---|
PREFIX |
/usr/local |
Install prefix |
NR34LIB |
off | Set to ON to skip bundled rnnoise/libspecbleach |
CC |
gcc |
C compiler |
CFLAGS |
-pthread -O3 ... |
Compiler flags |
make NR34LIB=ON # build without NR3/NR4 noise reduction
make CC=clang
Clean
make clean
Android build
Prerequisites
- Android NDK r23 or newer
- FFTW source — download and extract into
third_party/fftw/:
wget https://www.fftw.org/fftw-3.3.10.tar.gz
tar xf fftw-3.3.10.tar.gz
mv fftw-3.3.10 third_party/fftw
- Java compiler — for building the
.classfile (Android Studio's JBR or any JDK)
Build
make android
# or directly
make -f Makefile.android
Output is placed into:
lib/android/
├── arm64-v8a/
│ ├── libfftw3.so
│ ├── libfftw3f.so
│ ├── libwdsp.so
│ └── libwdspj.so
├── armeabi-v7a/
│ └── ...
├── x86_64/
│ └── ...
└── java/
└── org/openhpsdr/dsp/Wdsp.class
libwdsp.so has FFTW linked statically — no separate FFTW dependency at runtime on the device.
Options
| Variable | Default | Description |
|---|---|---|
ANDROID_NDK |
/home/vladimir/Android/Sdk/ndk/29.0.14206865 |
Path to Android NDK |
ANDROID_API |
24 |
Minimum API level |
ANDROID_ABIS |
arm64-v8a armeabi-v7a x86_64 |
Target ABIs |
ANDROID_HOST_TAG |
auto-detected | Host platform (linux-x86_64, darwin-x86_64, etc.) |
FFTW_SRC |
third_party/fftw |
Path to FFTW source |
JAVAC |
/opt/android-studio/jbr/bin/javac |
Java compiler |
make -f Makefile.android \
ANDROID_NDK=~/Android/Sdk/ndk/26.3.11579264 \
ANDROID_API=26 \
ANDROID_ABIS=arm64-v8a
Clean
make -f Makefile.android clean
# removes obj/android/ and lib/android/
Using in an Android project
Copy lib/android/{abi}/ into your Android project's jniLibs:
app/src/main/jniLibs/
├── arm64-v8a/
│ ├── libwdsp.so
│ └── libwdspj.so
├── armeabi-v7a/
│ └── ...
└── x86_64/
└── ...
Add Wdsp.java to your source tree and load the libraries at startup:
System.loadLibrary("wdsp");
System.loadLibrary("wdspj");
Or use the singleton:
Wdsp wdsp = Wdsp.getInstance();
Description
Languages
C
99.9%
Java
0.1%