【问题标题】:how to play sound with AVAudioPCMBuffer如何使用 AVAudioPCMBuffer 播放声音
【发布时间】:2014-10-31 08:58:39
【问题描述】:

我无法使用 AVAudioPCMBuffer 播放声音(尽管我可以使用 AVAudioFile 播放)。 我收到了这个错误。

错误: AVAudioBuffer.mm:169:-[AVAudioPCMBuffer initWithPCMFormat:frameCapacity:]:所需条件为假:isCommonFormat

下面是我的代码,非常感谢您的帮助。

import UIKit
import AVFoundation

class ViewController: UIViewController {

let audioEngine: AVAudioEngine = AVAudioEngine()
let audioFilePlayer: AVAudioPlayerNode = AVAudioPlayerNode()

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    audioEngine.attachNode(audioFilePlayer)

    let filePath: String = NSBundle.mainBundle().pathForResource("test", ofType: "mp3")!
    let fileURL: NSURL = NSURL(fileURLWithPath: filePath)!
    let audioFile = AVAudioFile(forReading: fileURL, error: nil)
    let audioFormat = audioFile.fileFormat
    let audioFrameCount = UInt32(audioFile.length)
    let audioFileBuffer = AVAudioPCMBuffer(PCMFormat: audioFormat, frameCapacity: audioFrameCount)

    var mainMixer = audioEngine.mainMixerNode
    audioEngine.connect(audioFilePlayer, to:mainMixer, format: audioFileBuffer.format)

    audioFilePlayer.scheduleBuffer(audioFileBuffer, atTime: nil, options: nil, completionHandler: nil)

    var engineError: NSError?
    audioEngine.startAndReturnError(&engineError)

    audioFilePlayer.play()
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

}

【问题讨论】:

    标签: swift ios8 avaudiopcmbuffer avaudiofile avaudioplayernode


    【解决方案1】:

    让我分享一下,虽然我不完全理解,但这确实有效。

    import UIKit
    import AVFoundation
    
    class ViewController: UIViewController {
    
    var audioEngine: AVAudioEngine = AVAudioEngine()
    var audioFilePlayer: AVAudioPlayerNode = AVAudioPlayerNode()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    
    
        let filePath: String = NSBundle.mainBundle().pathForResource("test", ofType: "mp3")!
        println("\(filePath)")
        let fileURL: NSURL = NSURL(fileURLWithPath: filePath)!
        let audioFile = AVAudioFile(forReading: fileURL, error: nil)
        let audioFormat = audioFile.processingFormat
        let audioFrameCount = UInt32(audioFile.length)
        let audioFileBuffer = AVAudioPCMBuffer(PCMFormat: audioFormat, frameCapacity: audioFrameCount)
        audioFile.readIntoBuffer(audioFileBuffer, error: nil)
    
        var mainMixer = audioEngine.mainMixerNode
        audioEngine.attachNode(audioFilePlayer)
        audioEngine.connect(audioFilePlayer, to:mainMixer, format: audioFileBuffer.format)
        audioEngine.startAndReturnError(nil)
    
        audioFilePlayer.play()
        audioFilePlayer.scheduleBuffer(audioFileBuffer, atTime: nil, options: nil, completionHandler: nil)
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    }
    

    【讨论】:

      【解决方案2】:

      问题是您将 PCM 缓冲区的格式设置为非 PCM 格式。因此,您需要使用 AVAudioFile 的 processingFormat 创建您的 AVAudioPCMBuffer

      【讨论】:

        【解决方案3】:

        在使用AVAudioPCMBuffer() 时,如果您尝试使用不是mixer.outputFormat(forBus: 0) 的 pcmFormat 会出现奇怪的错误

        它不会接受单声道格式,它会抱怨混音器的输出格式与您的格式不匹配,即使您描述的格式完全相同,也不会产生解释问题所在的错误。

        【讨论】:

          【解决方案4】:

          将@Bick 的代码更新到Swift 5.3

          代码逻辑很容易搞定

          • 首先,准备数据

          创建一个空的AVAudioPCMBuffer,然后在其中填充音频数据。

          • 其次,连接节点,用数据玩

            import UIKit
            import AVFoundation
            
              class ViewControllerX: UIViewController {
            
                var audioEngine = AVAudioEngine()
                var audioFilePlayer = AVAudioPlayerNode()
            
                override func viewDidLoad() {
                  super.viewDidLoad()
            
                  // prepare the data
                  guard let filePath = Bundle.main.path(forResource: "test", ofType: "mp3") else{ return }
            
                  print("\(filePath)")
                  let fileURL = URL(fileURLWithPath: filePath)
                  do {
                      let audioFile = try AVAudioFile(forReading: fileURL)
            
                      let audioFormat = audioFile.processingFormat
                      let audioFrameCount = UInt32(audioFile.length)
                      guard let audioFileBuffer = AVAudioPCMBuffer(pcmFormat: audioFormat, frameCapacity: audioFrameCount) else{ return }
                      try audioFile.read(into: audioFileBuffer)
            
                      // connect the nodes, and use the data to play
                      let mainMixer = audioEngine.mainMixerNode
                      audioEngine.attach(audioFilePlayer)
                      audioEngine.connect(audioFilePlayer, to: mainMixer, format: audioFileBuffer.format)
            
                      try audioEngine.start()
            
                      audioFilePlayer.play()
                      audioFilePlayer.scheduleBuffer(audioFileBuffer, completionHandler: nil)
            
                  } catch {
                      print(error)
                  }
            
                }
            }
            

          【讨论】:

            【解决方案5】:

            您应该使用 audioFile.processingFormat 作为 AVAudioPCMBuffer 构造函数的参数,而不是调用 audioFile.fileFormat。

            let buffer = AVAudioPCMBuffer(pcmFormat: audioFile.processingFormat,
                                                        frameCapacity: bufferCapacity) 
            

            【讨论】:

              猜你喜欢
              • 2016-02-27
              • 2015-11-09
              • 2014-06-05
              • 1970-01-01
              • 1970-01-01
              • 2010-11-12
              • 1970-01-01
              • 2023-02-25
              • 1970-01-01
              相关资源
              最近更新 更多