diff --git a/cmd/sdrd/main.go b/cmd/sdrd/main.go index 6832e9b..40fb7f9 100644 --- a/cmd/sdrd/main.go +++ b/cmd/sdrd/main.go @@ -449,6 +449,7 @@ func runDSP(ctx context.Context, srcMgr *sourceManager, cfg config.Config, det * dcBlocker := dsp.NewDCBlocker(0.995) dcEnabled := cfg.DCBlock iqEnabled := cfg.IQBalance + plan := fftutil.NewCmplxPlan(cfg.FFTSize) useGPU := cfg.UseGPUFFT var gpuEngine *gpufft.Engine if useGPU && gpuState != nil && gpuState.Available { @@ -480,6 +481,7 @@ func runDSP(ctx context.Context, srcMgr *sourceManager, cfg config.Config, det * } if upd.window != nil { window = upd.window + plan = fftutil.NewCmplxPlan(cfg.FFTSize) } dcEnabled = upd.dcBlock iqEnabled = upd.iqBalance @@ -546,7 +548,7 @@ func runDSP(ctx context.Context, srcMgr *sourceManager, cfg config.Config, det * spectrum = fftutil.SpectrumFromFFT(out) } } else { - spectrum = fftutil.Spectrum(iq, window) + spectrum = fftutil.SpectrumWithPlan(iq, window, plan) } now := time.Now() finished, signals := det.Process(now, spectrum, cfg.CenterHz) diff --git a/internal/fft/fft.go b/internal/fft/fft.go index 36ab34c..33b6700 100644 --- a/internal/fft/fft.go +++ b/internal/fft/fft.go @@ -1,10 +1,6 @@ package fftutil -import ( - "math" - - "gonum.org/v1/gonum/dsp/fourier" -) +import "math" func Hann(n int) []float64 { w := make([]float64, n) @@ -21,6 +17,11 @@ func Hann(n int) []float64 { } func Spectrum(iq []complex64, window []float64) []float64 { + plan := NewCmplxPlan(len(iq)) + return SpectrumWithPlan(iq, window, plan) +} + +func SpectrumWithPlan(iq []complex64, window []float64, plan *CmplxPlan) []float64 { n := len(iq) if n == 0 { return nil @@ -34,9 +35,12 @@ func Spectrum(iq []complex64, window []float64) []float64 { } in[i] = complex(float64(real(v))*w, float64(imag(v))*w) } - fft := fourier.NewCmplxFFT(n) out := make([]complex128, n) - fft.Coefficients(out, in) + if plan != nil && plan.N() == n { + plan.FFT(out, in) + } else { + NewCmplxPlan(n).FFT(out, in) + } power := make([]float64, n) eps := 1e-12 diff --git a/internal/fft/plan.go b/internal/fft/plan.go new file mode 100644 index 0000000..c6ae297 --- /dev/null +++ b/internal/fft/plan.go @@ -0,0 +1,24 @@ +package fftutil + +import "gonum.org/v1/gonum/dsp/fourier" + +type CmplxPlan struct { + fft *fourier.CmplxFFT + n int +} + +func NewCmplxPlan(n int) *CmplxPlan { + if n <= 0 { + return &CmplxPlan{} + } + return &CmplxPlan{fft: fourier.NewCmplxFFT(n), n: n} +} + +func (p *CmplxPlan) N() int { return p.n } + +func (p *CmplxPlan) FFT(out, in []complex128) { + if p == nil || p.fft == nil { + return + } + p.fft.Coefficients(out, in) +} diff --git a/internal/sdrplay/sdrplay.go b/internal/sdrplay/sdrplay.go index 13f69e2..dcccc2d 100644 --- a/internal/sdrplay/sdrplay.go +++ b/internal/sdrplay/sdrplay.go @@ -128,6 +128,7 @@ func (s *Source) configure(sampleRate int, centerHz float64, gainDb float64, bwK if err := cErr(C.sdrplay_api_LockDeviceApi()); err != nil { return fmt.Errorf("sdrplay_api_LockDeviceApi: %w", err) } + defer func() { _ = cErr(C.sdrplay_api_UnlockDeviceApi()) }() var numDevs C.uint var devices [8]C.sdrplay_api_DeviceT @@ -139,10 +140,8 @@ func (s *Source) configure(sampleRate int, centerHz float64, gainDb float64, bwK } s.dev = devices[0] if err := cErr(C.sdrplay_api_SelectDevice(&s.dev)); err != nil { - _ = cErr(C.sdrplay_api_UnlockDeviceApi()) return fmt.Errorf("sdrplay_api_SelectDevice: %w", err) } - _ = cErr(C.sdrplay_api_UnlockDeviceApi()) var params *C.sdrplay_api_DeviceParamsT if err := cErr(C.sdrplay_api_GetDeviceParams(s.dev.dev, ¶ms)); err != nil {