Просмотр исходного кода

Refine window sources and span reporting

master
Jan Svabenik 16 часов назад
Родитель
Сommit
fa84453437
4 измененных файлов: 65 добавлений и 1 удалений
  1. +24
    -1
      cmd/sdrd/pipeline_runtime.go
  2. +15
    -0
      cmd/sdrd/pipeline_runtime_test.go
  3. +3
    -0
      internal/pipeline/window_rules.go
  4. +23
    -0
      internal/pipeline/window_rules_test.go

+ 24
- 1
cmd/sdrd/pipeline_runtime.go Просмотреть файл

@@ -296,12 +296,16 @@ func (rt *dspRuntime) buildRefinementInput(surv pipeline.SurveillanceResult) pip
for _, sc := range scheduled {
windows = append(windows, pipeline.RefinementWindowForCandidate(policy, sc.Candidate))
}
levelSpan := spanForPolicy(policy, float64(rt.cfg.SampleRate))
if _, maxSpan, ok := windowSpanBounds(windows); ok {
levelSpan = maxSpan
}
level := pipeline.AnalysisLevel{
Name: "refinement",
SampleRate: rt.cfg.SampleRate,
FFTSize: rt.cfg.FFTSize,
CenterHz: rt.cfg.CenterHz,
SpanHz: spanForPolicy(policy, float64(rt.cfg.SampleRate)),
SpanHz: levelSpan,
Source: "refinement-window",
}
input := pipeline.RefinementInput{
@@ -508,6 +512,25 @@ func spanForPolicy(policy pipeline.Policy, fallback float64) float64 {
return fallback
}

func windowSpanBounds(windows []pipeline.RefinementWindow) (float64, float64, bool) {
minSpan := 0.0
maxSpan := 0.0
ok := false
for _, w := range windows {
if w.SpanHz <= 0 {
continue
}
if !ok || w.SpanHz < minSpan {
minSpan = w.SpanHz
}
if !ok || w.SpanHz > maxSpan {
maxSpan = w.SpanHz
}
ok = true
}
return minSpan, maxSpan, ok
}

func surveillanceLevels(policy pipeline.Policy, primary pipeline.AnalysisLevel, secondary pipeline.AnalysisLevel) []pipeline.AnalysisLevel {
levels := []pipeline.AnalysisLevel{primary}
strategy := strings.ToLower(strings.TrimSpace(policy.SurveillanceStrategy))


+ 15
- 0
cmd/sdrd/pipeline_runtime_test.go Просмотреть файл

@@ -57,3 +57,18 @@ func TestSurveillanceLevelsRespectStrategy(t *testing.T) {
t.Fatalf("expected secondary level for multi-res, got %d", len(levels))
}
}

func TestWindowSpanBounds(t *testing.T) {
windows := []pipeline.RefinementWindow{
{SpanHz: 8000},
{SpanHz: 16000},
{SpanHz: 12000},
}
minSpan, maxSpan, ok := windowSpanBounds(windows)
if !ok {
t.Fatalf("expected spans to be found")
}
if minSpan != 8000 || maxSpan != 16000 {
t.Fatalf("unexpected span bounds: min %.0f max %.0f", minSpan, maxSpan)
}
}

+ 3
- 0
internal/pipeline/window_rules.go Просмотреть файл

@@ -42,12 +42,15 @@ func RefinementWindowForCandidate(policy Policy, candidate Candidate) Refinement
}
if policy.RefinementMinSpanHz > 0 && span < policy.RefinementMinSpanHz {
span = policy.RefinementMinSpanHz
windowSource = "policy:min_span"
}
if policy.RefinementMaxSpanHz > 0 && span > policy.RefinementMaxSpanHz {
span = policy.RefinementMaxSpanHz
windowSource = "policy:max_span"
}
if span <= 0 {
span = 12000
windowSource = "default"
}
return RefinementWindow{
CenterHz: candidate.CenterHz,


+ 23
- 0
internal/pipeline/window_rules_test.go Просмотреть файл

@@ -0,0 +1,23 @@
package pipeline

import "testing"

func TestRefinementWindowClampsToPolicy(t *testing.T) {
policy := Policy{RefinementMinSpanHz: 12000, RefinementMaxSpanHz: 20000, RefinementAutoSpan: false}
win := RefinementWindowForCandidate(policy, Candidate{CenterHz: 1e6, BandwidthHz: 8000})
if win.SpanHz != 12000 || win.Source != "policy:min_span" {
t.Fatalf("expected min clamp, got span %.0f source %q", win.SpanHz, win.Source)
}
win = RefinementWindowForCandidate(policy, Candidate{CenterHz: 1e6, BandwidthHz: 50000})
if win.SpanHz != 20000 || win.Source != "policy:max_span" {
t.Fatalf("expected max clamp, got span %.0f source %q", win.SpanHz, win.Source)
}
}

func TestRefinementWindowDefaultsWhenEmpty(t *testing.T) {
policy := Policy{RefinementAutoSpan: false}
win := RefinementWindowForCandidate(policy, Candidate{CenterHz: 1e6, BandwidthHz: 0})
if win.SpanHz != 12000 || win.Source != "default" {
t.Fatalf("expected default span, got span %.0f source %q", win.SpanHz, win.Source)
}
}

Загрузка…
Отмена
Сохранить