For completeness, this is the view I'm experimenting with:
import AVFoundation
import SwiftUI
class EngineerPlayer {
let audioEngine = AVAudioEngine()
let playerNode = AVAudioPlayerNode()
let environmentNode = AVAudioEnvironmentNode()
init(_ url: URL) throws {
let audioFile = try AVAudioFile(forReading: url)
let mono = AVAudioFormat(standardFormatWithSampleRate: audioFile.processingFormat.sampleRate, channels: 1)
let stereo = AVAudioFormat(standardFormatWithSampleRate: audioFile.processingFormat.sampleRate, channels: 2)
audioEngine.attach(playerNode)
audioEngine.attach(environmentNode)
audioEngine.connect(playerNode, to: environmentNode, format: mono)
audioEngine.connect(environmentNode, to: audioEngine.mainMixerNode, format: stereo)
audioEngine.prepare()
try audioEngine.start()
environmentNode.renderingAlgorithm = .HRTFHQ
playerNode.pointSourceInHeadMode = .mono
playerNode.position = AVAudio3DPoint(x: 0, y: 2, z: 10)
playerNode.scheduleFile(audioFile, at: nil, completionHandler: nil)
}
func updatePosition(_ angleInDegrees: Float) {
environmentNode.listenerAngularOrientation = AVAudio3DAngularOrientation(yaw: angleInDegrees, pitch: 0, roll: 0)
}
}
struct SpatialView: View {
var player: EngineerPlayer
init() {
do {
try player = EngineerPlayer(Bundle.main.url(forResource: "beat", withExtension: "aiff")!)
} catch {
fatalError("error with aiff")
}
}
var body: some View {
Button("Start") {
player.playerNode.play()
}
Button("Move it") {
player.playerNode.position.y -= 0.5
}
Button("Move it back") {
player.playerNode.position.y = 2.0
}
}
}
#Preview {
SpatialView()
}
It's copied and pasted from Engineer, except I only call play() when the button is tapped. Tapping "Move it" repeatedly brings the source closer in the y direction and then eventually farther away to the rear. But I only hear it get louder then quieter, coming out of my keyboard. So the AVAudioEnvironmentNode is modeling in 3D and doing the right computation, but it's not rendered using psychoacoustics to provide a 3D effect.
Settings I have turned on include the Head Pose capability, Spatial Audio Profile capability, and Background Mode for audio.