I want to instantly save the sound with AVAudioEngine's effect.

Hi,

I'm creating a process to read an existing audio file, add an effect using AVAudioEngine, and then save it as another audio file. However, with the following method using an AVAudioPlayerNode, the save process must wait until the end of playback.

import UIKit

import AVFoundation



class ViewController: UIViewController {

    

    let engine = AVAudioEngine()

    let playerNode = AVAudioPlayerNode()

    let reverbNode = AVAudioUnitReverb()

    

    override func viewDidLoad() {

        super.viewDidLoad()



        do {

            

            let url = URL(fileURLWithPath: Bundle.main.path(forResource: "original", ofType: "mp3")!)

            let file = try AVAudioFile(forReading: url)

            

            // playerNode

            engine.attach(playerNode)



            // reverbNode

            reverbNode.loadFactoryPreset(.largeChamber)

            reverbNode.wetDryMix = 5.0

            engine.attach(reverbNode)



            

            engine.connect(playerNode, to: reverbNode, format: file.processingFormat)

            engine.connect(reverbNode, to: engine.mainMixerNode, format: file.processingFormat)



            playerNode.scheduleFile(file, at: nil, completionCallbackType: .dataPlayedBack){ [self] _ in

                reverbNode.removeTap(onBus: 0)

            }





            // start

            try engine.start()

            playerNode.play()





            

            let url2 = URL(fileURLWithPath: fileInDocumentsDirectory(filename: "changed.wav"))

            let outputFile = try! AVAudioFile(forWriting: url2, settings: playerNode.outputFormat(forBus: 0).settings)



            reverbNode.installTap(onBus: 0, bufferSize: AVAudioFrameCount(reverbNode.outputFormat(forBus: 0).sampleRate), format: reverbNode.outputFormat(forBus: 0)) { (buffer, when) in

                do {

                    try outputFile.write(from: buffer)

                } catch let error {

                    print(error)

                }

            }

        } catch {

            print(error.localizedDescription)

        }

    }





    func getDocumentsURL() -> NSURL {

        let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] as NSURL

        return documentsURL

    }

    

    func fileInDocumentsDirectory(filename: String) -> String {

        let fileURL = getDocumentsURL().appendingPathComponent(filename)

        return fileURL!.path

    }

}

Is there a way to complete the writing without waiting for the playback to complete? My ideal is to complete the write in the time required by CPU and storage performance.

It seems that reverbNode.installTap(...) { (buffer, when) in ...} in the code is processed in parallel with the current playback position, so I would like to dramatically improve the processing speed.

Best regards.

I want to instantly save the sound with AVAudioEngine's effect.
 
 
Q