diff options
Diffstat (limited to 'servers/spatial_sound/spatial_sound_server_sw.cpp')
| -rw-r--r-- | servers/spatial_sound/spatial_sound_server_sw.cpp | 1071 |
1 files changed, 0 insertions, 1071 deletions
diff --git a/servers/spatial_sound/spatial_sound_server_sw.cpp b/servers/spatial_sound/spatial_sound_server_sw.cpp deleted file mode 100644 index d550134d82..0000000000 --- a/servers/spatial_sound/spatial_sound_server_sw.cpp +++ /dev/null @@ -1,1071 +0,0 @@ -/*************************************************************************/ -/* spatial_sound_server_sw.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2017 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 "spatial_sound_server_sw.h" -#include "os/os.h" -#include "servers/audio/audio_filter_sw.h" - - - -int SpatialSoundServerSW::InternalAudioStream::get_channel_count() const { - - return AudioServer::get_singleton()->get_default_channel_count(); -} - -void SpatialSoundServerSW::InternalAudioStream::set_mix_rate(int p_rate) { - - -} - -void SpatialSoundServerSW::InternalAudioStream::update() { - - owner->_update_sources(); -} - -bool SpatialSoundServerSW::InternalAudioStream::mix(int32_t *p_buffer,int p_frames) { - - return owner->internal_buffer_mix(p_buffer,p_frames); -} - -void SpatialSoundServerSW::_update_sources() { - - _THREAD_SAFE_METHOD_ - for (Set<Source*>::Element *E=streaming_sources.front();E;E=E->next()) { - - Source *s=E->get(); - ERR_CONTINUE(!s->stream); - s->stream->update(); - } -} - - -SpatialSoundServerSW::Room::Room() { - - //params[ROOM_PARAM_SPEED_OF_SOUND]=343.0; - params[ROOM_PARAM_SPEED_OF_SOUND_SCALE]=1; - params[ROOM_PARAM_DOPPLER_FACTOR]=1.0; - params[ROOM_PARAM_PITCH_SCALE]=1.0; - params[ROOM_PARAM_VOLUME_SCALE_DB]=0; - params[ROOM_PARAM_REVERB_SEND]=0; - params[ROOM_PARAM_CHORUS_SEND]=0; - params[ROOM_PARAM_ATTENUATION_SCALE]=1.0; - params[ROOM_PARAM_ATTENUATION_HF_CUTOFF]=5000; - params[ROOM_PARAM_ATTENUATION_HF_FLOOR_DB]=-24.0; - params[ROOM_PARAM_ATTENUATION_HF_RATIO_EXP]=1.0; - params[ROOM_PARAM_ATTENUATION_REVERB_SCALE]=0.0; - override_other_sources=false; - reverb=ROOM_REVERB_HALL; - octree_id=0; - level=-1; - - -} - - -SpatialSoundServerSW::Source::Source() { - - params[SOURCE_PARAM_VOLUME_DB]=0.0; - params[SOURCE_PARAM_PITCH_SCALE]=1.0; - params[SOURCE_PARAM_ATTENUATION_MIN_DISTANCE]=1; - params[SOURCE_PARAM_ATTENUATION_MAX_DISTANCE]=100; - params[SOURCE_PARAM_ATTENUATION_DISTANCE_EXP]=1.0; //linear (and not really good) - params[SOURCE_PARAM_EMISSION_CONE_DEGREES]=180.0; //cone disabled - params[SOURCE_PARAM_EMISSION_CONE_ATTENUATION_DB]=-6.0; //minus 6 db attenuation - stream=NULL; - voices.resize(1); - last_voice=0; -} - -SpatialSoundServerSW::Source::Voice::Voice() { - - active=false; - restart=false; - pitch_scale=1.0; - volume_scale=0.0; - voice_rid=AudioServer::get_singleton()->voice_create(); - -} -SpatialSoundServerSW::Source::Voice::~Voice() { - - AudioServer::get_singleton()->free(voice_rid); -} - - -SpatialSoundServerSW::Listener::Listener() { - - params[LISTENER_PARAM_VOLUME_SCALE_DB]=0.0; - params[LISTENER_PARAM_PITCH_SCALE]=1.0; - params[LISTENER_PARAM_ATTENUATION_SCALE]=1.0; - params[LISTENER_PARAM_RECEPTION_CONE_DEGREES]=60.0; - params[LISTENER_PARAM_RECEPTION_CONE_ATTENUATION_DB]=-6; // minus six decibels - -} - -/* SPACE */ -RID SpatialSoundServerSW::space_create() { - - Space* space = memnew( Space ); - RID space_rid = space_owner.make_rid(space); - space->default_room=room_create(); - room_set_space(space->default_room,space_rid); - return space_rid; -} - -/* ROOM */ - -RID SpatialSoundServerSW::room_create() { - - Room *room = memnew( Room ); - return room_owner.make_rid(room); -} - -void SpatialSoundServerSW::room_set_space(RID p_room,RID p_space) { - - Room *room = room_owner.get(p_room); - ERR_FAIL_COND(!room); - - if (room->space.is_valid()) { - - Space *space = space_owner.get(room->space); - space->rooms.erase(p_room); - space->octree.erase(room->octree_id); - //room->octree_id=0; - } - - room->space=RID(); - - if (p_space.is_valid()) { - - Space *space = space_owner.get(p_space); - ERR_FAIL_COND(!space); - space->rooms.insert(p_room); - room->octree_id=space->octree.create(room,Rect3()); - //set bounds - Rect3 aabb = room->bounds.is_empty()?Rect3():room->bounds.get_aabb(); - space->octree.move(room->octree_id,room->transform.xform(aabb)); - room->space=p_space; - } - - -} - -RID SpatialSoundServerSW::room_get_space(RID p_room) const { - - Room *room = room_owner.get(p_room); - ERR_FAIL_COND_V(!room,RID()); - - - return room->space; -} - - - -void SpatialSoundServerSW::room_set_bounds(RID p_room, const BSP_Tree& p_bounds) { - - Room *room = room_owner.get(p_room); - ERR_FAIL_COND(!room); - - room->bounds=p_bounds; - - if (!room->space.is_valid()) - return; - - Rect3 aabb = room->bounds.is_empty()?Rect3():room->bounds.get_aabb(); - Space* space = space_owner.get(room->space); - ERR_FAIL_COND(!space); - - space->octree.move(room->octree_id,room->transform.xform(aabb)); - -} -BSP_Tree SpatialSoundServerSW::room_get_bounds(RID p_room) const { - Room *room = room_owner.get(p_room); - ERR_FAIL_COND_V(!room,BSP_Tree()); - - return room->bounds; -} - -void SpatialSoundServerSW::room_set_transform(RID p_room, const Transform& p_transform) { - - if (space_owner.owns(p_room)) - p_room=space_owner.get(p_room)->default_room; - - Room *room = room_owner.get(p_room); - ERR_FAIL_COND(!room); - room->transform=p_transform; - room->inverse_transform=p_transform.affine_inverse(); // needs to be done to unscale BSP properly - - if (!room->space.is_valid()) - return; - - if (!room->bounds.is_empty()) { - - Space* space = space_owner.get(room->space); - ERR_FAIL_COND(!space); - - space->octree.move(room->octree_id,room->transform.xform(room->bounds.get_aabb())); - } -} - -Transform SpatialSoundServerSW::room_get_transform(RID p_room) const { - - if (space_owner.owns(p_room)) - p_room=space_owner.get(p_room)->default_room; - - Room *room = room_owner.get(p_room); - ERR_FAIL_COND_V(!room,Transform()); - return room->transform; -} - - -void SpatialSoundServerSW::room_set_param(RID p_room, RoomParam p_param, float p_value) { - - if (space_owner.owns(p_room)) - p_room=space_owner.get(p_room)->default_room; - - ERR_FAIL_INDEX(p_param,ROOM_PARAM_MAX); - Room *room = room_owner.get(p_room); - ERR_FAIL_COND(!room); - room->params[p_param]=p_value; - -} -float SpatialSoundServerSW::room_get_param(RID p_room, RoomParam p_param) const { - - if (space_owner.owns(p_room)) - p_room=space_owner.get(p_room)->default_room; - - ERR_FAIL_INDEX_V(p_param,ROOM_PARAM_MAX,0); - Room *room = room_owner.get(p_room); - ERR_FAIL_COND_V(!room,0); - return room->params[p_param]; -} - -void SpatialSoundServerSW::room_set_level(RID p_room, int p_level) { - - Room *room = room_owner.get(p_room); - ERR_FAIL_COND(!room); - room->level =p_level; - -} - -int SpatialSoundServerSW::room_get_level(RID p_room) const { - - Room *room = room_owner.get(p_room); - ERR_FAIL_COND_V(!room,0); - return room->level; - -} - - -void SpatialSoundServerSW::room_set_reverb(RID p_room, RoomReverb p_reverb) { - - if (space_owner.owns(p_room)) - p_room=space_owner.get(p_room)->default_room; - - Room *room = room_owner.get(p_room); - ERR_FAIL_COND(!room); - room->reverb=p_reverb; - -} -SpatialSoundServerSW::RoomReverb SpatialSoundServerSW::room_get_reverb(RID p_room) const { - - if (space_owner.owns(p_room)) - p_room=space_owner.get(p_room)->default_room; - - Room *room = room_owner.get(p_room); - ERR_FAIL_COND_V(!room,ROOM_REVERB_SMALL); - return room->reverb; -} - -//useful for underwater or rooms with very strange conditions -void SpatialSoundServerSW::room_set_force_params_to_all_sources(RID p_room, bool p_force) { - - if (space_owner.owns(p_room)) - p_room=space_owner.get(p_room)->default_room; - - Room *room = room_owner.get(p_room); - ERR_FAIL_COND(!room); - room->override_other_sources=p_force; - -} -bool SpatialSoundServerSW::room_is_forcing_params_to_all_sources(RID p_room) const { - - if (space_owner.owns(p_room)) - p_room=space_owner.get(p_room)->default_room; - - Room *room = room_owner.get(p_room); - ERR_FAIL_COND_V(!room,false); - return room->override_other_sources; -} - -/* SOURCE */ - -RID SpatialSoundServerSW::source_create(RID p_space) { - - Space *space = space_owner.get(p_space); - ERR_FAIL_COND_V(!space,RID()); - - Source *source = memnew( Source ); - source->space=p_space; - RID source_rid = source_owner.make_rid(source); - space->sources.insert(source_rid); - - return source_rid; -} - - -void SpatialSoundServerSW::source_set_polyphony(RID p_source,int p_voice_count) { - - - ERR_FAIL_COND(p_voice_count<=0); // more than 32 is too much, change this if you really need more - if (p_voice_count>32) { - - ERR_PRINT("Voices will be clipped to 32"); - p_voice_count=32; - } - Source *source = source_owner.get(p_source); - ERR_FAIL_COND(!source); - - if (p_voice_count<source->voices.size()) { - - for(int i=p_voice_count;i<source->voices.size();i++) { - active_voices.erase(ActiveVoice(source,i)); //erase from active voices - } - } - source->voices.resize(p_voice_count); - -} - -int SpatialSoundServerSW::source_get_polyphony(RID p_source) const { - - Source *source = source_owner.get(p_source); - ERR_FAIL_COND_V(!source,-1); - return source->voices.size(); - -} - -void SpatialSoundServerSW::source_set_transform(RID p_source, const Transform& p_transform) { - - Source *source = source_owner.get(p_source); - ERR_FAIL_COND(!source); - source->transform=p_transform; - source->transform.orthonormalize(); -} -Transform SpatialSoundServerSW::source_get_transform(RID p_source) const { - - Source *source = source_owner.get(p_source); - ERR_FAIL_COND_V(!source,Transform()); - return source->transform; -} - -void SpatialSoundServerSW::source_set_param(RID p_source, SourceParam p_param, float p_value) { - - ERR_FAIL_INDEX(p_param,SOURCE_PARAM_MAX); - Source *source = source_owner.get(p_source); - ERR_FAIL_COND(!source); - source->params[p_param]=p_value; - -} -float SpatialSoundServerSW::source_get_param(RID p_source, SourceParam p_param) const { - ERR_FAIL_INDEX_V(p_param,SOURCE_PARAM_MAX,0); - Source *source = source_owner.get(p_source); - ERR_FAIL_COND_V(!source,0); - return source->params[p_param]; - - -} - -void SpatialSoundServerSW::source_set_audio_stream(RID p_source, AudioServer::AudioStream *p_stream) { - - Source *source = source_owner.get(p_source); - ERR_FAIL_COND(!source); - AudioServer::get_singleton()->lock(); - source->stream=p_stream; - _THREAD_SAFE_METHOD_ - - if (!p_stream) { - streaming_sources.erase(source); - active_voices.erase(ActiveVoice(source,VOICE_IS_STREAM)); - } else { - streaming_sources.insert(source); - active_voices.insert(ActiveVoice(source,VOICE_IS_STREAM)); - zeromem(source->stream_data.filter_state,sizeof(Source::StreamData::FilterState)*4); //reset filter for safetyness - p_stream->set_mix_rate(AudioServer::get_singleton()->get_default_mix_rate()); - } - - AudioServer::get_singleton()->unlock(); - -} //null to unset - -SpatialSoundServer::SourceVoiceID SpatialSoundServerSW::source_play_sample(RID p_source, RID p_sample, int p_mix_rate, int p_voice) { - - Source *source = source_owner.get(p_source); - ERR_FAIL_COND_V(!source,SOURCE_INVALID_VOICE); - - int to_play=0; - - if (p_voice==SOURCE_NEXT_VOICE) { - to_play=source->last_voice+1; - if (to_play>=source->voices.size()) - to_play=0; - - } else - to_play=p_voice; - - ERR_FAIL_INDEX_V(to_play,source->voices.size(),SOURCE_INVALID_VOICE); - - source->voices[to_play].restart=true; - source->voices[to_play].sample_rid=p_sample; - source->voices[to_play].sample_mix_rate=p_mix_rate; - source->voices[to_play].pitch_scale=1; - source->voices[to_play].volume_scale=0; - source->last_voice=to_play; - active_voices.insert(ActiveVoice(source,to_play)); - return to_play; -} - -/* VOICES */ -void SpatialSoundServerSW::source_voice_set_pitch_scale(RID p_source, SourceVoiceID p_voice, float p_pitch_scale) { - - Source *source = source_owner.get(p_source); - ERR_FAIL_COND(!source); - ERR_FAIL_INDEX(p_voice,source->voices.size()); - source->voices[p_voice].pitch_scale=p_pitch_scale; - -} -void SpatialSoundServerSW::source_voice_set_volume_scale_db(RID p_source, SourceVoiceID p_voice, float p_db) { - - Source *source = source_owner.get(p_source); - ERR_FAIL_COND(!source); - ERR_FAIL_INDEX(p_voice,source->voices.size()); - source->voices[p_voice].volume_scale=p_db; - -} - -bool SpatialSoundServerSW::source_is_voice_active(RID p_source, SourceVoiceID p_voice) const { - - Source *source = source_owner.get(p_source); - ERR_FAIL_COND_V(!source,false); - ERR_FAIL_INDEX_V(p_voice,source->voices.size(),false); - return source->voices[p_voice].active || source->voices[p_voice].restart; - -} -void SpatialSoundServerSW::source_stop_voice(RID p_source, SourceVoiceID p_voice) { - - Source *source = source_owner.get(p_source); - ERR_FAIL_COND(!source); - ERR_FAIL_INDEX(p_voice,source->voices.size()); - if (source->voices[p_voice].active) { - AudioServer::get_singleton()->voice_stop(source->voices[p_voice].voice_rid); - } - source->voices[p_voice].active=false; - source->voices[p_voice].restart=false; - active_voices.erase(ActiveVoice(source,p_voice)); -} - -/* LISTENER */ - -RID SpatialSoundServerSW::listener_create() { - - Listener *listener = memnew( Listener ); - RID listener_rid = listener_owner.make_rid(listener); - return listener_rid; - -} - -void SpatialSoundServerSW::listener_set_space(RID p_listener,RID p_space) { - - Listener *listener = listener_owner.get(p_listener); - ERR_FAIL_COND(!listener); - - if (listener->space.is_valid()) { - - Space *lspace = space_owner.get(listener->space); - ERR_FAIL_COND(!lspace); - lspace->listeners.erase(p_listener); - } - - listener->space=RID(); - - if (p_space.is_valid()) { - Space *space = space_owner.get(p_space); - ERR_FAIL_COND(!space); - - listener->space=p_space; - space->listeners.insert(p_listener); - } - -} - -void SpatialSoundServerSW::listener_set_transform(RID p_listener, const Transform& p_transform) { - - Listener *listener = listener_owner.get(p_listener); - ERR_FAIL_COND(!listener); - listener->transform=p_transform; - listener->transform.orthonormalize(); //must be done.. -} -Transform SpatialSoundServerSW::listener_get_transform(RID p_listener) const { - - Listener *listener = listener_owner.get(p_listener); - ERR_FAIL_COND_V(!listener,Transform()); - return listener->transform; -} - -void SpatialSoundServerSW::listener_set_param(RID p_listener, ListenerParam p_param, float p_value) { - - ERR_FAIL_INDEX(p_param,LISTENER_PARAM_MAX); - Listener *listener = listener_owner.get(p_listener); - ERR_FAIL_COND(!listener); - listener->params[p_param]=p_value; -} - -float SpatialSoundServerSW::listener_get_param(RID p_listener, ListenerParam p_param) const { - - ERR_FAIL_INDEX_V(p_param,LISTENER_PARAM_MAX,0); - Listener *listener = listener_owner.get(p_listener); - ERR_FAIL_COND_V(!listener,0); - return listener->params[p_param]; -} - - -/* MISC */ - -void SpatialSoundServerSW::free(RID p_id) { - - - if (space_owner.owns(p_id)) { - - Space *space = space_owner.get(p_id); - free(space->default_room); - - while(space->listeners.size()) { - listener_set_space(space->listeners.front()->get(),RID()); - } - while(space->sources.size()) { - free(space->sources.front()->get()); - } - while(space->rooms.size()) { - room_set_space(space->rooms.front()->get(),RID()); - } - space_owner.free(p_id); - memdelete(space); - - } else if (source_owner.owns(p_id)) { - - Source *source = source_owner.get(p_id); - if (source->stream) - source_set_audio_stream(p_id,NULL); - - Space *space = space_owner.get(source->space); - ERR_FAIL_COND(!space); - space->sources.erase(p_id); - for(int i=0;i<source->voices.size();i++) { - active_voices.erase(ActiveVoice(source,i)); - } - source_owner.free(p_id); - memdelete(source); - } else if (listener_owner.owns(p_id)) { - - Listener *listener = listener_owner.get(p_id); - if (listener->space.is_valid()) { - Space *space = space_owner.get(listener->space); - ERR_FAIL_COND(!space); - space->listeners.erase(p_id); - } - listener_owner.free(p_id); - memdelete(listener); - - } else if (room_owner.owns(p_id)) { - - Room *room = room_owner.get(p_id); - - if (room->space.is_valid()) { - Space *space = space_owner.get(room->space); - ERR_FAIL_COND(!space); - space->octree.erase(room->octree_id); - space->rooms.erase(p_id); - } - room_owner.free(p_id); - memdelete(room); - } else { - ERR_PRINT("Attempt to free invalid ID") ; - } - -} - -void SpatialSoundServerSW::_clean_up_owner(RID_OwnerBase *p_owner, const char *p_area) { - - List<RID> rids; - p_owner->get_owned_list(&rids); - - for(List<RID>::Element *I=rids.front();I;I=I->next()) { - if (OS::get_singleton()->is_stdout_verbose()) { - - print_line("Leaked RID ("+itos(I->get().get_id())+") of type "+String(p_area)); - } - free(I->get()); - } -} - -void SpatialSoundServerSW::init() { - - internal_buffer = memnew_arr(int32_t, INTERNAL_BUFFER_SIZE*INTERNAL_BUFFER_MAX_CHANNELS); - internal_buffer_channels=AudioServer::get_singleton()->get_default_channel_count(); - - internal_audio_stream = memnew( InternalAudioStream ); - internal_audio_stream->owner=this; - internal_audio_stream_rid = AudioServer::get_singleton()->audio_stream_create(internal_audio_stream); - - AudioServer::get_singleton()->stream_set_active(internal_audio_stream_rid,true); - -} - - - -static float _get_attenuation(float cosine, float angle, float attenuation) { - - - float listener_ang = Math::rad2deg(Math::acos(cosine))-angle; - - if (listener_ang>0 && angle<180.0) { - listener_ang/=(180.0-angle); - return Math::db2linear(Math::sin(listener_ang*(Math_PI/2.0))*attenuation); - } - return 1.0; -} - - -bool SpatialSoundServerSW::internal_buffer_mix(int32_t *p_buffer,int p_frames) { - - if (streaming_sources.size()==0) - return false; //nothing to mix - - - for (Set<Source*>::Element *E=streaming_sources.front();E;E=E->next()) { - - Source *s=E->get(); - ERR_CONTINUE(!s->stream); - - int channels = s->stream->get_channel_count(); - Source::StreamData &sd=s->stream_data; - - int todo=p_frames; - - AudioFilterSW filter; - filter.set_sampling_rate(AudioServer::get_singleton()->get_default_mix_rate()); - filter.set_cutoff(sd.filter_cutoff); - filter.set_gain(sd.filter_gain); - filter.set_resonance(1); - filter.set_mode(AudioFilterSW::HIGHSHELF); - filter.set_stages(1); - AudioFilterSW::Coeffs coefs; - filter.prepare_coefficients(&coefs); - - int32_t in[4]; -#ifndef SPATIAL_SOUND_SERVER_NO_FILTER -#define DO_FILTER(m_c)\ - {\ - float val = in[m_c];\ - float pre=val;\ - val = val*coefs.b0 + sd.filter_state[m_c].hb[0]*coefs.b1 + sd.filter_state[m_c].hb[1]*coefs.b2 + sd.filter_state[m_c].ha[0]*coefs.a1 + sd.filter_state[m_c].ha[1]*coefs.a2;\ - sd.filter_state[m_c].ha[1]=sd.filter_state[m_c].ha[0];\ - sd.filter_state[m_c].hb[1]=sd.filter_state[m_c].hb[0]; \ - sd.filter_state[m_c].hb[0]=pre;\ - sd.filter_state[m_c].ha[0]=val;\ - in[m_c]=Math::fast_ftoi(val);\ - } -#else -#define DO_FILTER(m_c) -#endif - - while(todo) { - - int to_mix=MIN(todo,INTERNAL_BUFFER_SIZE); - - s->stream->mix(internal_buffer,to_mix); - - switch(internal_buffer_channels) { - - case 2: { - - float p = sd.panning.x*0.5+0.5; - float panf[2]={ (1.0-p),p }; - panf[0]*=sd.volume; - panf[1]*=sd.volume; - - int32_t pan[2]={Math::fast_ftoi(panf[0]*(1<<16)),Math::fast_ftoi(panf[1]*(1<<16))}; - - switch(channels) { - case 1: { - - for(int i=0;i<to_mix;i++) { - - in[0]=internal_buffer[i]; - in[1]=internal_buffer[i]; - DO_FILTER(0); - DO_FILTER(1); - p_buffer[(i<<1)+0]=((in[0]>>16)*pan[0]); - p_buffer[(i<<1)+1]=((in[1]>>16)*pan[1]); - } - } break; - case 2: { - - for(int i=0;i<to_mix;i++) { - - in[0]=internal_buffer[(i<<1)+0]; - in[1]=internal_buffer[(i<<1)+1]; - DO_FILTER(0); - DO_FILTER(1); - p_buffer[(i<<1)+0]=((in[0]>>16)*pan[0]); - p_buffer[(i<<1)+1]=((in[1]>>16)*pan[1]); - } - } break; - case 4: { - - for(int i=0;i<to_mix;i++) { - - in[0]=(internal_buffer[(i<<2)+0]+internal_buffer[(i<<2)+2])>>1; - in[1]=(internal_buffer[(i<<2)+1]+internal_buffer[(i<<2)+3])>>1; - DO_FILTER(0); - DO_FILTER(1); - p_buffer[(i<<1)+0]=((in[0]>>16)*pan[0]); - p_buffer[(i<<1)+1]=((in[1]>>16)*pan[1]); - } - } break; - - } break; - - } break; - case 4: { - - float xp = sd.panning.x*0.5+0.5; - float yp = sd.panning.y*0.5+0.5; - float panf[4]={ (1.0-xp)*(1.0-yp),(xp)*(1.0-yp),(1.0-xp)*(yp),(xp)*(yp) }; - panf[0]*=sd.volume; - panf[1]*=sd.volume; - panf[2]*=sd.volume; - panf[3]*=sd.volume; - - int32_t pan[4]={ - Math::fast_ftoi(panf[0]*(1<<16)), - Math::fast_ftoi(panf[1]*(1<<16)), - Math::fast_ftoi(panf[2]*(1<<16)), - Math::fast_ftoi(panf[3]*(1<<16))}; - - switch(channels) { - case 1: { - - for(int i=0;i<to_mix;i++) { - - in[0]=internal_buffer[i]; - in[1]=internal_buffer[i]; - in[2]=internal_buffer[i]; - in[3]=internal_buffer[i]; - DO_FILTER(0); - DO_FILTER(1); - DO_FILTER(2); - DO_FILTER(3); - p_buffer[(i<<2)+0]=((in[0]>>16)*pan[0]); - p_buffer[(i<<2)+1]=((in[1]>>16)*pan[1]); - p_buffer[(i<<2)+2]=((in[2]>>16)*pan[2]); - p_buffer[(i<<2)+3]=((in[3]>>16)*pan[3]); - } - } break; - case 2: { - - for(int i=0;i<to_mix;i++) { - - in[0]=internal_buffer[(i<<1)+0]; - in[1]=internal_buffer[(i<<1)+1]; - in[2]=internal_buffer[(i<<1)+0]; - in[3]=internal_buffer[(i<<1)+1]; - DO_FILTER(0); - DO_FILTER(1); - DO_FILTER(2); - DO_FILTER(3); - p_buffer[(i<<2)+0]=((in[0]>>16)*pan[0]); - p_buffer[(i<<2)+1]=((in[1]>>16)*pan[1]); - p_buffer[(i<<2)+2]=((in[2]>>16)*pan[2]); - p_buffer[(i<<2)+3]=((in[3]>>16)*pan[3]); - } - } break; - case 4: { - - for(int i=0;i<to_mix;i++) { - - in[0]=internal_buffer[(i<<2)+0]; - in[1]=internal_buffer[(i<<2)+1]; - in[2]=internal_buffer[(i<<2)+2]; - in[3]=internal_buffer[(i<<2)+3]; - DO_FILTER(0); - DO_FILTER(1); - DO_FILTER(2); - DO_FILTER(3); - p_buffer[(i<<2)+0]=((in[0]>>16)*pan[0]); - p_buffer[(i<<2)+1]=((in[1]>>16)*pan[1]); - p_buffer[(i<<2)+2]=((in[2]>>16)*pan[2]); - p_buffer[(i<<2)+3]=((in[3]>>16)*pan[3]); - } - } break; - - } break; - - } break; - case 6: { - - - } break; - } - p_buffer+=to_mix*internal_buffer_channels; - todo-=to_mix; - - } - - } - - return true; -} - -void SpatialSoundServerSW::update(float p_delta) { - - List<ActiveVoice> to_disable; - - - for(Set<ActiveVoice>::Element *E=active_voices.front();E;E=E->next()) { - - Source *source = E->get().source; - int voice = E->get().voice; - - if (voice!=VOICE_IS_STREAM) { - Source::Voice &v=source->voices[voice]; - ERR_CONTINUE(!v.active && !v.restart); // likely a bug... - } - - //this could be optimized at some point... am not sure - Space *space=space_owner.get(source->space); - Room *room=room_owner.get(space->default_room); - int max_level=-0x80000000; - int rooms_culled = space->octree.cull_point(source->transform.origin,cull_rooms,MAX_CULL_ROOMS); - for(int i=0;i<rooms_culled;i++) { - - Room *r=cull_rooms[i]; - ERR_CONTINUE( r->bounds.is_empty() ); // how did this happen?? - if (r->level<=max_level) //ignore optimization (level too low) - continue; - Vector3 local_point = r->inverse_transform.xform(source->transform.origin); - if (!r->bounds.point_is_inside(local_point)) - continue; - room=r; - max_level=r->level; - - } - - - //compute mixing weights (support for multiple listeners in the same output) - float total_distance=0; - for(Set<RID>::Element *L=space->listeners.front();L;L=L->next()) { - Listener *listener=listener_owner.get(L->get()); - total_distance+=listener->transform.origin.distance_to(source->transform.origin); - } - - //compute spatialization variables, weighted according to distance - float volume_attenuation = 0.0; - float air_absorption_hf_cutoff = 0.0; - float air_absorption = 0.0; - float pitch_scale=1.0; - Vector3 panning; - - - //print_line("listeners: "+itos(space->listeners.size())); - - - for(Set<RID>::Element *L=space->listeners.front();L;L=L->next()) { - - Listener *listener=listener_owner.get(L->get()); - - Vector3 rel_vector = listener->transform.xform_inv(source->transform.origin); - Vector3 source_rel_vector = source->transform.xform_inv(listener->transform.origin).normalized(); - float distance=rel_vector.length(); - float weight = distance/total_distance; - float pscale=1.0; - - float distance_scale=listener->params[LISTENER_PARAM_ATTENUATION_SCALE]*room->params[ROOM_PARAM_ATTENUATION_SCALE]; - float distance_min=source->params[SOURCE_PARAM_ATTENUATION_MIN_DISTANCE]*distance_scale; - float distance_max=source->params[SOURCE_PARAM_ATTENUATION_MAX_DISTANCE]*distance_scale; - float attenuation_exp=source->params[SOURCE_PARAM_ATTENUATION_DISTANCE_EXP]; - float attenuation=1; - - //print_line("DIST MIN: "+rtos(distance_min)); - //print_line("DIST MAX: "+rtos(distance_max)); - if (distance_max>0) { - distance = CLAMP(distance,distance_min,distance_max); - attenuation = Math::pow(1.0 - ((distance - distance_min)/(distance_max-distance_min)),CLAMP(attenuation_exp,0.001,16)); - } - - float hf_attenuation_cutoff = room->params[ROOM_PARAM_ATTENUATION_HF_CUTOFF]; - float hf_attenuation_exp = room->params[ROOM_PARAM_ATTENUATION_HF_RATIO_EXP]; - float hf_attenuation_floor = room->params[ROOM_PARAM_ATTENUATION_HF_FLOOR_DB]; - float absorption=Math::db2linear(Math::lerp(hf_attenuation_floor,0,Math::pow(attenuation,hf_attenuation_exp))); - - // source emission cone - - float emission_deg=source->params[SOURCE_PARAM_EMISSION_CONE_DEGREES]; - float emission_attdb=source->params[SOURCE_PARAM_EMISSION_CONE_ATTENUATION_DB]; - absorption*=_get_attenuation(source_rel_vector.dot(Vector3(0,0,-1)),emission_deg,emission_attdb); - - Vector3 vpanning=rel_vector.normalized(); - - //listener stuff - - { - - // head cone - - float reception_deg=listener->params[LISTENER_PARAM_RECEPTION_CONE_DEGREES]; - float reception_attdb=listener->params[LISTENER_PARAM_RECEPTION_CONE_ATTENUATION_DB]; - - absorption*=_get_attenuation(vpanning.dot(Vector3(0,0,-1)),reception_deg,reception_attdb); - - // scale - - attenuation*=Math::db2linear(listener->params[LISTENER_PARAM_VOLUME_SCALE_DB]); - pscale*=Math::db2linear(listener->params[LISTENER_PARAM_PITCH_SCALE]); - - - } - - - - - //add values - - volume_attenuation+=weight*attenuation; // plus other stuff i guess - air_absorption+=weight*absorption; - air_absorption_hf_cutoff+=weight*hf_attenuation_cutoff; - panning+=vpanning*weight; - //pitch_scale+=pscale*weight; - - } - - RoomReverb reverb_room; - float reverb_send; - - /* APPLY ROOM SETTINGS */ - - { - pitch_scale*=room->params[ROOM_PARAM_PITCH_SCALE]; - volume_attenuation*=Math::db2linear(room->params[ROOM_PARAM_VOLUME_SCALE_DB]); - reverb_room=room->reverb; - reverb_send=Math::lerp(1.0,volume_attenuation,room->params[ROOM_PARAM_ATTENUATION_REVERB_SCALE])*room->params[ROOM_PARAM_REVERB_SEND]; - - } - - /* UPDATE VOICE & STREAM */ - - - - if (voice==VOICE_IS_STREAM) { - - //update voice!! - source->stream_data.panning=panning; - source->stream_data.volume=volume_attenuation*Math::db2linear(source->params[SOURCE_PARAM_VOLUME_DB]); - source->stream_data.reverb=reverb_room; - source->stream_data.reverb_send=reverb_send; - source->stream_data.filter_gain=air_absorption; - source->stream_data.filter_cutoff=air_absorption_hf_cutoff; - - if (!source->stream) //stream is gone bye bye - to_disable.push_back(ActiveVoice(source,voice)); // oh well.. - - } else if (voice>=0) { - //update stream!! - Source::Voice &v=source->voices[voice]; - - if (v.restart) - AudioServer::get_singleton()->voice_play(v.voice_rid,v.sample_rid); - - float volume_scale = Math::db2linear(v.volume_scale)*Math::db2linear(source->params[SOURCE_PARAM_VOLUME_DB]); - float volume = volume_attenuation*volume_scale; - reverb_send*=volume_scale; - int mix_rate = v.sample_mix_rate*v.pitch_scale*pitch_scale*source->params[SOURCE_PARAM_PITCH_SCALE]; - - - if (mix_rate<=0) { - ERR_PRINT("Invalid mix rate for voice (0) check for invalid pitch_scale param."); - to_disable.push_back(ActiveVoice(source,voice)); // oh well.. - continue; //invalid mix rate, disabling - } - if (v.restart || v.last_volume!=volume) - AudioServer::get_singleton()->voice_set_volume(v.voice_rid,volume); - if (v.restart || v.last_mix_rate!=mix_rate) - AudioServer::get_singleton()->voice_set_mix_rate(v.voice_rid,mix_rate); - if (v.restart || v.last_filter_gain!=air_absorption || v.last_filter_cutoff!=air_absorption_hf_cutoff) - AudioServer::get_singleton()->voice_set_filter(v.voice_rid,AudioServer::FILTER_HIGH_SHELF,air_absorption_hf_cutoff,1.0,air_absorption); - if (v.restart || v.last_panning!=panning) - AudioServer::get_singleton()->voice_set_pan(v.voice_rid,panning.x,panning.y,panning.z); - if (v.restart || v.last_reverb_room!=reverb_room || v.last_reverb_send!=reverb_send) - AudioServer::get_singleton()->voice_set_reverb(v.voice_rid,AudioServer::ReverbRoomType(reverb_room),reverb_send); - - v.last_volume=volume; - v.last_mix_rate=mix_rate; - v.last_filter_gain=air_absorption; - v.last_filter_cutoff=air_absorption_hf_cutoff; - v.last_panning=panning; - v.restart=false; - v.active=true; - - if (!AudioServer::get_singleton()->voice_is_active(v.voice_rid)) - to_disable.push_back(ActiveVoice(source,voice)); // oh well.. - } - } - - while(to_disable.size()) { - - ActiveVoice av = to_disable.front()->get(); - av.source->voices[av.voice].active=false; - av.source->voices[av.voice].restart=false; - active_voices.erase(av); - to_disable.pop_front(); - } - -} -void SpatialSoundServerSW::finish() { - - AudioServer::get_singleton()->free(internal_audio_stream_rid); - memdelete(internal_audio_stream); - - _clean_up_owner(&source_owner,"Source"); - _clean_up_owner(&listener_owner,"Listener"); - _clean_up_owner(&room_owner,"Room"); - _clean_up_owner(&space_owner,"Space"); - - memdelete_arr(internal_buffer); -} - -SpatialSoundServerSW::SpatialSoundServerSW() { - -} |
