AKOfflineRenderNode - 调度AKAudioPlayers,只有最后一个玩家渲染

时间:2017-11-18 23:11:08

标签: swift audiokit

尝试在iOS 11.1上使用AudioKit 4.0,Swift 4渲染一系列AKAudioPlayers时获得一些奇怪的结果

我知道开发分支(https://github.com/AudioKit/AudioKit/commit/09aedf7c119a399ab00026ddfb91ae6778570176)上的AudioKit.renderToFile替代方案,但如果可能的话,我想覆盖iOS 9+

预期结果: 一个长音频文件,每个文件(URL)按顺序呈现

实际结果: 仅渲染最后一个计划文件(在生成的wav文件中的正确偏移处)

奇怪的是,如果我将它们全部安排在0偏移处,它们都会被渲染。另外,如果我在没有渲染的情况下回放东西,听起来是正确的(尽管我必须调整AVAudioTime以使用mach_absolute_time)

似乎安排AKAudioPlayer取消前​​一个。

设定:

  class func initialize (){

    // .... 

    do {
         try AKSettings.setSession(category: .playAndRecord, with: .allowBluetoothA2DP)
     } catch {
         AKLog("Could not set session category.")
     }
     //AKSettings.playbackWhileMuted = true
     AKSettings.defaultToSpeaker = true

     mainMixer = AKMixer()
     offlineRender = AKOfflineRenderNode()

     mainMixer! >>> offlineRender!
     AudioKit.output = offlineRender!
     AudioKit.start()

     // .... 

渲染:

class func testRender(urls: [URL], dest: URL, offset: TimeInterval = 2){

      // Stop / Start AudioKit when switching internalRenderEnabled, otherwise I get the following error:
      // *** Terminating app due to uncaught exception 'com.apple.coreaudio.avfaudio', reason: 'player started when engine not running' 

     AudioKit.stop()

     var players = [AKAudioPlayer]()
     var scheduleTime : TimeInterval = 0

     // create players
     for url in urls {
         do {
             let file = try AKAudioFile(forReading: url)
             let player = try AKAudioPlayer(file: file)
             players.append(player)
             player.connect(to: mainMixer!)
             print("Connecting player")
         } catch {
             print("error reading")
         }

     }


     offlineRender!.internalRenderEnabled = false
     AudioKit.start()

     for player in players{
         do {
             //  0 instead of mach_absolute_time(), otherwise the result is silent
             let avTime = AKAudioPlayer.secondsToAVAudioTime(hostTime: 0, time: scheduleTime)
             // schedule and play according to:
             // https://stackoverflow.com/questions/45799686/how-to-apply-audio-effect-to-a-file-and-write-to-filesystem-ios/45807586#45807586
             player.schedule(from: 0, to: player.duration, avTime: nil)
             player.play(at: avTime);
             scheduleTime += offset
         } catch {
              print("error reading")
         }

     }

     // add some padding
     scheduleTime += 3

     let duration = scheduleTime
     do {
         try offlineRender!.renderToURL(dest, seconds: duration)

     } catch {
         print("error rendering")
     }

     // cleanup
     players.forEach { $0.schedule(from: 0, to: $0.duration, avTime: nil)}
     players.forEach({$0.stop()})
     players.forEach({$0.disconnectOutput()})

     offlineRender!.internalRenderEnabled = true


 }

感谢任何帮助!

2 个答案:

答案 0 :(得分:3)

从iOS 11.0开始,不推荐使用AKOfflineRenderNode。版本4.0.4有一个AudioKit.renderToFile方法来替换它。它最近更新(2017年底)。

答案 1 :(得分:3)

所以看起来AKOFflineRednerNode确实在即将推出的AudioKit版本中被弃用,而且不适用于iOS11。阅读GitHub上讨论问题的评论听起来好像计划是将新的(iOS11 +)离线渲染和旧的(iOS9-10)封装在一个通用接口(AudioKit.renderToFile)下。但是现在它似乎只是iOS11。

使用dev版本进行一些测试(在此处安装说明:https://github.com/audiokit/AudioKit/blob/master/Frameworks/README.md)后,我获得了以下代码:

try AudioKit.renderToFile(outputFile, seconds: duration, prerender: {
    var scheduleTime : TimeInterval = 0
   for player in players{
        let dspTime = AVAudioTime(sampleTime: AVAudioFramePosition(scheduleTime * AKSettings.sampleRate), atRate: AKSettings.sampleRate)

        player.play(at: dspTime)
        scheduleTime += offset
    }
})

除非有人能够提供使得OnlineRenderNode在iOS11上运行的解决方法,并且直到正式发布带有renderToFile的AudioKit,这才是我能找到的最佳答案。