AVAudioEngine manualRenderingMode outputting silence with more than two channels

My code is supposed to play a file from an AVAudioPlayerNode through my custom Audio Unit (V3) and render offline to an output file using manualRenderingMode. This seems to work fine if the file is mono or stereo, but as soon as more than tow channels are present, it stops working. The output file has the correct number of channels and the expected length, but the content is silence. I tried installing a tap on the output of my audio unit and writing to the output file from there, and this works fine. However, I need this to work as intended and write to file AVAudioEngine.renderOffline.



Below, I am posting a sample code that exhibits the same behaviour but has a simpler configuration: the engine operates offline and has only a file player node connected to the mainMixerNode. The output is saved to a file. Again, this code works fine for mono or stereo, but generates a silent output file in case of a 4-channels input file. 


public func renderOffline(from inputUrl: URL, to outputUrl: URL) {
        let engine         = AVAudioEngine()
        let player         = AVAudioPlayerNode()
        let frameCount     : AVAudioFrameCount = 1024
        var numFrames      : AVAudioFrameCount
        var framesToRender : AVAudioFrameCount = 0
        var result         : AVAudioEngineManualRenderingStatus


        guard let inFile = try? AVAudioFile(forReading: inputUrl),
              let outFile = try? AVAudioFile(forWriting: outputUrl, settings: inFile.processingFormat.settings),
              let buffer = AVAudioPCMBuffer(pcmFormat: inFile.processingFormat, frameCapacity: frameCount) else {
                return
        }


        engine.attach(player)
        engine.connect(player, to: engine.mainMixerNode, format: inFile.processingFormat)
       
        do {
            try engine.enableManualRenderingMode(.offline, format: inFile.processingFormat, maximumFrameCount: frameCount)
            try engine.start()
        } catch {
            return
        }


        let fileLength = AVAudioFrameCount(inFile.length)
       
        player.scheduleFile(inFile, at: nil, completionHandler: nil)
        player.prepare(withFrameCount: fileLength)
        player.play()
       
        while engine.manualRenderingSampleTime < inFile.length {
            numFrames = fileLength - frameCount
            framesToRender = min(buffer.frameCapacity, numFrames)
           
            do {
                result = try engine.renderOffline(framesToRender, to: buffer)
                if result == .success {
                    try outFile.write(from: buffer)
                }
            } catch {
                break
            }
        }
       
        player.stop()
        engine.stop()
    }



Replies

anyone?

I think each AVAudioPlayerNode can play a max of two channels per buffer. I would create more player nodes as needed and specify the blend between them (probably using a AVAudioMixerNode)