import XCTest @testable import Ten31Transcripts /// Channel-verified self detection: self = mic active AND louder than system, so a /// remote speaker (in the system channel) is never mislabeled as the local user. final class ChannelSelfVADTests: XCTestCase { private let win = 0.05 func testSelfSpanWhereMicDominates() { // Self talks windows 0–9 (mic loud, system silent), other talks 10–19. let mic = Array(repeating: Float(0.15), count: 10) + Array(repeating: Float(0.0), count: 10) let sys = Array(repeating: Float(0.0), count: 10) + Array(repeating: Float(0.15), count: 10) let spans = ChannelSelfVAD.selfSpans(micRMS: mic, systemRMS: sys, windowSec: win) XCTAssertEqual(spans.count, 1) XCTAssertEqual(spans.first?.start ?? -1, 0.0, accuracy: 0.001) XCTAssertEqual(spans.first?.end ?? -1, 0.5, accuracy: win + 0.001) // ~windows 0–9 } func testRemoteEchoIntoMicIsNotSelf() { // Remote person loud in system, only faintly echoed into mic (below margin). let mic = Array(repeating: Float(0.02), count: 20) let sys = Array(repeating: Float(0.15), count: 20) XCTAssertTrue(ChannelSelfVAD.selfSpans(micRMS: mic, systemRMS: sys, windowSec: win).isEmpty) } func testSilenceProducesNoSpans() { let q = Array(repeating: Float(0.003), count: 20) XCTAssertTrue(ChannelSelfVAD.selfSpans(micRMS: q, systemRMS: q, windowSec: win).isEmpty) } func testShortBlipDropped() { // 2 active windows < minWindows(3) → ignored. let mic: [Float] = [0.2, 0.2] + Array(repeating: Float(0.0), count: 18) let sys = Array(repeating: Float(0.0), count: 20) XCTAssertTrue(ChannelSelfVAD.selfSpans(micRMS: mic, systemRMS: sys, windowSec: win).isEmpty) } func testHangoverBridgesShortGap() { // Brief dip (2 windows) inside a self turn stays ONE span, not two. let mic = Array(repeating: Float(0.2), count: 8) + [0.0, 0.0] + Array(repeating: Float(0.2), count: 8) let sys = Array(repeating: Float(0.0), count: 18) let spans = ChannelSelfVAD.selfSpans(micRMS: mic, systemRMS: sys, windowSec: win) XCTAssertEqual(spans.count, 1) } }