|
- //go:build cufft && windows
-
- package gpudemod
-
- import (
- "errors"
- "math"
- "unsafe"
-
- "sdr-visual-suite/internal/dsp"
- )
-
- func (r *BatchRunner) shiftFilterDecimateBatchImpl(iq []complex64) ([][]complex64, []int, error) {
- outs := make([][]complex64, len(r.slots))
- rates := make([]int, len(r.slots))
- streams := make([]streamHandle, len(r.slots))
- for i := range streams {
- s, _ := bridgeStreamCreate()
- streams[i] = s
- }
- defer func() {
- for _, s := range streams {
- if s != nil {
- _ = bridgeStreamDestroy(s)
- }
- }
- }()
- for i := range r.slots {
- if !r.slots[i].active {
- continue
- }
- out, rate, err := r.shiftFilterDecimateSlot(iq, r.slots[i].job, streams[i])
- if err != nil {
- return nil, nil, err
- }
- r.slots[i].out = out
- r.slots[i].rate = rate
- outs[i] = out
- rates[i] = rate
- }
- return outs, rates, nil
- }
-
- func (r *BatchRunner) shiftFilterDecimateSlot(iq []complex64, job ExtractJob, stream streamHandle) ([]complex64, int, error) {
- e := r.eng
- if e == nil || !e.cudaReady {
- return nil, 0, ErrUnavailable
- }
- if len(iq) == 0 {
- return nil, 0, nil
- }
- cutoff := job.BW / 2
- if cutoff < 200 {
- cutoff = 200
- }
- taps := e.firTaps
- if len(taps) == 0 {
- base64 := dsp.LowpassFIR(cutoff, e.sampleRate, 101)
- taps = make([]float32, len(base64))
- for i, v := range base64 {
- taps[i] = float32(v)
- }
- e.SetFIR(taps)
- }
- decim := int(math.Round(float64(e.sampleRate) / float64(job.OutRate)))
- if decim < 1 {
- decim = 1
- }
- n := len(iq)
- nOut := n / decim
- if nOut <= 0 {
- return nil, 0, errors.New("not enough output samples after decimation")
- }
- bytesIn := uintptr(n) * unsafe.Sizeof(complex64(0))
- if bridgeMemcpyH2D(unsafe.Pointer(e.dIQIn), unsafe.Pointer(&iq[0]), bytesIn) != 0 {
- return nil, 0, errors.New("cudaMemcpy H2D failed")
- }
- phaseInc := -2.0 * math.Pi * job.OffsetHz / float64(e.sampleRate)
- if bridgeLaunchFreqShiftStream(e.dIQIn, e.dShifted, n, phaseInc, e.phase, stream) != 0 {
- return nil, 0, errors.New("gpu freq shift failed")
- }
- if bridgeLaunchFIRStream(e.dShifted, e.dFiltered, n, len(taps), stream) != 0 {
- return nil, 0, errors.New("gpu FIR failed")
- }
- if bridgeLaunchDecimateStream(e.dFiltered, e.dDecimated, nOut, decim, stream) != 0 {
- return nil, 0, errors.New("gpu decimate failed")
- }
- if bridgeStreamSync(stream) != 0 {
- return nil, 0, errors.New("cuda stream sync failed")
- }
- out := make([]complex64, nOut)
- outBytes := uintptr(nOut) * unsafe.Sizeof(complex64(0))
- if bridgeMemcpyD2H(unsafe.Pointer(&out[0]), unsafe.Pointer(e.dDecimated), outBytes) != 0 {
- return nil, 0, errors.New("cudaMemcpy D2H failed")
- }
- return out, e.sampleRate / decim, nil
- }
|