Having issues controlling the volume of participant taps using the participant’s local volume.
I have sliders in my UI for each participant to adjust the local volume for each player.
They trigger the script below to set the local volume for each participant across all channels they are active in. In my case we have a Dead channel that uses a Channel Tap and an Alive channel that only uses participant taps created using CreateParticipantTap when the event ParticipantAddedToChannel is triggered.
I also have a similar script to locally mute the audio and that seems to work but adjusting the same participants volume has no effect on the participant tap. The dead channel however is affected properly on a per player basis, just not the particpant taps on the Alive channel.
public void SetLocalVolume(int volume, string participantName)
{
//Set local just to be safe
var participant = activePlayerTaps.Find(t => t.participantName == participantName);
Debug.Log($"SetLocalVolume: {participantName}");
if (participant != null)
{
participant.participant.SetLocalVolume(volume);
Debug.Log($"Set volume for {participantName} locally.");
}
// Find all the ActiveChannels and set the volume for the participant
foreach (var channel in VivoxService.Instance.ActiveChannels)
{
Debug.Log($"Checking channel: {channel.Key}");
var participants = channel.Value;
Debug.Log($"Participants: {participants.Count}");
// Set the volume for the participant
foreach (var p in participants)
{
Debug.Log($"Checking participant: {p.DisplayName}");
if (p.DisplayName == participantName)
{
p.SetLocalVolume(volume);
Debug.Log($"Set volume for {participantName} in channel: {channel.Key}");
break;
}
}
}
}
The console logs all come up true as finding the correct player and setting the volume, but the participant taps audio level does not seem to change at all.
Edit: I also forgot to add this, the participant tap that is created has a slightly different name shown in the inspector of unity than expected. I’m using anon_1231241241 type names while testing, and it seems to truncate the anon_ and just shows the rest in the inspector.
// Create a participant tap directly
GameObject participantObject = participant.CreateVivoxParticipantTap(participant.DisplayName);
if (participantObject == null)
{
Debug.LogError($"Failed to create participant tap for: {participant.DisplayName}");
return;
}
Edit 2: I did look under VivoxParticipant.cs and found that the ParticipantName for the creation of this tap is getting set to PlayerId on line 207
A nuance of using participant taps and silencing the Vivox audio (default behaviour of CreateVivoxParticipantTap) is that you must use the AudioSource attached to the newly created VivoxParticipantTap Gameobject to control things like volume. Conveniently, you can access this by calling participant.ParticipantTapAudioSource, for example.
This likely explains why you see behavior differences between the dead channel (no participant taps) and the alive channel (participant taps used). The dead channel volume adjustments should work as expected when making calls such as participant.participant.SetLocalVolume(volume); but the audio of participants in the alive channel will need to be adjusted via participant.ParticipantTapAudioSource.volume = volume
The volume-adjustment APIs on our VivoxParticipant object should work as expected in the absence of participant taps.
I realize that this is not well documented and we’ll fix that, so thank you for bringing this up!
If you want to use the same API and simply pivot how you adjust the volume based on which channel is used, a volume converter may be useful since Vivox uses a volume range of -50 to 50 and an AudioSource’s range is 0 to 1. I’ll add an example in case it helps~
// Adjust these based on what you actually have configured for the min and max Vivox volume.
[SerializeField] float vivoxMinVolume = -50f;
[SerializeField] float vivoxMaxVolume = 50f;
// Used to convert Vivox volume (-50 to 50) to AudioSource volume (0 to 1).
public float ConvertVivoxVolumeToAudioSourceVolume(float vivoxVolume)
{
// 1. Clamp the raw volume value to the specified range
vivoxVolume = Mathf.Clamp(vivoxVolume, vivoxMinVolume, vivoxMaxVolume);
// 2. Normalize the raw volume to 0 to 1
return Mathf.InverseLerp(vivoxMinVolume , vivoxMaxVolume, vivoxVolume);
}
Please let me know if I can elaborate further on anything or if the info provided does not unblock you!
Gotcha, yeah I was working on a route to just adjust the audiosource instead for the participant taps but I thought there just might be a bug preventing that from working. Thanks for the heads up!
I’ll try to sync them up best I can but the noise levels the channels make vs the audio source are quite different.
Well assume you turn a local players noise to +50, it get’s pretty blown out but sometimes you need to do that to hear someone if they can’t adjust their own volume.
With adjusting the audiosource’s I can’t really go above 1, so I think I’d have to change the range to replicate more of a -50 → 0 range instead of -50 → +50 so that I can keep both the channels and audio sources sounding about the same in volume. At least that’s what I’m doing right now and it seems to work, but doesn’t allow me to get full use out of the 0 → +50 range.
Ideally I thought that adjusting the SetLocalVolume would modify the “clip” that’s being sent to the AudioSource Participant Tap so that I could avoid managing the audiosource and keep them more in sync with the dead channel.
We will have to reconsider whether SetLocalVolume should affect the volume of participant audio that goes to the Participant Tap since there are so few options for boosting Unity Audio Source volume above 1.0 (0 dBFS).
A workaround is possible if you route all participant audio taps to a Mixer Group. You can use the Attenuation Volume to get up to 20 dB of boost. You can even compensate for a fixed Mixer Group boost of +20 dB in your Audio Sources volumes by setting them to 0.1 (-20 dB), then 0.1 would be the new “1.0” and 1.0 would be something like 10.0 (+20 dB).
When boosting above 1.0 (0 dBFS), the distortion can be made warmer by adding a Compressor after the Attenuation Volume boost.