Multiverse Voice Server
From Multiverse
| Multiverse Servers |
|
Installing • Installing on Linux • Running • Troubleshooting • FAQ • Release Notes • Updating • JMX Monitoring & Mgmt. |
| Infrastructure |
|
Platform Architecture • Registering a World • Proxy Server • Event Handling • World Manager • Voice Server |
| Messaging System |
|
Perception Messaging • Using Extension Messages • Message Marshalling • Multi-subject Messaging • Message Catalog |
| Object Architecture |
|
World Instancing • Server Object Search • Server Regions • Server Markers |
| Scalability and Performance |
| Reference |
|
File Layout • Property File • Logging • API |
| Voice Chat System |
|
Voice Chat System • Multiverse Voice Server • Configuring Voice Chat • |
Contents |
Overview
The voice server plug-in provides an API that enables you to implement the voice paradigm of your choice. Each client using voice chat maintains a connection directly to the voice server plug-in, instead of going through the proxy server; this minimizes delays.
The server does not perform voice mixing; rather, each client sends its voice data on a separate voice channel. Initially, the client sends the proxy server the player OID, and the proxy returns the IP address and port of the voice server. The client then initiates a new connection to the voice server.
For information on the corresponding client voice API, see ClientAPI.Voice, MarsVoice, and MarsStandardCommands.HandleVoice().
Voice groups
A voice group is a dynamically-created association of players. At any given time, a user can be a member of at most one voice group.
There are two pre-defined voice group classes that cover common cases:
- A non-positional voice group, in which sound volume is independent of the position of the players; and at any instant all players hear the same collection of speakers. The voice group can be used for presentations, raid groups, guild chat and so on. The
NonpositionalVoiceGroupclass defines this type of voice group. - A positional voice group, in which group membership for a given player is based on the other players nearby, and sound volume falls off with distance. For positional voice groups, hearing is not necessarily symmetric, in that it's possible for a speaker you can't hear to hear you. Positional voice groups are the right thing for chatting up nearby players on a dance floor, for instance. The
PositionalVoiceGroupclass defines this type of voice group.
These two voice group classes are built on the BasicVoiceGroup class, which provides a general mechanism to maintain arbitrary speaker/listener relationships. The pre-defined voice groups will cover most use-cases, but if needed, you can define your own voice group class for custom "connectivity" between players by implementing the VoiceGroup interface.
The VoiceGroup Interface
The voice plugin accesses voice groups using the methods of the VoiceGroup interface.
All VoiceGroup methods refer to members by member OID, and make no assumptions about underlying data structures representing members or speaker/listener relationships.
The VoiceGroup methods:
- Add and remove members, and determine if a given OID is the OID of some member.
- Handle an event method after a member is added, and after a member is removed from a group.
- Specify the set of OIDs of players allowed to be in the group, retrieve the set of OIDs of players allowed to be in the group, and determine if a particular OID would be allowed to be a member of the group.
- Set members to be listening or not listening.
- Set members to be allowed to speak or not allowed to speak.
- Set members to be currently speaking or not currently speaking.
- Gets the default priority for a new member.
- Send voice data to the members of the group who are currently listening to a particular speaker.
- Determine if the member is listening, or allowed to speak, or currently speaking.
The BasicVoiceGroup class
BasicVoiceGroup maintains a collection of GroupMember instances. GroupMembers represent the listener/speaker relationships with the group using attributes that map a speaker to a list of listener group members, and a listener to the map of speaker to voice number. The relationship is general enough to represent most sorts of speaker/listener relationships.
BasicVoiceGroup sends messages to listeners using the VoiceSender instance that is a constructor argument.
BasicVoiceGroup is an abstract class that implements the VoiceGroup interface; subclasses must implement methods to:
- Add a member, and generate the member added event. See below for the details.
- Remove a member and generate the member removed event. See below for the details.
- Determine if the group is a positional group.
- Change whether a member is currently speaking or not.
- Change whether a member is listening or not.
- Recompute the speaker members that a listener member should hear right now.
After a member is added to a group, BasicVoiceGroup sends an ExtensionMessage with information about the member. The MessageType of the message is VoiceClient.MSG_TYPE_VOICE_MEMBER_ADDED, and the properties of the message are:
| Property Name | Type | Description |
|---|---|---|
| memberOid | long | The oid of the member. |
| groupOid | long | The oid of the group to which the member was added. |
| allowedSpeaker | boolean | True if the member is allowed to speak; false otherwise. |
| micVoiceNumber | int | The voice number of incoming voice frames for the added member; always 0 in the current release. |
| listenToYourself | boolean | True if voice frames from the new member should be sent back to the member. This is only used when the user wants to set the microphone level. |
After a member is removed from a group, BasicVoiceGroup sends an ExtensionMessage with information about the member. The MessageType of the message is VoiceClient.MSG_TYPE_VOICE_MEMBER_REMOVED, and the properties of the message are:
| Property Name | Type | Description |
|---|---|---|
| memberOid | long | The oid of the member. |
| groupOid | long | The oid of the group to which the member was removed. |
| allowedSpeaker | boolean | True if the member was allowed to speak before he was removed; false otherwise. |
Non-positional voice groups
In a non-positional voice group, all listeners in the group hear the same set of speakers, and the sound is "ambient" rather than falling off with distance. Use non-positional voice groups to implement presentations and "raid groups."
The NonpositionalVoiceGroup class defines a non-positional voice group. This class maintains a single list of current speakers, and all listeners hear those speakers. NonpositionalVoiceGroup uses the general
speaker/listener association mechanism provided by its supertype BasicVoiceGroup,
though since all listeners in the group hear the same speaker, it would be possible to use
a simpler mechanism. The voice numbers of voice channels to each listener are not the same in general from listener to listener.
Positional voice groups
In a positional voice group, each listener hears the players who are nearby, and the volume falls off with increasing distance between speaker and listener. So in general, each listener hears a different set of speakers, and the relationship between speaker and listener is non-symmetric: a user may be able to hear another user who cannot hear him.
The PositionalVoiceGroup class defines a positional voice group.
The VoiceSender Interface
The VoiceSender interface enables voice groups to send messages to VoiceConnection objects.
The interface's methods include:
- Sending a message to a player allocating or deallocating a voice channel from the voice server to the client. That channel is referred to in subsequent voice data messages by a
voiceNumber, a small integer, supplied in the allocate voice message. - Sending data messages containing voice data to the client, identifying the voice channel using the
voiceNumberin the message. - Sending extension messages generated by voice groups as a result of handling member added and member removed events.
- Deallocating the voice channel identified by the
voiceNumber
GroupMember
Members of all voice groups derived from BasicVoiceGroup are instances of the GroupMember class (or a sub-class). GroupMember contains:
- The member OID, priority and index.
- Whether the member is allowed to speak; currently speaking; and currently listening.
- The VoiceConnection object for the member.
- The data structures necessary to maintain speaker/listener relationships.
PositionalGroupMember
PositionalGroupMember is a subclass of GroupMember that adds just a field with a list representing the set of members in
audible radius.
VoiceClient
Just as other plug-ins are divided into a client class (for example, WorldManagerClient) and a plug-in class (for example, WorldManagerPlugin), the server side of the voice system is divided into VoiceClient, containing APIs to allow other plugins to interact with the voice server, and VoicePlugin, which manages voice groups and voice connections to clients.
From your plug-in, usually in a different process than the VoicePlugin, you can perform all the operations supported by the VoiceGroup interface using the APIs defined in VoiceClient, and all the messaging details are handled below the API level.
Voice server plug-in properties
The following table describes the properties that affect the voice server plug-in.
Set the values of these properties in the server properties file, multiverse.properties.
| Property Name | Default Value | Description |
|---|---|---|
| multiverse.voiceserver | localhost | Host name that the proxy server returns when a client sends an extension message requesting the host and port number of the voice server plug-in. |
| multiverse.voiceport | localhost | Port number that the proxy server returns when a client sends an extension message requesting the host and port number of the voice server plug-in. |
Testing properties
The following table describes properties used for testing the voice system. Do not use them in operational worlds: instead create all voice groups explicitly. All these properties are commented out by default in the server properties file.
| Property Name | Default Value | Description |
|---|---|---|
| multiverse.precreated_nonpositional_voice_group | None | An integer (long) value. The voice plug-in creates a non-positional voice group with the specified value. |
| multiverse.precreated_positional_voice_group | None | An integer (long) value. The voice plug-in creates a positional voice group with the specified value. |
| multiverse.autocreate_referenced_voice_groups | None | A boolean. If true, and a client tries to join a non-existent group, the voice plugin will create it as a non-positional voice group. |
