소스 검색

feat: extend gpudemod to multiple demod modes

master
Jan Svabenik 2 일 전
부모
커밋
f4f0e07e0a
3개의 변경된 파일60개의 추가작업 그리고 17개의 파일을 삭제
  1. BIN
      internal/demod/gpudemod/build/kernels.obj
  2. +36
    -11
      internal/demod/gpudemod/gpudemod.go
  3. +24
    -6
      internal/recorder/demod.go

BIN
internal/demod/gpudemod/build/kernels.obj 파일 보기


+ 36
- 11
internal/demod/gpudemod/gpudemod.go 파일 보기

@@ -203,17 +203,24 @@ func (e *Engine) Demod(iq []complex64, offsetHz float64, bw float64, mode DemodT
if len(iq) > e.maxSamples {
return nil, 0, errors.New("sample count exceeds engine capacity")
}
if mode != DemodNFM {
return nil, 0, errors.New("CUDA demod phase 1 currently supports NFM only")
}

// Real CUDA boundary is now present. If the launch wrappers are not yet backed
// by actual kernels, we fall back to the existing CPU DSP path below.
_ = fmt.Sprintf("%s:%0.3f", phaseStatus(), offsetHz)
shifted, ok := e.tryCUDAFreqShift(iq, offsetHz)
if !ok || !ValidateFreqShift(iq, e.sampleRate, offsetHz, shifted, 1e-3) {
e.lastShiftUsedGPU = ok && ValidateFreqShift(iq, e.sampleRate, offsetHz, shifted, 1e-3)
if !e.lastShiftUsedGPU {
shifted = dsp.FreqShift(iq, e.sampleRate, offsetHz)
}

var outRate int
switch mode {
case DemodNFM, DemodAM, DemodUSB, DemodLSB, DemodCW:
outRate = 48000
case DemodWFM:
outRate = 192000
default:
return nil, 0, errors.New("unsupported demod type")
}

cutoff := bw / 2
if cutoff < 200 {
cutoff = 200
@@ -224,15 +231,35 @@ func (e *Engine) Demod(iq []complex64, offsetHz float64, bw float64, mode DemodT
taps = append(make([]float32, 0, len(base)), base...)
}
filtered := dsp.ApplyFIR(shifted, taps)
outRate := demod.NFM{}.OutputSampleRate()
decim := int(math.Round(float64(e.sampleRate) / float64(outRate)))
if decim < 1 {
decim = 1
}
dec := dsp.Decimate(filtered, decim)
inputRate := e.sampleRate / decim
audio := demod.NFM{}.Demod(dec, inputRate)
return audio, inputRate, nil

switch mode {
case DemodNFM:
if gpuAudio, ok := e.tryCUDAFMDiscrim(dec); ok {
return gpuAudio, inputRate, nil
}
return demod.NFM{}.Demod(dec, inputRate), inputRate, nil
case DemodWFM:
if gpuAudio, ok := e.tryCUDAFMDiscrim(dec); ok {
return gpuAudio, inputRate, nil
}
return demod.WFM{}.Demod(dec, inputRate), inputRate, nil
case DemodAM:
return demod.AM{}.Demod(dec, inputRate), inputRate, nil
case DemodUSB:
return demod.USB{}.Demod(dec, inputRate), inputRate, nil
case DemodLSB:
return demod.LSB{}.Demod(dec, inputRate), inputRate, nil
case DemodCW:
return demod.CW{}.Demod(dec, inputRate), inputRate, nil
default:
return nil, 0, errors.New("unsupported demod type")
}
}

func (e *Engine) Close() {
@@ -254,5 +281,3 @@ func (e *Engine) Close() {
e.firTaps = nil
e.cudaReady = false
}
aReady = false
}

+ 24
- 6
internal/recorder/demod.go 파일 보기

@@ -30,12 +30,30 @@ func (m *Manager) demodAndWrite(dir string, ev detector.Event, iq []complex64, f
offset := ev.CenterHz - m.centerHz
var audio []float32
var inputRate int
if m.gpuDemod != nil && name == "NFM" {
if gpuAudio, gpuRate, err := m.gpuDemod.Demod(iq, offset, bw, gpudemod.DemodNFM); err == nil {
audio = gpuAudio
inputRate = gpuRate
if m.gpuDemod.LastShiftUsedGPU() {
log.Printf("gpudemod: validated GPU freq-shift used for event %d", ev.ID)
if m.gpuDemod != nil {
var gpuMode gpudemod.DemodType
var useGPU bool
switch name {
case "NFM":
gpuMode, useGPU = gpudemod.DemodNFM, true
case "WFM":
gpuMode, useGPU = gpudemod.DemodWFM, true
case "AM":
gpuMode, useGPU = gpudemod.DemodAM, true
case "USB":
gpuMode, useGPU = gpudemod.DemodUSB, true
case "LSB":
gpuMode, useGPU = gpudemod.DemodLSB, true
case "CW":
gpuMode, useGPU = gpudemod.DemodCW, true
}
if useGPU {
if gpuAudio, gpuRate, err := m.gpuDemod.Demod(iq, offset, bw, gpuMode); err == nil {
audio = gpuAudio
inputRate = gpuRate
if m.gpuDemod.LastShiftUsedGPU() {
log.Printf("gpudemod: validated GPU freq-shift used for event %d (%s)", ev.ID, name)
}
}
}
}


불러오는 중...
취소
저장