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
28 changes: 28 additions & 0 deletions doc/classes/AudioServer.xml
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,25 @@
If [param active] is [code]false[/code], stops the input stream if it is running.
</description>
</method>
<method name="start_playback_stream">
<return type="void" />
<param index="0" name="playback" type="AudioStreamPlayback" />
<param index="1" name="bus" type="StringName" />
<param index="2" name="volume_db_offset" type="float" default="0" />
<param index="3" name="mix_target" type="int" enum="AudioServer.MixTarget" default="0" />
<param index="4" name="start_time" type="float" default="0" />
<param index="5" name="pitch_scale" type="float" default="1" />
<description>
Plays [param playback] on the [param bus] audio bus from beginning, or from given [param start_time] in seconds.
</description>
</method>
<method name="stop_playback_stream">
<return type="void" />
<param index="0" name="playback" type="AudioStreamPlayback" />
<description>
Stops the [AudioStreamPlayback].
</description>
</method>
<method name="swap_bus_effects">
<return type="void" />
<param index="0" name="bus_idx" type="int" />
Expand Down Expand Up @@ -432,5 +451,14 @@
<constant name="PLAYBACK_TYPE_MAX" value="3" enum="PlaybackType" experimental="">
Represents the size of the [enum PlaybackType] enum.
</constant>
<constant name="MIX_TARGET_STEREO" value="0" enum="MixTarget">
The audio will be played only on the first channel. This is the default.
</constant>
<constant name="MIX_TARGET_SURROUND" value="1" enum="MixTarget">
The audio will be played on all surround channels.
</constant>
<constant name="MIX_TARGET_CENTER" value="2" enum="MixTarget">
The audio will be played on the second channel, which is usually the center.
</constant>
</constants>
</class>
8 changes: 4 additions & 4 deletions doc/classes/AudioStreamPlayer.xml
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
<member name="max_polyphony" type="int" setter="set_max_polyphony" getter="get_max_polyphony" default="1">
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.
</member>
<member name="mix_target" type="int" setter="set_mix_target" getter="get_mix_target" enum="AudioStreamPlayer.MixTarget" default="0">
<member name="mix_target" type="int" setter="set_mix_target" getter="get_mix_target" enum="AudioServer.MixTarget" default="0">
The mix target channels. Has no effect when two speakers or less are detected (see [enum AudioServer.SpeakerMode]).
</member>
<member name="pitch_scale" type="float" setter="set_pitch_scale" getter="get_pitch_scale" default="1.0">
Expand Down Expand Up @@ -105,13 +105,13 @@
</signal>
</signals>
<constants>
<constant name="MIX_TARGET_STEREO" value="0" enum="MixTarget">
<constant name="MIX_TARGET_STEREO" value="0" enum="MixTarget" deprecated="Use [constant AudioServer.MIX_TARGET_STEREO] instead.">
The audio will be played only on the first channel. This is the default.
</constant>
<constant name="MIX_TARGET_SURROUND" value="1" enum="MixTarget">
<constant name="MIX_TARGET_SURROUND" value="1" enum="MixTarget" deprecated="Use [constant AudioServer.MIX_TARGET_SURROUND] instead.">
The audio will be played on all surround channels.
</constant>
<constant name="MIX_TARGET_CENTER" value="2" enum="MixTarget">
<constant name="MIX_TARGET_CENTER" value="2" enum="MixTarget" deprecated="Use [constant AudioServer.MIX_TARGET_CENTER] instead.">
The audio will be played on the second channel, which is usually the center.
</constant>
</constants>
Expand Down
6 changes: 6 additions & 0 deletions misc/extension_api_validation/4.6-stable/GH-#117430.txt
Original file line number Diff line number Diff line change
@@ -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.
7 changes: 7 additions & 0 deletions scene/audio/audio_stream_player.compat.inc
Original file line number Diff line number Diff line change
Expand Up @@ -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
43 changes: 3 additions & 40 deletions scene/audio/audio_stream_player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand All @@ -181,40 +181,7 @@ bool AudioStreamPlayer::get_stream_paused() const {
}

Vector<AudioFrame> AudioStreamPlayer::_get_volume_vector() {
Vector<AudioFrame> 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 {
Expand Down Expand Up @@ -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() {
Expand Down
10 changes: 7 additions & 3 deletions scene/audio/audio_stream_player.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -116,4 +118,6 @@ class AudioStreamPlayer : public Node {
~AudioStreamPlayer();
};

#ifndef DISABLE_DEPRECATED
VARIANT_ENUM_CAST(AudioStreamPlayer::MixTarget)
#endif // DISABLE_DEPRECATED
62 changes: 62 additions & 0 deletions servers/audio/audio_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1319,6 +1319,61 @@ void AudioServer::stop_playback_stream(Ref<AudioStreamPlayback> p_playback) {
} while (!playback_node->state.compare_exchange_strong(old_state, new_state));
}

Vector<AudioFrame> AudioServer::create_volume_vector(float p_volume_db, MixTarget p_mix_target) const {
Vector<AudioFrame> 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<AudioStreamPlayback> 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<AudioFrame> 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<AudioSamplePlayback> 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<AudioStreamPlayback> p_playback, const StringName &p_bus, Vector<AudioFrame> p_volumes) {
ERR_FAIL_COND(p_volumes.size() != MAX_CHANNELS_PER_BUS);

Expand Down Expand Up @@ -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");
Expand All @@ -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() {
Expand Down
10 changes: 10 additions & 0 deletions servers/audio/audio_server.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -436,6 +442,9 @@ class AudioServer : public Object {
void start_playback_stream(Ref<AudioStreamPlayback> p_playback, const HashMap<StringName, Vector<AudioFrame>> &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<AudioStreamPlayback> p_playback);

Vector<AudioFrame> create_volume_vector(float p_volume_db, MixTarget p_mix_target) const;
void _start_playback_stream(Ref<AudioStreamPlayback> 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<AudioStreamPlayback> p_playback, const StringName &p_bus, Vector<AudioFrame> p_volumes);
void set_playback_bus_volumes_linear(Ref<AudioStreamPlayback> p_playback, const HashMap<StringName, Vector<AudioFrame>> &p_bus_volumes);
void set_playback_all_bus_volumes_linear(Ref<AudioStreamPlayback> p_playback, Vector<AudioFrame> p_volumes);
Expand Down Expand Up @@ -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);
Expand Down
Loading