diff --git a/slab/macos-audio/Sources/ACMacAudio/RoomReceiver.swift b/slab/macos-audio/Sources/ACMacAudio/RoomReceiver.swift index b0295056c..8b41f4df1 100644 --- a/slab/macos-audio/Sources/ACMacAudio/RoomReceiver.swift +++ b/slab/macos-audio/Sources/ACMacAudio/RoomReceiver.swift @@ -128,6 +128,7 @@ public final class ACAudioRoomReceiver: @unchecked Sendable { private let store = ACAudioPacketStore() private var nonce: UInt32 = 0 private var didLogAudio = false + private var didLogSignal = false private var lastTrafficNanos: UInt64 = 0 public init(configuration: Configuration) { self.configuration = configuration } @@ -232,6 +233,10 @@ public final class ACAudioRoomReceiver: @unchecked Sendable { self.didLogAudio = true self.log("audio locked at \(packet.sampleRate) Hz, \(self.configuration.channel.name), gain \(self.configuration.gain)") } + if !self.didLogSignal, packet.pcm16.contains(where: { $0 > 2 && $0 < 254 }) { + self.didLogSignal = true + self.log("signal present (non-silent audio arriving)") + } default: break } } diff --git a/slab/macos-audio/Sources/ACMacAudio/RoomSender.swift b/slab/macos-audio/Sources/ACMacAudio/RoomSender.swift index 524fa4198..bfd15bdf1 100644 --- a/slab/macos-audio/Sources/ACMacAudio/RoomSender.swift +++ b/slab/macos-audio/Sources/ACMacAudio/RoomSender.swift @@ -30,6 +30,7 @@ public final class ACAudioRoomSender: @unchecked Sendable { private var sequence: UInt32 = 0 private var nextPresentationNanos: UInt64 = 0 private var lastAudioNanos: UInt64 = 0 + private var lastMeterNanos: UInt64 = 0 public init(configuration: Configuration = .init()) { self.configuration = configuration @@ -147,6 +148,23 @@ public final class ACAudioRoomSender: @unchecked Sendable { return } + // Level meter every ~5 s: "locked but silent" downstream is + // indistinguishable from success without knowing what the tap + // actually carries. + let meterNow = ACHostClock.nowNanos() + if meterNow &- lastMeterNanos > 5_000_000_000 { + lastMeterNanos = meterNow + var peak: Float = 0 + for channel in 0..<2 { + for frame in 0.. peak { peak = v } + } + } + log(String(format: "tap level peak %.4f (%u frames, %d clients)", + peak, output.frameLength, connectedClients.count)) + } + let now = ACHostClock.nowNanos() if nextPresentationNanos == 0 || now > lastAudioNanos + 250_000_000 { session = UInt32.random(in: 1...UInt32.max)