Game Voice
Feature Overview
Concept Explanation
- Range: The range within which a listener can receive audio.
- Orientation: Refers to the position and facing direction of the listener in the game world coordinates. For details, please refer to
5 Set Current Position of Listener. - Listener: The user in the room who receives audio.
- Speaker: The user in the room who sends audio.
Feature Description
Starting from version 2.11.0, ZEGO Express SDK has added a game voice module, mainly including: range voice, 3D audio effects, and team voice.
| Feature | Description |
|---|---|
Range Voice | Listeners in the room have range limitations on the distance they can receive audio. If a speaker is farther away than this range, they cannot be heard. To ensure voice clarity, when more than 20 people nearby are speaking, only the voices of the 20 speakers closest to the listener can be heard. Suppose the maximum range for audio reception is set to R, and the distance between the speaker and the listener is r, then:
![]() The above figure only shows the example when the range voice mode is "World". For more information on sound reachability under different mode combinations, please refer to Set Common Voice Mode. |
| 3D Audio Effects | Sound has 3D spatial perception and attenuates with distance. |
Common Voice Mode | Players can choose to join a team and support freely switching between "World", "Team Only", and "Secret Team" voice modes in the room.
Note
|
Applicable Scenarios
Game voice features are applicable to battle royale games and metaverse scenarios.
In battle royale games, team voice provides squad functionality. Teams can be changed before and after the game starts. Developers do not need to focus on stream grouping and publishing/playing implementation, and can directly implement team voice features.
In battle royale games and metaverse scenarios, 3D audio effects are provided. When listening to speakers' audio effects, there is a sense of direction and distance, making the scene feel more realistic.
Sample Source Code Download
Please refer to Download Sample Source Code to obtain the source code.
For related source code, please check the files in the "/ZegoExpressExample/Examples/AdvancedAudioProcessing/RangeAudio" directory.
Prerequisites
Before implementing range voice, please ensure:
- A project has been created in the ZEGOCLOUD Console, and valid AppID and AppSign have been obtained. For details, please refer to Console - Project Information.
- ZEGO Express SDK has been integrated into the project, and basic audio/video publishing and playing functionality has been implemented. For details, please refer to Quick Start - Integration and Quick Start - Implementation.
Important Notes
Please pay close attention to the following when using the range voice feature to avoid integration issues.
If you are already using the real-time audio/video functionality of ZEGO Express SDK, please note the following:
- Since the range voice feature module is implemented based on the ZegoExpressEngine's publishing and playing interface functionality, you do not need to focus on the concept of publishing and playing when using it. In the range voice scenario, the concept of publishing audio streams is converted to "turning on the microphone", and the concept of playing audio streams is converted to "turning on the speaker". It is recommended that you do not use the startPublishingStream and startPlayingStream interfaces for publishing and playing operations while integrating the range voice feature, to avoid effect conflicts.
- The related callbacks for publishing and playing in the range voice feature module (onPublisherStateUpdate, onPlayerStateUpdate, onPublisherQualityUpdate, and onPlayerQualityUpdate) no longer take effect.
Usage Steps
The above figure only shows the core steps and interfaces for implementing game voice functionality. Developers can implement other related interfaces according to business needs, referring to the detailed introduction in the documentation below.
1 Create Engine
Call the createEngine interface, pass the obtained AppID and AppSign to the parameters "appID" and "appSign", and create an engine singleton object. The engine currently only supports creating one instance at the same time, and will return null if exceeded.
ZegoEngineProfile profile;
// AppID and AppSign are assigned by ZEGO to each App; for security reasons, it is recommended to store AppSign in the App's business backend and obtain it from the backend when needed
profile.appID = appID;
profile.appSign = appSign;
profile.scenario = ZegoScenario::ZEGO_SCENARIO_DEFAULT;
// Create engine instance
IZegoExpressEngine* engine = ZegoExpressSDK::createEngine(profile, nullptr);
if (engine== nullptr) {
printf("Failed to create engine");
return;
}
IZegoEventHandler* pEventHandler = std::make_share<IZegoEventHandler>();
engine->setEventHandler(pEventHandler);2 Create Range Voice Module
Call the createRangeAudio method to create a range voice instance.
IZegoRangeAudio* rangeAudio = engine->createRangeAudio();
if (rangeAudio == nullptr) {
printf("Failed to create range voice instance module");
}3 Listen to Range Voice Event Callbacks
You can call the setEventHandler interface as needed to set event callbacks for the microphone, used to listen to microphone on/off state onRangeAudioMicrophoneStateUpdate notifications.
class MyRangeAudioEventHandler: public IZegoRangeAudioEventHandler{
public:
// Callback for status change when player plays a sound effect
virtual void onRangeAudioMicrophoneStateUpdate(IZegoRangeAudio* /*rangeAudio*/, ZegoRangeAudioMicrophoneState /*state*/, int /*errorCode*/) {
if(ZEGO_RANGE_AUDIO_MICROPHONE_STATE_TURNING_ON == state)
{
// Microphone turning on
}
else if(ZEGO_RANGE_AUDIO_MICROPHONE_STATE_OFF == state)
{
// Microphone turned off
}
else if(ZEGO_RANGE_AUDIO_MICROPHONE_STATE_ON== state)
{
// Microphone successfully turned on
}
}
IZegoRangeAudio* pRangeAudioEventHandler = std::make_share<IZegoRangeAudioEventHandler>();
rangeAudio->setEventHandler(pRangeAudioEventHandler);4 Login Room
After creating a ZegoUser user object by passing in the userID and userName parameters, call the loginRoom interface, pass in the roomID parameter and user parameter, and log in to the room.
- Within the same AppID, ensure that roomID is globally unique.
- Within the same AppID, ensure that userID is globally unique. It is recommended that developers set it to a meaningful value and associate userID with their business account system.
- userID cannot be empty, otherwise login to the room will fail.
ZegoUser user;
user.userID = "test";
user.userName = "testName";
ZegoRoomConfig roomConfig;
engine->loginRoom("123",user,roomConfig);After the user has successfully logged in to the room, if the application exits abnormally, when restarting the application, the developer needs to first call the logoutRoom interface to leave the room, and then call the loginRoom interface to log in to the room again.
5 Set Current Position of Listener
Developers can call the updateSelfPosition interface to set their own position and orientation, or update their position and facing direction in the world coordinate system when their own orientation changes.
- If this interface is not called to set position information before calling enableSpeaker to turn on the speaker, audio from people other than the team cannot be received.
- The coordinate values of the three axes of the local coordinate system can be obtained by converting the rotation angle of a third-party 3D engine into a matrix.
| Parameter Name | Description |
| position | The coordinates of oneself in the world coordinate system. The parameter is a float array of length 3, with the three values representing the coordinate values of front, right, and up respectively. |
| axisForward | The unit vector of the front axis of the local coordinate system. The parameter is a float array of length 3, with the three values representing the coordinate values of front, right, and up respectively. |
| axisRight | The unit vector of the right axis of the local coordinate system. The parameter is a float array of length 3, with the three values representing the coordinate values of front, right, and up respectively. |
| axisUp | The unit vector of the up axis of the local coordinate system. The parameter is a float array of length 3, with the three values representing the coordinate values of front, right, and up respectively. |

// Self's coordinates in the world coordinate system, in the order of front, right, up.
float position[3] = {100.0, 100.0, 100.0};
// Unit vector of the front orientation of the local coordinate system.
float axisForward[3] = {1.0,0.0,0.0};
// Unit vector of the right orientation of the local coordinate system.
float axisRight[3] = {0.0,1.0,0.0};
// Unit vector of the up orientation of the local coordinate system.
float axisUp[3] = {0.0,0.0,1.0};
rangeAudio->updateSelfPosition(position, axisForward, axisRight, axisUp);6 Add or Update Speaker Position Information
After successfully logging in to the room, you can call the updateAudioSource interface to add or update speaker position information.
- In World mode: Need to update the positions of the listener and all speakers in the room. In Secret Team mode: Need to update the positions of all speakers in World mode within the audio reception range in the room. If speaker positions are not set, or speakers are beyond the listener's range, situations where sound cannot be heard will occur.
- Here, speakers refer to other people in the room, and listeners refer to oneself.
- userID: The ID of another speaking user in the room.
- position: The coordinates of the speaker in the world coordinate system. The parameter is a float array of length 3, with the three values representing the coordinate values of front, right, and up respectively.
// User's coordinates in the world coordinate system, in the order of front, right, up.
float position[3] = {100.0, 100.0, 100.0};
// Add/update user position
rangeAudio->updateAudioSource("abc",position);7 (Optional) Set Audio Reception Range
Call the setAudioReceiveRange interface to set the maximum range for the listener to receive audio, that is, taking oneself as the starting point, a 3D space with the set distance as the stereo space. After setting this range, when 3D audio effects are enabled, the sound will attenuate as the distance increases until it exceeds the set range, at which point there will be no more sound.
// Set the maximum range for audio reception. Sound from audio sources beyond this range will not be heard
rangeAudio->setAudioReceiveRange(1000);You can also further control the attenuation range through the setAudioReceiveRange interface. When the distance is less than min, the volume will not attenuate as the distance increases; when the distance is greater than max, the other party's sound cannot be heard.
// Set the attenuation range interval [min, max] for 3D audio effects
ZegoReceiveRangeParam param;
param.min = reciveRangeMin;
param.max = reciveRangeMax;
rangeAudio->setAudioReceiveRange(param);If the audio reception range is not set, it means only team members' voices can be received, and all voices outside the team cannot be received. After setting this, team voice will not be limited by the audio reception range and will not have 3D audio effects.
8 (Optional) Implement 3D Audio Effects
Enable 3D Audio Effects
Call the enableSpatializer interface to set 3D audio effects. When enable is true, it means 3D audio effects are enabled. At this time, the audio of non-team members in the room will change with spatial perception as the distance and direction of the speaker from oneself change. When false, it means 3D audio effects are disabled. (Can be enabled or disabled at any time)
This feature only takes effect for people outside the team.
rangeAudio->enableSpatializer(true);Set 3D Audio Effects for Local Player
Developers can use the media player or audio effect player as a sound source and set its position in the world coordinate system. This feature can be applied to playing background music at a specified location in a virtual world scene, giving it 3D audio effects.
To implement this feature, complete the following steps:
- Call the enableSpatializer interface to enable 3D audio effects.
- Set 3D audio effects for the local player
-
Media Player:
NotePlease refer to Media Player to learn how to create a media player and load media resources.
- Call the createMediaPlayer interface to create a media player.
- Call the IZegoMediaPlayer.updatePosition interface to set the media player's position in the world coordinate system.
- Call the loadResourceWithConfig interface to load media resources.
-
Audio Effect Player:
NotePlease refer to Audio Effect File Player to learn how to create an audio effect player and load audio effect resources.
- Call the createAudioEffectPlayer interface to create an audio effect player.
- Call the IZegoAudioEffectPlayer.start interface to play audio effect resources.
- After receiving the onAudioEffectPlayStateUpdate callback status as
ZegoAudioEffectPlayState.Playing, call the IZegoAudioEffectPlayer.updatePosition interface to set the position of the currently playing audio effect resource in the world coordinate system.
-
// Enable 3D audio effects, this step is a prerequisite
rangeAudio->enableSpatializer(true);
// Set the position of the local player
// Media player
// 1. Create a media player
IZegoMediaPlayer* mediaPlayer = engine->createMediaPlayer();
// 2. Set the media player's position in the world coordinate system, in the order of front, right, up
float mediaPlayerPosition[3] = {0, 0, 0};
mediaPlayer->updatePosition(mediaPlayerPosition);
// 3. Use the media player to load media resources
ZegoMediaPlayerResource resource;
resource.loadType = ZEGO_MULTIMEDIA_LOAD_TYPE_FILE_PATH;
resource.filePath = "path";
mediaPlayer->loadResourceWithConfig(resource, [=](int errorCode) {
if (errorCode == 0)
mediaPlayer->start();
});
// Audio effect player
// 1. Create an audio effect player
IZegoAudioEffectPlayer* audioEffectPlayer = engine->createAudioEffectPlayer();
// 2. Start playing audio effect resources
unsigned int effectSoundID = 1;
std::string path = "path";
audioEffectPlayer->start(effectSoundID, path);
// 3. After receiving the [onAudioEffectPlayStateUpdate] callback status as ZegoAudioEffectPlayState.Playing
// Set the audio effect player's position in the world coordinate system, in the order of front, right, up
float audioEffectPlayerPosition[3] = {0, 0, 0};
audioEffectPlayer->updatePosition(effectSoundID, audioEffectPlayerPosition);9 Enable Microphone and Speaker
After successfully logging in to the room:
-
Call the enableMicrophone interface to set whether to enable the microphone. When enable is true, it means enabled, and the SDK will automatically use the main channel to publish audio streams; when false, it means disabled. (Can be enabled or disabled at any time)
Developers can listen to the onRangeAudioMicrophoneStateUpdate event callback to get the updated microphone status.
-
Call the enableSpeaker interface to set whether to enable the speaker. When enable is true, it means enabled, and audio streams in the room will be automatically played; when false, it means disabled. (Can be enabled or disabled at any time)
After calling the enableSpeaker interface, when the maximum playing stream limit is exceeded (currently 20 streams), team member audio streams (team mode needs to be set) will be played first, and then audio streams within the world closest to the own range will be played.
// Enable microphone
rangeAudio->enableMicrophone(true);
// Enable speaker
rangeAudio->enableSpeaker(true);10 (Optional) Join Team and Set Voice Mode
Join Team
Call the setTeamID interface to set the team ID you want to join as needed (can change ID at any time). After setting the ID, you can directly join. After joining a team, communication with teammates in the same team is not limited by range voice and 3D audio effects.
rangeAudio->setTeamID("123");Set Common Voice Mode
Call the setRangeAudioMode interface to set the range voice mode (can switch modes at any time). When the mode parameter is ZegoRangeAudioModeWorld or ZegoRangeAudioSecretTeam, it means you can hear the voices of all people in World mode; when the value is ZegoRangeAudioModeTeam, it means you can only hear the voices of other members in the same team.
| Voice Mode | Parameter Value | Feature Description |
|---|---|---|
| World | ZEGO_RANGE_AUDIO_MODE_WORLD | After setting this mode, this user can communicate with team members and can also communicate with people in World mode within the range. |
| Team Only | ZEGO_RANGE_AUDIO_MODE_TEAM | After setting this mode, this user can only communicate with team members. |
| Secret Team | ZEGO_RANGE_AUDIO_MODE_SECRET_TEAM | After setting this mode, this user can communicate with team members and can unidirectionally receive voices from people in World mode within the range. |
rangeAudio->setRangeAudioMode(ZegoRangeAudioMode::ZEGO_RANGE_AUDIO_MODE_WORLD);Under different range voice modes, the receivability of speakers' voices varies.
- Assume user A's mode is "World", then the voice receivability of user B under different range voice modes is as follows:
| Same Team | Within Maximum Range | Range Voice Mode | Can A hear B's voice | Can B hear A's voice |
|---|---|---|---|---|
| Yes | Yes | World | Yes | Yes |
| Team Only | Yes | Yes | ||
| Secret Team | Yes | Yes | ||
| No | World | Yes | Yes | |
| Team Only | Yes | Yes | ||
| Secret Team | Yes | Yes | ||
| No | Yes | World | Yes | Yes |
| Team Only | No | No | ||
| Secret Team | No | Yes | ||
| No | World | No | No | |
| Team Only | No | No | ||
| Secret Team | No | No |
- Assume user A's mode is "Team Only", then the voice receivability of user B under different range voice modes is as follows:
| Same Team | Within Maximum Range | Range Voice Mode | Can A hear B's voice | Can B hear A's voice |
|---|---|---|---|---|
| Yes | Yes | World | Yes | Yes |
| Team Only | Yes | Yes | ||
| Secret Team | Yes | Yes | ||
| No | World | Yes | Yes | |
| Team Only | Yes | Yes | ||
| Secret Team | Yes | Yes | ||
| No | Yes | World | No | No |
| Team Only | No | No | ||
| Secret Team | No | No | ||
| No | World | No | No | |
| Team Only | No | No | ||
| Secret Team | No | No |
- Assume user A's mode is "Secret Team", then the voice receivability of user B under different range voice modes is as follows:
| Same Team | Within Maximum Range | Range Voice Mode | Can A hear B's voice | Can B hear A's voice |
|---|---|---|---|---|
| Yes | Yes | World | Yes | Yes |
| Team Only | Yes | Yes | ||
| Secret Team | Yes | Yes | ||
| No | World | Yes | Yes | |
| Team Only | Yes | Yes | ||
| Secret Team | Yes | Yes | ||
| No | Yes | World | Yes | No |
| Team Only | No | No | ||
| Secret Team | No | No | ||
| No | World | No | No | |
| Team Only | No | No | ||
| Secret Team | No | No |
Set Custom Voice Mode
- Custom voice mode and common voice mode cannot be used at the same time.
- If you need to use custom voice mode, please ensure that all online users in game voice are using Express SDK version 3.3.0 or above.
Through custom voice mode, you can freely control the audio sending and receiving logic to complete various audio interactions. Examples are as follows: Assume A, B, and C are members of the same team, and C is within A's reception range. The expected audio experience can be achieved through the configuration in the table
| User | Speaking Expectation | Listening Expectation | Speaking Mode Configuration | Listening Mode Configuration | Remarks |
|---|---|---|---|---|---|
| A | Send audio to team members and other users within range | Receive audio from team members and other users within range | All | All | A can communicate with both B and C at the same time |
| B | Send audio only to team members | Receive audio only from team members | Team | Team | B can only communicate with A |
| C | Send audio only to users within range | Receive audio only from users within range | World | World | C can only communicate with A |
rangeAudio->setRangeAudioCustomMode(ZegoRangeAudioSpeakMode::ZEGO_RANGE_AUDIO_SPEAK_MODE_ALL, ZegoRangeAudioListenMode::ZEGO_RANGE_AUDIO_LISTEN_MODE_ALL);11 Destroy Range Voice Module
When the range voice module is no longer needed, call the destroyRangeAudio interface to destroy it and release the resources occupied by the range voice module.
engine->destroyRangeAudio(rangeAudio);12 Leave Room
Call the logoutRoom interface to leave the room. After leaving, the microphone and speaker will be automatically turned off (i.e., cannot send your own audio, and cannot hear other people's voices), and the speaker information list will be cleared.
// Leave room
engine->logoutRoom("roomID");FAQ
- How many streams can be played simultaneously within the reception range?
To ensure voice clarity, when more than 20 people nearby are speaking, only the voices of the 20 speakers closest to you can be heard. If there are more than 20 people at the same distance, it depends on the order in which each userID was first passed when calling the updateAudioSource interface.
- Does the "range" in range voice refer to the reception range or the speaking range?
The "range" in range voice refers to the reception range.
- Do team members have 3D audio effects when co-hosting in team voice?
Voice within the team has the effect of ordinary co-hosting, and there are no 3D audio effects for now.
- If I am already calling the publishing interface, will there be conflicts when using range voice?
Range voice currently uses the main channel to send audio. If the customer is already using the main channel, there will be conflicts.

