Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement audio stream playback parameters. #86473

Merged
merged 1 commit into from
Jan 16, 2024
Merged
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
13 changes: 13 additions & 0 deletions doc/classes/AudioStream.xml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@
<description>
</description>
</method>
<method name="_get_parameter_list" qualifiers="virtual const">
<return type="Dictionary[]" />
<description>
Return the controllable parameters of this stream. This array contains dictionaries with a property info description format (see [method Object.get_property_list]). Additionally, the default value for this parameter must be added tho each dictionary in "default_value" field.
</description>
</method>
<method name="_get_stream_name" qualifiers="virtual const">
<return type="String" />
<description>
Expand Down Expand Up @@ -62,4 +68,11 @@
</description>
</method>
</methods>
<signals>
<signal name="parameter_list_changed">
<description>
Signal to be emitted to notify when the parameter list changed.
</description>
</signal>
</signals>
</class>
15 changes: 15 additions & 0 deletions doc/classes/AudioStreamPlayback.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,13 @@
<description>
</description>
</method>
<method name="_get_parameter" qualifiers="virtual const">
<return type="Variant" />
<param index="0" name="name" type="StringName" />
<description>
Return the current value of a playback parameter by name (see [method AudioStream._get_parameter_list]).
</description>
</method>
<method name="_get_playback_position" qualifiers="virtual const">
<return type="float" />
<description>
Expand All @@ -39,6 +46,14 @@
<description>
</description>
</method>
<method name="_set_parameter" qualifiers="virtual">
<return type="void" />
<param index="0" name="name" type="StringName" />
<param index="1" name="value" type="Variant" />
<description>
Set the current value of a playback parameter by name (see [method AudioStream._get_parameter_list]).
</description>
</method>
<method name="_start" qualifiers="virtual">
<return type="void" />
<param index="0" name="from_pos" type="float" />
Expand Down
29 changes: 27 additions & 2 deletions modules/minimp3/audio_stream_mp3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,9 @@ int AudioStreamPlaybackMP3::_mix_internal(AudioFrame *p_buffer, int p_frames) {
int frames_mixed_this_step = p_frames;

int beat_length_frames = -1;
bool beat_loop = mp3_stream->has_loop() && mp3_stream->get_bpm() > 0 && mp3_stream->get_beat_count() > 0;
bool use_loop = looping_override ? looping : mp3_stream->loop;
adamscott marked this conversation as resolved.
Show resolved Hide resolved

bool beat_loop = use_loop && mp3_stream->get_bpm() > 0 && mp3_stream->get_beat_count() > 0;
if (beat_loop) {
beat_length_frames = mp3_stream->get_beat_count() * mp3_stream->sample_rate * 60 / mp3_stream->get_bpm();
}
Expand Down Expand Up @@ -82,7 +84,7 @@ int AudioStreamPlaybackMP3::_mix_internal(AudioFrame *p_buffer, int p_frames) {

else {
//EOF
if (mp3_stream->loop) {
if (use_loop) {
seek(mp3_stream->loop_offset);
loops++;
} else {
Expand Down Expand Up @@ -143,6 +145,25 @@ void AudioStreamPlaybackMP3::tag_used_streams() {
mp3_stream->tag_used(get_playback_position());
}

void AudioStreamPlaybackMP3::set_parameter(const StringName &p_name, const Variant &p_value) {
if (p_name == SNAME("looping")) {
if (p_value == Variant()) {
looping_override = false;
looping = false;
} else {
looping_override = true;
looping = p_value;
}
}
}

Variant AudioStreamPlaybackMP3::get_parameter(const StringName &p_name) const {
reduz marked this conversation as resolved.
Show resolved Hide resolved
if (looping_override && p_name == SNAME("looping")) {
return looping;
}
return Variant();
}

Copy link
Contributor

@MJacred MJacred Jan 14, 2024

Choose a reason for hiding this comment

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

In line 191, add this

mp3s->looping = loop;

to inherit looping setting from stream and to have the same logic as ogg vorbis.

Copy link
Member Author

Choose a reason for hiding this comment

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

ah that line should actually be removed instead, since its ignored.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah, I get it. If the overwrite is deactivated, the inspector can't read looping and the audio player mustn't read it.

AudioStreamPlaybackMP3::~AudioStreamPlaybackMP3() {
if (mp3d) {
mp3dec_ex_close(mp3d);
Expand Down Expand Up @@ -232,6 +253,10 @@ bool AudioStreamMP3::is_monophonic() const {
return false;
}

void AudioStreamMP3::get_parameter_list(List<Parameter> *r_parameters) {
r_parameters->push_back(Parameter(PropertyInfo(Variant::BOOL, "looping", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_CHECKABLE), Variant()));
reduz marked this conversation as resolved.
Show resolved Hide resolved
}

void AudioStreamMP3::set_bpm(double p_bpm) {
ERR_FAIL_COND(p_bpm < 0);
bpm = p_bpm;
Expand Down
7 changes: 7 additions & 0 deletions modules/minimp3/audio_stream_mp3.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ class AudioStreamPlaybackMP3 : public AudioStreamPlaybackResampled {
AudioFrame loop_fade[FADE_SIZE];
int loop_fade_remaining = FADE_SIZE;

bool looping_override = false;
bool looping = false;
KoBeWi marked this conversation as resolved.
Show resolved Hide resolved
mp3dec_ex_t *mp3d = nullptr;
uint32_t frames_mixed = 0;
bool active = false;
Expand All @@ -72,6 +74,9 @@ class AudioStreamPlaybackMP3 : public AudioStreamPlaybackResampled {

virtual void tag_used_streams() override;

virtual void set_parameter(const StringName &p_name, const Variant &p_value) override;
virtual Variant get_parameter(const StringName &p_name) const override;

AudioStreamPlaybackMP3() {}
~AudioStreamPlaybackMP3();
};
Expand Down Expand Up @@ -126,6 +131,8 @@ class AudioStreamMP3 : public AudioStream {

virtual bool is_monophonic() const override;

virtual void get_parameter_list(List<Parameter> *r_parameters) override;

AudioStreamMP3();
virtual ~AudioStreamMP3();
};
Expand Down
32 changes: 28 additions & 4 deletions modules/vorbis/audio_stream_ogg_vorbis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,9 @@ int AudioStreamPlaybackOggVorbis::_mix_internal(AudioFrame *p_buffer, int p_fram
int todo = p_frames;

int beat_length_frames = -1;
bool beat_loop = vorbis_stream->has_loop();
if (beat_loop && vorbis_stream->get_bpm() > 0 && vorbis_stream->get_beat_count() > 0) {
bool use_loop = looping_override ? looping : vorbis_stream->loop;

if (use_loop && vorbis_stream->get_bpm() > 0 && vorbis_stream->get_beat_count() > 0) {
beat_length_frames = vorbis_stream->get_beat_count() * vorbis_data->get_sampling_rate() * 60 / vorbis_stream->get_bpm();
}

Expand Down Expand Up @@ -99,7 +100,7 @@ int AudioStreamPlaybackOggVorbis::_mix_internal(AudioFrame *p_buffer, int p_fram
} else
**/

if (beat_loop && beat_length_frames <= (int)frames_mixed) {
if (use_loop && beat_length_frames <= (int)frames_mixed) {
// End of file when doing beat-based looping. <= used instead of == because importer editing
if (!have_packets_left && !have_samples_left) {
//Nothing remaining, so do nothing.
Expand All @@ -125,7 +126,7 @@ int AudioStreamPlaybackOggVorbis::_mix_internal(AudioFrame *p_buffer, int p_fram
if (!have_packets_left && !have_samples_left) {
// Actual end of file!
bool is_not_empty = mixed > 0 || vorbis_stream->get_length() > 0;
if (vorbis_stream->loop && is_not_empty) {
if (use_loop && is_not_empty) {
//loop

seek(vorbis_stream->loop_offset);
Expand Down Expand Up @@ -257,6 +258,25 @@ void AudioStreamPlaybackOggVorbis::tag_used_streams() {
vorbis_stream->tag_used(get_playback_position());
}

void AudioStreamPlaybackOggVorbis::set_parameter(const StringName &p_name, const Variant &p_value) {
if (p_name == SNAME("looping")) {
if (p_value == Variant()) {
looping_override = false;
looping = false;
} else {
looping_override = true;
looping = p_value;
}
}
}

Variant AudioStreamPlaybackOggVorbis::get_parameter(const StringName &p_name) const {
if (looping_override && p_name == SNAME("looping")) {
return looping;
}
return Variant();
}

void AudioStreamPlaybackOggVorbis::seek(double p_time) {
ERR_FAIL_COND(!ready);
ERR_FAIL_COND(vorbis_stream.is_null());
Expand Down Expand Up @@ -493,6 +513,10 @@ bool AudioStreamOggVorbis::is_monophonic() const {
return false;
}

void AudioStreamOggVorbis::get_parameter_list(List<Parameter> *r_parameters) {
r_parameters->push_back(Parameter(PropertyInfo(Variant::BOOL, "looping", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_CHECKABLE), Variant()));
}

void AudioStreamOggVorbis::_bind_methods() {
ClassDB::bind_static_method("AudioStreamOggVorbis", D_METHOD("load_from_buffer", "buffer"), &AudioStreamOggVorbis::load_from_buffer);
ClassDB::bind_static_method("AudioStreamOggVorbis", D_METHOD("load_from_file", "path"), &AudioStreamOggVorbis::load_from_file);
Expand Down
7 changes: 7 additions & 0 deletions modules/vorbis/audio_stream_ogg_vorbis.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ class AudioStreamPlaybackOggVorbis : public AudioStreamPlaybackResampled {

uint32_t frames_mixed = 0;
bool active = false;
bool looping_override = false;
bool looping = false;
int loops = 0;

enum {
Expand Down Expand Up @@ -95,6 +97,9 @@ class AudioStreamPlaybackOggVorbis : public AudioStreamPlaybackResampled {

virtual void tag_used_streams() override;

virtual void set_parameter(const StringName &p_name, const Variant &p_value) override;
virtual Variant get_parameter(const StringName &p_name) const override;

AudioStreamPlaybackOggVorbis() {}
~AudioStreamPlaybackOggVorbis();
};
Expand Down Expand Up @@ -152,6 +157,8 @@ class AudioStreamOggVorbis : public AudioStream {

virtual bool is_monophonic() const override;

virtual void get_parameter_list(List<Parameter> *r_parameters) override;

AudioStreamOggVorbis();
virtual ~AudioStreamOggVorbis();
};
Expand Down
69 changes: 69 additions & 0 deletions scene/2d/audio_stream_player_2d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
#include "scene/main/window.h"
#include "scene/resources/world_2d.h"

#define PARAM_PREFIX "parameters/"
KoBeWi marked this conversation as resolved.
Show resolved Hide resolved

void AudioStreamPlayer2D::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
Expand Down Expand Up @@ -222,9 +224,36 @@ void AudioStreamPlayer2D::_update_panning() {
last_mix_count = AudioServer::get_singleton()->get_mix_count();
}

void AudioStreamPlayer2D::_update_stream_parameters() {
if (stream.is_null()) {
return;
}

List<AudioStream::Parameter> parameters;
stream->get_parameter_list(&parameters);
for (const AudioStream::Parameter &K : parameters) {
const PropertyInfo &pi = K.property;
StringName key = PARAM_PREFIX + pi.name;
if (!playback_parameters.has(key)) {
ParameterData pd;
pd.path = pi.name;
pd.value = K.default_value;
playback_parameters.insert(key, pd);
}
}
}

void AudioStreamPlayer2D::set_stream(Ref<AudioStream> p_stream) {
if (stream.is_valid()) {
stream->disconnect(SNAME("parameter_list_changed"), callable_mp(this, &AudioStreamPlayer2D::_update_stream_parameters));
}
stop();
stream = p_stream;
_update_stream_parameters();
if (stream.is_valid()) {
stream->connect(SNAME("parameter_list_changed"), callable_mp(this, &AudioStreamPlayer2D::_update_stream_parameters));
}
notify_property_list_changed();
}

Ref<AudioStream> AudioStreamPlayer2D::get_stream() const {
Expand Down Expand Up @@ -262,6 +291,10 @@ void AudioStreamPlayer2D::play(float p_from_pos) {
Ref<AudioStreamPlayback> stream_playback = stream->instantiate_playback();
ERR_FAIL_COND_MSG(stream_playback.is_null(), "Failed to instantiate playback.");

for (const KeyValue<StringName, ParameterData> &K : playback_parameters) {
stream_playback->set_parameter(K.value.path, K.value.value);
}

stream_playbacks.push_back(stream_playback);
setplayback = stream_playback;
setplay.set(p_from_pos);
Expand Down Expand Up @@ -430,6 +463,42 @@ void AudioStreamPlayer2D::_on_bus_renamed(int p_bus_index, const StringName &p_o
notify_property_list_changed();
}

bool AudioStreamPlayer2D::_set(const StringName &p_name, const Variant &p_value) {
HashMap<StringName, ParameterData>::Iterator I = playback_parameters.find(p_name);
if (!I) {
return false;
}
ParameterData &pd = I->value;
pd.value = p_value;
for (Ref<AudioStreamPlayback> &playback : stream_playbacks) {
playback->set_parameter(pd.path, pd.value);
}
return true;
}

bool AudioStreamPlayer2D::_get(const StringName &p_name, Variant &r_ret) const {
HashMap<StringName, ParameterData>::ConstIterator I = playback_parameters.find(p_name);
if (!I) {
return false;
}

r_ret = I->value.value;
return true;
}

void AudioStreamPlayer2D::_get_property_list(List<PropertyInfo> *p_list) const {
if (stream.is_null()) {
return;
}
List<AudioStream::Parameter> parameters;
stream->get_parameter_list(&parameters);
for (const AudioStream::Parameter &K : parameters) {
PropertyInfo pi = K.property;
pi.name = PARAM_PREFIX + pi.name;
p_list->push_back(pi);
}
}

void AudioStreamPlayer2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_stream", "stream"), &AudioStreamPlayer2D::set_stream);
ClassDB::bind_method(D_METHOD("get_stream"), &AudioStreamPlayer2D::get_stream);
Expand Down
12 changes: 12 additions & 0 deletions scene/2d/audio_stream_player_2d.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,11 +89,23 @@ class AudioStreamPlayer2D : public Node2D {
float panning_strength = 1.0f;
float cached_global_panning_strength = 0.5f;

struct ParameterData {
StringName path;
Variant value;
};

HashMap<StringName, ParameterData> playback_parameters;
void _update_stream_parameters();

protected:
void _validate_property(PropertyInfo &p_property) const;
void _notification(int p_what);
static void _bind_methods();

bool _set(const StringName &p_name, const Variant &p_value);
bool _get(const StringName &p_name, Variant &r_ret) const;
void _get_property_list(List<PropertyInfo> *p_list) const;

public:
void set_stream(Ref<AudioStream> p_stream);
Ref<AudioStream> get_stream() const;
Expand Down
Loading
Loading