Skip to content

Adding an equalizer to AudioPlayer

Stephen Booth edited this page Dec 11, 2024 · 3 revisions

The withEngine(_:) function on AudioPlayer may be used to add an AVAudioUnit (such as AVAudioUnitEQ) to the processing graph.

Graph modifications may only be made between playerNode and engine.mainMixerNode.

For example, you can add an equalizer to the processing graph with code similar to the following:

class PlayerController {
	let player: AudioPlayer
	var equalizer: AVAudioUnitEQ! = nil

	init() {
		player = AudioPlayer()
		player.delegate = self

		// Insert an equalizer between the player and main mixer nodes
		equalizer = AVAudioUnitEQ()
		equalizer.globalGain = -6
		equalizer.bypass = false

		player.withEngine { engine in
			guard let mainMixerInputConnectionPoint = engine.inputConnectionPoint(for: engine.mainMixerNode, inputBus: 0) else {
				os_log(.fault, "AVAudioEngine missing main mixer node")
				return
			}
			guard let mainMixerInputNode = mainMixerInputConnectionPoint.node else {
				os_log(.fault, "AVAudioEngine missing input node to main mixer node")
				return
			}

			engine.attach(self.equalizer)
			engine.disconnectNodeInput(engine.mainMixerNode)
			engine.connect(self.equalizer, to: engine.mainMixerNode, format: nil)
			engine.connect(mainMixerInputNode, to: self.equalizer, format: nil)
		}
	}

	// Reconnect the equalizer using the new format
	func audioPlayer(_ audioPlayer: AudioPlayer, reconfigureProcessingGraph engine: AVAudioEngine, with format: AVAudioFormat) -> AVAudioNode {
		engine.disconnectNodeOutput(equalizer)
		engine.connect(equalizer, to: engine.mainMixerNode, format: format)
		return equalizer
	}
}

It might also be necessary to insert a format converter AVAudioUnit (kAudioUnitType_FormatConverter) before the equalizer if the equalizer does not support the new format.

Clone this wiki locally