diff --git a/drivers/mpc/audio_stream_mpc.cpp b/drivers/mpc/audio_stream_mpc.cpp index 67f21f922c0..fe6aa05d000 100644 --- a/drivers/mpc/audio_stream_mpc.cpp +++ b/drivers/mpc/audio_stream_mpc.cpp @@ -1,7 +1,7 @@ #include "audio_stream_mpc.h" -Error AudioStreamMPC::_open_file() { +Error AudioStreamPlaybackMPC::_open_file() { if (f) { memdelete(f); @@ -41,7 +41,7 @@ Error AudioStreamMPC::_open_file() { return OK; } -void AudioStreamMPC::_close_file() { +void AudioStreamPlaybackMPC::_close_file() { if (f) { memdelete(f); @@ -52,7 +52,7 @@ void AudioStreamMPC::_close_file() { data_ofs=0; } -int AudioStreamMPC::_read_file(void *p_dst,int p_bytes) { +int AudioStreamPlaybackMPC::_read_file(void *p_dst,int p_bytes) { if (f) return f->get_buffer((uint8_t*)p_dst,p_bytes); @@ -68,7 +68,7 @@ int AudioStreamMPC::_read_file(void *p_dst,int p_bytes) { return p_bytes; } -bool AudioStreamMPC::_seek_file(int p_pos){ +bool AudioStreamPlaybackMPC::_seek_file(int p_pos){ if (p_pos<0 || p_pos>streamlen) return false; @@ -83,7 +83,7 @@ bool AudioStreamMPC::_seek_file(int p_pos){ return true; } -int AudioStreamMPC::_tell_file() const{ +int AudioStreamPlaybackMPC::_tell_file() const{ if (f) return f->get_pos(); @@ -93,13 +93,13 @@ int AudioStreamMPC::_tell_file() const{ } -int AudioStreamMPC::_sizeof_file() const{ +int AudioStreamPlaybackMPC::_sizeof_file() const{ //print_line("sizeof file, get: "+itos(streamlen)); return streamlen; } -bool AudioStreamMPC::_canseek_file() const{ +bool AudioStreamPlaybackMPC::_canseek_file() const{ //print_line("canseek file, get true"); return true; @@ -107,51 +107,46 @@ bool AudioStreamMPC::_canseek_file() const{ ///////////////////// -mpc_int32_t AudioStreamMPC::_mpc_read(mpc_reader *p_reader,void *p_dst, mpc_int32_t p_bytes) { +mpc_int32_t AudioStreamPlaybackMPC::_mpc_read(mpc_reader *p_reader,void *p_dst, mpc_int32_t p_bytes) { - AudioStreamMPC *smpc=(AudioStreamMPC *)p_reader->data; + AudioStreamPlaybackMPC *smpc=(AudioStreamPlaybackMPC *)p_reader->data; return smpc->_read_file(p_dst,p_bytes); } -mpc_bool_t AudioStreamMPC::_mpc_seek(mpc_reader *p_reader,mpc_int32_t p_offset) { +mpc_bool_t AudioStreamPlaybackMPC::_mpc_seek(mpc_reader *p_reader,mpc_int32_t p_offset) { - AudioStreamMPC *smpc=(AudioStreamMPC *)p_reader->data; + AudioStreamPlaybackMPC *smpc=(AudioStreamPlaybackMPC *)p_reader->data; return smpc->_seek_file(p_offset); } -mpc_int32_t AudioStreamMPC::_mpc_tell(mpc_reader *p_reader) { +mpc_int32_t AudioStreamPlaybackMPC::_mpc_tell(mpc_reader *p_reader) { - AudioStreamMPC *smpc=(AudioStreamMPC *)p_reader->data; + AudioStreamPlaybackMPC *smpc=(AudioStreamPlaybackMPC *)p_reader->data; return smpc->_tell_file(); } -mpc_int32_t AudioStreamMPC::_mpc_get_size(mpc_reader *p_reader) { +mpc_int32_t AudioStreamPlaybackMPC::_mpc_get_size(mpc_reader *p_reader) { - AudioStreamMPC *smpc=(AudioStreamMPC *)p_reader->data; + AudioStreamPlaybackMPC *smpc=(AudioStreamPlaybackMPC *)p_reader->data; return smpc->_sizeof_file(); } -mpc_bool_t AudioStreamMPC::_mpc_canseek(mpc_reader *p_reader) { +mpc_bool_t AudioStreamPlaybackMPC::_mpc_canseek(mpc_reader *p_reader) { - AudioStreamMPC *smpc=(AudioStreamMPC *)p_reader->data; + AudioStreamPlaybackMPC *smpc=(AudioStreamPlaybackMPC *)p_reader->data; return smpc->_canseek_file(); } -bool AudioStreamMPC::_can_mix() const { - return /*active &&*/ !paused; -} - - -void AudioStreamMPC::update() { +int AudioStreamPlaybackMPC::mix(int16_t* p_bufer,int p_frames) { if (!active || paused) - return; + return 0; - int todo=get_todo(); + int todo=p_frames; while(todo>MPC_DECODER_BUFFER_LENGTH/si.channels) { @@ -162,7 +157,7 @@ void AudioStreamMPC::update() { mpc_status err = mpc_demux_decode(demux, &frame); if (frame.bits!=-1) { - int16_t *dst_buff = get_write_buffer(); + int16_t *dst_buff = p_bufer; #ifdef MPC_FIXED_POINT @@ -185,21 +180,21 @@ void AudioStreamMPC::update() { #endif int frames = frame.samples; - write(frames); + p_bufer+=si.channels*frames; todo-=frames; } else { if (err != MPC_STATUS_OK) { stop(); - ERR_EXPLAIN("Error decoding MPC"); - ERR_FAIL(); + ERR_PRINT("Error decoding MPC"); + break; } else { //finished if (!loop) { stop(); - return; + break; } else { @@ -213,9 +208,11 @@ void AudioStreamMPC::update() { } } } + + return p_frames-todo; } -Error AudioStreamMPC::_reload() { +Error AudioStreamPlaybackMPC::_reload() { ERR_FAIL_COND_V(demux!=NULL, ERR_FILE_ALREADY_IN_USE); @@ -224,31 +221,40 @@ Error AudioStreamMPC::_reload() { demux = mpc_demux_init(&reader); ERR_FAIL_COND_V(!demux,ERR_CANT_CREATE); - mpc_demux_get_info(demux, &si); - _setup(si.channels,si.sample_freq,MPC_DECODER_BUFFER_LENGTH*2/si.channels); return OK; } -void AudioStreamMPC::set_file(const String& p_file) { +void AudioStreamPlaybackMPC::set_file(const String& p_file) { file=p_file; + Error err = _open_file(); + ERR_FAIL_COND(err!=OK); + demux = mpc_demux_init(&reader); + ERR_FAIL_COND(!demux); + mpc_demux_get_info(demux, &si); + stream_min_size=MPC_DECODER_BUFFER_LENGTH*2/si.channels; + stream_rate=si.sample_freq; + stream_channels=si.channels; + + mpc_demux_exit(demux); + demux=NULL; + _close_file(); + } -String AudioStreamMPC::get_file() const { +String AudioStreamPlaybackMPC::get_file() const { return file; } -void AudioStreamMPC::play() { +void AudioStreamPlaybackMPC::play(float p_offset) { - _THREAD_SAFE_METHOD_ - if (active) stop(); active=false; @@ -262,9 +268,9 @@ void AudioStreamMPC::play() { } -void AudioStreamMPC::stop() { +void AudioStreamPlaybackMPC::stop() { + - _THREAD_SAFE_METHOD_ if (!active) return; if (demux) { @@ -275,70 +281,58 @@ void AudioStreamMPC::stop() { active=false; } -bool AudioStreamMPC::is_playing() const { +bool AudioStreamPlaybackMPC::is_playing() const { - return active || (get_total() - get_todo() -1 > 0); + return active; } -void AudioStreamMPC::set_paused(bool p_paused) { - paused=p_paused; -} -bool AudioStreamMPC::is_paused(bool p_paused) const { - - return paused; -} - -void AudioStreamMPC::set_loop(bool p_enable) { +void AudioStreamPlaybackMPC::set_loop(bool p_enable) { loop=p_enable; } -bool AudioStreamMPC::has_loop() const { +bool AudioStreamPlaybackMPC::has_loop() const { return loop; } -float AudioStreamMPC::get_length() const { +float AudioStreamPlaybackMPC::get_length() const { return 0; } -String AudioStreamMPC::get_stream_name() const { +String AudioStreamPlaybackMPC::get_stream_name() const { return ""; } -int AudioStreamMPC::get_loop_count() const { +int AudioStreamPlaybackMPC::get_loop_count() const { return 0; } -float AudioStreamMPC::get_pos() const { +float AudioStreamPlaybackMPC::get_pos() const { return 0; } -void AudioStreamMPC::seek_pos(float p_time) { +void AudioStreamPlaybackMPC::seek_pos(float p_time) { } -AudioStream::UpdateMode AudioStreamMPC::get_update_mode() const { - return UPDATE_THREAD; -} +void AudioStreamPlaybackMPC::_bind_methods() { -void AudioStreamMPC::_bind_methods() { - - ObjectTypeDB::bind_method(_MD("set_file","name"),&AudioStreamMPC::set_file); - ObjectTypeDB::bind_method(_MD("get_file"),&AudioStreamMPC::get_file); + ObjectTypeDB::bind_method(_MD("set_file","name"),&AudioStreamPlaybackMPC::set_file); + ObjectTypeDB::bind_method(_MD("get_file"),&AudioStreamPlaybackMPC::get_file); ADD_PROPERTYNZ( PropertyInfo(Variant::STRING,"file",PROPERTY_HINT_FILE,"mpc"), _SCS("set_file"), _SCS("get_file")); } -AudioStreamMPC::AudioStreamMPC() { +AudioStreamPlaybackMPC::AudioStreamPlaybackMPC() { - preload=true; + preload=false; f=NULL; streamlen=0; data_ofs=0; @@ -356,7 +350,7 @@ AudioStreamMPC::AudioStreamMPC() { } -AudioStreamMPC::~AudioStreamMPC() { +AudioStreamPlaybackMPC::~AudioStreamPlaybackMPC() { stop(); diff --git a/drivers/mpc/audio_stream_mpc.h b/drivers/mpc/audio_stream_mpc.h index 8fb0ed13de4..122d0d0bbb4 100644 --- a/drivers/mpc/audio_stream_mpc.h +++ b/drivers/mpc/audio_stream_mpc.h @@ -1,18 +1,17 @@ #ifndef AUDIO_STREAM_MPC_H #define AUDIO_STREAM_MPC_H -#include "scene/resources/audio_stream_resampled.h" +#include "scene/resources/audio_stream.h" #include "os/file_access.h" #include "mpc/mpcdec.h" #include "os/thread_safe.h" #include "io/resource_loader.h" //#include "../libmpcdec/decoder.h" //#include "../libmpcdec/internal.h" -class AudioStreamMPC : public AudioStreamResampled { - OBJ_TYPE( AudioStreamMPC, AudioStreamResampled ); +class AudioStreamPlaybackMPC : public AudioStreamPlayback { - _THREAD_SAFE_CLASS_ + OBJ_TYPE( AudioStreamPlaybackMPC, AudioStreamPlayback ); bool preload; FileAccess *f; @@ -39,7 +38,9 @@ class AudioStreamMPC : public AudioStreamResampled { static mpc_int32_t _mpc_get_size(mpc_reader *p_reader); static mpc_bool_t _mpc_canseek(mpc_reader *p_reader); - virtual bool _can_mix() const ; + int stream_min_size; + int stream_rate; + int stream_channels; protected: Error _open_file(); @@ -59,12 +60,10 @@ public: void set_file(const String& p_file); String get_file() const; - virtual void play(); + virtual void play(float p_offset=0); virtual void stop(); virtual bool is_playing() const; - virtual void set_paused(bool p_paused); - virtual bool is_paused(bool p_paused) const; virtual void set_loop(bool p_enable); virtual bool has_loop() const; @@ -78,13 +77,35 @@ public: virtual float get_pos() const; virtual void seek_pos(float p_time); - virtual UpdateMode get_update_mode() const; - virtual void update(); + virtual int get_channels() const { return stream_channels; } + virtual int get_mix_rate() const { return stream_rate; } - AudioStreamMPC(); - ~AudioStreamMPC(); + virtual int get_minimum_buffer_size() const { return stream_min_size; } + virtual int mix(int16_t* p_bufer,int p_frames); + + virtual void set_loop_restart_time(float p_time) { } + + AudioStreamPlaybackMPC(); + ~AudioStreamPlaybackMPC(); }; +class AudioStreamMPC : public AudioStream { + + OBJ_TYPE( AudioStreamMPC, AudioStream ); + + String file; +public: + + Ref instance_playback() { + Ref pb = memnew( AudioStreamPlaybackMPC ); + pb->set_file(file); + return pb; + } + + void set_file(const String& p_file) { file=p_file; } + + +}; class ResourceFormatLoaderAudioStreamMPC : public ResourceFormatLoader { public: diff --git a/drivers/speex/audio_stream_speex.cpp b/drivers/speex/audio_stream_speex.cpp index 2cffb170494..2440969345e 100644 --- a/drivers/speex/audio_stream_speex.cpp +++ b/drivers/speex/audio_stream_speex.cpp @@ -15,14 +15,15 @@ static _FORCE_INLINE_ uint16_t le_short(uint16_t s) } -void AudioStreamSpeex::update() { +int AudioStreamPlaybackSpeex::mix(int16_t* p_buffer,int p_frames) { + + - _THREAD_SAFE_METHOD_; //printf("update, loops %i, read ofs %i\n", (int)loops, read_ofs); //printf("playing %i, paused %i\n", (int)playing, (int)paused); if (!active || !playing || paused || !data.size()) - return; + return 0; /* if (read_ofs >= data.size()) { @@ -35,12 +36,13 @@ void AudioStreamSpeex::update() { }; */ - int todo = get_todo(); + int todo = p_frames; if (todo < page_size) { - return; + return 0; }; - int eos = 0; + int eos = 0; + bool reloaded=false; while (todo > page_size) { @@ -92,7 +94,7 @@ void AudioStreamSpeex::update() { for (int j=0;j!=nframes;j++) { - int16_t* out = get_write_buffer(); + int16_t* out = p_buffer; int ret; /*Decode frame*/ @@ -120,7 +122,7 @@ void AudioStreamSpeex::update() { /*Convert to short and save to output file*/ - for (int i=0;i& p_data) { + + data=p_data; + reload(); +} + + +void AudioStreamPlaybackSpeex::play(float p_from_pos) { + + + + reload(); + if (!active) + return; + playing = true; + +} +void AudioStreamPlaybackSpeex::stop(){ + + + unload(); + playing = false; + +} +bool AudioStreamPlaybackSpeex::is_playing() const{ + + return playing; +} + + +void AudioStreamPlaybackSpeex::set_loop(bool p_enable){ + + loops = p_enable; +} +bool AudioStreamPlaybackSpeex::has_loop() const{ + + return loops; +} + +float AudioStreamPlaybackSpeex::get_length() const{ + + return 0; +} + +String AudioStreamPlaybackSpeex::get_stream_name() const{ + + return ""; +} + +int AudioStreamPlaybackSpeex::get_loop_count() const{ + + return 0; +} + +float AudioStreamPlaybackSpeex::get_pos() const{ + + return 0; +} +void AudioStreamPlaybackSpeex::seek_pos(float p_time){ + + }; -void AudioStreamSpeex::set_file(const String& p_file){ - if (filename == p_file) + +AudioStreamPlaybackSpeex::AudioStreamPlaybackSpeex() { + + active=false; + st = NULL; + stream_channels=1; + stream_srate=1; + stream_minbuff_size=1; + +} + +AudioStreamPlaybackSpeex::~AudioStreamPlaybackSpeex() { + + unload(); +} + + + + + +//////////////////////////////////////// + + + +void AudioStreamSpeex::set_file(const String& p_file) { + + if (this->file == p_file) return; - if (active) { - unload(); - } + this->file=p_file; if (p_file == "") { data.resize(0); @@ -434,100 +525,11 @@ void AudioStreamSpeex::set_file(const String& p_file){ }; ERR_FAIL_COND(err != OK); - filename = p_file; + this->file = p_file; data.resize(file->get_len()); int read = file->get_buffer(&data[0], data.size()); memdelete(file); - reload(); -} - -void AudioStreamSpeex::play() { - - _THREAD_SAFE_METHOD_ - - reload(); - if (!active) - return; - playing = true; - -} -void AudioStreamSpeex::stop(){ - - _THREAD_SAFE_METHOD_ - unload(); - playing = false; - _clear(); -} -bool AudioStreamSpeex::is_playing() const{ - - return _is_ready() && (playing || (get_total() - get_todo() -1 > 0)); -} - -void AudioStreamSpeex::set_paused(bool p_paused){ - - playing = !p_paused; - paused = p_paused; -} -bool AudioStreamSpeex::is_paused(bool p_paused) const{ - - return paused; -} - -void AudioStreamSpeex::set_loop(bool p_enable){ - - loops = p_enable; -} -bool AudioStreamSpeex::has_loop() const{ - - return loops; -} - -float AudioStreamSpeex::get_length() const{ - - return 0; -} - -String AudioStreamSpeex::get_stream_name() const{ - - return ""; -} - -int AudioStreamSpeex::get_loop_count() const{ - - return 0; -} - -float AudioStreamSpeex::get_pos() const{ - - return 0; -} -void AudioStreamSpeex::seek_pos(float p_time){ - - -}; - -bool AudioStreamSpeex::_can_mix() const { - - //return playing; - return data.size() != 0; -}; - - -AudioStream::UpdateMode AudioStreamSpeex::get_update_mode() const { - - return UPDATE_THREAD; -} - -AudioStreamSpeex::AudioStreamSpeex() { - - active=false; - st = NULL; -} - -AudioStreamSpeex::~AudioStreamSpeex() { - - unload(); } RES ResourceFormatLoaderAudioStreamSpeex::load(const String &p_path, const String& p_original_path, Error *r_error) { diff --git a/drivers/speex/audio_stream_speex.h b/drivers/speex/audio_stream_speex.h index f9e0fce6660..570e8467348 100644 --- a/drivers/speex/audio_stream_speex.h +++ b/drivers/speex/audio_stream_speex.h @@ -1,7 +1,7 @@ #ifndef AUDIO_STREAM_SPEEX_H #define AUDIO_STREAM_SPEEX_H -#include "scene/resources/audio_stream_resampled.h" +#include "scene/resources/audio_stream.h" #include "speex/speex.h" #include "os/file_access.h" #include "io/resource_loader.h" @@ -14,10 +14,10 @@ #include -class AudioStreamSpeex : public AudioStreamResampled { +class AudioStreamPlaybackSpeex : public AudioStreamPlayback { + + OBJ_TYPE(AudioStreamPlaybackSpeex, AudioStreamPlayback); - OBJ_TYPE(AudioStreamSpeex, AudioStreamResampled); - _THREAD_SAFE_CLASS_ void *st; SpeexBits bits; @@ -45,6 +45,9 @@ class AudioStreamSpeex : public AudioStreamResampled { ogg_int64_t page_granule, last_granule; int skip_samples, page_nb_packets; + int stream_channels; + int stream_srate; + int stream_minbuff_size; void* process_header(ogg_packet *op, int *frame_size, int *rate, int *nframes, int *channels, int *extra_headers); @@ -52,7 +55,7 @@ class AudioStreamSpeex : public AudioStreamResampled { protected: - virtual bool _can_mix() const; + //virtual bool _can_mix() const; Dictionary _get_bundled() const; void _set_bundled(const Dictionary& dict); @@ -60,16 +63,12 @@ protected: public: - void set_file(const String& p_file); - String get_file() const; + void set_data(const Vector& p_data); - virtual void play(); + virtual void play(float p_from_pos=0); virtual void stop(); virtual bool is_playing() const; - virtual void set_paused(bool p_paused); - virtual bool is_paused(bool p_paused) const; - virtual void set_loop(bool p_enable); virtual bool has_loop() const; @@ -82,13 +81,39 @@ public: virtual float get_pos() const; virtual void seek_pos(float p_time); - virtual UpdateMode get_update_mode() const; - virtual void update(); + virtual int get_channels() const { return stream_channels; } + virtual int get_mix_rate() const { return stream_srate; } - AudioStreamSpeex(); - ~AudioStreamSpeex(); + virtual int get_minimum_buffer_size() const { return stream_minbuff_size; } + virtual int mix(int16_t* p_bufer,int p_frames); + + virtual void set_loop_restart_time(float p_time) { } //no loop restart, ignore + + AudioStreamPlaybackSpeex(); + ~AudioStreamPlaybackSpeex(); }; + + +class AudioStreamSpeex : public AudioStream { + + OBJ_TYPE(AudioStreamSpeex,AudioStream); + + Vector data; + String file; +public: + + Ref instance_playback() { + Ref pb = memnew( AudioStreamPlaybackSpeex ); + pb->set_data(data); + return pb; + } + + void set_file(const String& p_file); + +}; + + class ResourceFormatLoaderAudioStreamSpeex : public ResourceFormatLoader { public: virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL); diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp index 314e13cee4a..05af7ee900f 100644 --- a/drivers/unix/os_unix.cpp +++ b/drivers/unix/os_unix.cpp @@ -226,7 +226,8 @@ uint64_t OS_Unix::get_unix_time() const { uint64_t OS_Unix::get_system_time_msec() const { struct timeval tv_now; gettimeofday(&tv_now, NULL); - localtime(&tv_now.tv_usec); + //localtime(&tv_now.tv_usec); + localtime((const long *)&tv_now.tv_usec); uint64_t msec = tv_now.tv_usec/1000; return msec; } diff --git a/drivers/vorbis/audio_stream_ogg_vorbis.cpp b/drivers/vorbis/audio_stream_ogg_vorbis.cpp index ee9ba8da4d5..ca055c8b620 100644 --- a/drivers/vorbis/audio_stream_ogg_vorbis.cpp +++ b/drivers/vorbis/audio_stream_ogg_vorbis.cpp @@ -30,7 +30,7 @@ -size_t AudioStreamOGGVorbis::_ov_read_func(void *p_dst,size_t p_data, size_t p_count, void *_f) { +size_t AudioStreamPlaybackOGGVorbis::_ov_read_func(void *p_dst,size_t p_data, size_t p_count, void *_f) { //printf("read to %p, %i bytes, %i nmemb, %p\n",p_dst,p_data,p_count,_f); FileAccess *fa=(FileAccess*)_f; @@ -46,7 +46,7 @@ size_t AudioStreamOGGVorbis::_ov_read_func(void *p_dst,size_t p_data, size_t p_c return read; } -int AudioStreamOGGVorbis::_ov_seek_func(void *_f,ogg_int64_t offs, int whence) { +int AudioStreamPlaybackOGGVorbis::_ov_seek_func(void *_f,ogg_int64_t offs, int whence) { //printf("seek to %p, offs %i, whence %i\n",_f,(int)offs,whence); @@ -76,7 +76,7 @@ int AudioStreamOGGVorbis::_ov_seek_func(void *_f,ogg_int64_t offs, int whence) { #endif } -int AudioStreamOGGVorbis::_ov_close_func(void *_f) { +int AudioStreamPlaybackOGGVorbis::_ov_close_func(void *_f) { // printf("close %p\n",_f); if (!_f) @@ -86,7 +86,7 @@ int AudioStreamOGGVorbis::_ov_close_func(void *_f) { fa->close(); return 0; } -long AudioStreamOGGVorbis::_ov_tell_func(void *_f) { +long AudioStreamPlaybackOGGVorbis::_ov_tell_func(void *_f) { //printf("close %p\n",_f); @@ -95,38 +95,32 @@ long AudioStreamOGGVorbis::_ov_tell_func(void *_f) { } -bool AudioStreamOGGVorbis::_can_mix() const { - return /*playing &&*/ !paused; -} +int AudioStreamPlaybackOGGVorbis::mix(int16_t* p_bufer,int p_frames) { + if (!playing) + return 0; -void AudioStreamOGGVorbis::update() { - - _THREAD_SAFE_METHOD_ - - if (!playing && !setting_up) - return; - + int total=p_frames; while (true) { - int todo = get_todo(); + int todo = p_frames; - if (todo==0 || todo0) { + seek_pos(p_from); + } } -void AudioStreamOGGVorbis::_close_file() { +void AudioStreamPlaybackOGGVorbis::_close_file() { if (f) { + memdelete(f); f=NULL; } } -void AudioStreamOGGVorbis::stop() { - - _THREAD_SAFE_METHOD_ +bool AudioStreamPlaybackOGGVorbis::is_playing() const { + return playing; +} +void AudioStreamPlaybackOGGVorbis::stop() { _clear_stream(); playing=false; - _clear(); -} - -AudioStreamOGGVorbis::UpdateMode AudioStreamOGGVorbis::get_update_mode() const { - - return UPDATE_THREAD; + //_clear(); } -bool AudioStreamOGGVorbis::is_playing() const { +float AudioStreamPlaybackOGGVorbis::get_pos() const { - return playing || (get_total() - get_todo() -1 > 0); -} - -float AudioStreamOGGVorbis::get_pos() const { - - int32_t frames = int32_t(frames_mixed) - (int32_t(get_total()) - get_todo()); + int32_t frames = int32_t(frames_mixed); if (frames < 0) frames=0; return double(frames) / stream_srate; } -void AudioStreamOGGVorbis::seek_pos(float p_time) { +void AudioStreamPlaybackOGGVorbis::seek_pos(float p_time) { + - _THREAD_SAFE_METHOD_ if (!playing) return; @@ -237,32 +234,75 @@ void AudioStreamOGGVorbis::seek_pos(float p_time) { frames_mixed=stream_srate*p_time; } -String AudioStreamOGGVorbis::get_stream_name() const { +String AudioStreamPlaybackOGGVorbis::get_stream_name() const { return ""; } -void AudioStreamOGGVorbis::set_loop(bool p_enable) { +void AudioStreamPlaybackOGGVorbis::set_loop(bool p_enable) { loops=p_enable; } -bool AudioStreamOGGVorbis::has_loop() const { +bool AudioStreamPlaybackOGGVorbis::has_loop() const { return loops; } -int AudioStreamOGGVorbis::get_loop_count() const { +int AudioStreamPlaybackOGGVorbis::get_loop_count() const { return repeats; } -void AudioStreamOGGVorbis::set_file(const String& p_file) { +Error AudioStreamPlaybackOGGVorbis::set_file(const String& p_file) { file=p_file; + stream_valid=false; + Error err; + f=FileAccess::open(file,FileAccess::READ,&err); + + if (err) { + ERR_FAIL_COND_V( err, err ); + } + + int errv = ov_open_callbacks(f,&vf,NULL,0,_ov_callbacks); + switch(errv) { + + case OV_EREAD: { // - A read from media returned an error. + memdelete(f); f=NULL; + ERR_FAIL_V( ERR_FILE_CANT_READ ); + } break; + case OV_EVERSION: // - Vorbis version mismatch. + case OV_ENOTVORBIS: { // - Bitstream is not Vorbis data. + memdelete(f); f=NULL; + ERR_FAIL_V( ERR_FILE_UNRECOGNIZED ); + } break; + case OV_EBADHEADER: { // - Invalid Vorbis bitstream header. + memdelete(f); f=NULL; + ERR_FAIL_V( ERR_FILE_CORRUPT ); + } break; + case OV_EFAULT: { // - Internal logic fault; indicates a bug or heap/stack corruption. + memdelete(f); f=NULL; + ERR_FAIL_V( ERR_BUG ); + } break; + } + const vorbis_info *vinfo=ov_info(&vf,-1); + stream_channels=vinfo->channels; + stream_srate=vinfo->rate; + ogg_int64_t len = ov_time_total(&vf,-1); + length=len/1000.0; + ov_clear(&vf); + memdelete(f); + f=NULL; + stream_valid=true; + + + return OK; } -Error AudioStreamOGGVorbis::_load_stream() { +Error AudioStreamPlaybackOGGVorbis::_load_stream() { + + ERR_FAIL_COND_V(!stream_valid,ERR_UNCONFIGURED); _clear_stream(); if (file=="") @@ -270,52 +310,31 @@ Error AudioStreamOGGVorbis::_load_stream() { Error err; f=FileAccess::open(file,FileAccess::READ,&err); - - if (err) { ERR_FAIL_COND_V( err, err ); } int errv = ov_open_callbacks(f,&vf,NULL,0,_ov_callbacks); - - - const vorbis_info *vinfo=ov_info(&vf,-1); - stream_channels=vinfo->channels; - stream_srate=vinfo->rate; - Error serr = _setup(stream_channels,stream_srate); - - if (serr) { - _close_file(); - ERR_FAIL_V( ERR_INVALID_DATA ); - } - switch(errv) { case OV_EREAD: { // - A read from media returned an error. - _close_file(); + memdelete(f); f=NULL; ERR_FAIL_V( ERR_FILE_CANT_READ ); } break; case OV_EVERSION: // - Vorbis version mismatch. case OV_ENOTVORBIS: { // - Bitstream is not Vorbis data. - _close_file(); + memdelete(f); f=NULL; ERR_FAIL_V( ERR_FILE_UNRECOGNIZED ); } break; case OV_EBADHEADER: { // - Invalid Vorbis bitstream header. - _close_file(); + memdelete(f); f=NULL; ERR_FAIL_V( ERR_FILE_CORRUPT ); } break; case OV_EFAULT: { // - Internal logic fault; indicates a bug or heap/stack corruption. - - _close_file(); + memdelete(f); f=NULL; ERR_FAIL_V( ERR_BUG ); } break; } - - - ogg_int64_t len = ov_time_total(&vf,-1); - - length=len/1000.0; - repeats=0; stream_loaded=true; @@ -324,16 +343,16 @@ Error AudioStreamOGGVorbis::_load_stream() { } -float AudioStreamOGGVorbis::get_length() const { +float AudioStreamPlaybackOGGVorbis::get_length() const { if (!stream_loaded) { - if (const_cast(this)->_load_stream()!=OK) + if (const_cast(this)->_load_stream()!=OK) return 0; } return length; } -void AudioStreamOGGVorbis::_clear_stream() { +void AudioStreamPlaybackOGGVorbis::_clear_stream() { if (!stream_loaded) return; @@ -346,18 +365,18 @@ void AudioStreamOGGVorbis::_clear_stream() { playing=false; } -void AudioStreamOGGVorbis::set_paused(bool p_paused) { +void AudioStreamPlaybackOGGVorbis::set_paused(bool p_paused) { paused=p_paused; } -bool AudioStreamOGGVorbis::is_paused(bool p_paused) const { +bool AudioStreamPlaybackOGGVorbis::is_paused(bool p_paused) const { return paused; } -AudioStreamOGGVorbis::AudioStreamOGGVorbis() { +AudioStreamPlaybackOGGVorbis::AudioStreamPlaybackOGGVorbis() { loops=false; playing=false; @@ -367,17 +386,18 @@ AudioStreamOGGVorbis::AudioStreamOGGVorbis() { _ov_callbacks.tell_func=_ov_tell_func; f = NULL; stream_loaded=false; - repeats=0; - setting_up=false; + stream_valid=false; + repeats=0; paused=true; stream_channels=0; stream_srate=0; current_section=0; length=0; + loop_restart_time=0; } -AudioStreamOGGVorbis::~AudioStreamOGGVorbis() { +AudioStreamPlaybackOGGVorbis::~AudioStreamPlaybackOGGVorbis() { _clear_stream(); diff --git a/drivers/vorbis/audio_stream_ogg_vorbis.h b/drivers/vorbis/audio_stream_ogg_vorbis.h index 5e3649d9803..827d8b0be39 100644 --- a/drivers/vorbis/audio_stream_ogg_vorbis.h +++ b/drivers/vorbis/audio_stream_ogg_vorbis.h @@ -29,17 +29,16 @@ #ifndef AUDIO_STREAM_OGG_VORBIS_H #define AUDIO_STREAM_OGG_VORBIS_H -#include "scene/resources/audio_stream_resampled.h" +#include "scene/resources/audio_stream.h" #include "vorbis/vorbisfile.h" #include "os/file_access.h" #include "io/resource_loader.h" #include "os/thread_safe.h" -class AudioStreamOGGVorbis : public AudioStreamResampled { - OBJ_TYPE(AudioStreamOGGVorbis,AudioStreamResampled); - _THREAD_SAFE_CLASS_ +class AudioStreamPlaybackOGGVorbis : public AudioStreamPlayback { + OBJ_TYPE(AudioStreamPlaybackOGGVorbis,AudioStreamPlayback); enum { MIN_MIX=1024 @@ -54,9 +53,6 @@ class AudioStreamOGGVorbis : public AudioStreamResampled { static int _ov_close_func(void *_f); static long _ov_tell_func(void *_f); - - virtual bool _can_mix() const; - String file; int64_t frames_mixed; @@ -67,7 +63,7 @@ class AudioStreamOGGVorbis : public AudioStreamResampled { int stream_srate; int current_section; - volatile bool setting_up; + bool paused; bool loops; int repeats; @@ -76,17 +72,21 @@ class AudioStreamOGGVorbis : public AudioStreamResampled { void _clear_stream(); void _close_file(); + bool stream_valid; + float loop_restart_time; + public: - void set_file(const String& p_file); + Error set_file(const String& p_file); - - virtual void play(); + virtual void play(float p_from=0); virtual void stop(); virtual bool is_playing() const; + virtual void set_loop_restart_time(float p_time) { loop_restart_time=0; } + virtual void set_paused(bool p_paused); virtual bool is_paused(bool p_paused) const; @@ -102,11 +102,32 @@ public: virtual float get_pos() const; virtual void seek_pos(float p_time); - virtual UpdateMode get_update_mode() const; - virtual void update(); + virtual int get_channels() const { return stream_channels; } + virtual int get_mix_rate() const { return stream_srate; } + + virtual int get_minimum_buffer_size() const { return 0; } + virtual int mix(int16_t* p_bufer,int p_frames); + + AudioStreamPlaybackOGGVorbis(); + ~AudioStreamPlaybackOGGVorbis(); +}; + + +class AudioStreamOGGVorbis : public AudioStream { + + OBJ_TYPE(AudioStreamOGGVorbis,AudioStream); + + String file; +public: + + Ref instance_playback() { + Ref pb = memnew( AudioStreamPlaybackOGGVorbis ); + pb->set_file(file); + return pb; + } + + void set_file(const String& p_file) { file=p_file; } - AudioStreamOGGVorbis(); - ~AudioStreamOGGVorbis(); }; class ResourceFormatLoaderAudioStreamOGGVorbis : public ResourceFormatLoader { diff --git a/main/main.cpp b/main/main.cpp index c313157b65d..9b7e190e039 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -339,7 +339,6 @@ Error Main::setup(const char *execpath,int argc, char *argv[],bool p_second_phas init_custom_pos=Point2(x,y); init_use_custom_pos=true; - force_res=true; N=I->next()->next(); } else { diff --git a/platform/iphone/SCsub b/platform/iphone/SCsub index d495e3b5fc5..d755b3dba03 100644 --- a/platform/iphone/SCsub +++ b/platform/iphone/SCsub @@ -34,5 +34,5 @@ obj = env_ios.Object('godot_iphone.cpp') prog = None prog = env_ios.Program('#bin/godot', [obj] + iphone_lib) -action = "dsymutil "+File(prog)[0].path+" -o " + File(prog)[0].path + ".dSYM" +action = "$IPHONEPATH/usr/bin/dsymutil "+File(prog)[0].path+" -o " + File(prog)[0].path + ".dSYM" env.AddPostAction(prog, action) diff --git a/platform/iphone/detect.py b/platform/iphone/detect.py index 6be3539b9d0..e7a262a2bc2 100644 --- a/platform/iphone/detect.py +++ b/platform/iphone/detect.py @@ -11,7 +11,8 @@ def get_name(): def can_build(): import sys - if sys.platform == 'darwin': + import os + if sys.platform == 'darwin' or os.environ.has_key("OSXCROSS_IOS"): return True return False @@ -28,6 +29,7 @@ def get_opts(): ('ios_gles22_override', 'Force GLES2.0 on iOS', 'yes'), ('ios_appirater', 'Enable Appirater', 'no'), ('ios_exceptions', 'Use exceptions when compiling on playbook', 'yes'), + ('ios_triple', 'Triple for ios toolchain', ''), ] def get_flags(): @@ -48,9 +50,10 @@ def configure(env): # env['CC'] = '$IPHONEPATH/Developer/usr/bin/gcc' # env['CXX'] = '$IPHONEPATH/Developer/usr/bin/g++' - env['CC'] = '$IPHONEPATH/usr/bin/clang' - env['CXX'] = '$IPHONEPATH/usr/bin/clang++' - env['AR'] = 'ar' + env['CC'] = '$IPHONEPATH/usr/bin/${ios_triple}clang' + env['CXX'] = '$IPHONEPATH/usr/bin/${ios_triple}clang++' + env['AR'] = '$IPHONEPATH/usr/bin/${ios_triple}ar' + env['RANLIB'] = '$IPHONEPATH/usr/bin/${ios_triple}ranlib' import string if (env["bits"]=="64"): diff --git a/scene/3d/spatial_stream_player.cpp b/scene/3d/spatial_stream_player.cpp index 84e68bf4186..b81d98e8bf9 100644 --- a/scene/3d/spatial_stream_player.cpp +++ b/scene/3d/spatial_stream_player.cpp @@ -30,21 +30,79 @@ +int SpatialStreamPlayer::InternalStream::get_channel_count() const { + + return player->sp_get_channel_count(); +} +void SpatialStreamPlayer::InternalStream::set_mix_rate(int p_rate){ + + return player->sp_set_mix_rate(p_rate); +} +bool SpatialStreamPlayer::InternalStream::mix(int32_t *p_buffer,int p_frames){ + + return player->sp_mix(p_buffer,p_frames); +} +void SpatialStreamPlayer::InternalStream::update(){ + + player->sp_update(); +} + + +int SpatialStreamPlayer::sp_get_channel_count() const { + + return playback->get_channels(); +} + +void SpatialStreamPlayer::sp_set_mix_rate(int p_rate){ + + server_mix_rate=p_rate; +} + +bool SpatialStreamPlayer::sp_mix(int32_t *p_buffer,int p_frames) { + + if (resampler.is_ready()) { + return resampler.mix(p_buffer,p_frames); + } + + return false; +} + +void SpatialStreamPlayer::sp_update() { + + _THREAD_SAFE_METHOD_ + if (!paused && resampler.is_ready() && playback.is_valid()) { + + if (!playback->is_playing()) { + //stream depleted data, but there's still audio in the ringbuffer + //check that all this audio has been flushed before stopping the stream + int to_mix = resampler.get_total() - resampler.get_todo(); + if (to_mix==0) { + stop(); + return; + } + + return; + } + + int todo =resampler.get_todo(); + int wrote = playback->mix(resampler.get_write_buffer(),todo); + resampler.write(wrote); + } +} + + + void SpatialStreamPlayer::_notification(int p_what) { switch(p_what) { - case NOTIFICATION_ENTER_WORLD: { + case NOTIFICATION_ENTER_TREE: { -// set_idle_process(false); //don't annoy + //set_idle_process(false); //don't annoy + if (stream.is_valid() && autoplay && !get_tree()->is_editor_hint()) + play(); } break; - case NOTIFICATION_PROCESS: { - -// if (!stream.is_null()) -// stream->update(); - - } break; - case NOTIFICATION_EXIT_WORLD: { + case NOTIFICATION_EXIT_TREE: { stop(); //wathever it may be doing, stop } break; @@ -58,12 +116,20 @@ void SpatialStreamPlayer::set_stream(const Ref &p_stream) { stop(); stream=p_stream; + if (!stream.is_null()) { - - stream->set_loop(loops); + playback=stream->instance_playback(); + playback->set_loop(loops); + playback->set_loop_restart_time(loop_point); + AudioServer::get_singleton()->lock(); + resampler.setup(playback->get_channels(),playback->get_mix_rate(),server_mix_rate,buffering_ms,playback->get_minimum_buffer_size()); + AudioServer::get_singleton()->unlock(); + } else { + AudioServer::get_singleton()->lock(); + resampler.clear(); + playback.unref(); + AudioServer::get_singleton()->unlock(); } - - } Ref SpatialStreamPlayer::get_stream() const { @@ -72,18 +138,25 @@ Ref SpatialStreamPlayer::get_stream() const { } -void SpatialStreamPlayer::play() { +void SpatialStreamPlayer::play(float p_from_offset) { - if (!is_inside_tree()) + ERR_FAIL_COND(!is_inside_tree()); + if (playback.is_null()) return; - if (stream.is_null()) - return; - if (stream->is_playing()) + if (playback->is_playing()) stop(); - stream->play(); - SpatialSoundServer::get_singleton()->source_set_audio_stream(get_source_rid(),stream->get_audio_stream()); - //if (stream->get_update_mode()!=AudioStream::UPDATE_NONE) - // set_idle_process(true); + + _THREAD_SAFE_METHOD_ + playback->play(p_from_offset); + //feed the ringbuffer as long as no update callback is going on + sp_update(); + + SpatialSoundServer::get_singleton()->source_set_audio_stream(get_source_rid(),&internal_stream); + +// AudioServer::get_singleton()->stream_set_active(stream_rid,true); +// AudioServer::get_singleton()->stream_set_volume_scale(stream_rid,volume); +// if (stream->get_update_mode()!=AudioStream::UPDATE_NONE) +// set_idle_process(true); } @@ -91,28 +164,30 @@ void SpatialStreamPlayer::stop() { if (!is_inside_tree()) return; - if (stream.is_null()) + if (playback.is_null()) return; + _THREAD_SAFE_METHOD_ + //AudioServer::get_singleton()->stream_set_active(stream_rid,false); SpatialSoundServer::get_singleton()->source_set_audio_stream(get_source_rid(),NULL); - stream->stop(); + playback->stop(); //set_idle_process(false); } bool SpatialStreamPlayer::is_playing() const { - if (stream.is_null()) + if (playback.is_null()) return false; - return stream->is_playing(); + return playback->is_playing(); } void SpatialStreamPlayer::set_loop(bool p_enable) { loops=p_enable; - if (stream.is_null()) + if (playback.is_null()) return; - stream->set_loop(loops); + playback->set_loop(loops); } bool SpatialStreamPlayer::has_loop() const { @@ -120,6 +195,46 @@ bool SpatialStreamPlayer::has_loop() const { return loops; } +void SpatialStreamPlayer::set_volume(float p_vol) { + + volume=p_vol; + if (stream_rid.is_valid()) + AudioServer::get_singleton()->stream_set_volume_scale(stream_rid,volume); +} + +float SpatialStreamPlayer::get_volume() const { + + return volume; +} + +void SpatialStreamPlayer::set_loop_restart_time(float p_secs) { + + loop_point=p_secs; + if (playback.is_valid()) + playback->set_loop_restart_time(p_secs); +} + +float SpatialStreamPlayer::get_loop_restart_time() const { + + return loop_point; +} + + +void SpatialStreamPlayer::set_volume_db(float p_db) { + + if (p_db<-79) + set_volume(0); + else + set_volume(Math::db2linear(p_db)); +} + +float SpatialStreamPlayer::get_volume_db() const { + + if (volume==0) + return -80; + else + return Math::linear2db(volume); +} String SpatialStreamPlayer::get_stream_name() const { @@ -132,27 +247,85 @@ String SpatialStreamPlayer::get_stream_name() const { int SpatialStreamPlayer::get_loop_count() const { - if (stream.is_null()) + if (playback.is_null()) return 0; - return stream->get_loop_count(); + return playback->get_loop_count(); } float SpatialStreamPlayer::get_pos() const { - if (stream.is_null()) + if (playback.is_null()) return 0; - return stream->get_pos(); + return playback->get_pos(); } + +float SpatialStreamPlayer::get_length() const { + + if (playback.is_null()) + return 0; + return playback->get_length(); +} void SpatialStreamPlayer::seek_pos(float p_time) { - if (stream.is_null()) + if (playback.is_null()) return; - return stream->seek_pos(p_time); + return playback->seek_pos(p_time); } +void SpatialStreamPlayer::set_autoplay(bool p_enable) { + + autoplay=p_enable; +} + +bool SpatialStreamPlayer::has_autoplay() const { + + return autoplay; +} + +void SpatialStreamPlayer::set_paused(bool p_paused) { + + paused=p_paused; + //if (stream.is_valid()) + // stream->set_paused(p_paused); +} + +bool SpatialStreamPlayer::is_paused() const { + + return paused; +} + +void SpatialStreamPlayer::_set_play(bool p_play) { + + _play=p_play; + if (is_inside_tree()) { + if(_play) + play(); + else + stop(); + } + +} + +bool SpatialStreamPlayer::_get_play() const{ + + return _play; +} + +void SpatialStreamPlayer::set_buffering_msec(int p_msec) { + + buffering_ms=p_msec; +} + +int SpatialStreamPlayer::get_buffering_msec() const{ + + return buffering_ms; +} + + + void SpatialStreamPlayer::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_stream","stream:Stream"),&SpatialStreamPlayer::set_stream); @@ -163,28 +336,67 @@ void SpatialStreamPlayer::_bind_methods() { ObjectTypeDB::bind_method(_MD("is_playing"),&SpatialStreamPlayer::is_playing); + ObjectTypeDB::bind_method(_MD("set_paused","paused"),&SpatialStreamPlayer::set_paused); + ObjectTypeDB::bind_method(_MD("is_paused"),&SpatialStreamPlayer::is_paused); + ObjectTypeDB::bind_method(_MD("set_loop","enabled"),&SpatialStreamPlayer::set_loop); ObjectTypeDB::bind_method(_MD("has_loop"),&SpatialStreamPlayer::has_loop); + ObjectTypeDB::bind_method(_MD("set_volume","volume"),&SpatialStreamPlayer::set_volume); + ObjectTypeDB::bind_method(_MD("get_volume"),&SpatialStreamPlayer::get_volume); + + ObjectTypeDB::bind_method(_MD("set_volume_db","db"),&SpatialStreamPlayer::set_volume_db); + ObjectTypeDB::bind_method(_MD("get_volume_db"),&SpatialStreamPlayer::get_volume_db); + + ObjectTypeDB::bind_method(_MD("set_buffering_msec","msec"),&SpatialStreamPlayer::set_buffering_msec); + ObjectTypeDB::bind_method(_MD("get_buffering_msec"),&SpatialStreamPlayer::get_buffering_msec); + + ObjectTypeDB::bind_method(_MD("set_loop_restart_time","secs"),&SpatialStreamPlayer::set_loop_restart_time); + ObjectTypeDB::bind_method(_MD("get_loop_restart_time"),&SpatialStreamPlayer::get_loop_restart_time); + ObjectTypeDB::bind_method(_MD("get_stream_name"),&SpatialStreamPlayer::get_stream_name); ObjectTypeDB::bind_method(_MD("get_loop_count"),&SpatialStreamPlayer::get_loop_count); ObjectTypeDB::bind_method(_MD("get_pos"),&SpatialStreamPlayer::get_pos); ObjectTypeDB::bind_method(_MD("seek_pos","time"),&SpatialStreamPlayer::seek_pos); - ADD_PROPERTY( PropertyInfo(Variant::OBJECT, "stream/stream", PROPERTY_HINT_RESOURCE_TYPE,"AudioStream"), _SCS("set_stream"),_SCS("get_stream") ); - ADD_PROPERTY( PropertyInfo(Variant::BOOL, "stream/loop"), _SCS("set_loop"),_SCS("has_loop") ); + ObjectTypeDB::bind_method(_MD("set_autoplay","enabled"),&SpatialStreamPlayer::set_autoplay); + ObjectTypeDB::bind_method(_MD("has_autoplay"),&SpatialStreamPlayer::has_autoplay); + ObjectTypeDB::bind_method(_MD("get_length"),&SpatialStreamPlayer::get_length); + + ObjectTypeDB::bind_method(_MD("_set_play","play"),&SpatialStreamPlayer::_set_play); + ObjectTypeDB::bind_method(_MD("_get_play"),&SpatialStreamPlayer::_get_play); + + ADD_PROPERTY( PropertyInfo(Variant::OBJECT, "stream/stream", PROPERTY_HINT_RESOURCE_TYPE,"AudioStream"), _SCS("set_stream"), _SCS("get_stream") ); + ADD_PROPERTY( PropertyInfo(Variant::BOOL, "stream/play"), _SCS("_set_play"), _SCS("_get_play") ); + ADD_PROPERTY( PropertyInfo(Variant::BOOL, "stream/loop"), _SCS("set_loop"), _SCS("has_loop") ); + ADD_PROPERTY( PropertyInfo(Variant::REAL, "stream/volume_db", PROPERTY_HINT_RANGE,"-80,24,0.01"), _SCS("set_volume_db"), _SCS("get_volume_db") ); + ADD_PROPERTY( PropertyInfo(Variant::BOOL, "stream/autoplay"), _SCS("set_autoplay"), _SCS("has_autoplay") ); + ADD_PROPERTY( PropertyInfo(Variant::BOOL, "stream/paused"), _SCS("set_paused"), _SCS("is_paused") ); + ADD_PROPERTY( PropertyInfo(Variant::INT, "stream/loop_restart_time"), _SCS("set_loop_restart_time"), _SCS("get_loop_restart_time") ); + ADD_PROPERTY( PropertyInfo(Variant::INT, "stream/buffering_ms"), _SCS("set_buffering_msec"), _SCS("get_buffering_msec") ); } SpatialStreamPlayer::SpatialStreamPlayer() { + volume=1; loops=false; + paused=false; + autoplay=false; + _play=false; + server_mix_rate=1; + internal_stream.player=this; + stream_rid=AudioServer::get_singleton()->audio_stream_create(&internal_stream); + buffering_ms=500; + loop_point=0; + } SpatialStreamPlayer::~SpatialStreamPlayer() { + AudioServer::get_singleton()->free(stream_rid); + resampler.clear(); + } - - diff --git a/scene/3d/spatial_stream_player.h b/scene/3d/spatial_stream_player.h index 7e639a72329..f2775a4982b 100644 --- a/scene/3d/spatial_stream_player.h +++ b/scene/3d/spatial_stream_player.h @@ -31,16 +31,48 @@ #include "scene/resources/audio_stream.h" #include "scene/3d/spatial_player.h" - +#include "servers/audio/audio_rb_resampler.h" class SpatialStreamPlayer : public SpatialPlayer { OBJ_TYPE(SpatialStreamPlayer,SpatialPlayer); - Ref stream; - bool loops; -protected: + _THREAD_SAFE_CLASS_ + struct InternalStream : public AudioServer::AudioStream { + SpatialStreamPlayer *player; + virtual int get_channel_count() const; + virtual void set_mix_rate(int p_rate); //notify the stream of the mix rate + virtual bool mix(int32_t *p_buffer,int p_frames); + virtual void update(); + }; + + + InternalStream internal_stream; + Ref playback; + Ref stream; + + int sp_get_channel_count() const; + void sp_set_mix_rate(int p_rate); //notify the stream of the mix rate + bool sp_mix(int32_t *p_buffer,int p_frames); + void sp_update(); + + int server_mix_rate; + + RID stream_rid; + bool paused; + bool autoplay; + bool loops; + float volume; + float loop_point; + int buffering_ms; + + AudioRBResampler resampler; + + bool _play; + void _set_play(bool p_play); + bool _get_play() const; +protected: void _notification(int p_what); static void _bind_methods(); @@ -49,21 +81,37 @@ public: void set_stream(const Ref &p_stream); Ref get_stream() const; - void play(); + void play(float p_from_offset=0); void stop(); bool is_playing() const; + void set_paused(bool p_paused); + bool is_paused() const; + void set_loop(bool p_enable); bool has_loop() const; + void set_volume(float p_vol); + float get_volume() const; + + void set_loop_restart_time(float p_secs); + float get_loop_restart_time() const; + + void set_volume_db(float p_db); + float get_volume_db() const; String get_stream_name() const; - int get_loop_count() const; + int get_loop_count() const; float get_pos() const; void seek_pos(float p_time); + float get_length() const; + void set_autoplay(bool p_vol); + bool has_autoplay() const; + void set_buffering_msec(int p_msec); + int get_buffering_msec() const; SpatialStreamPlayer(); ~SpatialStreamPlayer(); diff --git a/scene/audio/stream_player.cpp b/scene/audio/stream_player.cpp index a097aacf196..699d0682874 100644 --- a/scene/audio/stream_player.cpp +++ b/scene/audio/stream_player.cpp @@ -28,6 +28,67 @@ /*************************************************************************/ #include "stream_player.h" +int StreamPlayer::InternalStream::get_channel_count() const { + + return player->sp_get_channel_count(); +} +void StreamPlayer::InternalStream::set_mix_rate(int p_rate){ + + return player->sp_set_mix_rate(p_rate); +} +bool StreamPlayer::InternalStream::mix(int32_t *p_buffer,int p_frames){ + + return player->sp_mix(p_buffer,p_frames); +} +void StreamPlayer::InternalStream::update(){ + + player->sp_update(); +} + + +int StreamPlayer::sp_get_channel_count() const { + + return playback->get_channels(); +} + +void StreamPlayer::sp_set_mix_rate(int p_rate){ + + server_mix_rate=p_rate; +} + +bool StreamPlayer::sp_mix(int32_t *p_buffer,int p_frames) { + + if (resampler.is_ready()) { + return resampler.mix(p_buffer,p_frames); + } + + return false; +} + +void StreamPlayer::sp_update() { + + _THREAD_SAFE_METHOD_ + if (!paused && resampler.is_ready() && playback.is_valid()) { + + if (!playback->is_playing()) { + //stream depleted data, but there's still audio in the ringbuffer + //check that all this audio has been flushed before stopping the stream + int to_mix = resampler.get_total() - resampler.get_todo(); + if (to_mix==0) { + stop(); + return; + } + + return; + } + + int todo =resampler.get_todo(); + int wrote = playback->mix(resampler.get_write_buffer(),todo); + resampler.write(wrote); + } +} + + void StreamPlayer::_notification(int p_what) { @@ -52,19 +113,21 @@ void StreamPlayer::set_stream(const Ref &p_stream) { stop(); - if (stream_rid.is_valid()) - AudioServer::get_singleton()->free(stream_rid); - stream_rid=RID(); - stream=p_stream; + if (!stream.is_null()) { - - stream->set_loop(loops); - stream->set_paused(paused); - stream_rid=AudioServer::get_singleton()->audio_stream_create(stream->get_audio_stream()); + playback=stream->instance_playback(); + playback->set_loop(loops); + playback->set_loop_restart_time(loop_point); + AudioServer::get_singleton()->lock(); + resampler.setup(playback->get_channels(),playback->get_mix_rate(),server_mix_rate,buffering_ms,playback->get_minimum_buffer_size()); + AudioServer::get_singleton()->unlock(); + } else { + AudioServer::get_singleton()->lock(); + resampler.clear(); + playback.unref(); + AudioServer::get_singleton()->unlock(); } - - } Ref StreamPlayer::get_stream() const { @@ -73,15 +136,18 @@ Ref StreamPlayer::get_stream() const { } -void StreamPlayer::play() { +void StreamPlayer::play(float p_from_offset) { ERR_FAIL_COND(!is_inside_tree()); - if (stream.is_null()) + if (playback.is_null()) return; - if (stream->is_playing()) + if (playback->is_playing()) stop(); - stream->play(); + _THREAD_SAFE_METHOD_ + playback->play(p_from_offset); + //feed the ringbuffer as long as no update callback is going on + sp_update(); AudioServer::get_singleton()->stream_set_active(stream_rid,true); AudioServer::get_singleton()->stream_set_volume_scale(stream_rid,volume); // if (stream->get_update_mode()!=AudioStream::UPDATE_NONE) @@ -93,28 +159,29 @@ void StreamPlayer::stop() { if (!is_inside_tree()) return; - if (stream.is_null()) + if (playback.is_null()) return; + _THREAD_SAFE_METHOD_ AudioServer::get_singleton()->stream_set_active(stream_rid,false); - stream->stop(); + playback->stop(); //set_idle_process(false); } bool StreamPlayer::is_playing() const { - if (stream.is_null()) + if (playback.is_null()) return false; - return stream->is_playing(); + return playback->is_playing(); } void StreamPlayer::set_loop(bool p_enable) { loops=p_enable; - if (stream.is_null()) + if (playback.is_null()) return; - stream->set_loop(loops); + playback->set_loop(loops); } bool StreamPlayer::has_loop() const { @@ -134,6 +201,19 @@ float StreamPlayer::get_volume() const { return volume; } +void StreamPlayer::set_loop_restart_time(float p_secs) { + + loop_point=p_secs; + if (playback.is_valid()) + playback->set_loop_restart_time(p_secs); +} + +float StreamPlayer::get_loop_restart_time() const { + + return loop_point; +} + + void StreamPlayer::set_volume_db(float p_db) { if (p_db<-79) @@ -161,31 +241,31 @@ String StreamPlayer::get_stream_name() const { int StreamPlayer::get_loop_count() const { - if (stream.is_null()) + if (playback.is_null()) return 0; - return stream->get_loop_count(); + return playback->get_loop_count(); } float StreamPlayer::get_pos() const { - if (stream.is_null()) + if (playback.is_null()) return 0; - return stream->get_pos(); + return playback->get_pos(); } float StreamPlayer::get_length() const { - if (stream.is_null()) + if (playback.is_null()) return 0; - return stream->get_length(); + return playback->get_length(); } void StreamPlayer::seek_pos(float p_time) { - if (stream.is_null()) + if (playback.is_null()) return; - return stream->seek_pos(p_time); + return playback->seek_pos(p_time); } @@ -202,8 +282,8 @@ bool StreamPlayer::has_autoplay() const { void StreamPlayer::set_paused(bool p_paused) { paused=p_paused; - if (stream.is_valid()) - stream->set_paused(p_paused); + //if (stream.is_valid()) + // stream->set_paused(p_paused); } bool StreamPlayer::is_paused() const { @@ -228,6 +308,17 @@ bool StreamPlayer::_get_play() const{ return _play; } +void StreamPlayer::set_buffering_msec(int p_msec) { + + buffering_ms=p_msec; +} + +int StreamPlayer::get_buffering_msec() const{ + + return buffering_ms; +} + + void StreamPlayer::_bind_methods() { @@ -251,6 +342,12 @@ void StreamPlayer::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_volume_db","db"),&StreamPlayer::set_volume_db); ObjectTypeDB::bind_method(_MD("get_volume_db"),&StreamPlayer::get_volume_db); + ObjectTypeDB::bind_method(_MD("set_buffering_msec","msec"),&StreamPlayer::set_buffering_msec); + ObjectTypeDB::bind_method(_MD("get_buffering_msec"),&StreamPlayer::get_buffering_msec); + + ObjectTypeDB::bind_method(_MD("set_loop_restart_time","secs"),&StreamPlayer::set_loop_restart_time); + ObjectTypeDB::bind_method(_MD("get_loop_restart_time"),&StreamPlayer::get_loop_restart_time); + ObjectTypeDB::bind_method(_MD("get_stream_name"),&StreamPlayer::get_stream_name); ObjectTypeDB::bind_method(_MD("get_loop_count"),&StreamPlayer::get_loop_count); @@ -271,6 +368,8 @@ void StreamPlayer::_bind_methods() { ADD_PROPERTY( PropertyInfo(Variant::REAL, "stream/volume_db", PROPERTY_HINT_RANGE,"-80,24,0.01"), _SCS("set_volume_db"), _SCS("get_volume_db") ); ADD_PROPERTY( PropertyInfo(Variant::BOOL, "stream/autoplay"), _SCS("set_autoplay"), _SCS("has_autoplay") ); ADD_PROPERTY( PropertyInfo(Variant::BOOL, "stream/paused"), _SCS("set_paused"), _SCS("is_paused") ); + ADD_PROPERTY( PropertyInfo(Variant::INT, "stream/loop_restart_time"), _SCS("set_loop_restart_time"), _SCS("get_loop_restart_time") ); + ADD_PROPERTY( PropertyInfo(Variant::INT, "stream/buffering_ms"), _SCS("set_buffering_msec"), _SCS("get_buffering_msec") ); } @@ -281,10 +380,17 @@ StreamPlayer::StreamPlayer() { paused=false; autoplay=false; _play=false; + server_mix_rate=1; + internal_stream.player=this; + stream_rid=AudioServer::get_singleton()->audio_stream_create(&internal_stream); + buffering_ms=500; + loop_point=0; + } StreamPlayer::~StreamPlayer() { - if (stream_rid.is_valid()) - AudioServer::get_singleton()->free(stream_rid); + AudioServer::get_singleton()->free(stream_rid); + resampler.clear(); + } diff --git a/scene/audio/stream_player.h b/scene/audio/stream_player.h index 21e2162188e..b5aa943067c 100644 --- a/scene/audio/stream_player.h +++ b/scene/audio/stream_player.h @@ -31,17 +31,43 @@ #include "scene/resources/audio_stream.h" #include "scene/main/node.h" +#include "servers/audio/audio_rb_resampler.h" class StreamPlayer : public Node { OBJ_TYPE(StreamPlayer,Node); + _THREAD_SAFE_CLASS_ + + struct InternalStream : public AudioServer::AudioStream { + StreamPlayer *player; + virtual int get_channel_count() const; + virtual void set_mix_rate(int p_rate); //notify the stream of the mix rate + virtual bool mix(int32_t *p_buffer,int p_frames); + virtual void update(); + }; + + + InternalStream internal_stream; + Ref playback; Ref stream; + + int sp_get_channel_count() const; + void sp_set_mix_rate(int p_rate); //notify the stream of the mix rate + bool sp_mix(int32_t *p_buffer,int p_frames); + void sp_update(); + + int server_mix_rate; + RID stream_rid; bool paused; bool autoplay; bool loops; float volume; + float loop_point; + int buffering_ms; + + AudioRBResampler resampler; bool _play; void _set_play(bool p_play); @@ -55,7 +81,7 @@ public: void set_stream(const Ref &p_stream); Ref get_stream() const; - void play(); + void play(float p_from_offset=0); void stop(); bool is_playing() const; @@ -68,6 +94,9 @@ public: void set_volume(float p_vol); float get_volume() const; + void set_loop_restart_time(float p_secs); + float get_loop_restart_time() const; + void set_volume_db(float p_db); float get_volume_db() const; @@ -81,6 +110,8 @@ public: void set_autoplay(bool p_vol); bool has_autoplay() const; + void set_buffering_msec(int p_msec); + int get_buffering_msec() const; StreamPlayer(); ~StreamPlayer(); diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index a53c69815fd..3727c2e8ec7 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -578,7 +578,8 @@ void register_scene_types() { ObjectTypeDB::register_type(); ObjectTypeDB::register_type(); ObjectTypeDB::register_virtual_type(); - ObjectTypeDB::register_type(); + ObjectTypeDB::register_virtual_type(); +// ObjectTypeDB::register_type(); ObjectTypeDB::register_virtual_type(); OS::get_singleton()->yield(); //may take time to init diff --git a/scene/resources/audio_stream.cpp b/scene/resources/audio_stream.cpp index 7694b8ef793..569ed8620d6 100644 --- a/scene/resources/audio_stream.cpp +++ b/scene/resources/audio_stream.cpp @@ -28,76 +28,34 @@ /*************************************************************************/ #include "audio_stream.h" +////////////////////////////// -int AudioStream::InternalAudioStream::get_channel_count() const { +void AudioStreamPlayback::_bind_methods() { - return owner->get_channel_count(); + ObjectTypeDB::bind_method(_MD("play","from_pos_sec"),&AudioStreamPlayback::play,DEFVAL(0)); + ObjectTypeDB::bind_method(_MD("stop"),&AudioStreamPlayback::stop); + ObjectTypeDB::bind_method(_MD("is_playing"),&AudioStreamPlayback::is_playing); -} + ObjectTypeDB::bind_method(_MD("set_loop","enabled"),&AudioStreamPlayback::set_loop); + ObjectTypeDB::bind_method(_MD("has_loop"),&AudioStreamPlayback::has_loop); -void AudioStream::InternalAudioStream::set_mix_rate(int p_rate) { + ObjectTypeDB::bind_method(_MD("get_loop_count"),&AudioStreamPlayback::get_loop_count); - owner->_mix_rate=p_rate; -} + ObjectTypeDB::bind_method(_MD("seek_pos","pos"),&AudioStreamPlayback::seek_pos); + ObjectTypeDB::bind_method(_MD("get_pos"),&AudioStreamPlayback::get_pos); -bool AudioStream::InternalAudioStream::mix(int32_t *p_buffer,int p_frames) { + ObjectTypeDB::bind_method(_MD("get_length"),&AudioStreamPlayback::get_length); + ObjectTypeDB::bind_method(_MD("get_channels"),&AudioStreamPlayback::get_channels); + ObjectTypeDB::bind_method(_MD("get_mix_rate"),&AudioStreamPlayback::get_mix_rate); + ObjectTypeDB::bind_method(_MD("get_minimum_buffer_size"),&AudioStreamPlayback::get_minimum_buffer_size); - return owner->mix(p_buffer,p_frames); -} -bool AudioStream::InternalAudioStream::can_update_mt() const { - - return owner->get_update_mode()==UPDATE_THREAD; -} - -void AudioStream::InternalAudioStream::update() { - - owner->update(); -} - -AudioServer::AudioStream *AudioStream::get_audio_stream() { - - return internal_audio_stream; } void AudioStream::_bind_methods() { - ObjectTypeDB::bind_method(_MD("play"),&AudioStream::play); - ObjectTypeDB::bind_method(_MD("stop"),&AudioStream::stop); - ObjectTypeDB::bind_method(_MD("is_playing"),&AudioStream::is_playing); - - ObjectTypeDB::bind_method(_MD("set_loop","enabled"),&AudioStream::set_loop); - ObjectTypeDB::bind_method(_MD("has_loop"),&AudioStream::has_loop); - - ObjectTypeDB::bind_method(_MD("get_stream_name"),&AudioStream::get_stream_name); - ObjectTypeDB::bind_method(_MD("get_loop_count"),&AudioStream::get_loop_count); - - ObjectTypeDB::bind_method(_MD("seek_pos","pos"),&AudioStream::seek_pos); - ObjectTypeDB::bind_method(_MD("get_pos"),&AudioStream::get_pos); - - ObjectTypeDB::bind_method(_MD("get_length"),&AudioStream::get_length); - - ObjectTypeDB::bind_method(_MD("get_update_mode"),&AudioStream::get_update_mode); - - ObjectTypeDB::bind_method(_MD("update"),&AudioStream::update); - - BIND_CONSTANT( UPDATE_NONE ); - BIND_CONSTANT( UPDATE_IDLE ); - BIND_CONSTANT( UPDATE_THREAD ); } -AudioStream::AudioStream() { - - _mix_rate=44100; - internal_audio_stream = memnew( InternalAudioStream ); - internal_audio_stream->owner=this; -} - - -AudioStream::~AudioStream() { - - memdelete(internal_audio_stream); -} diff --git a/scene/resources/audio_stream.h b/scene/resources/audio_stream.h index df33b64a4b4..b16e62b8c7b 100644 --- a/scene/resources/audio_stream.h +++ b/scene/resources/audio_stream.h @@ -31,72 +31,53 @@ #include "resource.h" #include "servers/audio_server.h" -#include "scene/resources/audio_stream.h" -class AudioStream : public Resource { +class AudioStreamPlayback : public Reference { - OBJ_TYPE( AudioStream, Resource ); - OBJ_SAVE_TYPE( AudioStream ); //children are all saved as AudioStream, so they can be exchanged - - friend class InternalAudioStream; - - struct InternalAudioStream : public AudioServer::AudioStream { - - ::AudioStream *owner; - virtual int get_channel_count() const; - virtual void set_mix_rate(int p_rate); //notify the stream of the mix rate - virtual bool mix(int32_t *p_buffer,int p_frames); - virtual bool can_update_mt() const; - virtual void update(); - }; - - - int _mix_rate; - InternalAudioStream *internal_audio_stream; + OBJ_TYPE( AudioStreamPlayback, Reference ); protected: - - _FORCE_INLINE_ int get_mix_rate() const { return _mix_rate; } - virtual int get_channel_count() const=0; - virtual bool mix(int32_t *p_buffer, int p_frames)=0; - static void _bind_methods(); public: - enum UpdateMode { - UPDATE_NONE, - UPDATE_IDLE, - UPDATE_THREAD - }; - AudioServer::AudioStream *get_audio_stream(); - - virtual void play()=0; + virtual void play(float p_from_pos=0)=0; virtual void stop()=0; virtual bool is_playing() const=0; - virtual void set_paused(bool p_paused)=0; - virtual bool is_paused(bool p_paused) const=0; - virtual void set_loop(bool p_enable)=0; virtual bool has_loop() const=0; - virtual float get_length() const=0; - - virtual String get_stream_name() const=0; + virtual void set_loop_restart_time(float p_time)=0; virtual int get_loop_count() const=0; virtual float get_pos() const=0; virtual void seek_pos(float p_time)=0; - virtual UpdateMode get_update_mode() const=0; - virtual void update()=0; + virtual int mix(int16_t* p_bufer,int p_frames)=0; + + virtual float get_length() const=0; + virtual String get_stream_name() const=0; + + virtual int get_channels() const=0; + virtual int get_mix_rate() const=0; + virtual int get_minimum_buffer_size() const=0; + +}; + +class AudioStream : public Resource { + + OBJ_TYPE( AudioStream, Resource ); + OBJ_SAVE_TYPE( AudioStream ); //children are all saved as AudioStream, so they can be exchanged + +protected: + static void _bind_methods(); +public: + + virtual Ref instance_playback()=0; + - AudioStream(); - ~AudioStream(); }; -VARIANT_ENUM_CAST( AudioStream::UpdateMode ); - #endif // AUDIO_STREAM_H diff --git a/scene/resources/audio_stream_resampled.cpp b/scene/resources/audio_stream_resampled.cpp index 6317780bd31..edbca60bd39 100644 --- a/scene/resources/audio_stream_resampled.cpp +++ b/scene/resources/audio_stream_resampled.cpp @@ -28,6 +28,9 @@ /*************************************************************************/ #include "audio_stream_resampled.h" #include "globals.h" + + +#if 0 int AudioStreamResampled::get_channel_count() const { if (!rb) @@ -382,3 +385,4 @@ AudioStreamResampled::~AudioStreamResampled() { } +#endif diff --git a/scene/resources/audio_stream_resampled.h b/scene/resources/audio_stream_resampled.h index 33cfb17e3fe..570c3118784 100644 --- a/scene/resources/audio_stream_resampled.h +++ b/scene/resources/audio_stream_resampled.h @@ -31,6 +31,7 @@ #include "scene/resources/audio_stream.h" +#if 0 class AudioStreamResampled : public AudioStream { OBJ_TYPE(AudioStreamResampled,AudioStream); @@ -160,5 +161,5 @@ public: AudioStreamResampled(); ~AudioStreamResampled(); }; - +#endif #endif // AUDIO_STREAM_RESAMPLED_H diff --git a/scene/resources/gibberish_stream.cpp b/scene/resources/gibberish_stream.cpp index 23b94c8f38e..7af81bd992f 100644 --- a/scene/resources/gibberish_stream.cpp +++ b/scene/resources/gibberish_stream.cpp @@ -29,6 +29,8 @@ #include "gibberish_stream.h" #include "servers/audio_server.h" +#if 0 + int AudioStreamGibberish::get_channel_count() const { return 1; @@ -328,3 +330,4 @@ AudioStreamGibberish::AudioStreamGibberish() { paused=false; active_voices=0; } +#endif diff --git a/scene/resources/gibberish_stream.h b/scene/resources/gibberish_stream.h index a52e629f83e..77393db9f46 100644 --- a/scene/resources/gibberish_stream.h +++ b/scene/resources/gibberish_stream.h @@ -29,7 +29,7 @@ #ifndef GIBBERISH_STREAM_H #define GIBBERISH_STREAM_H - +#if 0 #include "scene/resources/audio_stream.h" #include "scene/resources/sample_library.h" class AudioStreamGibberish : public AudioStream { @@ -109,4 +109,6 @@ public: AudioStreamGibberish(); }; +#endif + #endif // GIBBERISH_STREAM_H diff --git a/servers/audio/audio_rb_resampler.cpp b/servers/audio/audio_rb_resampler.cpp new file mode 100644 index 00000000000..d07d55f1b55 --- /dev/null +++ b/servers/audio/audio_rb_resampler.cpp @@ -0,0 +1,356 @@ +#include "audio_rb_resampler.h" + + +int AudioRBResampler::get_channel_count() const { + + if (!rb) + return 0; + + return channels; +} + + +template +uint32_t AudioRBResampler::_resample(int32_t *p_dest,int p_todo,int32_t p_increment) { + + uint32_t read=offset&MIX_FRAC_MASK; + + for (int i=0;i> MIX_FRAC_BITS; + uint32_t frac = offset & MIX_FRAC_MASK; +#ifndef FAST_AUDIO + ERR_FAIL_COND_V(pos>=rb_len,0); +#endif + uint32_t pos_next = (pos+1)&rb_mask; + //printf("rb pos %i\n",pos); + + // since this is a template with a known compile time value (C), conditionals go away when compiling. + if (C==1) { + + int32_t v0 = rb[pos]; + int32_t v0n=rb[pos_next]; +#ifndef FAST_AUDIO + v0+=(v0n-v0)*(int32_t)frac >> MIX_FRAC_BITS; +#endif + v0<<=16; + p_dest[i]=v0; + + } + if (C==2) { + + int32_t v0 = rb[(pos<<1)+0]; + int32_t v1 = rb[(pos<<1)+1]; + int32_t v0n=rb[(pos_next<<1)+0]; + int32_t v1n=rb[(pos_next<<1)+1]; + +#ifndef FAST_AUDIO + v0+=(v0n-v0)*(int32_t)frac >> MIX_FRAC_BITS; + v1+=(v1n-v1)*(int32_t)frac >> MIX_FRAC_BITS; +#endif + v0<<=16; + v1<<=16; + p_dest[(i<<1)+0]=v0; + p_dest[(i<<1)+1]=v1; + + } + + if (C==4) { + + int32_t v0 = rb[(pos<<2)+0]; + int32_t v1 = rb[(pos<<2)+1]; + int32_t v2 = rb[(pos<<2)+2]; + int32_t v3 = rb[(pos<<2)+3]; + int32_t v0n = rb[(pos_next<<2)+0]; + int32_t v1n=rb[(pos_next<<2)+1]; + int32_t v2n=rb[(pos_next<<2)+2]; + int32_t v3n=rb[(pos_next<<2)+3]; + +#ifndef FAST_AUDIO + v0+=(v0n-v0)*(int32_t)frac >> MIX_FRAC_BITS; + v1+=(v1n-v1)*(int32_t)frac >> MIX_FRAC_BITS; + v2+=(v2n-v2)*(int32_t)frac >> MIX_FRAC_BITS; + v3+=(v3n-v3)*(int32_t)frac >> MIX_FRAC_BITS; +#endif + v0<<=16; + v1<<=16; + v2<<=16; + v3<<=16; + p_dest[(i<<2)+0]=v0; + p_dest[(i<<2)+1]=v1; + p_dest[(i<<2)+2]=v2; + p_dest[(i<<2)+3]=v3; + + } + + if (C==6) { + + int32_t v0 = rb[(pos*6)+0]; + int32_t v1 = rb[(pos*6)+1]; + int32_t v2 = rb[(pos*6)+2]; + int32_t v3 = rb[(pos*6)+3]; + int32_t v4 = rb[(pos*6)+4]; + int32_t v5 = rb[(pos*6)+5]; + int32_t v0n = rb[(pos_next*6)+0]; + int32_t v1n=rb[(pos_next*6)+1]; + int32_t v2n=rb[(pos_next*6)+2]; + int32_t v3n=rb[(pos_next*6)+3]; + int32_t v4n=rb[(pos_next*6)+4]; + int32_t v5n=rb[(pos_next*6)+5]; + +#ifndef FAST_AUDIO + v0+=(v0n-v0)*(int32_t)frac >> MIX_FRAC_BITS; + v1+=(v1n-v1)*(int32_t)frac >> MIX_FRAC_BITS; + v2+=(v2n-v2)*(int32_t)frac >> MIX_FRAC_BITS; + v3+=(v3n-v3)*(int32_t)frac >> MIX_FRAC_BITS; + v4+=(v4n-v4)*(int32_t)frac >> MIX_FRAC_BITS; + v5+=(v5n-v5)*(int32_t)frac >> MIX_FRAC_BITS; +#endif + v0<<=16; + v1<<=16; + v2<<=16; + v3<<=16; + v4<<=16; + v5<<=16; + p_dest[(i*6)+0]=v0; + p_dest[(i*6)+1]=v1; + p_dest[(i*6)+2]=v2; + p_dest[(i*6)+3]=v3; + p_dest[(i*6)+4]=v4; + p_dest[(i*6)+5]=v5; + + } + + + } + + + return read>>MIX_FRAC_BITS;//rb_read_pos=offset>>MIX_FRAC_BITS; + +} + + +bool AudioRBResampler::mix(int32_t *p_dest, int p_frames) { + + + if (!rb) + return false; + + int write_pos_cache=rb_write_pos; + + int32_t increment=(src_mix_rate*MIX_FRAC_LEN)/target_mix_rate; + + int rb_todo; + + if (write_pos_cache==rb_read_pos) { + return false; //out of buffer + + } else if (rb_read_pos(p_dest,todo,increment); break; + case 2: read=_resample<2>(p_dest,todo,increment); break; + case 4: read=_resample<4>(p_dest,todo,increment); break; + case 6: read=_resample<6>(p_dest,todo,increment); break; + } +#if 1 + //end of stream, fadeout + int remaining = p_frames-todo; + if (remaining && todo>0) { + + //print_line("fadeout"); + for(int c=0;c>8; + uint32_t mul = (todo-i) * 256 /todo; + //print_line("mul: "+itos(i)+" "+itos(mul)); + p_dest[i*channels+c]=samp*mul; + } + + } + + } + +#else + int remaining = p_frames-todo; + if (remaining && todo>0) { + + + for(int c=0;c>8; + + for(int i=0;irb_todo) + read=rb_todo; + + rb_read_pos = (rb_read_pos+read)&rb_mask; + + + + + } + + return true; +} + + +Error AudioRBResampler::setup(int p_channels,int p_src_mix_rate,int p_target_mix_rate,int p_buffer_msec,int p_minbuff_needed) { + + ERR_FAIL_COND_V(p_channels!=1 && p_channels!=2 && p_channels!=4 && p_channels!=6,ERR_INVALID_PARAMETER); + + + //float buffering_sec = int(GLOBAL_DEF("audio/stream_buffering_ms",500))/1000.0; + int desired_rb_bits =nearest_shift(MAX((p_buffer_msec/1000.0)*p_src_mix_rate,p_minbuff_needed)); + + bool recreate=!rb; + + if (rb && (uint32_t(desired_rb_bits)!=rb_bits || channels!=uint32_t(p_channels))) { + //recreate + + memdelete_arr(rb); + memdelete_arr(read_buf); + recreate=true; + + } + + if (recreate) { + + channels=p_channels; + rb_bits=desired_rb_bits; + rb_len=(1< + uint32_t _resample(int32_t *p_dest,int p_todo,int32_t p_increment); + + +public: + + _FORCE_INLINE_ void flush() { + rb_read_pos=0; + rb_write_pos=0; + } + + _FORCE_INLINE_ bool is_ready() const{ + return rb!=NULL; + } + + + _FORCE_INLINE_ int get_total() const { + + return rb_len-1; + } + + _FORCE_INLINE_ int get_todo() const { //return amount of frames to mix + + int todo; + int read_pos_cache=rb_read_pos; + + if (read_pos_cache==rb_write_pos) { + todo=rb_len-1; + } else if (read_pos_cache>rb_write_pos) { + + todo=read_pos_cache-rb_write_pos-1; + } else { + + todo=(rb_len-rb_write_pos)+read_pos_cache-1; + } + + return todo; + } + + _FORCE_INLINE_ int16_t *get_write_buffer() { return read_buf; } + _FORCE_INLINE_ void write(uint32_t p_frames) { + + ERR_FAIL_COND(p_frames >= rb_len); + + switch(channels) { + case 1: { + + for(uint32_t i=0;i::Element *E=active_audio_streams.front();E;E=E->next()) { + for(List::Element *E=active_audio_streams.front();E;) { //stream might be removed durnig this callback + + List::Element *N=E->next(); if (E->get()->audio_stream && p_thread == E->get()->audio_stream->can_update_mt()) E->get()->audio_stream->update(); + + E=N; } } diff --git a/tools/editor/spatial_editor_gizmos.h b/tools/editor/spatial_editor_gizmos.h index 8d6730e2f1a..02f60db7f80 100644 --- a/tools/editor/spatial_editor_gizmos.h +++ b/tools/editor/spatial_editor_gizmos.h @@ -201,6 +201,8 @@ public: }; + + class SpatialPlayerSpatialGizmo : public SpatialGizmoTool { OBJ_TYPE(SpatialPlayerSpatialGizmo,SpatialGizmoTool); @@ -214,6 +216,8 @@ public: }; + + class TestCubeSpatialGizmo : public SpatialGizmoTool { OBJ_TYPE(TestCubeSpatialGizmo,SpatialGizmoTool);