# 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
├── Makefile.windows             — Windows cross-build (MinGW-w64, runs on Linux)
├── java/
│   └── org/openhpsdr/dsp/Wdsp.java
├── third_party/
│   ├── fftw-3.3.11/       — FFTW source (downloaded automatically)
│   ├── fftw-win64/        — FFTW Windows binaries (downloaded automatically)
│   ├── rnnoise/           — RNNoise noise suppression
│   └── libspecbleach/     — spectral noise reduction
├── obj/                   — object files (generated)
├── obj_win/               — Windows object files (generated)
├── lib/                   — built libraries (generated)
└── lib_win/               — Windows libraries (generated)
```

---

## Host build (Linux / macOS)

### Dependencies

**Linux:**
```bash
sudo apt install build-essential libfftw3-dev pkg-config default-jdk
```

**macOS:**
```bash
brew install fftw pkg-config
```

### Build

```bash
# 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

```bash
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 |

```bash
make NR34LIB=ON    # build without NR3/NR4 noise reduction
make CC=clang
```

### Clean

```bash
make clean
```

---

## Windows build (кросс-компиляция с Linux)

Сборка выполняется на Linux с помощью MinGW-w64. FFTW скачивается и собирается из исходников автоматически.

### Зависимости

```bash
# Arch
sudo pacman -S mingw-w64-gcc        # тянет mingw-w64-headers автоматически

# Debian / Ubuntu — нужен мета-пакет mingw-w64, а не только компилятор
sudo apt install mingw-w64

# Fedora
sudo dnf install mingw64-gcc        # тянет mingw64-headers автоматически
```

Также нужен `wget` или `curl`.

> **Debian/Ubuntu:** пакет `gcc-mingw-w64-x86-64` содержит только компилятор без Windows API заголовков — `Windows.h` не будет найден. Используйте `mingw-w64`.

### Сборка

```bash
# DLL + статическая библиотека (рекомендуется)
make -f Makefile.windows

# Только DLL
make -f Makefile.windows dll

# Только статическая библиотека
make -f Makefile.windows static
```

Результат в `lib_win/`:

| Файл | Назначение |
|---|---|
| `libwdsp.dll` | DLL для Windows |
| `libwdsp.dll.a` | Import library для MinGW (`-lwdsp`) |
| `libwdsp.a` | Статическая библиотека |
| `libfftw3-3.dll` | Runtime dependency — распространять вместе с DLL |
| `libfftw3f-3.dll` | Runtime dependency — распространять вместе с DLL |

### Линковка приложения

**MinGW:**
```bash
gcc myapp.c -Llib_win -lwdsp -o myapp.exe
```

**MSVC** — переименовать `libwdsp.dll.a` в `libwdsp.lib` и подключить обычным образом.

**Статически** (MinGW):
```bash
gcc myapp.c libwdsp.a third_party/rnnoise/librnnoise.a \
    third_party/libspecbleach/libspecbleach.a \
    -Lthird_party/fftw-win64 -lfftw3-3 -lfftw3f-3 -lavrt -lm -o myapp.exe
```

### Параметры

| Переменная | По умолчанию | Описание |
|---|---|---|
| `MINGW_PREFIX` | `x86_64-w64-mingw32` | Префикс MinGW toolchain |
| `FFTW_VERSION` | `3.3.11` | Версия FFTW |
| `CFLAGS` | `-O3 -Wno-parentheses` | Флаги компилятора |

```bash
make -f Makefile.windows MINGW_PREFIX=i686-w64-mingw32   # 32-bit Windows
```

### Очистка

```bash
make -f Makefile.windows clean       # артефакты сборки
make -f Makefile.windows distclean   # + удалить скачанный FFTW
```

---

## Android build

### Prerequisites

1. **Android NDK** r23 or newer
2. **Java compiler** — for building the `.class` file (Android Studio's JBR or any JDK)

FFTW 3.3.11 скачивается и собирается автоматически. Чтобы использовать уже скачанный исходник, передайте `FFTW_SRC=/path/to/fftw-3.3.11`.

### Build

```bash
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 |

```bash
make -f Makefile.android \
    ANDROID_NDK=~/Android/Sdk/ndk/26.3.11579264 \
    ANDROID_API=26 \
    ANDROID_ABIS=arm64-v8a
```

### Clean

```bash
make -f Makefile.android clean       # удаляет obj/android/ и lib/android/
make -f Makefile.android distclean   # + удаляет скачанный FFTW
```

---

## 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:

```java
System.loadLibrary("wdsp");
System.loadLibrary("wdspj");
```

Or use the singleton:

```java
Wdsp wdsp = Wdsp.getInstance();
```
