I was playing with AVAudioEngine to use it in an app. I am changing pitch and equalizer (gain) parameters with sliders while music was playing.
Pitch works but equalizer is not working. I could not find the cause.
var audioEngine = AVAudioEngine()
var audioFilePlayer = AVAudioPlayerNode()
let auTimePitch = AVAudioUnitTimePitch()
var equalizer = AVAudioUnitEQ()
func startEngine(){
guard let filePath: String = Bundle.main.path(forResource: "testMusic", ofType: "mp3") else{ return }
let fileURL: URL = URL(fileURLWithPath: filePath)
guard let audioFile = try? AVAudioFile(forReading: fileURL) else { return }
let audioFormat = audioFile.processingFormat
let audioFrameCount = UInt32(audioFile.length)
guard let audioFileBuffer = AVAudioPCMBuffer(pcmFormat: audioFormat,
frameCapacity: audioFrameCount) else { return }
do{
try audioFile.read(into: audioFileBuffer)
} catch{
print("over")
}
let mainMixer = audioEngine.mainMixerNode
auTimePitch.pitch = 1
auTimePitch.rate = 1
equalizer = AVAudioUnitEQ(numberOfBands: 5)
let bands = equalizer.bands
let freqs = [60, 230, 910, 4000, 14000]
for i in 0..<bands.count {
bands[i].frequency = Float(freqs[i])
bands[i].bypass = false
bands[i].filterType = .parametric
bands[i].gain = 0
bands[i].bandwidth = 1
}
let format = mainMixer.outputFormat(forBus: 0)
audioEngine.attach(audioFilePlayer)
audioEngine.attach(auTimePitch)
audioEngine.attach(equalizer)
audioEngine.connect(audioFilePlayer,
to: equalizer,
format: format)
audioEngine.connect(audioFilePlayer,
to:auTimePitch,
format: format)
audioEngine.connect(equalizer,
to: mainMixer,
format: format)
audioEngine.connect(auTimePitch,
to: mainMixer,
format: format)
try? audioEngine.start()
audioFilePlayer.play()
audioFilePlayer.scheduleBuffer(audioFileBuffer, at: nil,
options:AVAudioPlayerNodeBufferOptions.loops)
}
Your AVAudioEngine
graph looks a little weird (can AVAudioPlayerNode
have two outputs?), but if you attach your nodes:
audioEngine.attach(audioFilePlayer)
audioEngine.attach(equalizer)
audioEngine.attach(auTimePitch)
and use the file processing format, letting mainMixerNode
do format conversion
let format = audioFile.processingFormat
and connect the nodes in a more linear fashion:
audioEngine.connect(audioFilePlayer,
to: equalizer,
format: format)
audioEngine.connect(equalizer,
to:auTimePitch,
format: format)
audioEngine.connect(auTimePitch,
to: mainMixer,
format: format)
you can manipulate your equalizer, e.g suppressing lower frequencies and emphasizing higher ones:
bands[0].gain = -50
bands[4].gain = 24