summaryrefslogtreecommitdiff
path: root/scene/resources/gibberish_stream.cpp
diff options
context:
space:
mode:
authorJuan Linietsky <reduzio@gmail.com>2014-02-09 22:10:30 -0300
committerJuan Linietsky <reduzio@gmail.com>2014-02-09 22:10:30 -0300
commit0b806ee0fc9097fa7bda7ac0109191c9c5e0a1ac (patch)
tree276c4d099e178eb67fbd14f61d77b05e3808e9e3 /scene/resources/gibberish_stream.cpp
parent0e49da1687bc8192ed210947da52c9e5c5f301bb (diff)
GODOT IS OPEN SOURCE
Diffstat (limited to 'scene/resources/gibberish_stream.cpp')
-rw-r--r--scene/resources/gibberish_stream.cpp330
1 files changed, 330 insertions, 0 deletions
diff --git a/scene/resources/gibberish_stream.cpp b/scene/resources/gibberish_stream.cpp
new file mode 100644
index 0000000000..5dc73fc98a
--- /dev/null
+++ b/scene/resources/gibberish_stream.cpp
@@ -0,0 +1,330 @@
+/*************************************************************************/
+/* gibberish_stream.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#include "gibberish_stream.h"
+#include "servers/audio_server.h"
+
+int AudioStreamGibberish::get_channel_count() const {
+
+ return 1;
+}
+
+
+static float _get_vol_at_pos(int p_pos, int p_len, int p_x_fade) {
+
+ if (p_pos < p_x_fade)
+ return float(p_pos)/p_x_fade;
+ else if (p_pos>(p_len-p_x_fade))
+ return float(p_len-p_pos)/p_x_fade;
+ else
+ return 1.0;
+
+}
+ int AudioStreamGibberish::randomize() {
+
+ if (rand_idx==_rand_pool.size()) {
+
+ for(int i=0;i<_rand_pool.size();i++) {
+
+ SWAP(_rand_pool[i],_rand_pool[Math::rand()%_rand_pool.size()]);
+ }
+ rand_idx=0;
+ }
+
+ return _rand_pool[rand_idx++];
+}
+
+bool AudioStreamGibberish::mix(int32_t *p_buffer, int p_frames) {
+
+ if (!active)
+ return false;
+
+ zeromem(p_buffer,p_frames*sizeof(int32_t));
+
+ if (!paused && active_voices==0) {
+
+ active_voices=1;
+ playback[0].idx=randomize();
+ playback[0].fp_pos=0;
+ playback[0].scale=Math::random(1,1+pitch_random_scale);
+ }
+
+ for(int i=0;i<active_voices;i++) {
+
+ RID s = _samples[playback[i].idx]->get_rid();
+
+ uint64_t fp_pos=playback[i].fp_pos;
+ const void *data = AudioServer::get_singleton()->sample_get_data_ptr(s);
+ bool is16 = AudioServer::get_singleton()->sample_get_format(s)==AudioServer::SAMPLE_FORMAT_PCM16;
+ int skip = AudioServer::get_singleton()->sample_is_stereo(s) ? 1: 0;
+ uint64_t max = AudioServer::get_singleton()->sample_get_length(s) * uint64_t(FP_LEN);
+ int mrate = AudioServer::get_singleton()->sample_get_mix_rate(s) * pitch_scale * playback[i].scale;
+ uint64_t increment = uint64_t(mrate) * uint64_t(FP_LEN) / get_mix_rate();
+
+
+ float vol_begin = _get_vol_at_pos(fp_pos>>FP_BITS,max>>FP_BITS,xfade_time*mrate);
+ float vol_end = _get_vol_at_pos((fp_pos+p_frames*increment)>>FP_BITS,max>>FP_BITS,xfade_time*mrate);
+
+ int32_t vol = CLAMP(int32_t(vol_begin * 65535),0,65535);
+ int32_t vol_to = CLAMP(int32_t(vol_end * 65535),0,65535);
+ int32_t vol_inc = (vol_to-vol)/p_frames;
+
+ bool done=false;
+
+ if (is16) {
+
+ const int16_t *smp = (int16_t*)data;
+ for(int i=0;i<p_frames;i++) {
+
+ if (fp_pos >= max) {
+ done=true;
+ break;
+ }
+
+ int idx = (fp_pos>>FP_BITS)<<skip;
+ p_buffer[i]+=int32_t(smp[idx])*vol;
+ vol+=vol_inc;
+
+ fp_pos+=increment;
+ }
+ } else {
+
+ const int8_t *smp = (int8_t*)data;
+ for(int i=0;i<p_frames;i++) {
+
+ if (fp_pos >= max) {
+ done=true;
+ break;
+ }
+
+ int idx = (fp_pos>>FP_BITS)<<skip;
+ p_buffer[i]+=(int32_t(smp[idx])<<8)*vol;
+ vol+=vol_inc;
+ fp_pos+=increment;
+ }
+
+ }
+
+ playback[i].fp_pos=fp_pos;
+ if (!paused && active_voices==1 && (vol_end < vol_begin || done)) {
+ //xfade to something else i gues
+ active_voices=2;
+ playback[1].idx=randomize();
+ playback[1].fp_pos=0;
+ playback[1].scale=Math::random(1,1+pitch_random_scale);
+ }
+
+ if (done) {
+
+ if (i==0 && active_voices==2) {
+ playback[0]=playback[1];
+ i--;
+ }
+ active_voices--;
+
+ }
+ }
+
+ return true;
+}
+
+
+void AudioStreamGibberish::play() {
+ if (active)
+ stop();
+
+
+ if (!phonemes.is_valid())
+ return;
+
+
+ List<StringName> slist;
+ phonemes->get_sample_list(&slist);
+ if (slist.size()==0)
+ return;
+
+ _samples.resize(slist.size());
+ _rand_pool.resize(slist.size());
+
+ int i=0;
+ for(List<StringName>::Element *E=slist.front();E;E=E->next()) {
+
+ _rand_pool[i]=i;
+ _samples[i++]=phonemes->get_sample(E->get());
+ }
+
+ rand_idx=0;
+ active_voices=0;
+ active=true;
+}
+
+void AudioStreamGibberish::stop(){
+
+ active=false;
+
+
+}
+
+bool AudioStreamGibberish::is_playing() const {
+
+ return active;
+}
+
+
+void AudioStreamGibberish::set_paused(bool p_paused){
+
+ paused=p_paused;
+}
+
+bool AudioStreamGibberish::is_paused(bool p_paused) const{
+
+ return paused;
+}
+
+void AudioStreamGibberish::set_loop(bool p_enable){
+
+
+}
+
+bool AudioStreamGibberish::has_loop() const{
+
+ return false;
+}
+
+
+float AudioStreamGibberish::get_length() const{
+
+ return 0;
+}
+
+
+String AudioStreamGibberish::get_stream_name() const{
+
+ return "Gibberish";
+}
+
+
+int AudioStreamGibberish::get_loop_count() const{
+
+ return 0;
+}
+
+
+float AudioStreamGibberish::get_pos() const{
+
+ return 0;
+}
+
+void AudioStreamGibberish::seek_pos(float p_time){
+
+
+}
+
+
+AudioStream::UpdateMode AudioStreamGibberish::get_update_mode() const{
+
+ return AudioStream::UPDATE_NONE;
+}
+
+void AudioStreamGibberish::update(){
+
+
+}
+
+
+void AudioStreamGibberish::set_phonemes(const Ref<SampleLibrary>& p_phonemes) {
+
+ phonemes=p_phonemes;
+
+}
+
+Ref<SampleLibrary> AudioStreamGibberish::get_phonemes() const {
+
+ return phonemes;
+}
+
+void AudioStreamGibberish::set_xfade_time(float p_xfade) {
+
+ xfade_time=p_xfade;
+}
+
+float AudioStreamGibberish::get_xfade_time() const {
+
+ return xfade_time;
+}
+
+void AudioStreamGibberish::set_pitch_scale(float p_scale) {
+
+ pitch_scale=p_scale;
+}
+
+float AudioStreamGibberish::get_pitch_scale() const {
+
+ return pitch_scale;
+}
+
+void AudioStreamGibberish::set_pitch_random_scale(float p_random_scale) {
+
+ pitch_random_scale=p_random_scale;
+}
+
+float AudioStreamGibberish::get_pitch_random_scale() const {
+
+ return pitch_random_scale;
+}
+
+void AudioStreamGibberish::_bind_methods() {
+
+ ObjectTypeDB::bind_method(_MD("set_phonemes","phonemes"),&AudioStreamGibberish::set_phonemes);
+ ObjectTypeDB::bind_method(_MD("get_phonemes"),&AudioStreamGibberish::get_phonemes);
+
+ ObjectTypeDB::bind_method(_MD("set_pitch_scale","pitch_scale"),&AudioStreamGibberish::set_pitch_scale);
+ ObjectTypeDB::bind_method(_MD("get_pitch_scale"),&AudioStreamGibberish::get_pitch_scale);
+
+ ObjectTypeDB::bind_method(_MD("set_pitch_random_scale","pitch_random_scale"),&AudioStreamGibberish::set_pitch_random_scale);
+ ObjectTypeDB::bind_method(_MD("get_pitch_random_scale"),&AudioStreamGibberish::get_pitch_random_scale);
+
+ ObjectTypeDB::bind_method(_MD("set_xfade_time","sec"),&AudioStreamGibberish::set_xfade_time);
+ ObjectTypeDB::bind_method(_MD("get_xfade_time"),&AudioStreamGibberish::get_xfade_time);
+
+ ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"phonemes",PROPERTY_HINT_RESOURCE_TYPE,"SampleLibrary"),_SCS("set_phonemes"),_SCS("get_phonemes"));
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"pitch_scale",PROPERTY_HINT_RANGE,"0.01,64,0.01"),_SCS("set_pitch_scale"),_SCS("get_pitch_scale"));
+ 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"));
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"xfade_sec",PROPERTY_HINT_RANGE,"0.001,0.5,0.001"),_SCS("set_xfade_time"),_SCS("get_xfade_time"));
+
+}
+
+AudioStreamGibberish::AudioStreamGibberish() {
+
+ xfade_time=0.1;
+ pitch_scale=1;
+ pitch_random_scale=0;
+ active=false;
+ paused=false;
+ active_voices=0;
+}