Voice
Warning
Prerequisites:
Any code from the prerequisites can be omitted to make it easier to read. If you do want the complete code, look at the repository examples.
Create/Join
| GDScript |
|---|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38 | extends Node
var application_id: int = 123456789012345678
var client := DiscordClient.new()
func _ready() -> void:
client.set_application_id(application_id)
client.set_status_changed_callback(_on_status_changed)
func _process(_delta: float) -> void:
Discord.run_callbacks()
func _on_status_changed(status: DiscordClientStatus.Enum, _error: DiscordClientError.Enum, _error_detail: int) -> void:
var enum_str: String = Discord.enum_to_string(status, DiscordClientStatus.id)
print("Status changed to %s" % enum_str)
if status == DiscordClientStatus.READY:
client.create_or_join_lobby("your-unique-lobby-secret", _on_joined_lobby)
func _on_joined_lobby(result: DiscordClientResult, lobby_id: int) -> void:
if result.successful():
print("đŽ Successfully joined lobby!")
var call: DiscordCall = client.start_call(lobby_id)
if call:
print("đ¤ Voice call operation initiated...")
else:
print("âšī¸ Already in this voice channel")
else:
print("â Failed to join lobby: %s" % result.error())
|
Note
Once you join, you are officially in a voice chat!
Unless you mute, your microphone input will be captured and sent to others.
Controls
We can manipulate the voice settings for a specific call or for all calls.
Specific Call
| GDScript |
|---|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53 | extends Node
var application_id: int = 123456789012345678
var target_id: int = 987654323109876543
var client := DiscordClient.new()
func _ready() -> void:
client.set_application_id(application_id)
client.set_status_changed_callback(_on_status_changed)
func _process(_delta: float) -> void:
Discord.run_callbacks()
func _on_status_changed(status: DiscordClientStatus.Enum, _error: DiscordClientError.Enum, _error_detail: int) -> void:
var enum_str: String = Discord.enum_to_string(status, DiscordClientStatus.id)
print("Status changed to %s" % enum_str)
if status == DiscordClientStatus.READY:
client.create_or_join_lobby("your-unique-lobby-secret", _on_joined_lobby)
func _on_joined_lobby(result: DiscordClientResult, lobby_id: int) -> void:
if result.successful():
print("đŽ Successfully joined lobby!")
var call: DiscordCall = client.start_call(lobby_id)
if call:
print("đ¤ Voice call operation initiated...")
else:
print("âšī¸ Already in this voice channel")
# Let's give a second to simulate interacting from anywhere in your code.
get_tree().create_timer(1).timeout.connect(_on_call_started.bind(lobby_id))
else:
print("â Failed to join lobby: %s" % result.error())
func _on_call_started(lobby_id: int) -> void:
var call: DiscordCall = client.get_call(lobby_id)
if call:
call.set_self_mute(true)
call.set_self_deaf(false)
call.set_participant_volume(target_id, 150.0)
call.set_vad_threshold(false, -30.0)
|
All Calls
| GDScript |
|---|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70 | extends Node
var application_id: int = 123456789012345678
var target_id: int = 987654323109876543
var client := DiscordClient.new()
func _ready() -> void:
client.set_application_id(application_id)
client.set_status_changed_callback(_on_status_changed)
func _process(_delta: float) -> void:
Discord.run_callbacks()
func _on_status_changed(status: DiscordClientStatus.Enum, _error: DiscordClientError.Enum, _error_detail: int) -> void:
var enum_str: String = Discord.enum_to_string(status, DiscordClientStatus.id)
print("Status changed to %s" % enum_str)
if status == DiscordClientStatus.READY:
client.create_or_join_lobby("your-unique-lobby-secret", _on_joined_lobby)
func _on_joined_lobby(result: DiscordClientResult, lobby_id: int) -> void:
if result.successful():
print("đŽ Successfully joined lobby!")
var call: DiscordCall = client.start_call(lobby_id)
if call:
print("đ¤ Voice call operation initiated...")
else:
print("âšī¸ Already in this voice channel")
# Let's give a second to simulate interacting from anywhere in your code.
get_tree().create_timer(1).timeout.connect(_on_call_started.bind(lobby_id))
else:
print("â Failed to join lobby: %s" % result.error())
func _on_call_started(lobby_id: int) -> void:
var call: DiscordCall = client.get_call(lobby_id)
if call:
call.set_self_mute(true)
call.set_self_deaf(false)
call.set_participant_volume(target_id, 150.0)
call.set_vad_threshold(false, -30.0)
client.set_self_mute_all(true)
client.set_input_volume(75.0)
client.set_output_volume(120.0)
client.set_no_audio_input_threshold(-60.0)
client.set_no_audio_input_callback(_on_audio_crossing_threshold)
client.set_noise_suppression(true)
client.set_echo_cancellation(true)
client.set_automatic_gain_control(true)
client.set_noise_cancellation(true)
func _on_audio_crossing_threshold(input_detected: bool) -> void:
if not input_detected:
print("đ Mic appears to be silent â check your device settings.")
else:
print("đ Mic is receiving audio again")
|
Audio Processing
Warning
While the SDK provide ways to manipulate audio when received, the GDExtension still doesn't support it.
Changing the values of the variables has no effect in the audio.
| GDScript |
|---|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55 | extends Node
var application_id: int = 123456789012345678
var target_id: int = 987654323109876543
var client := DiscordClient.new()
func _ready() -> void:
client.set_application_id(application_id)
client.set_status_changed_callback(_on_status_changed)
func _process(_delta: float) -> void:
Discord.run_callbacks()
func _on_status_changed(status: DiscordClientStatus.Enum, _error: DiscordClientError.Enum, _error_detail: int) -> void:
var enum_str: String = Discord.enum_to_string(status, DiscordClientStatus.id)
print("Status changed to %s" % enum_str)
if status == DiscordClientStatus.READY:
client.create_or_join_lobby("your-unique-lobby-secret", _on_joined_lobby)
func _on_joined_lobby(result: DiscordClientResult, lobby_id: int) -> void:
if result.successful():
print("đŽ Successfully joined lobby!")
var call: DiscordCall = client.start_call_with_audio_callbacks(lobby_id, _on_audio_received, _on_audio_captured)
if call:
print("đ¤ Voice call operation initiated...")
else:
print("âšī¸ Already in this voice channel")
else:
print("â Failed to join lobby: %s" % result.error())
func _on_audio_received(user_id: int, data: Array[int], samples_per_channel: int, sample_rate: int, channels: int, out_should_mute: bool) -> void:
# Changing "data" doesn't reflect into SDK.
for i in data.size():
data[i] *= 0.5
# Changing "out_should_mute" doesn't reflect into SDK.
out_should_mute = true
var total_num_samples = samples_per_channel * channels
func _on_audio_captured(data: Array[int], samples_per_channel: int, sample_rate: int, channels: int) -> void:
pass
|
Leave
Specific Call
| GDScript |
|---|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76 | extends Node
var application_id: int = 123456789012345678
var target_id: int = 987654323109876543
var client := DiscordClient.new()
func _ready() -> void:
client.set_application_id(application_id)
client.set_status_changed_callback(_on_status_changed)
func _process(_delta: float) -> void:
Discord.run_callbacks()
func _on_status_changed(status: DiscordClientStatus.Enum, _error: DiscordClientError.Enum, _error_detail: int) -> void:
var enum_str: String = Discord.enum_to_string(status, DiscordClientStatus.id)
print("Status changed to %s" % enum_str)
if status == DiscordClientStatus.READY:
client.create_or_join_lobby("your-unique-lobby-secret", _on_joined_lobby)
func _on_joined_lobby(result: DiscordClientResult, lobby_id: int) -> void:
if result.successful():
print("đŽ Successfully joined lobby!")
var call: DiscordCall = client.start_call(lobby_id)
if call:
print("đ¤ Voice call operation initiated...")
else:
print("âšī¸ Already in this voice channel")
# Let's give a second to simulate interacting from anywhere in your code.
get_tree().create_timer(1).timeout.connect(_on_call_started.bind(lobby_id))
else:
print("â Failed to join lobby: %s" % result.error())
func _on_call_started(lobby_id: int) -> void:
var call: DiscordCall = client.get_call(lobby_id)
if call:
call.set_self_mute(true)
call.set_self_deaf(false)
call.set_participant_volume(target_id, 150.0)
call.set_vad_threshold(false, -30.0)
client.set_self_mute_all(true)
client.set_input_volume(75.0)
client.set_output_volume(120.0)
client.set_no_audio_input_threshold(-60.0)
client.set_no_audio_input_callback(_on_audio_crossing_threshold)
client.set_noise_suppression(true)
client.set_echo_cancellation(true)
client.set_automatic_gain_control(true)
client.set_noise_cancellation(true)
client.end_call(lobby_id, _on_call_ended)
func _on_audio_crossing_threshold(input_detected: bool) -> void:
if not input_detected:
print("đ Mic appears to be silent â check your device settings.")
else:
print("đ Mic is receiving audio again")
func _on_call_ended() -> void:
print("đ Call ended successfully")
|
All Calls
| GDScript |
|---|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76 | extends Node
var application_id: int = 123456789012345678
var target_id: int = 987654323109876543
var client := DiscordClient.new()
func _ready() -> void:
client.set_application_id(application_id)
client.set_status_changed_callback(_on_status_changed)
func _process(_delta: float) -> void:
Discord.run_callbacks()
func _on_status_changed(status: DiscordClientStatus.Enum, _error: DiscordClientError.Enum, _error_detail: int) -> void:
var enum_str: String = Discord.enum_to_string(status, DiscordClientStatus.id)
print("Status changed to %s" % enum_str)
if status == DiscordClientStatus.READY:
client.create_or_join_lobby("your-unique-lobby-secret", _on_joined_lobby)
func _on_joined_lobby(result: DiscordClientResult, lobby_id: int) -> void:
if result.successful():
print("đŽ Successfully joined lobby!")
var call: DiscordCall = client.start_call(lobby_id)
if call:
print("đ¤ Voice call operation initiated...")
else:
print("âšī¸ Already in this voice channel")
# Let's give a second to simulate interacting from anywhere in your code.
get_tree().create_timer(1).timeout.connect(_on_call_started.bind(lobby_id))
else:
print("â Failed to join lobby: %s" % result.error())
func _on_call_started(lobby_id: int) -> void:
var call: DiscordCall = client.get_call(lobby_id)
if call:
call.set_self_mute(true)
call.set_self_deaf(false)
call.set_participant_volume(target_id, 150.0)
call.set_vad_threshold(false, -30.0)
client.set_self_mute_all(true)
client.set_input_volume(75.0)
client.set_output_volume(120.0)
client.set_no_audio_input_threshold(-60.0)
client.set_no_audio_input_callback(_on_audio_crossing_threshold)
client.set_noise_suppression(true)
client.set_echo_cancellation(true)
client.set_automatic_gain_control(true)
client.set_noise_cancellation(true)
client.end_calls(_on_calls_ended)
func _on_audio_crossing_threshold(input_detected: bool) -> void:
if not input_detected:
print("đ Mic appears to be silent â check your device settings.")
else:
print("đ Mic is receiving audio again")
func _on_calls_ended() -> void:
print("đ All calls ended successfully")
|
Check
Call
| GDScript |
|---|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43 | extends Node
var application_id: int = 123456789012345678
var client := DiscordClient.new()
func _ready() -> void:
client.set_application_id(application_id)
client.set_status_changed_callback(_on_status_changed)
func _process(_delta: float) -> void:
Discord.run_callbacks()
func _on_status_changed(status: DiscordClientStatus.Enum, _error: DiscordClientError.Enum, _error_detail: int) -> void:
var enum_str: String = Discord.enum_to_string(status, DiscordClientStatus.id)
print("Status changed to %s" % enum_str)
if status == DiscordClientStatus.READY:
client.create_or_join_lobby("your-unique-lobby-secret", _on_joined_lobby)
func _on_joined_lobby(result: DiscordClientResult, lobby_id: int) -> void:
if result.successful():
print("đŽ Successfully joined lobby!")
var lobby = client.get_lobby_handle(lobby_id)
if lobby is DiscordLobbyHandle:
var call_info = lobby.get_call_info_handle()
if call_info is DiscordCallInfoHandle:
var participants: Array[int] = call_info.get_participants()
print("Active call with %s participants" % participants.size())
else:
print("No active voice call in this lobby")
else:
print("â Failed to join lobby: %s" % result.error())
|
Participant
| GDScript |
|---|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52 | extends Node
var application_id: int = 123456789012345678
var client := DiscordClient.new()
func _ready() -> void:
client.set_application_id(application_id)
client.set_status_changed_callback(_on_status_changed)
func _process(_delta: float) -> void:
Discord.run_callbacks()
func _on_status_changed(status: DiscordClientStatus.Enum, _error: DiscordClientError.Enum, _error_detail: int) -> void:
var enum_str: String = Discord.enum_to_string(status, DiscordClientStatus.id)
print("Status changed to %s" % enum_str)
if status == DiscordClientStatus.READY:
client.create_or_join_lobby("your-unique-lobby-secret", _on_joined_lobby)
func _on_joined_lobby(result: DiscordClientResult, lobby_id: int) -> void:
if result.successful():
print("đŽ Successfully joined lobby!")
var lobby = client.get_lobby_handle(lobby_id)
if lobby is DiscordLobbyHandle:
var call_info = lobby.get_call_info_handle()
if call_info is DiscordCallInfoHandle:
var participants = call_info.get_participants()
for participant_id in participants:
var voice_state = call_info.get_voice_state_handle(participant_id)
if voice_state is DiscordVoiceStateHandle:
var is_muted = voice_state.self_mute()
var is_deafened = voice_state.self_deaf()
print("Participant %s - Muted: %s, Deafened: %s" % [
participant_id,
"Yes" if is_muted else "No",
"Yes" if is_deafened else "No",
])
else:
print("â Failed to join lobby: %s" % result.error())
|
Import Settings
Instead of choosing a default voice settings or making the user adjust, we can import the user voice settings from the Discord client.
Fetch
| GDScript |
|---|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32 | extends Node
var application_id: int = 123456789012345678
var client := DiscordClient.new()
func _ready() -> void:
client.set_application_id(application_id)
client.get_voice_settings(_on_voice_settings)
func _process(_delta: float) -> void:
Discord.run_callbacks()
func _on_voice_settings(result: DiscordClientResult, settings: DiscordVoiceSettings) -> void:
if not result.successful():
print("â Failed to fetch voice settings: %s" % result.error())
return
print("Self mute: %s" % settings.self_mute())
print("Self deaf: %s" % settings.self_deaf())
print("Input volume: %s" % settings.input_volume()) # 0-100
print("Output volume: %s" % settings.output_volume()) # 0-200
# input_mode() is either DiscordVoiceInputModeType.VOICE_ACTIVITY or
# DiscordVoiceInputModeType.PUSH_TO_TALK
if settings.input_mode() == DiscordVoiceInputModeType.PUSH_TO_TALK:
# ptt_key() is a display string, e.g. "SHIFT + F", empty if unbound
print("Push-to-talk key: %s" % settings.ptt_key())
|
Changes Notification
| GDScript |
|---|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 | extends Node
var application_id: int = 123456789012345678
var client := DiscordClient.new()
func _ready() -> void:
client.set_application_id(application_id)
client.set_voice_settings_updated_callback(_on_voice_settings_updated)
func _process(_delta: float) -> void:
Discord.run_callbacks()
func _on_voice_settings_updated(settings: DiscordVoiceSettings) -> void:
print("đ Voice settings updated - self mute: %s" % settings.self_mute())
|
References