# nnr-lite native build (Linux / WSL / MSYS2).   make            -> build/libnnrlite.a
#                                                make test       -> compare against the real WDSP (needs libwdsp_ref.so)
CC      ?= gcc
OPT     ?= -O2
# NNR_REF=1 builds the original double-precision layers of WDSP's nnet.c (the reference);
# the default is the optimised layer code of nnet_fast.c.  XFLAGS: -DNNR_FAST_DOUBLE (fast
# layout, double maths), -DNNR_NO_VEC (no SIMD), -msse4.1 / -mavx2 ...
NNR_REF ?= 0
XFLAGS  ?=
ifeq ($(NNR_REF),0)
override XFLAGS += -DNNR_FAST
endif
CFLAGS  += -MMD -MP $(OPT) $(XFLAGS) -std=gnu11 -Wall -Wno-unused-function -Wno-unused-variable -Wno-parentheses -DNNET_NSLOTS=1 -Dkiss_fft_scalar=double
INC      = -Innr/compat -Innr/src -Innr/include -Ithird_party/kissfft
B        = build

LIBSRC = nnr/src/nnr.c nnr/src/nnet.c nnr/src/nnio.c nnr/src/nnr_nomodel.c nnr/src/nnr_lite.c \
         nnr/src/nnet_fast.c nnr/src/snb.c nnr/src/snb_fir.c nnr/src/snb_math.c nnr/src/resample.c nnr/src/snb_lite.c \
         nnr/compat/fftw_kiss.c third_party/kissfft/kiss_fft.c third_party/kissfft/kiss_fftr.c
LIBOBJ = $(patsubst %.c,$(B)/%.o,$(LIBSRC))

all: $(B)/libnnrlite.a
-include $(LIBOBJ:.o=.d)

$(B)/%.o: %.c
	@mkdir -p $(dir $@)
	$(CC) $(CFLAGS) $(INC) -c $< -o $@

$(B)/libnnrlite.a: $(LIBOBJ)
	ar rcs $@ $^

clean:
	rm -rf $(B)

.PHONY: all clean

# ---- tests -------------------------------------------------------------------------------------
# test driver against nnr-lite
$(B)/nnr_run_lite: test/nnr_run.c $(B)/libnnrlite.a
	$(CC) $(CFLAGS) $(INC) $< $(B)/libnnrlite.a -lm -o $@

# the same driver against the real WDSP (built separately with FFTW, see test/build_ref.sh)
REF ?= $(HOME)/wdsp_ref/libwdsp_ref.so
$(B)/nnr_run_ref: test/nnr_run.c
	@mkdir -p $(B)
	$(CC) $(OPT) -std=gnu11 -Innr/src $< $(REF) -Wl,-rpath,$(dir $(REF)) -lm -o $@

tests: $(B)/nnr_run_lite $(B)/nnr_run_ref
.PHONY: tests

$(B)/test_api: test/test_api.c $(B)/libnnrlite.a
	$(CC) $(CFLAGS) $(INC) $< $(B)/libnnrlite.a -lm -o $@
tests: $(B)/test_api

# ---- SNBA (spectral noise blanker): lite vs the real WDSP ------------------------------------------
$(B)/snb_run_lite: test/snb_run.c $(B)/libnnrlite.a
	$(CC) $(CFLAGS) $(INC) $< $(B)/libnnrlite.a -lm -o $@

# real WDSP at 48 kHz (original code)
$(B)/snb_run_ref: test/snb_run.c
	@mkdir -p $(B)
	$(CC) $(OPT) -std=gnu11 -DSNB_REF -Innr/src $< $(REF) -Wl,-rpath,$(dir $(REF)) -lm -o $@

# 16 kHz: nnr/src/snb.c (only the integer-ratio fix of calc_snba differs from WDSP) on the real WDSP resampler / math
$(B)/snb_run_ref16: test/snb_run.c nnr/src/snb.c
	@mkdir -p $(B)
	$(CC) $(OPT) -std=gnu11 -w -DSNB_REF $(INC) $^ $(REF) -Wl,-rpath,$(dir $(REF)) -lm -o $@

snbtests: $(B)/snb_run_lite $(B)/snb_run_ref $(B)/snb_run_ref16
.PHONY: snbtests

# ---- RADE V1 receiver (rade_rx_lite): rade_c + Opus FARGAN, see rade/THIRD_PARTY.md -------------------
RADE_SRC = $(addprefix rade/src/, rade_dsp.c rade_ofdm.c rade_bpf.c rade_acq.c rade_rx.c rade_dec.c rade_dec_init.c rade_rx_lite.c) \
           $(addprefix rade/opus/dnn/, nnet.c nnet_default.c parse_lpcnet_weights.c fargan.c fargan_init.c) \
           $(addprefix rade/opus/celt/, pitch.c celt_lpc.c kiss_fft.c mathops.c)
RADE_INC = -Irade/src -Irade/include -Irade/opus -Irade/opus/include -Irade/opus/celt -Irade/opus/dnn
$(B)/rade_lite_run: test/rade_lite_run.c $(RADE_SRC)
	@mkdir -p $(B)
	$(CC) $(OPT) -std=gnu11 -w -DHAVE_CONFIG_H $(RADE_INC) $^ -lm -o $@
radetests: $(B)/rade_lite_run
.PHONY: radetests
