69 lines
2.1 KiB
Swift
69 lines
2.1 KiB
Swift
import Foundation
|
|
|
|
/// Inserts text only while `shouldInsert()` says so (not when Sst itself is in front, nor for window recordings).
|
|
public struct GatedInserter: TextInserting {
|
|
private let inner: TextInserting
|
|
private let shouldInsert: () -> Bool
|
|
|
|
public init(inner: TextInserting, shouldInsert: @escaping () -> Bool) {
|
|
self.inner = inner
|
|
self.shouldInsert = shouldInsert
|
|
}
|
|
|
|
public func insert(_ text: String) async throws {
|
|
guard shouldInsert() else { return }
|
|
try await inner.insert(text)
|
|
}
|
|
}
|
|
|
|
/// Lets the app replace the speech model (for example after a model switch) without rebuilding the controller.
|
|
public final class SwappableTranscriber: Transcriber, @unchecked Sendable {
|
|
public enum SwapError: Error, LocalizedError {
|
|
case noTranscriber
|
|
|
|
public var errorDescription: String? { "Spraakmodel is nog niet geladen." }
|
|
}
|
|
|
|
private let lock = NSLock()
|
|
private var current: Transcriber?
|
|
|
|
public init(_ initial: Transcriber? = nil) {
|
|
current = initial
|
|
}
|
|
|
|
public func swap(to transcriber: Transcriber?) {
|
|
lock.withLock { current = transcriber }
|
|
}
|
|
|
|
public var hasTranscriber: Bool {
|
|
lock.withLock { current != nil }
|
|
}
|
|
|
|
public func transcribe(_ samples: [Float]) async throws -> String {
|
|
try await transcribe(samples, vocabulary: [])
|
|
}
|
|
|
|
public func transcribe(_ samples: [Float], vocabulary: [String]) async throws -> String {
|
|
guard let transcriber = lock.withLock({ current }) else { throw SwapError.noTranscriber }
|
|
return try await transcriber.transcribe(samples, vocabulary: vocabulary)
|
|
}
|
|
}
|
|
|
|
/// The latest input level, written from the audio thread and read by the meter once per frame.
|
|
public final class LevelSource: @unchecked Sendable {
|
|
private let lock = NSLock()
|
|
private var value = AudioLevel.silenceFloorDbfs
|
|
|
|
public init() {}
|
|
|
|
public var dbfs: Float { lock.withLock { value } }
|
|
|
|
public func update(_ dbfs: Float) {
|
|
lock.withLock { value = dbfs }
|
|
}
|
|
|
|
public func reset() {
|
|
update(AudioLevel.silenceFloorDbfs)
|
|
}
|
|
}
|