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
10 changes: 10 additions & 0 deletions doc/classes/ProjectSettings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,16 @@
<member name="audio/driver/output_latency.web" type="int" setter="" getter="" default="50">
Safer override for [member audio/driver/output_latency] in the Web platform, to avoid audio issues especially on mobile devices.
</member>
<member name="audio/driver/override_channel_out" type="int" setter="" getter="" default="0">
The channel index to send to the stereo output when [code]override_speaker_channels[/code] has forced there to be a higher number of actual channels.
</member>
<member name="audio/driver/override_channels" type="bool" setter="" getter="" default="false">
If [code]true[/code], the number of output channels will be set by [code]override_speaker_channels[/code] instead of the speaker mode of the output device.
[b]Note:[/b] This is only implemented in the PulseAudio audio driver on Linux. Other platforms are unaffected by this project setting.
</member>
<member name="audio/driver/override_speaker_channels" type="int" setter="" getter="" default="8">
The number of channels to use when [code]override_channels[/code] is set to [code]true[/code].
</member>
<member name="audio/general/2d_panning_strength" type="float" setter="" getter="" default="0.5">
The base strength of the panning effect for all [AudioStreamPlayer2D] nodes. The panning strength can be further scaled on each Node using [member AudioStreamPlayer2D.panning_strength]. A value of [code]0.0[/code] disables stereo panning entirely, leaving only volume attenuation in place. A value of [code]1.0[/code] completely mutes one of the channels if the sound is located exactly to the left (or right) of the listener.
The default value of [code]0.5[/code] is tuned for headphones. When using speakers, you may find lower values to sound better as speakers have a lower stereo separation compared to headphones.
Expand Down
33 changes: 25 additions & 8 deletions drivers/pulseaudio/audio_driver_pulseaudio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,6 @@ Error AudioDriverPulseAudio::detect_channels(bool input) {
ERR_PRINT("pa_context_get_sink_info_by_name error");
}
}

return OK;
}

Expand All @@ -200,23 +199,31 @@ Error AudioDriverPulseAudio::init_output_device() {
return err;
}

switch (pa_map.channels) {
print_verbose("PulseAudio: detected " + itos(pa_map.channels) + " output channels");
pa_channels = pa_map.channels;
if (GLOBAL_GET("audio/driver/override_channels") && (pa_map.channels == 2)) {
pa_channels = GLOBAL_GET("audio/driver/override_speaker_channels");
pa_channel0 = CLAMP((int)GLOBAL_GET("audio/driver/override_channel_out"), 0, pa_channels - 2);
print_verbose("PulseAudio: forcing " + itos(pa_channels) + " output channels, but outputting to " + itos(pa_channel0) + "," + itos(pa_channel0 + 1));
}

switch (pa_channels) {
case 1: // Mono
case 3: // Surround 2.1
case 5: // Surround 5.0
case 7: // Surround 7.0
channels = pa_map.channels + 1;
channels = pa_channels + 1;
break;

case 2: // Stereo
case 4: // Surround 4.0
case 6: // Surround 5.1
case 8: // Surround 7.1
channels = pa_map.channels;
channels = pa_channels;
break;

default:
WARN_PRINT("PulseAudio: Unsupported number of output channels: " + itos(pa_map.channels));
WARN_PRINT("PulseAudio: Unsupported number of output channels: " + itos(pa_channels));
pa_channel_map_init_stereo(&pa_map);
channels = 2;
break;
Expand All @@ -226,7 +233,7 @@ Error AudioDriverPulseAudio::init_output_device() {
buffer_frames = closest_power_of_2(tmp_latency * mix_rate / 1000);
pa_buffer_size = buffer_frames * pa_map.channels;

print_verbose("PulseAudio: detected " + itos(pa_map.channels) + " output channels");
print_verbose("PulseAudio: reserving " + itos(channels) + " bus channels");
print_verbose("PulseAudio: audio buffer frames: " + itos(buffer_frames) + " calculated output latency: " + itos(buffer_frames * 1000 / mix_rate) + "ms");

pa_sample_spec spec;
Expand Down Expand Up @@ -416,11 +423,10 @@ void AudioDriverPulseAudio::thread_func(void *p_udata) {
for (unsigned int i = 0; i < ad->pa_buffer_size; i++) {
out_ptr[i] = ad->samples_in[i] >> 16;
}
} else {
} else if (ad->channels == ad->pa_map.channels + 1) {
// Uneven amount of channels
unsigned int in_idx = 0;
unsigned int out_idx = 0;

for (unsigned int i = 0; i < ad->buffer_frames; i++) {
for (int j = 0; j < ad->pa_map.channels - 1; j++) {
out_ptr[out_idx++] = ad->samples_in[in_idx++] >> 16;
Expand All @@ -429,6 +435,17 @@ void AudioDriverPulseAudio::thread_func(void *p_udata) {
uint32_t r = ad->samples_in[in_idx++] >> 16;
out_ptr[out_idx++] = (l + r) / 2;
}
} else {
// override_channels case
unsigned int in_idx = 0;
unsigned int out_idx = 0;
for (unsigned int i = 0; i < ad->buffer_frames; i++) {
in_idx += ad->pa_channel0;
for (int j = 0; j < ad->pa_map.channels; j++) {
out_ptr[out_idx++] = ad->samples_in[in_idx++] >> 16;
}
in_idx += ad->channels - ad->pa_map.channels - ad->pa_channel0;
}
}
}

Expand Down
2 changes: 2 additions & 0 deletions drivers/pulseaudio/audio_driver_pulseaudio.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ class AudioDriverPulseAudio : public AudioDriver {
pa_stream *pa_rec_str = nullptr;
pa_channel_map pa_map = {};
pa_channel_map pa_rec_map = {};
int pa_channels = 2;
int pa_channel0 = 0;

String output_device_name = "Default";
String new_output_device = "Default";
Expand Down
3 changes: 3 additions & 0 deletions servers/audio_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,9 @@ void AudioDriverManager::initialize(int p_driver) {
GLOBAL_DEF_RST("audio/driver/enable_input", false);
GLOBAL_DEF_RST(PropertyInfo(Variant::INT, "audio/driver/mix_rate", PROPERTY_HINT_RANGE, "11025,192000,1,or_greater,suffix:Hz"), DEFAULT_MIX_RATE);
GLOBAL_DEF_RST(PropertyInfo(Variant::INT, "audio/driver/mix_rate.web", PROPERTY_HINT_RANGE, "0,192000,1,or_greater,suffix:Hz"), 0); // Safer default output_latency for web (use browser default).
GLOBAL_DEF_RST("audio/driver/override_channels", false);
GLOBAL_DEF_RST(PropertyInfo(Variant::INT, "audio/driver/override_speaker_channels", PROPERTY_HINT_RANGE, "2,8,1"), 8);
GLOBAL_DEF(PropertyInfo(Variant::INT, "audio/driver/override_channel_out", PROPERTY_HINT_RANGE, "0,6,1"), 0);

int failed_driver = -1;

Expand Down