diff --git a/doc/classes/AudioServer.xml b/doc/classes/AudioServer.xml
index bf6cd1ee08d9..39500fe1d827 100644
--- a/doc/classes/AudioServer.xml
+++ b/doc/classes/AudioServer.xml
@@ -359,6 +359,25 @@
If [param active] is [code]false[/code], stops the input stream if it is running.
+
+
+
+
+
+
+
+
+
+ Plays [param playback] on the [param bus] audio bus from beginning, or from given [param start_time] in seconds.
+
+
+
+
+
+
+ Stops the [AudioStreamPlayback].
+
+
@@ -432,5 +451,14 @@
Represents the size of the [enum PlaybackType] enum.
+
+ The audio will be played only on the first channel. This is the default.
+
+
+ The audio will be played on all surround channels.
+
+
+ The audio will be played on the second channel, which is usually the center.
+
diff --git a/doc/classes/AudioStreamPlayer.xml b/doc/classes/AudioStreamPlayer.xml
index dae089ea9f10..fe63720f1535 100644
--- a/doc/classes/AudioStreamPlayer.xml
+++ b/doc/classes/AudioStreamPlayer.xml
@@ -69,7 +69,7 @@
The maximum number of sounds this node can play at the same time. Calling [method play] after this value is reached will cut off the oldest sounds.
-
+
The mix target channels. Has no effect when two speakers or less are detected (see [enum AudioServer.SpeakerMode]).
@@ -105,13 +105,13 @@
-
+
The audio will be played only on the first channel. This is the default.
-
+
The audio will be played on all surround channels.
-
+
The audio will be played on the second channel, which is usually the center.
diff --git a/misc/extension_api_validation/4.6-stable/GH-#117430.txt b/misc/extension_api_validation/4.6-stable/GH-#117430.txt
new file mode 100644
index 000000000000..99ae85675f14
--- /dev/null
+++ b/misc/extension_api_validation/4.6-stable/GH-#117430.txt
@@ -0,0 +1,6 @@
+GH-117430
+---------
+Validate extension JSON: Error: Field 'classes/AudioStreamPlayer/methods/get_mix_target/return_value': type changed value in new API, from "enum::AudioStreamPlayer.MixTarget" to "enum::AudioServer.MixTarget".
+Validate extension JSON: Error: Field 'classes/AudioStreamPlayer/methods/set_mix_target/arguments/0': type changed value in new API, from "enum::AudioStreamPlayer.MixTarget" to "enum::AudioServer.MixTarget".
+
+Enum moved to AudioServer. Compatibility methods registered.
diff --git a/scene/audio/audio_stream_player.compat.inc b/scene/audio/audio_stream_player.compat.inc
index e16cd1a49786..2c4ff5468be5 100644
--- a/scene/audio/audio_stream_player.compat.inc
+++ b/scene/audio/audio_stream_player.compat.inc
@@ -40,6 +40,13 @@ bool AudioStreamPlayer::_is_autoplay_enabled_bind_compat_86907() {
void AudioStreamPlayer::_bind_compatibility_methods() {
ClassDB::bind_compatibility_method(D_METHOD("is_autoplay_enabled"), &AudioStreamPlayer::_is_autoplay_enabled_bind_compat_86907);
+
+ ClassDB::bind_compatibility_method(D_METHOD("set_mix_target", "target"), (void (AudioStreamPlayer::*)(MixTarget))&AudioStreamPlayer::set_mix_target);
+ ClassDB::bind_compatibility_method(D_METHOD("get_mix_target"), (MixTarget (AudioStreamPlayer::*)() const) & AudioStreamPlayer::get_mix_target);
+
+ BIND_ENUM_CONSTANT(MIX_TARGET_STEREO);
+ BIND_ENUM_CONSTANT(MIX_TARGET_SURROUND);
+ BIND_ENUM_CONSTANT(MIX_TARGET_CENTER);
}
#endif // DISABLE_DEPRECATED
diff --git a/scene/audio/audio_stream_player.cpp b/scene/audio/audio_stream_player.cpp
index 1eaa80718ec9..1148c5b3c9cc 100644
--- a/scene/audio/audio_stream_player.cpp
+++ b/scene/audio/audio_stream_player.cpp
@@ -160,11 +160,11 @@ bool AudioStreamPlayer::is_autoplay_enabled() const {
return internal->autoplay;
}
-void AudioStreamPlayer::set_mix_target(MixTarget p_target) {
+void AudioStreamPlayer::set_mix_target(AudioServer::MixTarget p_target) {
mix_target = p_target;
}
-AudioStreamPlayer::MixTarget AudioStreamPlayer::get_mix_target() const {
+AudioServer::MixTarget AudioStreamPlayer::get_mix_target() const {
return mix_target;
}
@@ -181,40 +181,7 @@ bool AudioStreamPlayer::get_stream_paused() const {
}
Vector AudioStreamPlayer::_get_volume_vector() {
- Vector volume_vector;
- // We need at most four stereo pairs (for 7.1 systems).
- volume_vector.resize(4);
-
- // Initialize the volume vector to zero.
- for (AudioFrame &channel_volume_db : volume_vector) {
- channel_volume_db = AudioFrame(0, 0);
- }
-
- float volume_linear = Math::db_to_linear(internal->volume_db);
-
- // Set the volume vector up according to the speaker mode and mix target.
- // TODO do we need to scale the volume down when we output to more channels?
- if (AudioServer::get_singleton()->get_speaker_mode() == AudioServer::SPEAKER_MODE_STEREO) {
- volume_vector.write[0] = AudioFrame(volume_linear, volume_linear);
- } else {
- switch (mix_target) {
- case MIX_TARGET_STEREO: {
- volume_vector.write[0] = AudioFrame(volume_linear, volume_linear);
- } break;
- case MIX_TARGET_SURROUND: {
- // TODO Make sure this is right.
- volume_vector.write[0] = AudioFrame(volume_linear, volume_linear);
- volume_vector.write[1] = AudioFrame(volume_linear, /* LFE= */ 1.0f);
- volume_vector.write[2] = AudioFrame(volume_linear, volume_linear);
- volume_vector.write[3] = AudioFrame(volume_linear, volume_linear);
- } break;
- case MIX_TARGET_CENTER: {
- // TODO Make sure this is right.
- volume_vector.write[1] = AudioFrame(volume_linear, /* LFE= */ 1.0f);
- } break;
- }
- }
- return volume_vector;
+ return AudioServer::get_singleton()->create_volume_vector(internal->volume_db, mix_target);
}
void AudioStreamPlayer::_validate_property(PropertyInfo &p_property) const {
@@ -293,10 +260,6 @@ void AudioStreamPlayer::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "playback_type", PROPERTY_HINT_ENUM, "Default,Stream,Sample"), "set_playback_type", "get_playback_type");
ADD_SIGNAL(MethodInfo("finished"));
-
- BIND_ENUM_CONSTANT(MIX_TARGET_STEREO);
- BIND_ENUM_CONSTANT(MIX_TARGET_SURROUND);
- BIND_ENUM_CONSTANT(MIX_TARGET_CENTER);
}
AudioStreamPlayer::AudioStreamPlayer() {
diff --git a/scene/audio/audio_stream_player.h b/scene/audio/audio_stream_player.h
index abaed688d1e4..a6c49a359081 100644
--- a/scene/audio/audio_stream_player.h
+++ b/scene/audio/audio_stream_player.h
@@ -42,16 +42,18 @@ class AudioStreamPlayer : public Node {
GDCLASS(AudioStreamPlayer, Node);
public:
+#ifndef DISABLE_DEPRECATED
enum MixTarget {
MIX_TARGET_STEREO,
MIX_TARGET_SURROUND,
MIX_TARGET_CENTER
};
+#endif // DISABLE_DEPRECATED
private:
AudioStreamPlayerInternal *internal = nullptr;
- MixTarget mix_target = MIX_TARGET_STEREO;
+ AudioServer::MixTarget mix_target = AudioServer::MIX_TARGET_STEREO;
void _set_playing(bool p_enable);
bool _is_active() const;
@@ -100,8 +102,8 @@ class AudioStreamPlayer : public Node {
void set_autoplay(bool p_enable);
bool is_autoplay_enabled() const;
- void set_mix_target(MixTarget p_target);
- MixTarget get_mix_target() const;
+ void set_mix_target(AudioServer::MixTarget p_target);
+ AudioServer::MixTarget get_mix_target() const;
void set_stream_paused(bool p_pause);
bool get_stream_paused() const;
@@ -116,4 +118,6 @@ class AudioStreamPlayer : public Node {
~AudioStreamPlayer();
};
+#ifndef DISABLE_DEPRECATED
VARIANT_ENUM_CAST(AudioStreamPlayer::MixTarget)
+#endif // DISABLE_DEPRECATED
diff --git a/servers/audio/audio_server.cpp b/servers/audio/audio_server.cpp
index 98bb2cebd942..893a97b059fe 100644
--- a/servers/audio/audio_server.cpp
+++ b/servers/audio/audio_server.cpp
@@ -1319,6 +1319,61 @@ void AudioServer::stop_playback_stream(Ref p_playback) {
} while (!playback_node->state.compare_exchange_strong(old_state, new_state));
}
+Vector AudioServer::create_volume_vector(float p_volume_db, MixTarget p_mix_target) const {
+ Vector volume_vector;
+ // We need at most four stereo pairs (for 7.1 systems).
+ volume_vector.resize(4);
+
+ // Initialize the volume vector to zero.
+ for (AudioFrame &channel_volume_db : volume_vector) {
+ channel_volume_db = AudioFrame(0, 0);
+ }
+
+ float volume_linear = Math::db_to_linear(p_volume_db);
+
+ // Set the volume vector up according to the speaker mode and mix target.
+ // TODO do we need to scale the volume down when we output to more channels?
+ if (get_speaker_mode() == AudioServer::SPEAKER_MODE_STEREO) {
+ volume_vector.write[0] = AudioFrame(volume_linear, volume_linear);
+ } else {
+ switch (p_mix_target) {
+ case MIX_TARGET_STEREO: {
+ volume_vector.write[0] = AudioFrame(volume_linear, volume_linear);
+ } break;
+ case MIX_TARGET_SURROUND: {
+ // TODO Make sure this is right.
+ volume_vector.write[0] = AudioFrame(volume_linear, volume_linear);
+ volume_vector.write[1] = AudioFrame(volume_linear, /* LFE= */ 1.0f);
+ volume_vector.write[2] = AudioFrame(volume_linear, volume_linear);
+ volume_vector.write[3] = AudioFrame(volume_linear, volume_linear);
+ } break;
+ case MIX_TARGET_CENTER: {
+ // TODO Make sure this is right.
+ volume_vector.write[1] = AudioFrame(volume_linear, /* LFE= */ 1.0f);
+ } break;
+ }
+ }
+
+ return volume_vector;
+}
+
+void AudioServer::_start_playback_stream(Ref p_playback, const StringName &p_bus, float p_volume_db_offset, MixTarget p_mix_target, float p_start_time, float p_pitch_scale) {
+ ERR_FAIL_COND(p_playback.is_null());
+
+ Vector volume_vector = create_volume_vector(p_volume_db_offset, p_mix_target);
+ start_playback_stream(p_playback, p_bus, volume_vector, p_start_time, p_pitch_scale);
+
+ // Sample handling.
+ if (p_playback->get_is_sample() && p_playback->get_sample_playback().is_valid()) {
+ Ref sample_playback = p_playback->get_sample_playback();
+ sample_playback->offset = p_start_time;
+ sample_playback->bus = p_bus;
+ sample_playback->volume_vector = volume_vector;
+ sample_playback->pitch_scale = p_pitch_scale;
+ start_sample_playback(sample_playback);
+ }
+}
+
void AudioServer::set_playback_bus_exclusive(Ref p_playback, const StringName &p_bus, Vector p_volumes) {
ERR_FAIL_COND(p_volumes.size() != MAX_CHANNELS_PER_BUS);
@@ -2113,6 +2168,9 @@ void AudioServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_stream_registered_as_sample", "stream"), &AudioServer::is_stream_registered_as_sample);
ClassDB::bind_method(D_METHOD("register_stream_as_sample", "stream"), &AudioServer::register_stream_as_sample);
+ ClassDB::bind_method(D_METHOD("start_playback_stream", "playback", "bus", "volume_db_offset", "mix_target", "start_time", "pitch_scale"), &AudioServer::_start_playback_stream, DEFVAL(0), DEFVAL(MIX_TARGET_STEREO), DEFVAL(0), DEFVAL(1));
+ ClassDB::bind_method(D_METHOD("stop_playback_stream", "playback"), &AudioServer::stop_playback_stream);
+
ADD_PROPERTY(PropertyInfo(Variant::INT, "bus_count"), "set_bus_count", "get_bus_count");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "output_device"), "set_output_device", "get_output_device");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "input_device"), "set_input_device", "get_input_device");
@@ -2133,6 +2191,10 @@ void AudioServer::_bind_methods() {
BIND_ENUM_CONSTANT(PLAYBACK_TYPE_STREAM);
BIND_ENUM_CONSTANT(PLAYBACK_TYPE_SAMPLE);
BIND_ENUM_CONSTANT(PLAYBACK_TYPE_MAX);
+
+ BIND_ENUM_CONSTANT(MIX_TARGET_STEREO);
+ BIND_ENUM_CONSTANT(MIX_TARGET_SURROUND);
+ BIND_ENUM_CONSTANT(MIX_TARGET_CENTER);
}
AudioServer::AudioServer() {
diff --git a/servers/audio/audio_server.h b/servers/audio/audio_server.h
index 104b162f2806..e89aeddd6c7f 100644
--- a/servers/audio/audio_server.h
+++ b/servers/audio/audio_server.h
@@ -196,6 +196,12 @@ class AudioServer : public Object {
PLAYBACK_TYPE_MAX
};
+ enum MixTarget {
+ MIX_TARGET_STEREO,
+ MIX_TARGET_SURROUND,
+ MIX_TARGET_CENTER
+ };
+
enum {
AUDIO_DATA_INVALID_ID = -1,
MAX_CHANNELS_PER_BUS = 4,
@@ -436,6 +442,9 @@ class AudioServer : public Object {
void start_playback_stream(Ref p_playback, const HashMap> &p_bus_volumes, float p_start_time = 0, float p_pitch_scale = 1, float p_highshelf_gain = 0, float p_attenuation_cutoff_hz = 0);
void stop_playback_stream(Ref p_playback);
+ Vector create_volume_vector(float p_volume_db, MixTarget p_mix_target) const;
+ void _start_playback_stream(Ref p_playback, const StringName &p_bus, float p_volume_db_offset = 0, MixTarget p_mix_target = MIX_TARGET_STEREO, float p_start_time = 0, float p_pitch_scale = 1);
+
void set_playback_bus_exclusive(Ref p_playback, const StringName &p_bus, Vector p_volumes);
void set_playback_bus_volumes_linear(Ref p_playback, const HashMap> &p_bus_volumes);
void set_playback_all_bus_volumes_linear(Ref p_playback, Vector p_volumes);
@@ -526,6 +535,7 @@ class AudioServer : public Object {
VARIANT_ENUM_CAST(AudioServer::SpeakerMode)
VARIANT_ENUM_CAST(AudioServer::PlaybackType)
+VARIANT_ENUM_CAST(AudioServer::MixTarget)
class AudioBusLayout : public Resource {
GDCLASS(AudioBusLayout, Resource);