Skip to content

Commit e9058c7

Browse files
Add support for overriding speaker_mode.
Add support (via project settings) to AudioServer to change the speaker_mode that Godot uses internally, independent of the audio driver used. Can accept a 'Default' value, using the audio driver speaker_mode, or use the specified mode. This is intended to be used to help troubleshoot audio issues when testing with different speaker setups, but can be used to force a specific speaker_mode on projects where appropriate. Co-authored-by: A Thousand Ships <[email protected]>
1 parent 4d1f26e commit e9058c7

File tree

3 files changed

+77
-6
lines changed

3 files changed

+77
-6
lines changed

doc/classes/ProjectSettings.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -464,6 +464,10 @@
464464
<member name="audio/general/ios/session_category" type="int" setter="" getter="" default="0">
465465
Sets the [url=https://developer.apple.com/documentation/avfaudio/avaudiosessioncategory]AVAudioSessionCategory[/url] on iOS. Use the [code]Playback[/code] category to get sound output, even if the phone is in silent mode.
466466
</member>
467+
<member name="audio/general/speaker_mode" type="int" setter="" getter="" default="-1">
468+
The speaker mode used internally by Godot. [code]Default[/code] will use the audio driver's speaker mode, while other values will override the internal speaker mode, and thus the number of audio channels, used by the [AudioServer].
469+
When the internal speaker mode differs from the driver's speaker mode, audio channels will be muted, ignored, or mapped to the audio driver's channels.
470+
</member>
467471
<member name="audio/general/text_to_speech" type="bool" setter="" getter="" default="false">
468472
If [code]true[/code], text-to-speech support is enabled on startup, otherwise it is enabled first time TTS method is used, see [method DisplayServer.tts_get_voices] and [method DisplayServer.tts_speak].
469473
[b]Note:[/b] Enabling TTS can cause addition idle CPU usage and interfere with the sleep mode, so consider disabling it if TTS is not used.

servers/audio_server.cpp

Lines changed: 65 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ void AudioServer::_driver_process(int p_frames, int32_t *p_buffer) {
264264
#endif
265265

266266
if (channel_count != get_channel_count()) {
267-
// Amount of channels changed due to a output_device change
267+
// Number of channels changed due to a output_device or speaker_mode change
268268
// reinitialize the buses channels and buffers
269269
init_channels_and_buffers();
270270
}
@@ -282,8 +282,9 @@ void AudioServer::_driver_process(int p_frames, int32_t *p_buffer) {
282282
int from = buffer_size - to_mix;
283283
int from_buf = p_frames - todo;
284284

285-
//master master, send to output
286-
int cs = master->channels.size();
285+
// Channels size from driver and channels used by master
286+
int cs = get_driver_channel_count();
287+
int mcs = master->channels.size();
287288

288289
// Take away 1 from the stride, as we are manually incrementing by 1 for stereo.
289290
uintptr_t stride_minus_one = (cs * 2) - 1;
@@ -293,9 +294,9 @@ void AudioServer::_driver_process(int p_frames, int32_t *p_buffer) {
293294
int32_t *dest = &p_buffer[from_buf * (cs * 2) + (k * 2)];
294295

295296
#ifdef DEBUG_ENABLED
296-
if (!debug_mute && master->channels[k].active) {
297+
if (!debug_mute && k < mcs && master->channels[k].active) {
297298
#else
298-
if (master->channels[k].active) {
299+
if (k < mcs && master->channels[k].active) {
299300
#endif // DEBUG_ENABLED
300301
const AudioFrame *buf = master->channels[k].buffer.ptr();
301302

@@ -1485,6 +1486,24 @@ String AudioServer::get_driver_name() const {
14851486
return AudioDriver::get_singleton()->get_name();
14861487
}
14871488

1489+
AudioServer::SpeakerMode AudioServer::get_driver_speaker_mode() const {
1490+
return (AudioServer::SpeakerMode)AudioDriver::get_singleton()->get_speaker_mode();
1491+
}
1492+
1493+
int AudioServer::get_driver_channel_count() const {
1494+
switch (get_driver_speaker_mode()) {
1495+
case SPEAKER_MODE_STEREO:
1496+
return 1;
1497+
case SPEAKER_SURROUND_31:
1498+
return 2;
1499+
case SPEAKER_SURROUND_51:
1500+
return 3;
1501+
case SPEAKER_SURROUND_71:
1502+
return 4;
1503+
}
1504+
ERR_FAIL_V(1);
1505+
}
1506+
14881507
void AudioServer::notify_listener_changed() {
14891508
for (CallbackItem *ci : listener_changed_callback_list) {
14901509
ci->callback(ci->userdata);
@@ -1493,6 +1512,9 @@ void AudioServer::notify_listener_changed() {
14931512

14941513
void AudioServer::init_channels_and_buffers() {
14951514
channel_count = get_channel_count();
1515+
1516+
print_verbose(vformat("AudioServer: Speaker mode set to %s, initializing %d stereo channel(s)", _get_speaker_mode_name(), channel_count));
1517+
14961518
temp_buffer.resize(channel_count);
14971519
mix_buffer.resize(buffer_size + LOOKAHEAD_BUFFER_SIZE);
14981520

@@ -1512,6 +1534,9 @@ void AudioServer::init_channels_and_buffers() {
15121534
void AudioServer::init() {
15131535
channel_disable_threshold_db = GLOBAL_DEF_RST(PropertyInfo(Variant::FLOAT, "audio/buses/channel_disable_threshold_db", PROPERTY_HINT_RANGE, "-80,0,0.1,suffix:dB"), -60.0);
15141536
channel_disable_frames = float(GLOBAL_DEF_RST(PropertyInfo(Variant::FLOAT, "audio/buses/channel_disable_time", PROPERTY_HINT_RANGE, "0,5,0.01,or_greater"), 2.0)) * get_mix_rate();
1537+
1538+
speaker_mode_config = GLOBAL_DEF(PropertyInfo(Variant::INT, "audio/general/speaker_mode", PROPERTY_HINT_ENUM, "Default:-1,Stereo:0,Surround 3.1:1,Surround 5.1:2,Surround 7.1:3"), -1);
1539+
15151540
// TODO: Buffer size is hardcoded for now. This would be really nice to have as a project setting because currently it limits audio latency to an absolute minimum of 11ms with default mix rate, but there's some additional work required to make that happen. See TODOs in `_mix_step_for_channel`.
15161541
// When this becomes a project setting, it should be specified in milliseconds rather than raw sample count, because 512 samples at 192khz is shorter than it is at 48khz, for example.
15171542
buffer_size = 512;
@@ -1532,6 +1557,14 @@ void AudioServer::init() {
15321557
#endif
15331558

15341559
GLOBAL_DEF_RST(PropertyInfo(Variant::INT, "audio/video/video_delay_compensation_ms", PROPERTY_HINT_RANGE, "-1000,1000,1,suffix:ms"), 0);
1560+
1561+
ProjectSettings::get_singleton()->connect("settings_changed", callable_mp(this, &AudioServer::project_settings_changed));
1562+
}
1563+
1564+
void AudioServer::project_settings_changed() {
1565+
lock();
1566+
speaker_mode_config = GLOBAL_GET("audio/general/speaker_mode");
1567+
unlock();
15351568
}
15361569

15371570
void AudioServer::update() {
@@ -1654,7 +1687,33 @@ void AudioServer::unlock() {
16541687
}
16551688

16561689
AudioServer::SpeakerMode AudioServer::get_speaker_mode() const {
1657-
return (AudioServer::SpeakerMode)AudioDriver::get_singleton()->get_speaker_mode();
1690+
switch (speaker_mode_config) {
1691+
case 0:
1692+
return SPEAKER_MODE_STEREO;
1693+
case 1:
1694+
return SPEAKER_SURROUND_31;
1695+
case 2:
1696+
return SPEAKER_SURROUND_51;
1697+
case 3:
1698+
return SPEAKER_SURROUND_71;
1699+
default:
1700+
return get_driver_speaker_mode();
1701+
}
1702+
}
1703+
1704+
String AudioServer::_get_speaker_mode_name() const {
1705+
switch (speaker_mode_config) {
1706+
case 0:
1707+
return "Stereo";
1708+
case 1:
1709+
return "Surround 3.1";
1710+
case 2:
1711+
return "Surround 5.1";
1712+
case 3:
1713+
return "Surround 7.1";
1714+
default:
1715+
return "Default";
1716+
}
16581717
}
16591718

16601719
float AudioServer::get_mix_rate() const {

servers/audio_server.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,8 @@ class AudioServer : public Object {
224224
int channel_count = 0;
225225
int to_mix = 0;
226226

227+
int speaker_mode_config = -1;
228+
227229
float playback_speed_scale = 1.0f;
228230

229231
bool tag_used_audio_streams = false;
@@ -322,6 +324,8 @@ class AudioServer : public Object {
322324

323325
void _update_bus_effects(int p_bus);
324326

327+
String _get_speaker_mode_name() const;
328+
325329
static AudioServer *singleton;
326330

327331
void init_channels_and_buffers();
@@ -375,6 +379,8 @@ class AudioServer : public Object {
375379
bool get_debug_mute() const;
376380
#endif // DEBUG_ENABLED
377381

382+
void project_settings_changed();
383+
378384
void set_bus_count(int p_count);
379385
int get_bus_count() const;
380386

@@ -448,6 +454,8 @@ class AudioServer : public Object {
448454
uint64_t get_mixed_frames() const;
449455

450456
String get_driver_name() const;
457+
SpeakerMode get_driver_speaker_mode() const;
458+
int get_driver_channel_count() const;
451459

452460
void notify_listener_changed();
453461

0 commit comments

Comments
 (0)