【问题标题】:AKPlayer crashes when playing from buffer on channelCount conditionAKPlayer 在 channelCount 条件下从缓冲区播放时崩溃
【发布时间】:2018-10-28 07:05:32
【问题描述】:

我努力使以下场景按预期工作(代码将在下面提供)。

  1. 记录我的麦克风输入并将AVAudioPCMBuffer存储在内存中,这是通过AVAudioPCMBuffer扩展方法copy(from buffer: AVAudioPCMBuffer, readOffset: AVAudioFrameCount = default, frames: AVAudioFrameCount = default)完成的。 我确实在录制结束时获得了缓冲区

  2. 当记录结束时,将缓冲区传递给AKPlayer 并播放。这是一个代码 sn-p 来演示我的工作(我知道它不是完整的应用程序代码,如果需要我可以分享它):

.

private var player: AKPlayer = AKPlayer()
self.player.buffering = .always

// in the record complete callbak:
self.player.buffer = self.bufferRecorder?.pcmBuffer
self.player.volume = 1
self.player.play()
  • 请注意,电镀器连接到混音器,混音器最终连接到 AudioKit 输出。

当我检查和调试应用程序时,我可以看到缓冲区的长度正确,并且我的所有输出/输入设置都使用相同的处理格式(采样率、通道、比特率等)以及记录的缓冲区,但是我的应用仍然在这条线上崩溃:

2018-10-28 08:40:32.625001+0200 BeatmanApp[71037:6731884] [avae] AVAEInternal.h:70:_AVAE_Check: 
required condition is false: [AVAudioPlayerNode.mm:665:ScheduleBuffer: (_outputFormat.channelCount == buffer.format.channelCount)]

当我调试并浏览 AudioKit 代码时,我可以看到断线位于方法上的 AKPlayer+Playback.swiftline 162 上:playerNode.scheduleBuffer

更多可能有用的信息:

  • 记录的缓冲区长度为 16 秒。
  • 当我尝试在 tap 方法中将缓冲区直接传递到播放器节点时,它似乎工作正常,我确实听到了从麦克风到扬声器的延迟,但它确实播放了。
  • 我在调用 play 方法之前尝试在播放器上调用 prepare,没有帮助

谢谢!

【问题讨论】:

    标签: ios swift avfoundation avaudioplayer audiokit


    【解决方案1】:

    好的,这是非常不酷的调试会话。我必须调查AVAudioEngine 以及如何在那里完成这种情况,这当然不是我正在寻找的最终结果。这个任务帮助我理解了如何使用AudioKit 解决它(我的应用程序的一半是使用AudioKit 的工具实现的,所以用AVFoundation 重写它没有意义)。

    AFFoundation解决方案:

    private let engine = AVAudioEngine()
    private let bufferSize = 1024
    private let p: AVAudioPlayerNode = AVAudioPlayerNode()
    
    let audioSession = AVAudioSession.sharedInstance()
    do {
        try audioSession.setCategory(.playAndRecord, mode: .default, options: .defaultToSpeaker)
    } catch {
        print("Setting category to AVAudioSessionCategoryPlayback failed.")
    }
    
    let inputNode = self.engine.inputNode
    engine.connect(inputNode, to: engine.mainMixerNode, format: inputNode.inputFormat(forBus: 0))
    // !!! the following lines are the key to the solution.
    // !!! the player has to be attached to the engine before actually connected
    engine.attach(p) 
    engine.connect(p, to: engine.mainMixerNode, format: inputNode.inputFormat(forBus: 0)) 
    
    do {
        try engine.start()
    } catch {
        print("could not start engine \(error.localizedDescription)")
    }
    
    recordBufferAndPlay(duration: 4)
    

    recordBufferAndPlay函数:

    func recordBufferAndPlay(duration: Double){
        let inputNode = self.engine.inputNode
        let total: Double = AVAudioSession.sharedInstance().sampleRate * duration
        let totalBufferSize: UInt32 = UInt32(total)
    
        let recordedBuffer : AVAudioPCMBuffer! = AVAudioPCMBuffer(pcmFormat: inputNode.inputFormat(forBus: 0), frameCapacity: totalBufferSize)
    
        var alreadyRecorded = 0
        inputNode.installTap(onBus: 0, bufferSize: 256, format: inputNode.inputFormat(forBus: 0)) {
            (buffer: AVAudioPCMBuffer!, time: AVAudioTime!) -> Void in
            recordedBuffer.copy(from: buffer) // this helper function is taken from audio kit!
            alreadyRecorded = alreadyRecorded + Int(buffer.frameLength)
            print(alreadyRecorded, totalBufferSize)
            if(alreadyRecorded >= totalBufferSize){
                inputNode.removeTap(onBus: 0)
                self.p.scheduleBuffer(recordedBuffer, at: nil, options: .loops, completionHandler: {
                    print("completed playing")
                })
                self.p.play()
            }
        }
    }
    

    AudioKit解决方案:

    所以在 AudioKit 解决方案中,应该在您的 AKPlayer 对象上调用这些行。请注意,这应该在您实际启动引擎之前完成。

    self.player.buffering = .always
    AudioKit.engine.attach(self.player.playerNode)
    AudioKit.engine.connect(self.player.playerNode, to: self.mixer.inputNode, format: AudioKit.engine.inputNode.outputFormat(forBus: 0))
    

    记录的完成方式与您在 AVAudioEngine 中完成的方式非常相似,您在节点(麦克风或其他节点)上安装一个水龙头并记录 PCM 样本的缓冲区。

    【讨论】:

    • 嗨,我遇到了同样的错误,但是当 installTap 时,你能帮忙吗?
    猜你喜欢
    • 1970-01-01
    • 2011-10-31
    • 2013-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多