Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions doc/classes/ProjectSettings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -464,6 +464,10 @@
<member name="audio/general/ios/session_category" type="int" setter="" getter="" default="0">
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.
</member>
<member name="audio/general/speaker_mode" type="int" setter="" getter="" default="-1">
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].
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.
</member>
<member name="audio/general/text_to_speech" type="bool" setter="" getter="" default="false">
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].
[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.
Expand Down
71 changes: 65 additions & 6 deletions servers/audio_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ void AudioServer::_driver_process(int p_frames, int32_t *p_buffer) {
#endif

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

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

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

#ifdef DEBUG_ENABLED
if (!debug_mute && master->channels[k].active) {
if (!debug_mute && k < mcs && master->channels[k].active) {
#else
if (master->channels[k].active) {
if (k < mcs && master->channels[k].active) {
#endif // DEBUG_ENABLED
const AudioFrame *buf = master->channels[k].buffer.ptr();

Expand Down Expand Up @@ -1485,6 +1486,24 @@ String AudioServer::get_driver_name() const {
return AudioDriver::get_singleton()->get_name();
}

AudioServer::SpeakerMode AudioServer::get_driver_speaker_mode() const {
return (AudioServer::SpeakerMode)AudioDriver::get_singleton()->get_speaker_mode();
}

int AudioServer::get_driver_channel_count() const {
switch (get_driver_speaker_mode()) {
case SPEAKER_MODE_STEREO:
return 1;
case SPEAKER_SURROUND_31:
return 2;
case SPEAKER_SURROUND_51:
return 3;
case SPEAKER_SURROUND_71:
return 4;
}
ERR_FAIL_V(1);
}

void AudioServer::notify_listener_changed() {
for (CallbackItem *ci : listener_changed_callback_list) {
ci->callback(ci->userdata);
Expand All @@ -1493,6 +1512,9 @@ void AudioServer::notify_listener_changed() {

void AudioServer::init_channels_and_buffers() {
channel_count = get_channel_count();

print_verbose(vformat("AudioServer: Speaker mode set to %s, initializing %d stereo channel(s)", _get_speaker_mode_name(), channel_count));

temp_buffer.resize(channel_count);
mix_buffer.resize(buffer_size + LOOKAHEAD_BUFFER_SIZE);

Expand All @@ -1512,6 +1534,9 @@ void AudioServer::init_channels_and_buffers() {
void AudioServer::init() {
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);
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();

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);

// 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`.
// 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.
buffer_size = 512;
Expand All @@ -1532,6 +1557,14 @@ void AudioServer::init() {
#endif

GLOBAL_DEF_RST(PropertyInfo(Variant::INT, "audio/video/video_delay_compensation_ms", PROPERTY_HINT_RANGE, "-1000,1000,1,suffix:ms"), 0);

ProjectSettings::get_singleton()->connect("settings_changed", callable_mp(this, &AudioServer::project_settings_changed));
}

void AudioServer::project_settings_changed() {
lock();
speaker_mode_config = GLOBAL_GET("audio/general/speaker_mode");
unlock();
}
Comment on lines +1561 to 1568
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering if there's another setting that works like this in the project. This is primarily for the editor side, so should we wrap this behind a is_editor_hint()?


void AudioServer::update() {
Expand Down Expand Up @@ -1654,7 +1687,33 @@ void AudioServer::unlock() {
}

AudioServer::SpeakerMode AudioServer::get_speaker_mode() const {
return (AudioServer::SpeakerMode)AudioDriver::get_singleton()->get_speaker_mode();
switch (speaker_mode_config) {
case 0:
return SPEAKER_MODE_STEREO;
case 1:
return SPEAKER_SURROUND_31;
case 2:
return SPEAKER_SURROUND_51;
case 3:
return SPEAKER_SURROUND_71;
default:
return get_driver_speaker_mode();
}
}

String AudioServer::_get_speaker_mode_name() const {
switch (speaker_mode_config) {
case 0:
return "Stereo";
case 1:
return "Surround 3.1";
case 2:
return "Surround 5.1";
case 3:
return "Surround 7.1";
default:
return "Default";
}
}

float AudioServer::get_mix_rate() const {
Expand Down
8 changes: 8 additions & 0 deletions servers/audio_server.h
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,8 @@ class AudioServer : public Object {
int channel_count = 0;
int to_mix = 0;

int speaker_mode_config = -1;

float playback_speed_scale = 1.0f;

bool tag_used_audio_streams = false;
Expand Down Expand Up @@ -322,6 +324,8 @@ class AudioServer : public Object {

void _update_bus_effects(int p_bus);

String _get_speaker_mode_name() const;

static AudioServer *singleton;

void init_channels_and_buffers();
Expand Down Expand Up @@ -375,6 +379,8 @@ class AudioServer : public Object {
bool get_debug_mute() const;
#endif // DEBUG_ENABLED

void project_settings_changed();

void set_bus_count(int p_count);
int get_bus_count() const;

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

String get_driver_name() const;
SpeakerMode get_driver_speaker_mode() const;
int get_driver_channel_count() const;

void notify_listener_changed();

Expand Down