54 lines
1.4 KiB
Swift
54 lines
1.4 KiB
Swift
import Foundation
|
|
import OpenLessCore
|
|
|
|
final class BufferingAudioConsumer: AudioConsumer, @unchecked Sendable {
|
|
private let lock = NSLock()
|
|
private let maxBufferedBytes: Int
|
|
private var target: AudioConsumer?
|
|
private var bufferedChunks: [Data] = []
|
|
private var bufferedByteCount = 0
|
|
|
|
init(maxBufferedBytes: Int = 320_000) {
|
|
self.maxBufferedBytes = maxBufferedBytes
|
|
}
|
|
|
|
func consume(pcmChunk: Data) {
|
|
lock.lock()
|
|
if let target {
|
|
lock.unlock()
|
|
target.consume(pcmChunk: pcmChunk)
|
|
return
|
|
}
|
|
|
|
bufferedChunks.append(pcmChunk)
|
|
bufferedByteCount += pcmChunk.count
|
|
|
|
while bufferedByteCount > maxBufferedBytes, let first = bufferedChunks.first {
|
|
bufferedByteCount -= first.count
|
|
bufferedChunks.removeFirst()
|
|
}
|
|
lock.unlock()
|
|
}
|
|
|
|
func attach(_ target: AudioConsumer) {
|
|
lock.lock()
|
|
self.target = target
|
|
let pending = bufferedChunks
|
|
bufferedChunks.removeAll(keepingCapacity: true)
|
|
bufferedByteCount = 0
|
|
lock.unlock()
|
|
|
|
for chunk in pending {
|
|
target.consume(pcmChunk: chunk)
|
|
}
|
|
}
|
|
|
|
func clear() {
|
|
lock.lock()
|
|
target = nil
|
|
bufferedChunks.removeAll(keepingCapacity: false)
|
|
bufferedByteCount = 0
|
|
lock.unlock()
|
|
}
|
|
}
|