From 9f8f8efa6726a65dfafec37aa072d3598675ffc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20J=2E=20Est=C3=A9banez?= Date: Thu, 6 Apr 2017 19:00:19 +0200 Subject: [PATCH] Add priority to samples in a library --- doc/base/classes.xml | 19 ++++++++++++++ .../plugins/sample_library_editor_plugin.cpp | 25 +++++++++++++++---- scene/2d/sample_player_2d.cpp | 3 ++- scene/3d/spatial_sample_player.cpp | 1 + scene/audio/sample_player.cpp | 18 ++++++++++++- scene/audio/sample_player.h | 1 + scene/resources/sample_library.cpp | 18 +++++++++++++ scene/resources/sample_library.h | 4 +++ .../spatial_sound/spatial_sound_server_sw.cpp | 17 ++++++++++--- .../spatial_sound/spatial_sound_server_sw.h | 3 ++- .../spatial_sound_2d_server_sw.cpp | 17 ++++++++++--- .../spatial_sound_2d_server_sw.h | 3 ++- servers/spatial_sound_2d_server.h | 2 +- servers/spatial_sound_server.h | 2 +- 14 files changed, 116 insertions(+), 17 deletions(-) diff --git a/doc/base/classes.xml b/doc/base/classes.xml index aad217b8eb1..0f3e1a3f0cb 100644 --- a/doc/base/classes.xml +++ b/doc/base/classes.xml @@ -33677,6 +33677,7 @@ Library that contains a collection of [Sample], each identified by a text ID. This is used as a data container for the majority of the SamplePlayer classes and derivatives. + Sample players will never yield an active (currently playing) voice for a new playback request when there are no inactive voices available if the priority of the sample requested to be played is lower than that of every currently played samples. @@ -33737,6 +33738,15 @@ Return the volume (in dB) for the given sample. + + + + + + + Return the priority for the given sample. + + @@ -33755,6 +33765,15 @@ Set the volume (in dB) for the given sample. + + + + + + + Set the priority for the given sample. + + diff --git a/editor/plugins/sample_library_editor_plugin.cpp b/editor/plugins/sample_library_editor_plugin.cpp index 08231d6eb93..f626b4d33ad 100644 --- a/editor/plugins/sample_library_editor_plugin.cpp +++ b/editor/plugins/sample_library_editor_plugin.cpp @@ -175,6 +175,11 @@ void SampleLibraryEditor::_item_edited() { StringName n = s->get_text(0); sample_library->sample_set_pitch_scale(n, s->get_range(4)); + + } else if (tree->get_selected_column() == 5) { // Priority + + StringName n = s->get_text(0); + sample_library->sample_set_priority(n, s->get_range(5)); } } @@ -248,9 +253,16 @@ void SampleLibraryEditor::_update_library() { ti->set_editable(4, true); ti->set_range(4, sample_library->sample_get_pitch_scale(E->get())); + // Priority + ti->set_cell_mode(5, TreeItem::CELL_MODE_RANGE); + ti->set_range_config(5, 0, 100, 1); + ti->set_selectable(5, true); + ti->set_editable(5, true); + ti->set_range(5, sample_library->sample_get_priority(E->get())); + // Delete - ti->set_cell_mode(5, TreeItem::CELL_MODE_STRING); - ti->add_button(5, get_icon("Remove", "EditorIcons")); + ti->set_cell_mode(6, TreeItem::CELL_MODE_STRING); + ti->add_button(6, get_icon("Remove", "EditorIcons")); } //player->add_sample("default",sample); @@ -411,7 +423,7 @@ SampleLibraryEditor::SampleLibraryEditor() { file->set_mode(EditorFileDialog::MODE_OPEN_FILES); tree = memnew(Tree); - tree->set_columns(6); + tree->set_columns(7); add_child(tree); tree->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_BEGIN, 5); tree->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, 5); @@ -423,18 +435,21 @@ SampleLibraryEditor::SampleLibraryEditor() { tree->set_column_title(2, TTR("Format")); tree->set_column_title(3, "dB"); tree->set_column_title(4, TTR("Pitch")); - tree->set_column_title(5, ""); + tree->set_column_title(5, TTR("Priority")); + tree->set_column_title(6, ""); tree->set_column_min_width(1, 150); tree->set_column_min_width(2, 100); tree->set_column_min_width(3, 50); tree->set_column_min_width(4, 50); - tree->set_column_min_width(5, 32); + tree->set_column_min_width(5, 60); + tree->set_column_min_width(6, 32); tree->set_column_expand(1, false); tree->set_column_expand(2, false); tree->set_column_expand(3, false); tree->set_column_expand(4, false); tree->set_column_expand(5, false); + tree->set_column_expand(6, false); tree->set_drag_forwarding(this); diff --git a/scene/2d/sample_player_2d.cpp b/scene/2d/sample_player_2d.cpp index 07f0e3fb36b..5e958058aa8 100644 --- a/scene/2d/sample_player_2d.cpp +++ b/scene/2d/sample_player_2d.cpp @@ -130,8 +130,9 @@ SamplePlayer2D::VoiceID SamplePlayer2D::play(const String &p_sample, int p_voice Ref sample = library->get_sample(p_sample); float vol_change = library->sample_get_volume_db(p_sample); float pitch_change = library->sample_get_pitch_scale(p_sample); + int priority = library->sample_get_priority(p_sample); - VoiceID vid = SpatialSound2DServer::get_singleton()->source_play_sample(get_source_rid(), sample->get_rid(), sample->get_mix_rate() * pitch_change, p_voice); + VoiceID vid = SpatialSound2DServer::get_singleton()->source_play_sample(get_source_rid(), sample->get_rid(), sample->get_mix_rate() * pitch_change, p_voice, priority); if (vol_change) SpatialSound2DServer::get_singleton()->source_voice_set_volume_scale_db(get_source_rid(), vid, vol_change); diff --git a/scene/3d/spatial_sample_player.cpp b/scene/3d/spatial_sample_player.cpp index c2860b4f703..25873bcfb96 100644 --- a/scene/3d/spatial_sample_player.cpp +++ b/scene/3d/spatial_sample_player.cpp @@ -130,6 +130,7 @@ SpatialSamplePlayer::VoiceID SpatialSamplePlayer::play(const String &p_sample, i Ref sample = library->get_sample(p_sample); float vol_change = library->sample_get_volume_db(p_sample); float pitch_change = library->sample_get_pitch_scale(p_sample); + int priority = library->sample_get_priority(p_sample); VoiceID vid = SpatialSoundServer::get_singleton()->source_play_sample(get_source_rid(), sample->get_rid(), sample->get_mix_rate() * pitch_change, p_voice); if (vol_change) diff --git a/scene/audio/sample_player.cpp b/scene/audio/sample_player.cpp index dfccc5c7ce4..416d560b754 100644 --- a/scene/audio/sample_player.cpp +++ b/scene/audio/sample_player.cpp @@ -187,6 +187,7 @@ void SamplePlayer::Voice::clear() { reverb_room = REVERB_HALL; reverb_send = 0; active = false; + priority = 0; } SamplePlayer::Voice::~Voice() { @@ -214,13 +215,28 @@ SamplePlayer::VoiceID SamplePlayer::play(const String &p_name, bool unique) { Ref sample = library->get_sample(p_name); float vol_change = library->sample_get_volume_db(p_name); float pitch_change = library->sample_get_pitch_scale(p_name); + int priority = library->sample_get_priority(p_name); last_check++; - last_id = (last_id + 1) % voices.size(); + + const int num_voices = voices.size(); + bool found = false; + for (int i = 0; i < num_voices; i++) { + const int candidate = (last_id + 1 + i) % num_voices; + if (voices[candidate].priority <= priority) { + found = true; + last_id = candidate; + break; + } + } + + if (!found) + return INVALID_VOICE_ID; Voice &v = voices[last_id]; v.clear(); + v.priority = priority; v.mix_rate = sample->get_mix_rate() * (_default.pitch_scale * pitch_change); v.sample_mix_rate = sample->get_mix_rate(); v.check = last_check; diff --git a/scene/audio/sample_player.h b/scene/audio/sample_player.h index 0f026a08533..392679f05ff 100644 --- a/scene/audio/sample_player.h +++ b/scene/audio/sample_player.h @@ -74,6 +74,7 @@ private: uint32_t check; bool active; + int priority; int sample_mix_rate; int mix_rate; float volume; diff --git a/scene/resources/sample_library.cpp b/scene/resources/sample_library.cpp index e6ccdceb36f..752b988d80f 100644 --- a/scene/resources/sample_library.cpp +++ b/scene/resources/sample_library.cpp @@ -49,6 +49,7 @@ bool SampleLibrary::_set(const StringName &p_name, const Variant &p_value) { sd.sample = d["sample"]; sd.pitch_scale = d["pitch"]; sd.db = d["db"]; + sd.priority = d.has("priority") ? d["priority"] : Variant(0); // For libraries before priority was introduced } sample_map[name] = sd; @@ -70,6 +71,7 @@ bool SampleLibrary::_get(const StringName &p_name, Variant &r_ret) const { d["sample"] = sample_map[name].sample; d["pitch"] = sample_map[name].pitch_scale; d["db"] = sample_map[name].db; + d["priority"] = sample_map[name].priority; r_ret = d; } else { return false; @@ -170,6 +172,19 @@ float SampleLibrary::sample_get_pitch_scale(const StringName &p_name) const { return sample_map[p_name].pitch_scale; } +void SampleLibrary::sample_set_priority(const StringName &p_name, int p_priority) { + + ERR_FAIL_COND(!sample_map.has(p_name)); + sample_map[p_name].priority = p_priority; +} + +int SampleLibrary::sample_get_priority(const StringName &p_name) const { + + ERR_FAIL_COND_V(!sample_map.has(p_name), 0); + + return sample_map[p_name].priority; +} + Array SampleLibrary::_get_sample_list() const { List snames; @@ -199,6 +214,9 @@ void SampleLibrary::_bind_methods() { ObjectTypeDB::bind_method(_MD("sample_set_pitch_scale", "name", "pitch"), &SampleLibrary::sample_set_pitch_scale); ObjectTypeDB::bind_method(_MD("sample_get_pitch_scale", "name"), &SampleLibrary::sample_get_pitch_scale); + + ObjectTypeDB::bind_method(_MD("sample_set_priority", "name", "priority"), &SampleLibrary::sample_set_priority); + ObjectTypeDB::bind_method(_MD("sample_get_priority", "name"), &SampleLibrary::sample_get_priority); } SampleLibrary::SampleLibrary() { diff --git a/scene/resources/sample_library.h b/scene/resources/sample_library.h index 1928e55bb2d..d8008106b81 100644 --- a/scene/resources/sample_library.h +++ b/scene/resources/sample_library.h @@ -42,10 +42,12 @@ class SampleLibrary : public Resource { Ref sample; float db; float pitch_scale; + int priority; SampleData() { db = 0; pitch_scale = 1; + priority = 0; } }; @@ -67,6 +69,8 @@ public: float sample_get_volume_db(const StringName &p_name) const; void sample_set_pitch_scale(const StringName &p_name, float p_pitch); float sample_get_pitch_scale(const StringName &p_name) const; + void sample_set_priority(const StringName &p_name, int p_priority); + int sample_get_priority(const StringName &p_name) const; Ref get_sample(const StringName &p_name) const; void get_sample_list(List *p_samples) const; void remove_sample(const StringName &p_name); diff --git a/servers/spatial_sound/spatial_sound_server_sw.cpp b/servers/spatial_sound/spatial_sound_server_sw.cpp index b6021d8964a..410159d23c9 100644 --- a/servers/spatial_sound/spatial_sound_server_sw.cpp +++ b/servers/spatial_sound/spatial_sound_server_sw.cpp @@ -97,6 +97,7 @@ SpatialSoundServerSW::Source::Voice::Voice() { active = false; restart = false; + priority = 0; pitch_scale = 1.0; volume_scale = 0.0; voice_rid = AudioServer::get_singleton()->voice_create(); @@ -390,7 +391,7 @@ void SpatialSoundServerSW::source_set_audio_stream(RID p_source, AudioServer::Au } //null to unset -SpatialSoundServer::SourceVoiceID SpatialSoundServerSW::source_play_sample(RID p_source, RID p_sample, int p_mix_rate, int p_voice) { +SpatialSoundServer::SourceVoiceID SpatialSoundServerSW::source_play_sample(RID p_source, RID p_sample, int p_mix_rate, int p_voice, int p_priority) { Source *source = source_owner.get(p_source); ERR_FAIL_COND_V(!source, SOURCE_INVALID_VOICE); @@ -400,23 +401,33 @@ SpatialSoundServer::SourceVoiceID SpatialSoundServerSW::source_play_sample(RID p if (p_voice == SOURCE_NEXT_VOICE) { const int num_voices = source->voices.size(); bool free_found = false; + int lowest_priority_voice = 0; + int lowest_priority = 0x7FFFFFFF; for (int i = 0; i < num_voices; i++) { const int candidate = (source->last_voice + 1 + i) % num_voices; - if (!source->voices[candidate].active && !source->voices[candidate].restart) { + const Source::Voice &v = source->voices[candidate]; + if (!v.active && !v.restart) { free_found = true; to_play = candidate; break; } + if (v.priority < lowest_priority) { + lowest_priority = v.priority; + lowest_priority_voice = candidate; + } } if (!free_found) to_play = (source->last_voice + 1) % num_voices; - } else to_play = p_voice; ERR_FAIL_INDEX_V(to_play, source->voices.size(), SOURCE_INVALID_VOICE); + if ((source->voices[to_play].active || source->voices[to_play].restart) && source->voices[to_play].priority > p_priority) + return SOURCE_INVALID_VOICE; + source->voices[to_play].restart = true; + source->voices[to_play].priority = p_priority; source->voices[to_play].sample_rid = p_sample; source->voices[to_play].sample_mix_rate = p_mix_rate; source->voices[to_play].pitch_scale = 1; diff --git a/servers/spatial_sound/spatial_sound_server_sw.h b/servers/spatial_sound/spatial_sound_server_sw.h index e05b78a9410..54f276ede6a 100644 --- a/servers/spatial_sound/spatial_sound_server_sw.h +++ b/servers/spatial_sound/spatial_sound_server_sw.h @@ -101,6 +101,7 @@ class SpatialSoundServerSW : public SpatialSoundServer { RID sample_rid; bool active; bool restart; + int priority; float pitch_scale; float volume_scale; int sample_mix_rate; @@ -226,7 +227,7 @@ public: virtual float source_get_param(RID p_source, SourceParam p_param) const; virtual void source_set_audio_stream(RID p_source, AudioServer::AudioStream *p_stream); //null to unset - virtual SourceVoiceID source_play_sample(RID p_source, RID p_sample, int p_mix_rate, int p_voice = SOURCE_NEXT_VOICE); + virtual SourceVoiceID source_play_sample(RID p_source, RID p_sample, int p_mix_rate, int p_voice = SOURCE_NEXT_VOICE, int p_priority = 0); /* VOICES */ virtual void source_voice_set_pitch_scale(RID p_source, SourceVoiceID p_voice, float p_pitch_scale); virtual void source_voice_set_volume_scale_db(RID p_source, SourceVoiceID p_voice, float p_volume); diff --git a/servers/spatial_sound_2d/spatial_sound_2d_server_sw.cpp b/servers/spatial_sound_2d/spatial_sound_2d_server_sw.cpp index f9ec253c0c6..6f0ae891012 100644 --- a/servers/spatial_sound_2d/spatial_sound_2d_server_sw.cpp +++ b/servers/spatial_sound_2d/spatial_sound_2d_server_sw.cpp @@ -94,6 +94,7 @@ SpatialSound2DServerSW::Source::Voice::Voice() { active = false; restart = false; + priority = 0; pitch_scale = 1.0; volume_scale = 0.0; voice_rid = AudioServer::get_singleton()->voice_create(); @@ -387,7 +388,7 @@ void SpatialSound2DServerSW::source_set_audio_stream(RID p_source, AudioServer:: } //null to unset -SpatialSound2DServer::SourceVoiceID SpatialSound2DServerSW::source_play_sample(RID p_source, RID p_sample, int p_mix_rate, int p_voice) { +SpatialSound2DServer::SourceVoiceID SpatialSound2DServerSW::source_play_sample(RID p_source, RID p_sample, int p_mix_rate, int p_voice, int p_priority) { Source *source = source_owner.get(p_source); ERR_FAIL_COND_V(!source, SOURCE_INVALID_VOICE); @@ -397,23 +398,33 @@ SpatialSound2DServer::SourceVoiceID SpatialSound2DServerSW::source_play_sample(R if (p_voice == SOURCE_NEXT_VOICE) { const int num_voices = source->voices.size(); bool free_found = false; + int lowest_priority_voice = 0; + int lowest_priority = 0x7FFFFFFF; for (int i = 0; i < num_voices; i++) { const int candidate = (source->last_voice + 1 + i) % num_voices; - if (!source->voices[candidate].active && !source->voices[candidate].restart) { + const Source::Voice &v = source->voices[candidate]; + if (!v.active && !v.restart) { free_found = true; to_play = candidate; break; } + if (v.priority < lowest_priority) { + lowest_priority = v.priority; + lowest_priority_voice = candidate; + } } if (!free_found) to_play = (source->last_voice + 1) % num_voices; - } else to_play = p_voice; ERR_FAIL_INDEX_V(to_play, source->voices.size(), SOURCE_INVALID_VOICE); + if ((source->voices[to_play].active || source->voices[to_play].restart) && source->voices[to_play].priority > p_priority) + return SOURCE_INVALID_VOICE; + source->voices[to_play].restart = true; + source->voices[to_play].priority = p_priority; source->voices[to_play].sample_rid = p_sample; source->voices[to_play].sample_mix_rate = p_mix_rate; source->voices[to_play].pitch_scale = 1; diff --git a/servers/spatial_sound_2d/spatial_sound_2d_server_sw.h b/servers/spatial_sound_2d/spatial_sound_2d_server_sw.h index acc70e69c47..de4cfee68f8 100644 --- a/servers/spatial_sound_2d/spatial_sound_2d_server_sw.h +++ b/servers/spatial_sound_2d/spatial_sound_2d_server_sw.h @@ -100,6 +100,7 @@ class SpatialSound2DServerSW : public SpatialSound2DServer { RID sample_rid; bool active; bool restart; + int priority; float pitch_scale; float volume_scale; int sample_mix_rate; @@ -225,7 +226,7 @@ public: virtual float source_get_param(RID p_source, SourceParam p_param) const; virtual void source_set_audio_stream(RID p_source, AudioServer::AudioStream *p_stream); //null to unset - virtual SourceVoiceID source_play_sample(RID p_source, RID p_sample, int p_mix_rate, int p_voice = SOURCE_NEXT_VOICE); + virtual SourceVoiceID source_play_sample(RID p_source, RID p_sample, int p_mix_rate, int p_voice = SOURCE_NEXT_VOICE, int p_priority = 0); /* VOICES */ virtual void source_voice_set_pitch_scale(RID p_source, SourceVoiceID p_voice, float p_pitch_scale); virtual void source_voice_set_volume_scale_db(RID p_source, SourceVoiceID p_voice, float p_volume); diff --git a/servers/spatial_sound_2d_server.h b/servers/spatial_sound_2d_server.h index 7c577e8bec5..08833287e12 100644 --- a/servers/spatial_sound_2d_server.h +++ b/servers/spatial_sound_2d_server.h @@ -117,7 +117,7 @@ public: virtual float source_get_param(RID p_source, SourceParam p_param) const = 0; virtual void source_set_audio_stream(RID p_source, AudioServer::AudioStream *p_stream) = 0; //null to unset - virtual SourceVoiceID source_play_sample(RID p_source, RID p_sample, int p_mix_rate, int p_voice = SOURCE_NEXT_VOICE) = 0; + virtual SourceVoiceID source_play_sample(RID p_source, RID p_sample, int p_mix_rate, int p_voice = SOURCE_NEXT_VOICE, int p_priority = 0) = 0; //voices virtual void source_voice_set_pitch_scale(RID p_source, SourceVoiceID p_voice, float p_pitch_scale) = 0; virtual void source_voice_set_volume_scale_db(RID p_source, SourceVoiceID p_voice, float p_volume_db) = 0; diff --git a/servers/spatial_sound_server.h b/servers/spatial_sound_server.h index 72d3ae0af03..be37f9b5093 100644 --- a/servers/spatial_sound_server.h +++ b/servers/spatial_sound_server.h @@ -121,7 +121,7 @@ public: virtual float source_get_param(RID p_source, SourceParam p_param) const = 0; virtual void source_set_audio_stream(RID p_source, AudioServer::AudioStream *p_stream) = 0; //null to unset - virtual SourceVoiceID source_play_sample(RID p_source, RID p_sample, int p_mix_rate, int p_voice = SOURCE_NEXT_VOICE) = 0; + virtual SourceVoiceID source_play_sample(RID p_source, RID p_sample, int p_mix_rate, int p_voice = SOURCE_NEXT_VOICE, int p_priority = 0) = 0; //voices virtual void source_voice_set_pitch_scale(RID p_source, SourceVoiceID p_voice, float p_pitch_scale) = 0; virtual void source_voice_set_volume_scale_db(RID p_source, SourceVoiceID p_voice, float p_volume_db) = 0;