Selaa lähdekoodia

debug: add advanced boundary metering

debug/audio-clicks
Jan Svabenik 1 päivä sitten
vanhempi
commit
ffbc45d535
1 muutettua tiedostoa jossa 97 lisäystä ja 0 poistoa
  1. +97
    -0
      internal/recorder/streamer.go

+ 97
- 0
internal/recorder/streamer.go Näytä tiedosto

@@ -42,6 +42,14 @@ type streamSession struct {
prevAudioL float64 // second-to-last L sample for boundary transient detection
lastAudioSet bool

lastDecIQ complex64
prevDecIQ complex64
lastDecIQSet bool

lastDemodL float32
prevDemodL float64
lastDemodSet bool

// listenOnly sessions have no WAV file and no disk I/O.
// They exist solely to feed audio to live-listen subscribers.
listenOnly bool
@@ -786,11 +794,100 @@ func (sess *streamSession) processSnippet(snippet []complex64, snipRate int) ([]
dec = fullSnip
}

if logging.EnabledCategory("boundary") && len(dec) > 0 {
first := dec[0]
if sess.lastDecIQSet {
d2Re := math.Abs(2*float64(real(sess.lastDecIQ)) - float64(real(sess.prevDecIQ)) - float64(real(first)))
d2Im := math.Abs(2*float64(imag(sess.lastDecIQ)) - float64(imag(sess.prevDecIQ)) - float64(imag(first)))
d2Mag := math.Hypot(d2Re, d2Im)
if d2Mag > 0.15 {
logging.Warn("boundary", "dec_iq_boundary", "signal", sess.signalID, "d2", d2Mag)
}
}

headN := 16
if len(dec) < headN {
headN = len(dec)
}
tailN := 16
if len(dec) < tailN {
tailN = len(dec)
}
var headSum, tailSum, minMag, maxMag float64
minMag = math.MaxFloat64
for i, v := range dec {
mag := math.Hypot(float64(real(v)), float64(imag(v)))
if mag < minMag {
minMag = mag
}
if mag > maxMag {
maxMag = mag
}
if i < headN {
headSum += mag
}
}
for i := len(dec) - tailN; i < len(dec); i++ {
if i >= 0 {
v := dec[i]
tailSum += math.Hypot(float64(real(v)), float64(imag(v)))
}
}
headAvg := 0.0
if headN > 0 {
headAvg = headSum / float64(headN)
}
tailAvg := 0.0
if tailN > 0 {
tailAvg = tailSum / float64(tailN)
}
logging.Debug("boundary", "dec_iq_meter", "signal", sess.signalID, "len", len(dec), "head_avg", headAvg, "tail_avg", tailAvg, "min_mag", minMag, "max_mag", maxMag)
if tailAvg > 0 {
ratio := headAvg / tailAvg
if ratio < 0.75 || ratio > 1.25 {
logging.Warn("boundary", "dec_iq_head_tail_skew", "signal", sess.signalID, "head_avg", headAvg, "tail_avg", tailAvg, "ratio", ratio)
}
}

if len(dec) >= 2 {
sess.prevDecIQ = dec[len(dec)-2]
sess.lastDecIQ = dec[len(dec)-1]
} else {
sess.prevDecIQ = sess.lastDecIQ
sess.lastDecIQ = dec[0]
}
sess.lastDecIQSet = true
}

// --- FM/AM/etc Demod ---
audio := d.Demod(dec, actualDemodRate)
if len(audio) == 0 {
return nil, 0
}
if logging.EnabledCategory("boundary") {
stride := d.Channels()
if stride < 1 {
stride = 1
}
nFrames := len(audio) / stride
if nFrames > 0 {
first := float64(audio[0])
if sess.lastDemodSet {
d2 := math.Abs(2*float64(sess.lastDemodL) - sess.prevDemodL - first)
if d2 > 0.15 {
logging.Warn("boundary", "demod_boundary", "signal", sess.signalID, "d2", d2)
}
}
if nFrames >= 2 {
sess.prevDemodL = float64(audio[(nFrames-2)*stride])
sess.lastDemodL = audio[(nFrames-1)*stride]
} else {
sess.prevDemodL = float64(sess.lastDemodL)
sess.lastDemodL = audio[0]
}
sess.lastDemodSet = true
}
}
logging.Debug("boundary", "audio_path", "signal", sess.signalID, "demod", demodName, "actual_rate", actualDemodRate, "audio_len", len(audio), "channels", d.Channels(), "overlap_applied", overlapApplied, "prev_tail_valid", prevTailValid)

// --- Stateful stereo decode with conservative lock/hysteresis ---


Loading…
Peruuta
Tallenna