Swift 没有声音
我已经尝试了一段时间,现在如何从iOS中的URLSessionDataTask提供的数据流实时音频 我已经声明了一个用于管理玩家操作的自定义类,它如下所示:Swift 没有声音,swift,iphone,avfoundation,Swift,Iphone,Avfoundation,我已经尝试了一段时间,现在如何从iOS中的URLSessionDataTask提供的数据流实时音频 我已经声明了一个用于管理玩家操作的自定义类,它如下所示: import UIKit import AVFoundation class AudioDataPlayer: NSObject { //MARK:- Variables //MARK: Constants enum Status{ case playing case notPl
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)
}
}
我从论坛和apple documanetation网站上获得了代码。然而,也许我仍然不明白它是如何工作的,并且没有从设备发出声音
音频数据为48K、16位和2通道格式
有什么想法吗?如果音频数据是16位(可以假设为整数),则需要使用
pcmFormatInt16
而不是pcmFormatFloat32
初始化AVAudioFormat
对于这种格式来说,非交错似乎有点奇怪,因此您可能必须将
交错
设置为真
如果您的音频数据是16位(可以假设为整数),则需要使用pcmFormatInt16
而不是pcmFormatFloat32
初始化AVAudioFormat
对于这种格式,非交错似乎有点奇怪,因此您可能必须将
交错
设置为真
我尝试了您的建议,并得到以下错误-->019-02-14 08:10:46.177160+0000 MyAppl[307:10016]AUBase.cpp:832:DispatchSetProperty:ca_require:ValidFormat(inScope,inElement,newDesc)InvalidFormat连接StreamingAudioPlayerNode时出错您是否确实从url会话中获取了未压缩的原始音频样本,但没有任何标题信息等?所以它不是mp3或其他文件格式?我这样认为是因为我能够使用AudioFileWriteBytes将数据写入文件。值得一提的是,数据有不同的数组大小。@Reimondh您是如何修复ValidFormat
错误的?有同样的问题。我尝试了你的建议,我得到了以下错误-->019-02-14 08:10:46.177160+0000 MyAppl[307:10016]AUBase.cpp:832:DispatchSetProperty:ca_require:ValidFormat(inScope,inElement,newDesc)invalidFormat连接StreamingAudioPalyerNode时发生错误你真的确定你得到的是原始的吗,url会话中没有任何标题信息等的未压缩音频样本?所以它不是mp3或其他文件格式?我这样认为是因为我能够使用AudioFileWriteBytes将数据写入文件。值得一提的是,数据有不同的数组大小。@Reimondh您是如何修复ValidFormat
错误的?有同样的问题。