1 /*************************************************************************/ 2 /* gibberish_stream.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 "gibberish_stream.h" 31 #include "servers/audio_server.h" 32 33 //TODO: This class needs to be adapted to the new AudioStream API, 34 // or dropped if nobody cares about fixing it :) (GH-3307) 35 36 #if 0 37 38 int AudioStreamGibberish::get_channel_count() const { 39 40 return 1; 41 } 42 43 44 static float _get_vol_at_pos(int p_pos, int p_len, int p_x_fade) { 45 46 if (p_pos < p_x_fade) 47 return float(p_pos)/p_x_fade; 48 else if (p_pos>(p_len-p_x_fade)) 49 return float(p_len-p_pos)/p_x_fade; 50 else 51 return 1.0; 52 53 } 54 int AudioStreamGibberish::randomize() { 55 56 if (rand_idx==_rand_pool.size()) { 57 58 for(int i=0;i<_rand_pool.size();i++) { 59 60 SWAP(_rand_pool[i],_rand_pool[Math::rand()%_rand_pool.size()]); 61 } 62 rand_idx=0; 63 } 64 65 return _rand_pool[rand_idx++]; 66 } 67 68 bool AudioStreamGibberish::mix(int32_t *p_buffer, int p_frames) { 69 70 if (!active) 71 return false; 72 73 zeromem(p_buffer,p_frames*sizeof(int32_t)); 74 75 if (!paused && active_voices==0) { 76 77 active_voices=1; 78 playback[0].idx=randomize(); 79 playback[0].fp_pos=0; 80 playback[0].scale=Math::random(1,1+pitch_random_scale); 81 } 82 83 for(int i=0;i<active_voices;i++) { 84 85 RID s = _samples[playback[i].idx]->get_rid(); 86 87 uint64_t fp_pos=playback[i].fp_pos; 88 const void *data = AudioServer::get_singleton()->sample_get_data_ptr(s); 89 bool is16 = AudioServer::get_singleton()->sample_get_format(s)==AudioServer::SAMPLE_FORMAT_PCM16; 90 int skip = AudioServer::get_singleton()->sample_is_stereo(s) ? 1: 0; 91 uint64_t max = AudioServer::get_singleton()->sample_get_length(s) * uint64_t(FP_LEN); 92 int mrate = AudioServer::get_singleton()->sample_get_mix_rate(s) * pitch_scale * playback[i].scale; 93 uint64_t increment = uint64_t(mrate) * uint64_t(FP_LEN) / get_mix_rate(); 94 95 96 float vol_begin = _get_vol_at_pos(fp_pos>>FP_BITS,max>>FP_BITS,xfade_time*mrate); 97 float vol_end = _get_vol_at_pos((fp_pos+p_frames*increment)>>FP_BITS,max>>FP_BITS,xfade_time*mrate); 98 99 int32_t vol = CLAMP(int32_t(vol_begin * 65535),0,65535); 100 int32_t vol_to = CLAMP(int32_t(vol_end * 65535),0,65535); 101 int32_t vol_inc = (vol_to-vol)/p_frames; 102 103 bool done=false; 104 105 if (is16) { 106 107 const int16_t *smp = (int16_t*)data; 108 for(int i=0;i<p_frames;i++) { 109 110 if (fp_pos >= max) { 111 done=true; 112 break; 113 } 114 115 int idx = (fp_pos>>FP_BITS)<<skip; 116 p_buffer[i]+=int32_t(smp[idx])*vol; 117 vol+=vol_inc; 118 119 fp_pos+=increment; 120 } 121 } else { 122 123 const int8_t *smp = (int8_t*)data; 124 for(int i=0;i<p_frames;i++) { 125 126 if (fp_pos >= max) { 127 done=true; 128 break; 129 } 130 131 int idx = (fp_pos>>FP_BITS)<<skip; 132 p_buffer[i]+=(int32_t(smp[idx])<<8)*vol; 133 vol+=vol_inc; 134 fp_pos+=increment; 135 } 136 137 } 138 139 playback[i].fp_pos=fp_pos; 140 if (!paused && active_voices==1 && (vol_end < vol_begin || done)) { 141 //xfade to something else i gues 142 active_voices=2; 143 playback[1].idx=randomize(); 144 playback[1].fp_pos=0; 145 playback[1].scale=Math::random(1,1+pitch_random_scale); 146 } 147 148 if (done) { 149 150 if (i==0 && active_voices==2) { 151 playback[0]=playback[1]; 152 i--; 153 } 154 active_voices--; 155 156 } 157 } 158 159 return true; 160 } 161 162 163 void AudioStreamGibberish::play() { 164 if (active) 165 stop(); 166 167 168 if (!phonemes.is_valid()) 169 return; 170 171 172 List<StringName> slist; 173 phonemes->get_sample_list(&slist); 174 if (slist.size()==0) 175 return; 176 177 _samples.resize(slist.size()); 178 _rand_pool.resize(slist.size()); 179 180 int i=0; 181 for(List<StringName>::Element *E=slist.front();E;E=E->next()) { 182 183 _rand_pool[i]=i; 184 _samples[i++]=phonemes->get_sample(E->get()); 185 } 186 187 rand_idx=0; 188 active_voices=0; 189 active=true; 190 } 191 192 void AudioStreamGibberish::stop(){ 193 194 active=false; 195 196 197 } 198 199 bool AudioStreamGibberish::is_playing() const { 200 201 return active; 202 } 203 204 205 void AudioStreamGibberish::set_paused(bool p_paused){ 206 207 paused=p_paused; 208 } 209 210 bool AudioStreamGibberish::is_paused(bool p_paused) const{ 211 212 return paused; 213 } 214 215 void AudioStreamGibberish::set_loop(bool p_enable){ 216 217 218 } 219 220 bool AudioStreamGibberish::has_loop() const{ 221 222 return false; 223 } 224 225 226 float AudioStreamGibberish::get_length() const{ 227 228 return 0; 229 } 230 231 232 String AudioStreamGibberish::get_stream_name() const{ 233 234 return "Gibberish"; 235 } 236 237 238 int AudioStreamGibberish::get_loop_count() const{ 239 240 return 0; 241 } 242 243 244 float AudioStreamGibberish::get_pos() const{ 245 246 return 0; 247 } 248 249 void AudioStreamGibberish::seek_pos(float p_time){ 250 251 252 } 253 254 255 AudioStream::UpdateMode AudioStreamGibberish::get_update_mode() const{ 256 257 return AudioStream::UPDATE_NONE; 258 } 259 260 void AudioStreamGibberish::update(){ 261 262 263 } 264 265 266 void AudioStreamGibberish::set_phonemes(const Ref<SampleLibrary>& p_phonemes) { 267 268 phonemes=p_phonemes; 269 270 } 271 272 Ref<SampleLibrary> AudioStreamGibberish::get_phonemes() const { 273 274 return phonemes; 275 } 276 277 void AudioStreamGibberish::set_xfade_time(float p_xfade) { 278 279 xfade_time=p_xfade; 280 } 281 282 float AudioStreamGibberish::get_xfade_time() const { 283 284 return xfade_time; 285 } 286 287 void AudioStreamGibberish::set_pitch_scale(float p_scale) { 288 289 pitch_scale=p_scale; 290 } 291 292 float AudioStreamGibberish::get_pitch_scale() const { 293 294 return pitch_scale; 295 } 296 297 void AudioStreamGibberish::set_pitch_random_scale(float p_random_scale) { 298 299 pitch_random_scale=p_random_scale; 300 } 301 302 float AudioStreamGibberish::get_pitch_random_scale() const { 303 304 return pitch_random_scale; 305 } 306 307 void AudioStreamGibberish::_bind_methods() { 308 309 ObjectTypeDB::bind_method(_MD("set_phonemes","phonemes"),&AudioStreamGibberish::set_phonemes); 310 ObjectTypeDB::bind_method(_MD("get_phonemes"),&AudioStreamGibberish::get_phonemes); 311 312 ObjectTypeDB::bind_method(_MD("set_pitch_scale","pitch_scale"),&AudioStreamGibberish::set_pitch_scale); 313 ObjectTypeDB::bind_method(_MD("get_pitch_scale"),&AudioStreamGibberish::get_pitch_scale); 314 315 ObjectTypeDB::bind_method(_MD("set_pitch_random_scale","pitch_random_scale"),&AudioStreamGibberish::set_pitch_random_scale); 316 ObjectTypeDB::bind_method(_MD("get_pitch_random_scale"),&AudioStreamGibberish::get_pitch_random_scale); 317 318 ObjectTypeDB::bind_method(_MD("set_xfade_time","sec"),&AudioStreamGibberish::set_xfade_time); 319 ObjectTypeDB::bind_method(_MD("get_xfade_time"),&AudioStreamGibberish::get_xfade_time); 320 321 ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"phonemes",PROPERTY_HINT_RESOURCE_TYPE,"SampleLibrary"),_SCS("set_phonemes"),_SCS("get_phonemes")); 322 ADD_PROPERTY( PropertyInfo(Variant::REAL,"pitch_scale",PROPERTY_HINT_RANGE,"0.01,64,0.01"),_SCS("set_pitch_scale"),_SCS("get_pitch_scale")); 323 ADD_PROPERTY( PropertyInfo(Variant::REAL,"pitch_random_scale",PROPERTY_HINT_RANGE,"0,64,0.01"),_SCS("set_pitch_random_scale"),_SCS("get_pitch_random_scale")); 324 ADD_PROPERTY( PropertyInfo(Variant::REAL,"xfade_sec",PROPERTY_HINT_RANGE,"0.001,0.5,0.001"),_SCS("set_xfade_time"),_SCS("get_xfade_time")); 325 326 } 327 328 AudioStreamGibberish::AudioStreamGibberish() { 329 330 xfade_time=0.1; 331 pitch_scale=1; 332 pitch_random_scale=0; 333 active=false; 334 paused=false; 335 active_voices=0; 336 } 337 #endif 338