1 /*************************************************************************/
2 /* sample_player_2d.cpp */
3 /*************************************************************************/
4 /* This file is part of: */
5 /* GODOT ENGINE */
6 /* https://godotengine.org */
7 /*************************************************************************/
8 /* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
9 /* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
10 /* */
11 /* Permission is hereby granted, free of charge, to any person obtaining */
12 /* a copy of this software and associated documentation files (the */
13 /* "Software"), to deal in the Software without restriction, including */
14 /* without limitation the rights to use, copy, modify, merge, publish, */
15 /* distribute, sublicense, and/or sell copies of the Software, and to */
16 /* permit persons to whom the Software is furnished to do so, subject to */
17 /* the following conditions: */
18 /* */
19 /* The above copyright notice and this permission notice shall be */
20 /* included in all copies or substantial portions of the Software. */
21 /* */
22 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
25 /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26 /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29 /*************************************************************************/
30 #include "sample_player_2d.h"
31
32 #include "servers/audio_server.h"
33 #include "servers/spatial_sound_server.h"
34
_set(const StringName & p_name,const Variant & p_value)35 bool SamplePlayer2D::_set(const StringName &p_name, const Variant &p_value) {
36
37 String name = p_name;
38
39 if (name == "play/play") {
40 if (library.is_valid()) {
41
42 String what = p_value;
43 if (what == "")
44 stop_all();
45 else
46 play(what);
47
48 played_back = what;
49 }
50 } else
51 return false;
52
53 return true;
54 }
55
_get(const StringName & p_name,Variant & r_ret) const56 bool SamplePlayer2D::_get(const StringName &p_name, Variant &r_ret) const {
57
58 String name = p_name;
59
60 if (name == "play/play") {
61 r_ret = played_back;
62 } else
63 return false;
64
65 return true;
66 }
67
_get_property_list(List<PropertyInfo> * p_list) const68 void SamplePlayer2D::_get_property_list(List<PropertyInfo> *p_list) const {
69
70 String en = "";
71 if (library.is_valid()) {
72 List<StringName> samples;
73 Ref<SampleLibrary> ncl = library;
74 ncl->get_sample_list(&samples);
75 for (List<StringName>::Element *E = samples.front(); E; E = E->next()) {
76
77 en += ",";
78 en += E->get();
79 }
80 }
81
82 p_list->push_back(PropertyInfo(Variant::STRING, "play/play", PROPERTY_HINT_ENUM, en, PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_ANIMATE_AS_TRIGGER));
83 }
84
_notification(int p_what)85 void SamplePlayer2D::_notification(int p_what) {
86
87 switch (p_what) {
88
89 case NOTIFICATION_ENTER_TREE: {
90
91 SpatialSound2DServer::get_singleton()->source_set_polyphony(get_source_rid(), polyphony);
92
93 } break;
94 }
95 }
96
set_sample_library(const Ref<SampleLibrary> & p_library)97 void SamplePlayer2D::set_sample_library(const Ref<SampleLibrary> &p_library) {
98
99 library = p_library;
100 _change_notify();
101 update_configuration_warning();
102 }
103
get_sample_library() const104 Ref<SampleLibrary> SamplePlayer2D::get_sample_library() const {
105
106 return library;
107 }
108
set_polyphony(int p_voice_count)109 void SamplePlayer2D::set_polyphony(int p_voice_count) {
110
111 ERR_FAIL_COND(p_voice_count < 0 || p_voice_count > 64);
112 polyphony = p_voice_count;
113 if (get_source_rid().is_valid())
114 SpatialSound2DServer::get_singleton()->source_set_polyphony(get_source_rid(), polyphony);
115 }
116
get_polyphony() const117 int SamplePlayer2D::get_polyphony() const {
118
119 return polyphony;
120 }
121
play(const String & p_sample,int p_voice)122 SamplePlayer2D::VoiceID SamplePlayer2D::play(const String &p_sample, int p_voice) {
123
124 if (!get_source_rid().is_valid())
125 return INVALID_VOICE;
126 if (library.is_null())
127 return INVALID_VOICE;
128 if (!library->has_sample(p_sample))
129 return INVALID_VOICE;
130 Ref<Sample> sample = library->get_sample(p_sample);
131 float vol_change = library->sample_get_volume_db(p_sample);
132 float pitch_change = library->sample_get_pitch_scale(p_sample);
133 int priority = library->sample_get_priority(p_sample);
134
135 VoiceID vid = SpatialSound2DServer::get_singleton()->source_play_sample(get_source_rid(), sample->get_rid(), sample->get_mix_rate() * pitch_change, p_voice, priority);
136 if (vol_change)
137 SpatialSound2DServer::get_singleton()->source_voice_set_volume_scale_db(get_source_rid(), vid, vol_change);
138
139 if (random_pitch_scale) {
140 float ps = Math::random(-random_pitch_scale, random_pitch_scale);
141 if (ps > 0)
142 ps = 1.0 + ps;
143 else
144 ps = 1.0 / (1.0 - ps);
145 SpatialSound2DServer::get_singleton()->source_voice_set_pitch_scale(get_source_rid(), vid, ps * pitch_change);
146 }
147
148 return vid;
149 }
150 //voices
voice_set_pitch_scale(VoiceID p_voice,float p_pitch_scale)151 void SamplePlayer2D::voice_set_pitch_scale(VoiceID p_voice, float p_pitch_scale) {
152
153 if (!get_source_rid().is_valid())
154 return;
155
156 SpatialSound2DServer::get_singleton()->source_voice_set_pitch_scale(get_source_rid(), p_voice, p_pitch_scale);
157 }
158
voice_set_volume_scale_db(VoiceID p_voice,float p_volume_db)159 void SamplePlayer2D::voice_set_volume_scale_db(VoiceID p_voice, float p_volume_db) {
160
161 if (!get_source_rid().is_valid())
162 return;
163 SpatialSound2DServer::get_singleton()->source_voice_set_volume_scale_db(get_source_rid(), p_voice, p_volume_db);
164 }
165
is_voice_active(VoiceID p_voice) const166 bool SamplePlayer2D::is_voice_active(VoiceID p_voice) const {
167
168 if (!get_source_rid().is_valid())
169 return false;
170 return SpatialSound2DServer::get_singleton()->source_is_voice_active(get_source_rid(), p_voice);
171 }
172
stop_voice(VoiceID p_voice)173 void SamplePlayer2D::stop_voice(VoiceID p_voice) {
174
175 if (!get_source_rid().is_valid())
176 return;
177 SpatialSound2DServer::get_singleton()->source_stop_voice(get_source_rid(), p_voice);
178 }
179
stop_all()180 void SamplePlayer2D::stop_all() {
181
182 if (!get_source_rid().is_valid())
183 return;
184
185 for (int i = 0; i < polyphony; i++) {
186
187 SpatialSound2DServer::get_singleton()->source_stop_voice(get_source_rid(), i);
188 }
189 }
190
set_random_pitch_scale(float p_scale)191 void SamplePlayer2D::set_random_pitch_scale(float p_scale) {
192 random_pitch_scale = p_scale;
193 }
194
get_random_pitch_scale() const195 float SamplePlayer2D::get_random_pitch_scale() const {
196
197 return random_pitch_scale;
198 }
199
get_configuration_warning() const200 String SamplePlayer2D::get_configuration_warning() const {
201
202 if (library.is_null()) {
203 return TTR("A SampleLibrary resource must be created or set in the 'samples' property in order for SamplePlayer to play sound.");
204 }
205
206 return String();
207 }
208
_bind_methods()209 void SamplePlayer2D::_bind_methods() {
210
211 ObjectTypeDB::bind_method(_MD("set_sample_library", "library:SampleLibrary"), &SamplePlayer2D::set_sample_library);
212 ObjectTypeDB::bind_method(_MD("get_sample_library:SampleLibrary"), &SamplePlayer2D::get_sample_library);
213
214 ObjectTypeDB::bind_method(_MD("set_polyphony", "max_voices"), &SamplePlayer2D::set_polyphony);
215 ObjectTypeDB::bind_method(_MD("get_polyphony"), &SamplePlayer2D::get_polyphony);
216
217 ObjectTypeDB::bind_method(_MD("play", "sample", "voice"), &SamplePlayer2D::play, DEFVAL(NEXT_VOICE));
218 //voices,DEV
219 ObjectTypeDB::bind_method(_MD("voice_set_pitch_scale", "voice", "ratio"), &SamplePlayer2D::voice_set_pitch_scale);
220 ObjectTypeDB::bind_method(_MD("voice_set_volume_scale_db", "voice", "db"), &SamplePlayer2D::voice_set_volume_scale_db);
221
222 ObjectTypeDB::bind_method(_MD("is_voice_active", "voice"), &SamplePlayer2D::is_voice_active);
223 ObjectTypeDB::bind_method(_MD("stop_voice", "voice"), &SamplePlayer2D::stop_voice);
224 ObjectTypeDB::bind_method(_MD("stop_all"), &SamplePlayer2D::stop_all);
225
226 ObjectTypeDB::bind_method(_MD("set_random_pitch_scale", "val"), &SamplePlayer2D::set_random_pitch_scale);
227 ObjectTypeDB::bind_method(_MD("get_random_pitch_scale"), &SamplePlayer2D::get_random_pitch_scale);
228
229 BIND_CONSTANT(INVALID_VOICE);
230 BIND_CONSTANT(NEXT_VOICE);
231
232 ADD_PROPERTY(PropertyInfo(Variant::INT, "config/polyphony", PROPERTY_HINT_RANGE, "1,64,1"), _SCS("set_polyphony"), _SCS("get_polyphony"));
233 ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "config/samples", PROPERTY_HINT_RESOURCE_TYPE, "SampleLibrary"), _SCS("set_sample_library"), _SCS("get_sample_library"));
234 ADD_PROPERTY(PropertyInfo(Variant::REAL, "config/pitch_random", PROPERTY_HINT_RESOURCE_TYPE, "SampleLibrary"), _SCS("set_random_pitch_scale"), _SCS("get_random_pitch_scale"));
235 }
236
SamplePlayer2D()237 SamplePlayer2D::SamplePlayer2D() {
238
239 polyphony = 1;
240 random_pitch_scale = 0;
241 }
242
~SamplePlayer2D()243 SamplePlayer2D::~SamplePlayer2D() {
244 }
245