swift - AVAudioEngine没有声音
问题描述
我一直在尝试如何从 iOS 中的 URLSessionDataTask 提供的数据中流式传输实时音频。
我已经声明了一个用于管理玩家操作的自定义类,它看起来像这样:
import UIKit
import AVFoundation
class AudioDataPlayer: NSObject {
//MARK:- Variables
//MARK: Constants
enum Status{
case playing
case notPlaying
}
let audioPlayerQueue = DispatchQueue(label: "audioPlayerQueue", qos: DispatchQoS.userInteractive)
//MARK: Vars
private (set) var currentStatus:Status = .notPlaying
private var audioEngine: AVAudioEngine = AVAudioEngine()
private var streamingAudioPlayerNode: AVAudioPlayerNode = AVAudioPlayerNode()
private (set) var streamingAudioFormat: AVAudioFormat = AVAudioFormat(commonFormat: .pcmFormatFloat32, sampleRate: 48000, channels: 2, interleaved: false)!
//MARK:- Constructor
override init() {
super.init()
}
//MARK:- Private methods
//MARK:- Public methods
func processData(_ data:Data) throws{
if currentStatus == .notPlaying{
do{
try AVAudioSession.sharedInstance().setCategory(.playAndRecord, mode: .default, options: [.allowAirPlay])
try AVAudioSession.sharedInstance().setActive(true)
if #available(iOS 11.0, *) {
try audioEngine.enableManualRenderingMode(.realtime, format: streamingAudioFormat, maximumFrameCount: 3072)
}
audioEngine.attach(streamingAudioPlayerNode)
audioEngine.connect(streamingAudioPlayerNode, to: audioEngine.mainMixerNode, format: streamingAudioFormat)
currentStatus = .playing
}
catch{
print("\(logClassName) ERROR -> \(error.localizedDescription)")
}
}
audioPlayerQueue.async {
if let audioPCMBuffer = data.makePCMBuffer(format: self.streamingAudioFormat){
self.streamingAudioPlayerNode.scheduleBuffer(audioPCMBuffer, completionHandler: {
//TODO
})
if !self.audioEngine.isRunning{
try! self.audioEngine.start()
self.streamingAudioPlayerNode.play()
}
}
else{
print("\(self.logClassName) TEST -> Ignoring data to play ...")
}
}
}
func stop(){
audioEngine.stop()
audioEngine.detach(streamingAudioPlayerNode)
currentStatus = .notPlaying
}
}
管理传入数据的函数是“processData(_ data:Data)”,它从另一个类中调用如下:
let processingQueue = DispatchQueue(label: "processingQueue", qos: DispatchQoS.userInteractive)
var audioDataPlayer:AudioDataPlayer = AudioDataPlayer()
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
processingQueue.async {
try! self.audioDataPlayer.processData(data)
}
}
我从论坛和苹果文档网站获得了代码。但是,也许我仍然不太明白它是如何工作的,并且设备没有声音......
音频数据为 48K、16bit 和 2 通道格式。
有任何想法吗?
解决方案
如果您的音频数据是 16 位(假设为整数),您需要初始化AVAudioFormat
withpcmFormatInt16
而不是pcmFormatFloat32
.
对于这种格式来说,非交错似乎有点奇怪,所以你可能必须设置interleaved
为true
.
推荐阅读
- c# - 在 foreach 循环中跳过“n”次迭代
- laravel - CKEditor 图像限制
- arrays - 如何修复 json 模式以仅在需要时接受 json?
- node.js - 如何使用 Firebase 管理 API 创建 passwordResetLink?
- angular - 路由使用参数在父组件之前执行子组件
- swift - 获取图像后,uiimageview 不显示任何内容
- javascript - 如何为材料表 [dataSource] 正确格式化此数据?
- python - 与不同的模块共享一个功能
- mysql - 在 Mysql 8 中选择顺序表时出现语法错误
- php - phpmyadmin 中的错误 - `缺少 mysqli 扩展`