Add priority to samples in a library
This commit is contained in:
parent
3916d964de
commit
9f8f8efa67
@ -33677,6 +33677,7 @@
|
||||
</brief_description>
|
||||
<description>
|
||||
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.
|
||||
</description>
|
||||
<methods>
|
||||
<method name="add_sample">
|
||||
@ -33737,6 +33738,15 @@
|
||||
Return the volume (in dB) for the given sample.
|
||||
</description>
|
||||
</method>
|
||||
<method name="sample_get_priority" qualifiers="const">
|
||||
<return type="int">
|
||||
</return>
|
||||
<argument index="0" name="name" type="String">
|
||||
</argument>
|
||||
<description>
|
||||
Return the priority for the given sample.
|
||||
</description>
|
||||
</method>
|
||||
<method name="sample_set_pitch_scale">
|
||||
<argument index="0" name="name" type="String">
|
||||
</argument>
|
||||
@ -33755,6 +33765,15 @@
|
||||
Set the volume (in dB) for the given sample.
|
||||
</description>
|
||||
</method>
|
||||
<method name="sample_set_priority">
|
||||
<argument index="0" name="name" type="String">
|
||||
</argument>
|
||||
<argument index="1" name="priority" type="int">
|
||||
</argument>
|
||||
<description>
|
||||
Set the priority for the given sample.
|
||||
</description>
|
||||
</method>
|
||||
</methods>
|
||||
<constants>
|
||||
</constants>
|
||||
|
@ -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);
|
||||
|
||||
|
@ -130,8 +130,9 @@ SamplePlayer2D::VoiceID SamplePlayer2D::play(const String &p_sample, int p_voice
|
||||
Ref<Sample> 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);
|
||||
|
||||
|
@ -130,6 +130,7 @@ SpatialSamplePlayer::VoiceID SpatialSamplePlayer::play(const String &p_sample, i
|
||||
Ref<Sample> 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)
|
||||
|
@ -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> 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;
|
||||
|
@ -74,6 +74,7 @@ private:
|
||||
uint32_t check;
|
||||
bool active;
|
||||
|
||||
int priority;
|
||||
int sample_mix_rate;
|
||||
int mix_rate;
|
||||
float volume;
|
||||
|
@ -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<StringName> 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() {
|
||||
|
@ -42,10 +42,12 @@ class SampleLibrary : public Resource {
|
||||
Ref<Sample> 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<Sample> get_sample(const StringName &p_name) const;
|
||||
void get_sample_list(List<StringName> *p_samples) const;
|
||||
void remove_sample(const StringName &p_name);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user