Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

98 řádky
2.6KB

  1. //go:build cufft && windows
  2. package gpudemod
  3. import (
  4. "errors"
  5. "math"
  6. "unsafe"
  7. "sdr-visual-suite/internal/dsp"
  8. )
  9. func (r *BatchRunner) shiftFilterDecimateBatchImpl(iq []complex64) ([][]complex64, []int, error) {
  10. outs := make([][]complex64, len(r.slots))
  11. rates := make([]int, len(r.slots))
  12. streams := make([]streamHandle, len(r.slots))
  13. for i := range streams {
  14. s, _ := bridgeStreamCreate()
  15. streams[i] = s
  16. }
  17. defer func() {
  18. for _, s := range streams {
  19. if s != nil {
  20. _ = bridgeStreamDestroy(s)
  21. }
  22. }
  23. }()
  24. for i := range r.slots {
  25. if !r.slots[i].active {
  26. continue
  27. }
  28. out, rate, err := r.shiftFilterDecimateSlot(iq, r.slots[i].job, streams[i])
  29. if err != nil {
  30. return nil, nil, err
  31. }
  32. r.slots[i].out = out
  33. r.slots[i].rate = rate
  34. outs[i] = out
  35. rates[i] = rate
  36. }
  37. return outs, rates, nil
  38. }
  39. func (r *BatchRunner) shiftFilterDecimateSlot(iq []complex64, job ExtractJob, stream streamHandle) ([]complex64, int, error) {
  40. e := r.eng
  41. if e == nil || !e.cudaReady {
  42. return nil, 0, ErrUnavailable
  43. }
  44. if len(iq) == 0 {
  45. return nil, 0, nil
  46. }
  47. cutoff := job.BW / 2
  48. if cutoff < 200 {
  49. cutoff = 200
  50. }
  51. taps := e.firTaps
  52. if len(taps) == 0 {
  53. base64 := dsp.LowpassFIR(cutoff, e.sampleRate, 101)
  54. taps = make([]float32, len(base64))
  55. for i, v := range base64 {
  56. taps[i] = float32(v)
  57. }
  58. e.SetFIR(taps)
  59. }
  60. decim := int(math.Round(float64(e.sampleRate) / float64(job.OutRate)))
  61. if decim < 1 {
  62. decim = 1
  63. }
  64. n := len(iq)
  65. nOut := n / decim
  66. if nOut <= 0 {
  67. return nil, 0, errors.New("not enough output samples after decimation")
  68. }
  69. bytesIn := uintptr(n) * unsafe.Sizeof(complex64(0))
  70. if bridgeMemcpyH2D(unsafe.Pointer(e.dIQIn), unsafe.Pointer(&iq[0]), bytesIn) != 0 {
  71. return nil, 0, errors.New("cudaMemcpy H2D failed")
  72. }
  73. phaseInc := -2.0 * math.Pi * job.OffsetHz / float64(e.sampleRate)
  74. if bridgeLaunchFreqShiftStream(e.dIQIn, e.dShifted, n, phaseInc, e.phase, stream) != 0 {
  75. return nil, 0, errors.New("gpu freq shift failed")
  76. }
  77. if bridgeLaunchFIRStream(e.dShifted, e.dFiltered, n, len(taps), stream) != 0 {
  78. return nil, 0, errors.New("gpu FIR failed")
  79. }
  80. if bridgeLaunchDecimateStream(e.dFiltered, e.dDecimated, nOut, decim, stream) != 0 {
  81. return nil, 0, errors.New("gpu decimate failed")
  82. }
  83. if bridgeStreamSync(stream) != 0 {
  84. return nil, 0, errors.New("cuda stream sync failed")
  85. }
  86. out := make([]complex64, nOut)
  87. outBytes := uintptr(nOut) * unsafe.Sizeof(complex64(0))
  88. if bridgeMemcpyD2H(unsafe.Pointer(&out[0]), unsafe.Pointer(e.dDecimated), outBytes) != 0 {
  89. return nil, 0, errors.New("cudaMemcpy D2H failed")
  90. }
  91. return out, e.sampleRate / decim, nil
  92. }