This is my code use AVAudioEngine
for change voice in my app.
Can anyone point out what's wrong in this code of mine and help me get rid of the error message?
extension AudioPlayer {
func setupAudio(){
// initialize (recording) audio file
do{
audioFile = try AVAudioFile(forReading: recordedAudioURL as URL)
}catch{
print("Audio File Error ")
}
}
func playSound(rate: Float? = nil, pitch: Float? = nil, echo: Bool = false,reverb:Bool = false){
// initialize audio engine components
audioFile = AVAudioFile()
audioEngine = AVAudioEngine()
// node for playing audio
audioPlayerNode = AVAudioPlayerNode()
audioEngine.attach(audioPlayerNode)//attach the player node to the audio engine
audioMixer = AVAudioMixerNode()
audioEngine.attach(audioMixer)// attach a single output to the audio engine
//node for the adjusting rate/pitch
let changeRatePitchNode = AVAudioUnitTimePitch()
if let pitch = pitch {
changeRatePitchNode.pitch = pitch
}
if let rate = rate {
changeRatePitchNode.rate = rate
}
audioEngine.attach(changeRatePitchNode)
//node for the echo
let echoNode = AVAudioUnitDistortion()
echoNode.loadFactoryPreset(.multiEcho1)
audioEngine.attach(echoNode)
//node for the reverb
let reverbNode = AVAudioUnitReverb()
reverbNode.loadFactoryPreset(.cathedral)
reverbNode.wetDryMix = 50
audioEngine.attach(reverbNode)
//connect the player node to the output node
if echo == true && reverb == true{
connectAudioNode(audioPlayerNode,changeRatePitchNode,echoNode,reverbNode,audioMixer,audioEngine.outputNode)
}else if echo == true{
connectAudioNode(audioPlayerNode, changeRatePitchNode, echoNode,audioMixer,audioEngine.outputNode)
}else if reverb == true{
connectAudioNode(audioPlayerNode, changeRatePitchNode, echoNode, audioMixer, audioEngine.outputNode)
}else{
connectAudioNode(audioPlayerNode, changeRatePitchNode,audioMixer,audioEngine.outputNode)
}
//schedule to replay the entire audio file- phat lai toan bo tep am thanh
audioPlayerNode.stop()
audioPlayerNode.scheduleFile(audioFile, at: nil)
do{
try audioEngine.start()
}catch{
print("Not OutPut")
}
//generate media resource modeling assets at the specified URL
let audioAsset = AVURLAsset.init(url: recordedAudioURL)
// returns the representation t/g = (s)
let durationInSeconds = CMTimeGetSeconds(audioAsset.duration)
let length = 4000
let buffer = AVAudioPCMBuffer(pcmFormat: audioPlayerNode.outputFormat(forBus: 0), frameCapacity: AVAudioFrameCount(length))
buffer!.frameLength = AVAudioFrameCount(durationInSeconds)//bộ đêmj âm thanh cho định dạng PCM
// MARK: Create a new path after adding effects to the file
let dirPath: AnyObject = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory,FileManager.SearchPathDomainMask.userDomainMask, true)[0] as AnyObject
let tmpFileURL : NSURL = NSURL.fileURL(withPath: dirPath.appendingPathComponent("NewVoice.m4a")) as NSURL
filteredOutputURL = tmpFileURL
//setting for new file
do{
print(dirPath)
let settings = [AVFormatIDKey: kAudioFormatLinearPCM,
AVSampleRateKey: 44100,
AVNumberOfChannelsKey: 1]
self.newAudio = try AVAudioFile(forWriting: tmpFileURL as URL, settings: settings)
//setting for output
self.audioMixer.installTap(onBus: 0, bufferSize: (AVAudioFrameCount(durationInSeconds)), format: self.audioPlayerNode.outputFormat(forBus: 0)) { [self](buffer: AVAudioPCMBuffer!, time: AVAudioTime!) in
print(self.newAudio!.length)
print(self.audioFile.length)
if (self.newAudio!.length) < (self.audioFile.length){
do{
try self.newAudio!.write(from: buffer)
}catch {
print("error writing")
}
}else{
audioPlayerNode.removeTap(onBus: 0)
}
}
}catch _{
print("problem")
}
// MARK: Play Sound Effect
audioPlayerNode.play()
}
func connectAudioNode(_ nodes:AVAudioNode...){
for i in 0..<nodes.count-1{
audioEngine.connect(nodes[i], to: nodes[i + 1], format: audioFile.processingFormat)
}//*error here "processingFormat"*
}
}
error: "processingFormat" I don't know if it's because the link to read the file is wrong or what's wrong with my settings