Skip to content

Commit 58df991

Browse files
committed
Expose AudioServer stream playback functions
Expose `AudioServer::start_playback_stream` Expose `AudioServer::stop_playback_stream` Move `AudioStreamPlayer::MixTarget` to `AudioServer`
1 parent a596178 commit 58df991

File tree

8 files changed

+127
-47
lines changed

8 files changed

+127
-47
lines changed

doc/classes/AudioServer.xml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,25 @@
359359
If [param active] is [code]false[/code], stops the input stream if it is running.
360360
</description>
361361
</method>
362+
<method name="start_playback_stream">
363+
<return type="void" />
364+
<param index="0" name="playback" type="AudioStreamPlayback" />
365+
<param index="1" name="bus" type="StringName" />
366+
<param index="2" name="volume_db_offset" type="float" default="0" />
367+
<param index="3" name="mix_target" type="int" enum="AudioServer.MixTarget" default="0" />
368+
<param index="4" name="start_time" type="float" default="0" />
369+
<param index="5" name="pitch_scale" type="float" default="1" />
370+
<description>
371+
Plays [param playback] on the [param bus] audio bus from beginning, or from given [param start_time] in seconds.
372+
</description>
373+
</method>
374+
<method name="stop_playback_stream">
375+
<return type="void" />
376+
<param index="0" name="playback" type="AudioStreamPlayback" />
377+
<description>
378+
Stops the [AudioStreamPlayback].
379+
</description>
380+
</method>
362381
<method name="swap_bus_effects">
363382
<return type="void" />
364383
<param index="0" name="bus_idx" type="int" />
@@ -432,5 +451,14 @@
432451
<constant name="PLAYBACK_TYPE_MAX" value="3" enum="PlaybackType" experimental="">
433452
Represents the size of the [enum PlaybackType] enum.
434453
</constant>
454+
<constant name="MIX_TARGET_STEREO" value="0" enum="MixTarget">
455+
The audio will be played only on the first channel. This is the default.
456+
</constant>
457+
<constant name="MIX_TARGET_SURROUND" value="1" enum="MixTarget">
458+
The audio will be played on all surround channels.
459+
</constant>
460+
<constant name="MIX_TARGET_CENTER" value="2" enum="MixTarget">
461+
The audio will be played on the second channel, which is usually the center.
462+
</constant>
435463
</constants>
436464
</class>

doc/classes/AudioStreamPlayer.xml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@
6969
<member name="max_polyphony" type="int" setter="set_max_polyphony" getter="get_max_polyphony" default="1">
7070
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.
7171
</member>
72-
<member name="mix_target" type="int" setter="set_mix_target" getter="get_mix_target" enum="AudioStreamPlayer.MixTarget" default="0">
72+
<member name="mix_target" type="int" setter="set_mix_target" getter="get_mix_target" enum="AudioServer.MixTarget" default="0">
7373
The mix target channels. Has no effect when two speakers or less are detected (see [enum AudioServer.SpeakerMode]).
7474
</member>
7575
<member name="pitch_scale" type="float" setter="set_pitch_scale" getter="get_pitch_scale" default="1.0">
@@ -105,13 +105,13 @@
105105
</signal>
106106
</signals>
107107
<constants>
108-
<constant name="MIX_TARGET_STEREO" value="0" enum="MixTarget">
108+
<constant name="MIX_TARGET_STEREO" value="0" enum="MixTarget" deprecated="Use [constant AudioServer.MIX_TARGET_STEREO] instead.">
109109
The audio will be played only on the first channel. This is the default.
110110
</constant>
111-
<constant name="MIX_TARGET_SURROUND" value="1" enum="MixTarget">
111+
<constant name="MIX_TARGET_SURROUND" value="1" enum="MixTarget" deprecated="Use [constant AudioServer.MIX_TARGET_SURROUND] instead.">
112112
The audio will be played on all surround channels.
113113
</constant>
114-
<constant name="MIX_TARGET_CENTER" value="2" enum="MixTarget">
114+
<constant name="MIX_TARGET_CENTER" value="2" enum="MixTarget" deprecated="Use [constant AudioServer.MIX_TARGET_CENTER] instead.">
115115
The audio will be played on the second channel, which is usually the center.
116116
</constant>
117117
</constants>
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
GH-117430
2+
---------
3+
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".
4+
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".
5+
6+
Enum moved to AudioServer. Compatibility methods registered.

scene/audio/audio_stream_player.compat.inc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,13 @@ bool AudioStreamPlayer::_is_autoplay_enabled_bind_compat_86907() {
4040

4141
void AudioStreamPlayer::_bind_compatibility_methods() {
4242
ClassDB::bind_compatibility_method(D_METHOD("is_autoplay_enabled"), &AudioStreamPlayer::_is_autoplay_enabled_bind_compat_86907);
43+
44+
ClassDB::bind_compatibility_method(D_METHOD("set_mix_target", "target"), (void (AudioStreamPlayer::*)(MixTarget))&AudioStreamPlayer::set_mix_target);
45+
ClassDB::bind_compatibility_method(D_METHOD("get_mix_target"), (MixTarget (AudioStreamPlayer::*)() const) & AudioStreamPlayer::get_mix_target);
46+
47+
BIND_ENUM_CONSTANT(MIX_TARGET_STEREO);
48+
BIND_ENUM_CONSTANT(MIX_TARGET_SURROUND);
49+
BIND_ENUM_CONSTANT(MIX_TARGET_CENTER);
4350
}
4451

4552
#endif // DISABLE_DEPRECATED

scene/audio/audio_stream_player.cpp

Lines changed: 3 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -160,11 +160,11 @@ bool AudioStreamPlayer::is_autoplay_enabled() const {
160160
return internal->autoplay;
161161
}
162162

163-
void AudioStreamPlayer::set_mix_target(MixTarget p_target) {
163+
void AudioStreamPlayer::set_mix_target(AudioServer::MixTarget p_target) {
164164
mix_target = p_target;
165165
}
166166

167-
AudioStreamPlayer::MixTarget AudioStreamPlayer::get_mix_target() const {
167+
AudioServer::MixTarget AudioStreamPlayer::get_mix_target() const {
168168
return mix_target;
169169
}
170170

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

183183
Vector<AudioFrame> AudioStreamPlayer::_get_volume_vector() {
184-
Vector<AudioFrame> volume_vector;
185-
// We need at most four stereo pairs (for 7.1 systems).
186-
volume_vector.resize(4);
187-
188-
// Initialize the volume vector to zero.
189-
for (AudioFrame &channel_volume_db : volume_vector) {
190-
channel_volume_db = AudioFrame(0, 0);
191-
}
192-
193-
float volume_linear = Math::db_to_linear(internal->volume_db);
194-
195-
// Set the volume vector up according to the speaker mode and mix target.
196-
// TODO do we need to scale the volume down when we output to more channels?
197-
if (AudioServer::get_singleton()->get_speaker_mode() == AudioServer::SPEAKER_MODE_STEREO) {
198-
volume_vector.write[0] = AudioFrame(volume_linear, volume_linear);
199-
} else {
200-
switch (mix_target) {
201-
case MIX_TARGET_STEREO: {
202-
volume_vector.write[0] = AudioFrame(volume_linear, volume_linear);
203-
} break;
204-
case MIX_TARGET_SURROUND: {
205-
// TODO Make sure this is right.
206-
volume_vector.write[0] = AudioFrame(volume_linear, volume_linear);
207-
volume_vector.write[1] = AudioFrame(volume_linear, /* LFE= */ 1.0f);
208-
volume_vector.write[2] = AudioFrame(volume_linear, volume_linear);
209-
volume_vector.write[3] = AudioFrame(volume_linear, volume_linear);
210-
} break;
211-
case MIX_TARGET_CENTER: {
212-
// TODO Make sure this is right.
213-
volume_vector.write[1] = AudioFrame(volume_linear, /* LFE= */ 1.0f);
214-
} break;
215-
}
216-
}
217-
return volume_vector;
184+
return AudioServer::get_singleton()->create_volume_vector(internal->volume_db, mix_target);
218185
}
219186

220187
void AudioStreamPlayer::_validate_property(PropertyInfo &p_property) const {
@@ -293,10 +260,6 @@ void AudioStreamPlayer::_bind_methods() {
293260
ADD_PROPERTY(PropertyInfo(Variant::INT, "playback_type", PROPERTY_HINT_ENUM, "Default,Stream,Sample"), "set_playback_type", "get_playback_type");
294261

295262
ADD_SIGNAL(MethodInfo("finished"));
296-
297-
BIND_ENUM_CONSTANT(MIX_TARGET_STEREO);
298-
BIND_ENUM_CONSTANT(MIX_TARGET_SURROUND);
299-
BIND_ENUM_CONSTANT(MIX_TARGET_CENTER);
300263
}
301264

302265
AudioStreamPlayer::AudioStreamPlayer() {

scene/audio/audio_stream_player.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,16 +42,18 @@ class AudioStreamPlayer : public Node {
4242
GDCLASS(AudioStreamPlayer, Node);
4343

4444
public:
45+
#ifndef DISABLE_DEPRECATED
4546
enum MixTarget {
4647
MIX_TARGET_STEREO,
4748
MIX_TARGET_SURROUND,
4849
MIX_TARGET_CENTER
4950
};
51+
#endif // DISABLE_DEPRECATED
5052

5153
private:
5254
AudioStreamPlayerInternal *internal = nullptr;
5355

54-
MixTarget mix_target = MIX_TARGET_STEREO;
56+
AudioServer::MixTarget mix_target = AudioServer::MIX_TARGET_STEREO;
5557

5658
void _set_playing(bool p_enable);
5759
bool _is_active() const;
@@ -100,8 +102,8 @@ class AudioStreamPlayer : public Node {
100102
void set_autoplay(bool p_enable);
101103
bool is_autoplay_enabled() const;
102104

103-
void set_mix_target(MixTarget p_target);
104-
MixTarget get_mix_target() const;
105+
void set_mix_target(AudioServer::MixTarget p_target);
106+
AudioServer::MixTarget get_mix_target() const;
105107

106108
void set_stream_paused(bool p_pause);
107109
bool get_stream_paused() const;
@@ -116,4 +118,6 @@ class AudioStreamPlayer : public Node {
116118
~AudioStreamPlayer();
117119
};
118120

121+
#ifndef DISABLE_DEPRECATED
119122
VARIANT_ENUM_CAST(AudioStreamPlayer::MixTarget)
123+
#endif // DISABLE_DEPRECATED

servers/audio/audio_server.cpp

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1319,6 +1319,61 @@ void AudioServer::stop_playback_stream(Ref<AudioStreamPlayback> p_playback) {
13191319
} while (!playback_node->state.compare_exchange_strong(old_state, new_state));
13201320
}
13211321

1322+
Vector<AudioFrame> AudioServer::create_volume_vector(float p_volume_db, MixTarget p_mix_target) const {
1323+
Vector<AudioFrame> volume_vector;
1324+
// We need at most four stereo pairs (for 7.1 systems).
1325+
volume_vector.resize(4);
1326+
1327+
// Initialize the volume vector to zero.
1328+
for (AudioFrame &channel_volume_db : volume_vector) {
1329+
channel_volume_db = AudioFrame(0, 0);
1330+
}
1331+
1332+
float volume_linear = Math::db_to_linear(p_volume_db);
1333+
1334+
// Set the volume vector up according to the speaker mode and mix target.
1335+
// TODO do we need to scale the volume down when we output to more channels?
1336+
if (get_speaker_mode() == AudioServer::SPEAKER_MODE_STEREO) {
1337+
volume_vector.write[0] = AudioFrame(volume_linear, volume_linear);
1338+
} else {
1339+
switch (p_mix_target) {
1340+
case MIX_TARGET_STEREO: {
1341+
volume_vector.write[0] = AudioFrame(volume_linear, volume_linear);
1342+
} break;
1343+
case MIX_TARGET_SURROUND: {
1344+
// TODO Make sure this is right.
1345+
volume_vector.write[0] = AudioFrame(volume_linear, volume_linear);
1346+
volume_vector.write[1] = AudioFrame(volume_linear, /* LFE= */ 1.0f);
1347+
volume_vector.write[2] = AudioFrame(volume_linear, volume_linear);
1348+
volume_vector.write[3] = AudioFrame(volume_linear, volume_linear);
1349+
} break;
1350+
case MIX_TARGET_CENTER: {
1351+
// TODO Make sure this is right.
1352+
volume_vector.write[1] = AudioFrame(volume_linear, /* LFE= */ 1.0f);
1353+
} break;
1354+
}
1355+
}
1356+
1357+
return volume_vector;
1358+
}
1359+
1360+
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) {
1361+
ERR_FAIL_COND(p_playback.is_null());
1362+
1363+
Vector<AudioFrame> volume_vector = create_volume_vector(p_volume_db_offset, p_mix_target);
1364+
start_playback_stream(p_playback, p_bus, volume_vector, p_start_time, p_pitch_scale);
1365+
1366+
// Sample handling.
1367+
if (p_playback->get_is_sample() && p_playback->get_sample_playback().is_valid()) {
1368+
Ref<AudioSamplePlayback> sample_playback = p_playback->get_sample_playback();
1369+
sample_playback->offset = p_start_time;
1370+
sample_playback->bus = p_bus;
1371+
sample_playback->volume_vector = volume_vector;
1372+
sample_playback->pitch_scale = p_pitch_scale;
1373+
start_sample_playback(sample_playback);
1374+
}
1375+
}
1376+
13221377
void AudioServer::set_playback_bus_exclusive(Ref<AudioStreamPlayback> p_playback, const StringName &p_bus, Vector<AudioFrame> p_volumes) {
13231378
ERR_FAIL_COND(p_volumes.size() != MAX_CHANNELS_PER_BUS);
13241379

@@ -2113,6 +2168,9 @@ void AudioServer::_bind_methods() {
21132168
ClassDB::bind_method(D_METHOD("is_stream_registered_as_sample", "stream"), &AudioServer::is_stream_registered_as_sample);
21142169
ClassDB::bind_method(D_METHOD("register_stream_as_sample", "stream"), &AudioServer::register_stream_as_sample);
21152170

2171+
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));
2172+
ClassDB::bind_method(D_METHOD("stop_playback_stream", "playback"), &AudioServer::stop_playback_stream);
2173+
21162174
ADD_PROPERTY(PropertyInfo(Variant::INT, "bus_count"), "set_bus_count", "get_bus_count");
21172175
ADD_PROPERTY(PropertyInfo(Variant::STRING, "output_device"), "set_output_device", "get_output_device");
21182176
ADD_PROPERTY(PropertyInfo(Variant::STRING, "input_device"), "set_input_device", "get_input_device");
@@ -2133,6 +2191,10 @@ void AudioServer::_bind_methods() {
21332191
BIND_ENUM_CONSTANT(PLAYBACK_TYPE_STREAM);
21342192
BIND_ENUM_CONSTANT(PLAYBACK_TYPE_SAMPLE);
21352193
BIND_ENUM_CONSTANT(PLAYBACK_TYPE_MAX);
2194+
2195+
BIND_ENUM_CONSTANT(MIX_TARGET_STEREO);
2196+
BIND_ENUM_CONSTANT(MIX_TARGET_SURROUND);
2197+
BIND_ENUM_CONSTANT(MIX_TARGET_CENTER);
21362198
}
21372199

21382200
AudioServer::AudioServer() {

servers/audio/audio_server.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,12 @@ class AudioServer : public Object {
196196
PLAYBACK_TYPE_MAX
197197
};
198198

199+
enum MixTarget {
200+
MIX_TARGET_STEREO,
201+
MIX_TARGET_SURROUND,
202+
MIX_TARGET_CENTER
203+
};
204+
199205
enum {
200206
AUDIO_DATA_INVALID_ID = -1,
201207
MAX_CHANNELS_PER_BUS = 4,
@@ -436,6 +442,9 @@ class AudioServer : public Object {
436442
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);
437443
void stop_playback_stream(Ref<AudioStreamPlayback> p_playback);
438444

445+
Vector<AudioFrame> create_volume_vector(float p_volume_db, MixTarget p_mix_target) const;
446+
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);
447+
439448
void set_playback_bus_exclusive(Ref<AudioStreamPlayback> p_playback, const StringName &p_bus, Vector<AudioFrame> p_volumes);
440449
void set_playback_bus_volumes_linear(Ref<AudioStreamPlayback> p_playback, const HashMap<StringName, Vector<AudioFrame>> &p_bus_volumes);
441450
void set_playback_all_bus_volumes_linear(Ref<AudioStreamPlayback> p_playback, Vector<AudioFrame> p_volumes);
@@ -526,6 +535,7 @@ class AudioServer : public Object {
526535

527536
VARIANT_ENUM_CAST(AudioServer::SpeakerMode)
528537
VARIANT_ENUM_CAST(AudioServer::PlaybackType)
538+
VARIANT_ENUM_CAST(AudioServer::MixTarget)
529539

530540
class AudioBusLayout : public Resource {
531541
GDCLASS(AudioBusLayout, Resource);

0 commit comments

Comments
 (0)