Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

99 linhas
2.7KB

  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. for i := range r.slots {
  13. if !r.slots[i].active {
  14. continue
  15. }
  16. out, rate, err := r.shiftFilterDecimateSlot(iq, r.slots[i].job, nil)
  17. if err != nil {
  18. return nil, nil, err
  19. }
  20. r.slots[i].out = out
  21. r.slots[i].rate = rate
  22. outs[i] = out
  23. rates[i] = rate
  24. }
  25. return outs, rates, nil
  26. }
  27. func (r *BatchRunner) shiftFilterDecimateSlot(iq []complex64, job ExtractJob, stream streamHandle) ([]complex64, int, error) {
  28. e := r.eng
  29. if e == nil || !e.cudaReady {
  30. return nil, 0, ErrUnavailable
  31. }
  32. if len(iq) == 0 {
  33. return nil, 0, nil
  34. }
  35. cutoff := job.BW / 2
  36. if cutoff < 200 {
  37. cutoff = 200
  38. }
  39. base64 := dsp.LowpassFIR(cutoff, e.sampleRate, 101)
  40. taps := make([]float32, len(base64))
  41. for i, v := range base64 {
  42. taps[i] = float32(v)
  43. }
  44. if len(taps) == 0 {
  45. return nil, 0, errors.New("no FIR taps configured")
  46. }
  47. e.SetFIR(taps)
  48. if stream == nil {
  49. if bridgeDeviceSync() != 0 {
  50. return nil, 0, errors.New("cudaDeviceSynchronize failed")
  51. }
  52. }
  53. decim := int(math.Round(float64(e.sampleRate) / float64(job.OutRate)))
  54. if decim < 1 {
  55. decim = 1
  56. }
  57. n := len(iq)
  58. nOut := n / decim
  59. if nOut <= 0 {
  60. return nil, 0, errors.New("not enough output samples after decimation")
  61. }
  62. bytesIn := uintptr(n) * unsafe.Sizeof(complex64(0))
  63. if bridgeMemcpyH2D(unsafe.Pointer(e.dIQIn), unsafe.Pointer(&iq[0]), bytesIn) != 0 {
  64. return nil, 0, errors.New("cudaMemcpy H2D failed")
  65. }
  66. phaseInc := -2.0 * math.Pi * job.OffsetHz / float64(e.sampleRate)
  67. phaseStart := e.phase
  68. if bridgeLaunchFreqShiftStream(e.dIQIn, e.dShifted, n, phaseInc, phaseStart, stream) != 0 {
  69. return nil, 0, errors.New("gpu freq shift failed")
  70. }
  71. if bridgeLaunchFIRStream(e.dShifted, e.dFiltered, n, len(taps), stream) != 0 {
  72. return nil, 0, errors.New("gpu FIR failed")
  73. }
  74. if bridgeLaunchDecimateStream(e.dFiltered, e.dDecimated, nOut, decim, stream) != 0 {
  75. return nil, 0, errors.New("gpu decimate failed")
  76. }
  77. if stream != nil {
  78. if bridgeStreamSync(stream) != 0 {
  79. return nil, 0, errors.New("cuda stream sync failed")
  80. }
  81. } else {
  82. if bridgeDeviceSync() != 0 {
  83. return nil, 0, errors.New("cudaDeviceSynchronize failed")
  84. }
  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. e.phase = phaseStart + phaseInc*float64(n)
  92. return out, e.sampleRate / decim, nil
  93. }