mirror of
https://github.com/kunkundi/crossdesk.git
synced 2026-11-07 23:09:21 +08:00
[fix] use Float32 audio playback buffers on iOS
This commit is contained in:
@@ -214,10 +214,10 @@ private final class RemoteAudioPlayer {
|
|||||||
private let engine = AVAudioEngine()
|
private let engine = AVAudioEngine()
|
||||||
private let player = AVAudioPlayerNode()
|
private let player = AVAudioPlayerNode()
|
||||||
private let queue = DispatchQueue(label: "cn.crossdesk.mobile.audio")
|
private let queue = DispatchQueue(label: "cn.crossdesk.mobile.audio")
|
||||||
private let format = AVAudioFormat(commonFormat: .pcmFormatInt16,
|
// Older iOS audio units can reject an Int16 player-to-mixer connection
|
||||||
sampleRate: 48_000,
|
// with an Objective-C exception. Use the standard Float32 graph format.
|
||||||
channels: 1,
|
private let format = AVAudioFormat(standardFormatWithSampleRate: 48_000,
|
||||||
interleaved: false)!
|
channels: 1)!
|
||||||
private var enabled = true
|
private var enabled = true
|
||||||
private var queuedBuffers = 0
|
private var queuedBuffers = 0
|
||||||
|
|
||||||
@@ -250,18 +250,24 @@ private final class RemoteAudioPlayer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func enqueue(_ data: Data) {
|
func enqueue(_ data: Data) {
|
||||||
guard !data.isEmpty, data.count.isMultiple(of: MemoryLayout<Int16>.size) else { return }
|
guard !data.isEmpty, data.count.isMultiple(of: MemoryLayout<Int16>.size),
|
||||||
|
let frameCount = AVAudioFrameCount(exactly: data.count / MemoryLayout<Int16>.size) else { return }
|
||||||
queue.async {
|
queue.async {
|
||||||
guard self.enabled, self.queuedBuffers < 80 else { return }
|
guard self.enabled, self.queuedBuffers < 80 else { return }
|
||||||
self.startIfNeeded()
|
self.startIfNeeded()
|
||||||
guard self.engine.isRunning,
|
guard self.engine.isRunning,
|
||||||
let buffer = AVAudioPCMBuffer(pcmFormat: self.format,
|
let buffer = AVAudioPCMBuffer(pcmFormat: self.format,
|
||||||
frameCapacity: AVAudioFrameCount(data.count / 2)),
|
frameCapacity: frameCount),
|
||||||
let samples = buffer.int16ChannelData?[0] else { return }
|
let samples = buffer.floatChannelData?[0] else { return }
|
||||||
buffer.frameLength = buffer.frameCapacity
|
buffer.frameLength = buffer.frameCapacity
|
||||||
data.withUnsafeBytes { bytes in
|
data.withUnsafeBytes { bytes in
|
||||||
guard let source = bytes.baseAddress else { return }
|
// MiniRTC delivers native-endian signed 16-bit PCM. Data's
|
||||||
memcpy(samples, source, data.count)
|
// storage may be unaligned, including for short inline values.
|
||||||
|
for index in 0..<Int(frameCount) {
|
||||||
|
let sample = bytes.loadUnaligned(
|
||||||
|
fromByteOffset: index * MemoryLayout<Int16>.size, as: Int16.self)
|
||||||
|
samples[index] = Float(sample) / 32_768.0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
self.queuedBuffers += 1
|
self.queuedBuffers += 1
|
||||||
self.player.scheduleBuffer(buffer) {
|
self.player.scheduleBuffer(buffer) {
|
||||||
@@ -361,7 +367,7 @@ final class RemoteSessionModel: NSObject, ObservableObject, CrossDeskRTCBridgeDe
|
|||||||
let announcements = AnnouncementInbox()
|
let announcements = AnnouncementInbox()
|
||||||
let appUpdates = AppUpdateChecker()
|
let appUpdates = AppUpdateChecker()
|
||||||
private var appIsActive = false
|
private var appIsActive = false
|
||||||
private let audioPlayer = RemoteAudioPlayer()
|
private lazy var audioPlayer = RemoteAudioPlayer()
|
||||||
private var activeRemoteID = ""
|
private var activeRemoteID = ""
|
||||||
private var remoteAppVersion = ""
|
private var remoteAppVersion = ""
|
||||||
private var remoteHostInfoReceived = false
|
private var remoteHostInfoReceived = false
|
||||||
|
|||||||
Reference in New Issue
Block a user