gibberish_stream.cpp 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. /*************************************************************************/
  2. /* gibberish_stream.cpp */
  3. /*************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /*************************************************************************/
  8. /* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
  9. /* Copyright (c) 2014-2020 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. //TODO: This class needs to be adapted to the new AudioStream API,
  33. // or dropped if nobody cares about fixing it :) (GH-3307)
  34. #if 0
  35. int AudioStreamGibberish::get_channel_count() const {
  36. return 1;
  37. }
  38. static float _get_vol_at_pos(int p_pos, int p_len, int p_x_fade) {
  39. if (p_pos < p_x_fade)
  40. return float(p_pos)/p_x_fade;
  41. else if (p_pos>(p_len-p_x_fade))
  42. return float(p_len-p_pos)/p_x_fade;
  43. else
  44. return 1.0;
  45. }
  46. int AudioStreamGibberish::randomize() {
  47. if (rand_idx==_rand_pool.size()) {
  48. for(int i=0;i<_rand_pool.size();i++) {
  49. SWAP(_rand_pool[i],_rand_pool[Math::rand()%_rand_pool.size()]);
  50. }
  51. rand_idx=0;
  52. }
  53. return _rand_pool[rand_idx++];
  54. }
  55. bool AudioStreamGibberish::mix(int32_t *p_buffer, int p_frames) {
  56. if (!active)
  57. return false;
  58. zeromem(p_buffer,p_frames*sizeof(int32_t));
  59. if (!paused && active_voices==0) {
  60. active_voices=1;
  61. playback[0].idx=randomize();
  62. playback[0].fp_pos=0;
  63. playback[0].scale=Math::random(1,1+pitch_random_scale);
  64. }
  65. for(int i=0;i<active_voices;i++) {
  66. RID s = _samples[playback[i].idx]->get_rid();
  67. uint64_t fp_pos=playback[i].fp_pos;
  68. const void *data = AudioServer::get_singleton()->sample_get_data_ptr(s);
  69. bool is16 = AudioServer::get_singleton()->sample_get_format(s)==AudioServer::SAMPLE_FORMAT_PCM16;
  70. int skip = AudioServer::get_singleton()->sample_is_stereo(s) ? 1: 0;
  71. uint64_t max = AudioServer::get_singleton()->sample_get_length(s) * uint64_t(FP_LEN);
  72. int mrate = AudioServer::get_singleton()->sample_get_mix_rate(s) * pitch_scale * playback[i].scale;
  73. uint64_t increment = uint64_t(mrate) * uint64_t(FP_LEN) / get_mix_rate();
  74. float vol_begin = _get_vol_at_pos(fp_pos>>FP_BITS,max>>FP_BITS,xfade_time*mrate);
  75. float vol_end = _get_vol_at_pos((fp_pos+p_frames*increment)>>FP_BITS,max>>FP_BITS,xfade_time*mrate);
  76. int32_t vol = CLAMP(int32_t(vol_begin * 65535),0,65535);
  77. int32_t vol_to = CLAMP(int32_t(vol_end * 65535),0,65535);
  78. int32_t vol_inc = (vol_to-vol)/p_frames;
  79. bool done=false;
  80. if (is16) {
  81. const int16_t *smp = (int16_t*)data;
  82. for(int i=0;i<p_frames;i++) {
  83. if (fp_pos >= max) {
  84. done=true;
  85. break;
  86. }
  87. int idx = (fp_pos>>FP_BITS)<<skip;
  88. p_buffer[i]+=int32_t(smp[idx])*vol;
  89. vol+=vol_inc;
  90. fp_pos+=increment;
  91. }
  92. } else {
  93. const int8_t *smp = (int8_t*)data;
  94. for(int i=0;i<p_frames;i++) {
  95. if (fp_pos >= max) {
  96. done=true;
  97. break;
  98. }
  99. int idx = (fp_pos>>FP_BITS)<<skip;
  100. p_buffer[i]+=(int32_t(smp[idx])<<8)*vol;
  101. vol+=vol_inc;
  102. fp_pos+=increment;
  103. }
  104. }
  105. playback[i].fp_pos=fp_pos;
  106. if (!paused && active_voices==1 && (vol_end < vol_begin || done)) {
  107. //xfade to something else i gues
  108. active_voices=2;
  109. playback[1].idx=randomize();
  110. playback[1].fp_pos=0;
  111. playback[1].scale=Math::random(1,1+pitch_random_scale);
  112. }
  113. if (done) {
  114. if (i==0 && active_voices==2) {
  115. playback[0]=playback[1];
  116. i--;
  117. }
  118. active_voices--;
  119. }
  120. }
  121. return true;
  122. }
  123. void AudioStreamGibberish::play() {
  124. if (active)
  125. stop();
  126. if (!phonemes.is_valid())
  127. return;
  128. List<StringName> slist;
  129. phonemes->get_sample_list(&slist);
  130. if (slist.size()==0)
  131. return;
  132. _samples.resize(slist.size());
  133. _rand_pool.resize(slist.size());
  134. int i=0;
  135. for(List<StringName>::Element *E=slist.front();E;E=E->next()) {
  136. _rand_pool[i]=i;
  137. _samples[i++]=phonemes->get_sample(E->get());
  138. }
  139. rand_idx=0;
  140. active_voices=0;
  141. active=true;
  142. }
  143. void AudioStreamGibberish::stop(){
  144. active=false;
  145. }
  146. bool AudioStreamGibberish::is_playing() const {
  147. return active;
  148. }
  149. void AudioStreamGibberish::set_paused(bool p_paused){
  150. paused=p_paused;
  151. }
  152. bool AudioStreamGibberish::is_paused(bool p_paused) const{
  153. return paused;
  154. }
  155. void AudioStreamGibberish::set_loop(bool p_enable){
  156. }
  157. bool AudioStreamGibberish::has_loop() const{
  158. return false;
  159. }
  160. float AudioStreamGibberish::get_length() const{
  161. return 0;
  162. }
  163. String AudioStreamGibberish::get_stream_name() const{
  164. return "Gibberish";
  165. }
  166. int AudioStreamGibberish::get_loop_count() const{
  167. return 0;
  168. }
  169. float AudioStreamGibberish::get_pos() const{
  170. return 0;
  171. }
  172. void AudioStreamGibberish::seek_pos(float p_time){
  173. }
  174. AudioStream::UpdateMode AudioStreamGibberish::get_update_mode() const{
  175. return AudioStream::UPDATE_NONE;
  176. }
  177. void AudioStreamGibberish::update(){
  178. }
  179. void AudioStreamGibberish::set_phonemes(const Ref<SampleLibrary>& p_phonemes) {
  180. phonemes=p_phonemes;
  181. }
  182. Ref<SampleLibrary> AudioStreamGibberish::get_phonemes() const {
  183. return phonemes;
  184. }
  185. void AudioStreamGibberish::set_xfade_time(float p_xfade) {
  186. xfade_time=p_xfade;
  187. }
  188. float AudioStreamGibberish::get_xfade_time() const {
  189. return xfade_time;
  190. }
  191. void AudioStreamGibberish::set_pitch_scale(float p_scale) {
  192. pitch_scale=p_scale;
  193. }
  194. float AudioStreamGibberish::get_pitch_scale() const {
  195. return pitch_scale;
  196. }
  197. void AudioStreamGibberish::set_pitch_random_scale(float p_random_scale) {
  198. pitch_random_scale=p_random_scale;
  199. }
  200. float AudioStreamGibberish::get_pitch_random_scale() const {
  201. return pitch_random_scale;
  202. }
  203. void AudioStreamGibberish::_bind_methods() {
  204. ObjectTypeDB::bind_method(_MD("set_phonemes","phonemes"),&AudioStreamGibberish::set_phonemes);
  205. ObjectTypeDB::bind_method(_MD("get_phonemes"),&AudioStreamGibberish::get_phonemes);
  206. ObjectTypeDB::bind_method(_MD("set_pitch_scale","pitch_scale"),&AudioStreamGibberish::set_pitch_scale);
  207. ObjectTypeDB::bind_method(_MD("get_pitch_scale"),&AudioStreamGibberish::get_pitch_scale);
  208. ObjectTypeDB::bind_method(_MD("set_pitch_random_scale","pitch_random_scale"),&AudioStreamGibberish::set_pitch_random_scale);
  209. ObjectTypeDB::bind_method(_MD("get_pitch_random_scale"),&AudioStreamGibberish::get_pitch_random_scale);
  210. ObjectTypeDB::bind_method(_MD("set_xfade_time","sec"),&AudioStreamGibberish::set_xfade_time);
  211. ObjectTypeDB::bind_method(_MD("get_xfade_time"),&AudioStreamGibberish::get_xfade_time);
  212. ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"phonemes",PROPERTY_HINT_RESOURCE_TYPE,"SampleLibrary"),_SCS("set_phonemes"),_SCS("get_phonemes"));
  213. ADD_PROPERTY( PropertyInfo(Variant::REAL,"pitch_scale",PROPERTY_HINT_RANGE,"0.01,64,0.01"),_SCS("set_pitch_scale"),_SCS("get_pitch_scale"));
  214. 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"));
  215. ADD_PROPERTY( PropertyInfo(Variant::REAL,"xfade_sec",PROPERTY_HINT_RANGE,"0.001,0.5,0.001"),_SCS("set_xfade_time"),_SCS("get_xfade_time"));
  216. }
  217. AudioStreamGibberish::AudioStreamGibberish() {
  218. xfade_time=0.1;
  219. pitch_scale=1;
  220. pitch_random_scale=0;
  221. active=false;
  222. paused=false;
  223. active_voices=0;
  224. }
  225. #endif