Changing the volume of an SCNAudioPlayer in real time - Swift

I know a similar question was asked here...(https://forums.developer.apple.com/thread/27681)...but it doesnt give an example of how to do it which is what I am after as I can't work it out from the information provided.


I am trying to work out how I can change the volume of an

SCNAudioPlayer
in real time.


Currently, I have an

SCNAudioSource
connected to an
SCNAudioPlayer
. This audio player is then assigned to a
SCNNode
so that my sound makes use of SceneKits spatial audio processing.


As it stands, I am able to change the volume of each

SCNNode
using
SCNAudioSource.volume
triggered by the boolean variable
vol
. An extract of my code for this is shown below:


(audioSource, audioCount) = soundFileSelect(audioFileIndex: 0) 
audioSource?.isPositional = true 
if vol { 
audioSource?.volume = 1.0 
} 
else { 
audioSource?.volume = 0.0 
} 
let audioPlayer = SCNAudioPlayer(source: audioSource!) 
geometryNode.addAudioPlayer(audioPlayer) 
let play = SCNAction.playAudio(audioSource!, waitForCompletion: true) 
let loopPlay = SCNAction.repeatForever(play) 
geometryNode.runAction(loopPlay)


However, this only changes the default volume setting of the audio source, and so only happens when the node is spawned. I am trying to change the volume of it in real time, after a button press.


I feel I am missing something very simple, and have trolled the internet for documentation and examples but am really struggling. From Apple's API documentation I am fairly certain it can be done. As far as I can tell you have to use the

audioNode
property associated with the
SCNAudioPlayer
which forms part of the
AVAudioMixing
protocol. Using this
AVAudioMxing
volume property should be what I need!


However, for the life of me I can't work out how to implement this process in code within my current setup. I can access

mainMixer.volume
/
outputvolume
such as:


audioPlayer.audioNode?.engine?.mainMixerNode.outputVolume=0


but this doesn't seem to have any effect.


How do the AV and SCN components link together?


Any help or examples of how one goes about implementing this would be hugely appreciated!


Thanks in advanced.

Replies

I think you can change the volue with this code.


if let mixer = audioPlayer.audioNode as? AVAudioMixerNode {
     mixer.volume = 0.5
}

Yuki's solution doesn't work. The body of the if never executes. What is the solution of this issue?

if let player = audioPlayers.first?.audioNode as? AVAudioMixing {
    player.volume = min(yourValue, 1)
}

I found solution in different source! Worked for iOS 13 and 14. Thank Charlotte Magnusson!