Procházet zdrojové kódy

Gate boundary delta logging by category

master
Jan Svabenik před 1 dnem
rodič
revize
b20522ae93
1 změnil soubory, kde provedl 37 přidání a 11 odebrání
  1. +37
    -11
      internal/recorder/streamer.go

+ 37
- 11
internal/recorder/streamer.go Zobrazit soubor

@@ -37,6 +37,9 @@ type streamSession struct {
playbackMode string playbackMode string
stereoState string stereoState string
lastAudioTs time.Time lastAudioTs time.Time
lastAudioL float32
lastAudioR float32
lastAudioSet bool


// listenOnly sessions have no WAV file and no disk I/O. // listenOnly sessions have no WAV file and no disk I/O.
// They exist solely to feed audio to live-listen subscribers. // They exist solely to feed audio to live-listen subscribers.
@@ -390,7 +393,7 @@ func (st *Streamer) processFeed(msg streamFeedMsg) {
sess.wavSamples += int64(n / 2) sess.wavSamples += int64(n / 2)
} }
} }
// Gap logging for live-audio sessions
// Gap logging for live-audio sessions + boundary delta check
if len(sess.audioSubs) > 0 { if len(sess.audioSubs) > 0 {
if !sess.lastAudioTs.IsZero() { if !sess.lastAudioTs.IsZero() {
gap := time.Since(sess.lastAudioTs) gap := time.Since(sess.lastAudioTs)
@@ -398,6 +401,37 @@ func (st *Streamer) processFeed(msg streamFeedMsg) {
logging.Warn("gap", "audio_gap", "signal", sess.signalID, "gap_ms", gap.Milliseconds()) logging.Warn("gap", "audio_gap", "signal", sess.signalID, "gap_ms", gap.Milliseconds())
} }
} }
// boundary delta (compare previous last sample with current first sample)
if logging.EnabledCategory("boundary") && len(audio) > 0 {
if sess.lastAudioSet {
if sess.channels > 1 && len(audio) >= 2 {
dL := float64(audio[0] - sess.lastAudioL)
dR := float64(audio[1] - sess.lastAudioR)
if dL < 0 { dL = -dL }
if dR < 0 { dR = -dR }
if dL > 0.2 || dR > 0.2 {
logging.Warn("boundary", "audio_step", "signal", sess.signalID, "dL", dL, "dR", dR)
}
} else {
d := float64(audio[0] - sess.lastAudioL)
if d < 0 { d = -d }
if d > 0.2 {
logging.Warn("boundary", "audio_step", "signal", sess.signalID, "dL", d)
}
}
}
// store last sample
if sess.channels > 1 {
lastIdx := (len(audio)-2)
if lastIdx < 0 { lastIdx = 0 }
sess.lastAudioL = audio[lastIdx]
sess.lastAudioR = audio[lastIdx+1]
} else {
sess.lastAudioL = audio[len(audio)-1]
sess.lastAudioR = 0
}
sess.lastAudioSet = true
}
sess.lastAudioTs = time.Now() sess.lastAudioTs = time.Now()
} }
st.fanoutPCM(sess, pcm, pcmLen) st.fanoutPCM(sess, pcm, pcmLen)
@@ -642,6 +676,7 @@ func (sess *streamSession) processSnippet(snippet []complex64, snipRate int) ([]
// All FIR filtering is now stateful, so no additional overlap is needed. // All FIR filtering is now stateful, so no additional overlap is needed.
var fullSnip []complex64 var fullSnip []complex64
trimSamples := 0 trimSamples := 0
_ = trimSamples
if len(sess.overlapIQ) == 1 { if len(sess.overlapIQ) == 1 {
fullSnip = make([]complex64, 1+len(snippet)) fullSnip = make([]complex64, 1+len(snippet))
fullSnip[0] = sess.overlapIQ[0] fullSnip[0] = sess.overlapIQ[0]
@@ -692,16 +727,7 @@ func (sess *streamSession) processSnippet(snippet []complex64, snipRate int) ([]
} }


// --- Trim the 1-sample FM discriminator overlap --- // --- Trim the 1-sample FM discriminator overlap ---
if trimSamples > 0 {
audioTrim := trimSamples / decim1
if audioTrim < 1 {
audioTrim = 1 // at minimum trim 1 audio sample
}
if audioTrim > 0 && audioTrim < len(audio) {
logging.Debug("discrim", "audio_trim", "signal", sess.signalID, "trim", audioTrim, "decim1", decim1, "audio_len", len(audio))
audio = audio[audioTrim:]
}
}
// TEMP: skip audio trim to test if per-block trimming causes ticks


// --- Stateful stereo decode with conservative lock/hysteresis --- // --- Stateful stereo decode with conservative lock/hysteresis ---
channels := 1 channels := 1


Načítá se…
Zrušit
Uložit