import os /// Distributes one producer's audio to several feeds (one per route). /// /// `push` may run on a real-time thread: it only try-locks and otherwise uses the last known list. public final class AudioFanout: @unchecked Sendable { private let feeds = OSAllocatedUnfairLock<[AudioFeed]>(initialState: []) private var cached: [AudioFeed] = [] // producer thread only public init() {} public func add(_ feed: AudioFeed) { feeds.withLock { $0.append(feed) } } public func remove(_ feed: AudioFeed) { feeds.withLock { $0.removeAll { $0 === feed } } } public var isEmpty: Bool { feeds.withLock { $0.isEmpty } } public func push(planar data: UnsafePointer, channelStride: Int, channels: Int, frames: Int, sampleRate: Double) { if let current = feeds.withLockIfAvailable({ $0 }) { cached = current } for feed in cached { feed.push(planar: data, channelStride: channelStride, channels: channels, frames: frames, sampleRate: sampleRate) } } }