|
@@ -37,6 +37,8 @@
|
|
|
#include "scene/main/viewport.h"
|
|
|
#include "scene/scene_string_names.h"
|
|
|
|
|
|
+#define PARAM_PREFIX "parameters/"
|
|
|
+
|
|
|
// Based on "A Novel Multichannel Panning Method for Standard and Arbitrary Loudspeaker Configurations" by Ramy Sadek and Chris Kyriakakis (2004)
|
|
|
// Speaker-Placement Correction Amplitude Panning (SPCAP)
|
|
|
class Spcap {
|
|
@@ -525,9 +527,35 @@ Vector<AudioFrame> AudioStreamPlayer3D::_update_panning() {
|
|
|
return output_volume_vector;
|
|
|
}
|
|
|
|
|
|
+void AudioStreamPlayer3D::_update_stream_parameters() {
|
|
|
+ if (stream.is_null()) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ List<AudioStream::Parameter> parameters;
|
|
|
+ stream->get_parameter_list(¶meters);
|
|
|
+ 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 AudioStreamPlayer3D::set_stream(Ref<AudioStream> p_stream) {
|
|
|
+ if (stream.is_valid()) {
|
|
|
+ stream->disconnect(SNAME("parameter_list_changed"), callable_mp(this, &AudioStreamPlayer3D::_update_stream_parameters));
|
|
|
+ }
|
|
|
stop();
|
|
|
stream = p_stream;
|
|
|
+ _update_stream_parameters();
|
|
|
+ if (stream.is_valid()) {
|
|
|
+ stream->connect(SNAME("parameter_list_changed"), callable_mp(this, &AudioStreamPlayer3D::_update_stream_parameters));
|
|
|
+ }
|
|
|
+ notify_property_list_changed();
|
|
|
}
|
|
|
|
|
|
Ref<AudioStream> AudioStreamPlayer3D::get_stream() const {
|
|
@@ -579,6 +607,10 @@ void AudioStreamPlayer3D::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);
|
|
@@ -818,6 +850,42 @@ void AudioStreamPlayer3D::_on_bus_renamed(int p_bus_index, const StringName &p_o
|
|
|
notify_property_list_changed();
|
|
|
}
|
|
|
|
|
|
+bool AudioStreamPlayer3D::_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 AudioStreamPlayer3D::_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 AudioStreamPlayer3D::_get_property_list(List<PropertyInfo> *p_list) const {
|
|
|
+ if (stream.is_null()) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ List<AudioStream::Parameter> parameters;
|
|
|
+ stream->get_parameter_list(¶meters);
|
|
|
+ for (const AudioStream::Parameter &K : parameters) {
|
|
|
+ PropertyInfo pi = K.property;
|
|
|
+ pi.name = PARAM_PREFIX + pi.name;
|
|
|
+ p_list->push_back(pi);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
void AudioStreamPlayer3D::_bind_methods() {
|
|
|
ClassDB::bind_method(D_METHOD("set_stream", "stream"), &AudioStreamPlayer3D::set_stream);
|
|
|
ClassDB::bind_method(D_METHOD("get_stream"), &AudioStreamPlayer3D::get_stream);
|