0 Replies
      Latest reply on Sep 10, 2019 5:02 AM by tallereric
      tallereric Level 1 Level 1 (0 points)

        I'm trying to dynamically modify a graph of nodes in attached to an AVAudioEngine. The graph correctly outputs sound but then outputs silence as soon as I call connect(_:to:format:) .

         

        In  the below sample, I'd like to dynamically connect player to engine.mainMixerNode, but whenever I call toggleBypass I get silence.

         

        Is it possible to carry out this rewiring without pausing playback of the AVAudioPlayerNode?

         

        class Sample: UIViewController {
        
            let engine = AVAudioEngine()
            let player = AVAudioPlayerNode()
            let effectNode = AVAudioUnitDelay()
        
            @objc func toggleBypass() {
                if effectNode.numberOfInputs == 0 {
                    engine.connect(player, to: effectNode, format: file.processingFormat)
                    engine.connect(effectNode, to: engine.mainMixerNode, format: file.processingFormat)
                } else {
                    engine.connect(player, to: engine.mainMixerNode, format: file.processingFormat)
                }
            }
        
            override func viewDidLoad() {
                super.viewDidLoad()
                view.backgroundColor = .red
                view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(toggleBypass)))
        
                try! AVAudioSession.sharedInstance().setCategory(.playback)
                try! AVAudioSession.sharedInstance().setPreferredIOBufferDuration(0.005)
                try! AVAudioSession.sharedInstance().setActive(true, options: [])
        
                do {
                    engine.attach(player)
                    engine.attach(effectNode)
                    engine.connect(player, to: effectNode, format: file.processingFormat)
                    engine.connect(effectNode, to: engine.mainMixerNode, format: file.processingFormat)
        
                    player.scheduleBuffer(buffer, at: nil, options: .loops, completionHandler: nil)
        
                    engine.prepare()
                    try engine.start()
        
                    player.play()
                } catch {
                    assertionFailure(String(describing: error))
                }
            }
        
        
            lazy var file: AVAudioFile = {
                let fileURL = Bundle.main.url(forResource: "filename", withExtension: "mp3")!
                return try! AVAudioFile(forReading: fileURL)
            }()
        
        
            lazy var buffer: AVAudioPCMBuffer = {
                let buffer = AVAudioPCMBuffer(pcmFormat: file.processingFormat, frameCapacity: UInt32(file.length))!
                try! file.read(into: buffer)
                return buffer
            }()
        }