Saving Audio After Effect in iOS Saving Audio After Effect in iOS swift swift

Saving Audio After Effect in iOS


Here it is my solution to question :

func playAndRecord(pitch : Float, rate: Float, reverb: Float, echo: Float) {    // Initialize variables// These are global variables . if you want you can just  (let audioEngine = etc ..) init here these variables    audioEngine = AVAudioEngine()    audioPlayerNode = AVAudioPlayerNode()    audioEngine.attachNode(audioPlayerNode)    playerB = AVAudioPlayerNode()    audioEngine.attachNode(playerB)    // Setting the pitch    let pitchEffect = AVAudioUnitTimePitch()    pitchEffect.pitch = pitch    audioEngine.attachNode(pitchEffect)    // Setting the platback-rate    let playbackRateEffect = AVAudioUnitVarispeed()    playbackRateEffect.rate = rate    audioEngine.attachNode(playbackRateEffect)    // Setting the reverb effect    let reverbEffect = AVAudioUnitReverb()    reverbEffect.loadFactoryPreset(AVAudioUnitReverbPreset.Cathedral)    reverbEffect.wetDryMix = reverb    audioEngine.attachNode(reverbEffect)    // Setting the echo effect on a specific interval    let echoEffect = AVAudioUnitDelay()    echoEffect.delayTime = NSTimeInterval(echo)    audioEngine.attachNode(echoEffect)    // Chain all these up, ending with the output    audioEngine.connect(audioPlayerNode, to: playbackRateEffect, format: nil)    audioEngine.connect(playbackRateEffect, to: pitchEffect, format: nil)    audioEngine.connect(pitchEffect, to: reverbEffect, format: nil)    audioEngine.connect(reverbEffect, to: echoEffect, format: nil)    audioEngine.connect(echoEffect, to: audioEngine.mainMixerNode, format: nil)    // Good practice to stop before starting    audioPlayerNode.stop()    // Play the audio file // this player is also a global variable  AvAudioPlayer    if(player != nil){    player?.stop()    }    // audioFile here is our original audio    audioPlayerNode.scheduleFile(audioFile, atTime: nil, completionHandler: {        print("Complete")    })    try! audioEngine.start()    let dirPaths: AnyObject = NSSearchPathForDirectoriesInDomains( NSSearchPathDirectory.DocumentDirectory,  NSSearchPathDomainMask.UserDomainMask, true)[0]    let tmpFileUrl: NSURL = NSURL.fileURLWithPath(dirPaths.stringByAppendingPathComponent("effectedSound2.m4a"))//Save the tmpFileUrl into global varibale to not lose it (not important if you want to do something else)filteredOutputURL = tmpFileUrl    do{        print(dirPaths)        self.newAudio = try! AVAudioFile(forWriting: tmpFileUrl, settings:  [            AVFormatIDKey: NSNumber(unsignedInt:kAudioFormatAppleLossless),            AVEncoderAudioQualityKey : AVAudioQuality.Low.rawValue,            AVEncoderBitRateKey : 320000,            AVNumberOfChannelsKey: 2,            AVSampleRateKey : 44100.0            ])        let length = self.audioFile.length        audioEngine.mainMixerNode.installTapOnBus(0, bufferSize: 1024, format: self.audioEngine.mainMixerNode.inputFormatForBus(0)) {            (buffer: AVAudioPCMBuffer!, time: AVAudioTime!) -> Void in            print(self.newAudio.length)            print("=====================")            print(length)            print("**************************")            if (self.newAudio.length) < length {//Let us know when to stop saving the file, otherwise saving infinitely                do{                    //print(buffer)                    try self.newAudio.writeFromBuffer(buffer)                }catch _{                    print("Problem Writing Buffer")                }            }else{                self.audioEngine.mainMixerNode.removeTapOnBus(0)//if we dont remove it, will keep on tapping infinitely                //DO WHAT YOU WANT TO DO HERE WITH EFFECTED AUDIO             }        }    }catch _{        print("Problem")    }    audioPlayerNode.play()}


This doesn't seem to be hooked up correctly. I'm just learning all this myself, but I found that the effects are correctly added when you connect them to a mixer node. Also, you'll want to tap the mixer, not the engine output node. I've just copied your code and made a few modifications to take this into account.

private func playAudio(pitch : Float, rate: Float, reverb: Float, echo: Float) {    // Initialize variables    audioEngine = AVAudioEngine()    audioPlayerNode = AVAudioPlayerNode()    audioEngine.attachNode(audioPlayerNode)    // Setting the pitch    let pitchEffect = AVAudioUnitTimePitch()    pitchEffect.pitch = pitch    audioEngine.attachNode(pitchEffect)    // Setting the playback-rate    let playbackRateEffect = AVAudioUnitVarispeed()    playbackRateEffect.rate = rate    audioEngine.attachNode(playbackRateEffect)    // Setting the reverb effect    let reverbEffect = AVAudioUnitReverb()    reverbEffect.loadFactoryPreset(AVAudioUnitReverbPreset.Cathedral)    reverbEffect.wetDryMix = reverb    audioEngine.attachNode(reverbEffect)    // Setting the echo effect on a specific interval    let echoEffect = AVAudioUnitDelay()    echoEffect.delayTime = NSTimeInterval(echo)    audioEngine.attachNode(echoEffect)    // Set up a mixer node    let audioMixer = AVAudioMixerNode()    audioEngine.attachNode(audioMixer)    // Chain all these up, ending with the output    audioEngine.connect(audioPlayerNode, to: playbackRateEffect, format: nil)    audioEngine.connect(playbackRateEffect, to: pitchEffect, format: nil)    audioEngine.connect(pitchEffect, to: reverbEffect, format: nil)    audioEngine.connect(reverbEffect, to: echoEffect, format: nil)    audioEngine.connect(echoEffect, to: audioMixer, format: nil)    audioEngine.connect(audioMixer, to: audioEngine.outputNode, format: nil)    audioPlayerNode.stop()    let length = 4000    let buffer = AVAudioPCMBuffer(PCMFormat: audioPlayerNode.outputFormatForBus(0),frameCapacity:AVAudioFrameCount(length))    buffer.frameLength = AVAudioFrameCount(length)    try! audioEngine.start()    let dirPaths: AnyObject = NSSearchPathForDirectoriesInDomains( NSSearchPathDirectory.DocumentDirectory,  NSSearchPathDomainMask.UserDomainMask, true)[0]    let tmpFileUrl: NSURL = NSURL.fileURLWithPath(dirPaths.stringByAppendingPathComponent("effectedSound.m4a"))    do{        print(dirPaths)        let settings = [AVFormatIDKey: NSNumber(unsignedInt: kAudioFormatMPEG4AAC), AVSampleRateKey: NSNumber(integer: 44100), AVNumberOfChannelsKey: NSNumber(integer: 2)]        self.newAudio = try AVAudioFile(forWriting: tmpFileUrl, settings: settings)        audioMixer.installTapOnBus(0, bufferSize: (AVAudioFrameCount(self.player!.duration)), format: self.audioMixer.outputFormatForBus(0)){            (buffer: AVAudioPCMBuffer!, time: AVAudioTime!)  in            print(self.newAudio.length)            print("=====================")            print(self.audioFile.length)            print("**************************")            if (self.newAudio.length) < (self.audioFile.length){                do{                    //print(buffer)                    try self.newAudio.writeFromBuffer(buffer)                }catch _{                    print("Problem Writing Buffer")                }            }else{                self.audioMixer.removeTapOnBus(0)            }        }    }catch _{        print("Problem")    }    audioPlayerNode.play()}

I also had trouble getting the file formatted properly. I finally got it working when I changed my path of the output file from m4a to caf. One other suggestion is to not have nil for the format parameter. I used the audioFile.processingFormat. I hope this helps. My audio effects/mixing is functional, although I did not chain my effects. So feel free to ask questions.


just change the parameter unsigned int from kAudioFormatMPEG4AAC to kAudioFormatLinearPCM and also change file type to .caf it will sure helpfull my friend