diff options
Diffstat (limited to 'servers/audio_server.cpp')
| -rw-r--r-- | servers/audio_server.cpp | 614 |
1 files changed, 583 insertions, 31 deletions
diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp index 9b938a7f8..90e35c7fc 100644 --- a/servers/audio_server.cpp +++ b/servers/audio_server.cpp @@ -42,12 +42,16 @@ void AudioDriver::set_singleton() { void AudioDriver::audio_server_process(int p_frames,int32_t *p_buffer,bool p_update_mix_time) { - AudioServer * audio_server = static_cast<AudioServer*>(AudioServer::get_singleton()); + if (p_update_mix_time) update_mix_time(p_frames); -// audio_server->driver_process(p_frames,p_buffer); + + if (AudioServer::get_singleton()) + AudioServer::get_singleton()->_driver_process(p_frames,p_buffer); } + + void AudioDriver::update_mix_time(int p_frames) { _mix_amount+=p_frames; @@ -74,7 +78,6 @@ AudioDriver *AudioDriverManager::drivers[MAX_DRIVERS]; int AudioDriverManager::driver_count=0; - void AudioDriverManager::add_driver(AudioDriver *p_driver) { ERR_FAIL_COND(driver_count>=MAX_DRIVERS); @@ -97,13 +100,286 @@ AudioDriver *AudioDriverManager::get_driver(int p_driver) { ////////////////////////////////////////////// ////////////////////////////////////////////// +void AudioServer::_driver_process(int p_frames,int32_t* p_buffer) { + + int todo=p_frames; + + while(todo) { + + if (to_mix==0) { + _mix_step(); + } + + int to_copy = MIN(to_mix,todo); + + Bus *master = buses[0]; + + int from = buffer_size-to_mix; + int from_buf=p_frames-todo; + + //master master, send to output + int cs = master->channels.size(); + for(int k=0;k<cs;k++) { + + if (master->channels[k].active) { + + AudioFrame *buf = master->channels[k].buffer.ptr(); + + for(int j=0;j<to_copy;j++) { + + float l = CLAMP(buf[from+j].l,-1.0,1.0); + int32_t vl = l*((1<<20)-1); + p_buffer[(from_buf+j)*(cs*2)+k*2+0]=vl<<11; + + float r = CLAMP(buf[from+j].r,-1.0,1.0); + int32_t vr = r*((1<<20)-1); + p_buffer[(from_buf+j)*(cs*2)+k*2+1]=vr<<11; + } + + } else { + for(int j=0;j<to_copy;j++) { + + p_buffer[(from_buf+j)*(cs*2)+k*2+0]=0; + p_buffer[(from_buf+j)*(cs*2)+k*2+1]=0; + } + } + + } + + todo-=to_copy; + to_mix-=to_copy; + + } + +} + +void AudioServer::_mix_step() { + + for(int i=0;i<buses.size();i++) { + Bus *bus = buses[i]; + bus->index_cache=i; //might be moved around by editor, so.. + for(int k=0;k<bus->channels.size();k++) { + + bus->channels[k].used=false; + } + } + + //make callbacks for mixing the audio + for (Set<CallbackItem>::Element *E=callbacks.front();E;E=E->next()) { + + E->get().callback(E->get().userdata); + } + + for(int i=buses.size()-1;i>=0;i--) { + //go bus by bus + Bus *bus = buses[i]; + + + for(int k=0;k<bus->channels.size();k++) { + + if (bus->channels[k].active && !bus->channels[k].used) { + //buffer was not used, but it's still active, so it must be cleaned + AudioFrame *buf = bus->channels[k].buffer.ptr(); + + for(uint32_t j=0;j<buffer_size;j++) { + + buf[j]=AudioFrame(0,0); + } + } + + } + + + //process effects + for(int j=0;j<bus->effects.size();j++) { + + if (!bus->effects[j].enabled) + continue; + + for(int k=0;k<bus->channels.size();k++) { + + if (!bus->channels[k].active) + continue; + bus->channels[k].effect_instances[j]->process(bus->channels[k].buffer.ptr(),temp_buffer[k].ptr(),buffer_size); + } + + //swap buffers, so internal buffer always has the right data + for(int k=0;k<bus->channels.size();k++) { + + if (!buses[i]->channels[k].active) + continue; + SWAP(bus->channels[k].buffer,temp_buffer[k]); + } + } + + //process send + + Bus *send=NULL; + + if (i>0) { + //everything has a send save for master bus + if (!bus_map.has(bus->send)) { + send=buses[0]; + } else { + send=bus_map[bus->send]; + if (send->index_cache>=bus->index_cache) { //invalid, send to master + send=buses[0]; + } + } + } + + + for(int k=0;k<bus->channels.size();k++) { + + if (!bus->channels[k].active) + continue; + + AudioFrame *buf = bus->channels[k].buffer.ptr(); + + + AudioFrame peak = AudioFrame(0,0); + for(uint32_t j=0;j<buffer_size;j++) { + float l = ABS(buf[j].l); + if (l>peak.l) { + peak.l=l; + } + float r = ABS(buf[j].r); + if (r>peak.r) { + peak.r=r; + } + } + + bus->channels[k].peak_volume=AudioFrame(Math::linear2db(peak.l+0.0000000001),Math::linear2db(peak.r+0.0000000001)); + + + if (!bus->channels[k].used) { + //see if any audio is contained, because channel was not used + + + if (MAX(peak.r,peak.l) > Math::db2linear(channel_disable_treshold_db)) { + bus->channels[k].last_mix_with_audio=mix_frames; + } else if (mix_frames-bus->channels[k].last_mix_with_audio > channel_disable_frames ) { + bus->channels[k].active=false; + continue; //went inactive, dont mix. + } + } + + if (send) { + //if not master bus, send + AudioFrame *target_buf = thread_get_channel_mix_buffer(send->index_cache,k); + + for(uint32_t j=0;j<buffer_size;j++) { + target_buf[j]+=buf[j]; + } + } + + } + + } + + + mix_frames+=buffer_size; + to_mix=buffer_size; + +} + +AudioFrame *AudioServer::thread_get_channel_mix_buffer(int p_bus,int p_buffer) { + + ERR_FAIL_INDEX_V(p_bus,buses.size(),NULL); + ERR_FAIL_INDEX_V(p_buffer,buses[p_bus]->channels.size(),NULL); + + AudioFrame *data = buses[p_bus]->channels[p_buffer].buffer.ptr(); + + + if (!buses[p_bus]->channels[p_buffer].used) { + buses[p_bus]->channels[p_buffer].used=true; + buses[p_bus]->channels[p_buffer].active=true; + buses[p_bus]->channels[p_buffer].last_mix_with_audio=mix_frames; + for(uint32_t i=0;i<buffer_size;i++) { + data[i]=AudioFrame(0,0); + } + } + + return data; +} + +int AudioServer::thread_get_mix_buffer_size() const { + + return buffer_size; +} + +int AudioServer::thread_find_bus_index(const StringName& p_name) { + + if (bus_map.has(p_name)) { + return bus_map[p_name]->index_cache; + } else { + return 0; + } + +} + void AudioServer::set_bus_count(int p_count) { ERR_FAIL_COND(p_count<1); ERR_FAIL_INDEX(p_count,256); lock(); + int cb = buses.size(); + + if (p_count<buses.size()) { + for(int i=p_count;i<buses.size();i++) { + bus_map.erase(buses[i]->name); + memdelete(buses[i]); + } + } + buses.resize(p_count); + + for(int i=cb;i<buses.size();i++) { + + String attempt="New Bus"; + int attempts=1; + while(true) { + + bool name_free=true; + for(int j=0;j<i;j++) { + + if (buses[j]->name==attempt) { + name_free=false; + break; + } + } + + if (!name_free) { + attempts++; + attempt="New Bus " +itos(attempts); + } else { + break; + } + + } + + + buses[i]=memnew(Bus); + buses[i]->channels.resize(_get_channel_count()); + for(int j=0;j<_get_channel_count();j++) { + buses[i]->channels[j].buffer.resize(buffer_size); + } + buses[i]->name=attempt; + buses[i]->solo=false; + buses[i]->mute=false; + buses[i]->bypass=false; + buses[i]->volume_db=0; + if (i>0) { + buses[i]->send="Master"; + } + + bus_map[attempt]=buses[i]; + + } + unlock(); + + emit_signal("bus_layout_changed"); } int AudioServer::get_bus_count() const { @@ -111,42 +387,138 @@ int AudioServer::get_bus_count() const { return buses.size(); } -void AudioServer::set_bus_mode(int p_bus,BusMode p_mode) { + +void AudioServer::set_bus_name(int p_bus,const String& p_name) { ERR_FAIL_INDEX(p_bus,buses.size()); + if (p_bus==0 && p_name!="Master") + return; //bus 0 is always master + lock(); -} -AudioServer::BusMode AudioServer::get_bus_mode(int p_bus) const { + if (buses[p_bus]->name==p_name) { + unlock(); + return; + } - ERR_FAIL_INDEX_V(p_bus,buses.size(),BUS_MODE_STEREO); + String attempt=p_name; + int attempts=1; - return buses[p_bus].mode; -} + while(true) { -void AudioServer::set_bus_name(int p_bus,const String& p_name) { + bool name_free=true; + for(int i=0;i<buses.size();i++) { - ERR_FAIL_INDEX(p_bus,buses.size()); - buses[p_bus].name=p_name; + if (buses[i]->name==attempt) { + name_free=false; + break; + } + } + + if (name_free) { + break; + } + + attempts++; + attempt=p_name+" "+itos(attempts); + } + bus_map.erase(buses[p_bus]->name); + buses[p_bus]->name=attempt; + bus_map[attempt]=buses[p_bus]; + unlock(); + + emit_signal("bus_layout_changed"); } String AudioServer::get_bus_name(int p_bus) const { ERR_FAIL_INDEX_V(p_bus,buses.size(),String()); - return buses[p_bus].name; + return buses[p_bus]->name; } void AudioServer::set_bus_volume_db(int p_bus,float p_volume_db) { ERR_FAIL_INDEX(p_bus,buses.size()); - buses[p_bus].volume_db=p_volume_db; + buses[p_bus]->volume_db=p_volume_db; } float AudioServer::get_bus_volume_db(int p_bus) const { ERR_FAIL_INDEX_V(p_bus,buses.size(),0); - return buses[p_bus].volume_db; + return buses[p_bus]->volume_db; + +} + +void AudioServer::set_bus_send(int p_bus,const StringName& p_send) { + + ERR_FAIL_INDEX(p_bus,buses.size()); + + buses[p_bus]->send=p_send; + +} + +StringName AudioServer::get_bus_send(int p_bus) const { + + ERR_FAIL_INDEX_V(p_bus,buses.size(),StringName()); + return buses[p_bus]->send; + +} + + +void AudioServer::set_bus_solo(int p_bus,bool p_enable) { + + ERR_FAIL_INDEX(p_bus,buses.size()); + + buses[p_bus]->solo=p_enable; + +} + +bool AudioServer::is_bus_solo(int p_bus) const{ + + ERR_FAIL_INDEX_V(p_bus,buses.size(),false); + + return buses[p_bus]->solo; + +} + +void AudioServer::set_bus_mute(int p_bus,bool p_enable){ + + ERR_FAIL_INDEX(p_bus,buses.size()); + + buses[p_bus]->mute=p_enable; +} +bool AudioServer::is_bus_mute(int p_bus) const{ + + ERR_FAIL_INDEX_V(p_bus,buses.size(),false); + + return buses[p_bus]->mute; + +} + +void AudioServer::set_bus_bypass_effects(int p_bus,bool p_enable){ + + ERR_FAIL_INDEX(p_bus,buses.size()); + buses[p_bus]->bypass=p_enable; } +bool AudioServer::is_bus_bypassing_effects(int p_bus) const{ + + ERR_FAIL_INDEX_V(p_bus,buses.size(),false); + + return buses[p_bus]->bypass; + +} + + +void AudioServer::_update_bus_effects(int p_bus) { + + for(int i=0;i<buses[p_bus]->channels.size();i++) { + buses[p_bus]->channels[i].effect_instances.resize(buses[p_bus]->effects.size()); + for(int j=0;j<buses[p_bus]->effects.size();j++) { + buses[p_bus]->channels[i].effect_instances[j]=buses[p_bus]->effects[j].effect->instance(); + } + } +} + void AudioServer::add_bus_effect(int p_bus,const Ref<AudioEffect>& p_effect,int p_at_pos) { @@ -160,12 +532,14 @@ void AudioServer::add_bus_effect(int p_bus,const Ref<AudioEffect>& p_effect,int //fx.instance=p_effect->instance(); fx.enabled=true; - if (p_at_pos>=buses[p_bus].effects.size() || p_at_pos<0) { - buses[p_bus].effects.push_back(fx); + if (p_at_pos>=buses[p_bus]->effects.size() || p_at_pos<0) { + buses[p_bus]->effects.push_back(fx); } else { - buses[p_bus].effects.insert(p_at_pos,fx); + buses[p_bus]->effects.insert(p_at_pos,fx); } + _update_bus_effects(p_bus); + unlock(); } @@ -176,7 +550,8 @@ void AudioServer::remove_bus_effect(int p_bus,int p_effect) { lock(); - buses[p_bus].effects.remove(p_effect); + buses[p_bus]->effects.remove(p_effect); + _update_bus_effects(p_bus); unlock(); } @@ -185,52 +560,117 @@ int AudioServer::get_bus_effect_count(int p_bus) { ERR_FAIL_INDEX_V(p_bus,buses.size(),0); - return buses[p_bus].effects.size(); + return buses[p_bus]->effects.size(); } Ref<AudioEffect> AudioServer::get_bus_effect(int p_bus,int p_effect) { ERR_FAIL_INDEX_V(p_bus,buses.size(),Ref<AudioEffect>()); - ERR_FAIL_INDEX_V(p_effect,buses[p_bus].effects.size(),Ref<AudioEffect>()); + ERR_FAIL_INDEX_V(p_effect,buses[p_bus]->effects.size(),Ref<AudioEffect>()); - return buses[p_bus].effects[p_effect].effect; + return buses[p_bus]->effects[p_effect].effect; } void AudioServer::swap_bus_effects(int p_bus,int p_effect,int p_by_effect) { ERR_FAIL_INDEX(p_bus,buses.size()); - ERR_FAIL_INDEX(p_effect,buses[p_bus].effects.size()); - ERR_FAIL_INDEX(p_by_effect,buses[p_bus].effects.size()); + ERR_FAIL_INDEX(p_effect,buses[p_bus]->effects.size()); + ERR_FAIL_INDEX(p_by_effect,buses[p_bus]->effects.size()); lock(); - SWAP( buses[p_bus].effects[p_effect], buses[p_bus].effects[p_by_effect] ); + SWAP( buses[p_bus]->effects[p_effect], buses[p_bus]->effects[p_by_effect] ); + _update_bus_effects(p_bus); unlock(); } void AudioServer::set_bus_effect_enabled(int p_bus,int p_effect,bool p_enabled) { ERR_FAIL_INDEX(p_bus,buses.size()); - ERR_FAIL_INDEX(p_effect,buses[p_bus].effects.size()); - buses[p_bus].effects[p_effect].enabled=p_enabled; + ERR_FAIL_INDEX(p_effect,buses[p_bus]->effects.size()); + buses[p_bus]->effects[p_effect].enabled=p_enabled; } bool AudioServer::is_bus_effect_enabled(int p_bus,int p_effect) const { ERR_FAIL_INDEX_V(p_bus,buses.size(),false); - ERR_FAIL_INDEX_V(p_effect,buses[p_bus].effects.size(),false); - return buses[p_bus].effects[p_effect].enabled; + ERR_FAIL_INDEX_V(p_effect,buses[p_bus]->effects.size(),false); + return buses[p_bus]->effects[p_effect].enabled; + +} + +void AudioServer::move_bus(int p_bus,int p_to_bus) { + + ERR_FAIL_COND(p_bus<1 || p_bus>=buses.size()); + ERR_FAIL_COND(p_bus<1 || p_to_bus>=buses.size()); + + + +} + +float AudioServer::get_bus_peak_volume_left_db(int p_bus,int p_channel) const { + + ERR_FAIL_INDEX_V(p_bus,buses.size(),0); + ERR_FAIL_INDEX_V(p_channel,buses[p_bus]->channels.size(),0); + + return buses[p_bus]->channels[p_channel].peak_volume.l; + +} +float AudioServer::get_bus_peak_volume_right_db(int p_bus,int p_channel) const { + + ERR_FAIL_INDEX_V(p_bus,buses.size(),0); + ERR_FAIL_INDEX_V(p_channel,buses[p_bus]->channels.size(),0); + + return buses[p_bus]->channels[p_channel].peak_volume.r; + +} + +bool AudioServer::is_bus_channel_active(int p_bus,int p_channel) const { + + ERR_FAIL_INDEX_V(p_bus,buses.size(),false); + ERR_FAIL_INDEX_V(p_channel,buses[p_bus]->channels.size(),false); + + return buses[p_bus]->channels[p_channel].active; } void AudioServer::init() { + channel_disable_treshold_db=GLOBAL_DEF("audio/channel_disable_treshold_db",-60.0); + channel_disable_frames=float(GLOBAL_DEF("audio/channel_disable_time",2.0))*get_mix_rate(); + buffer_size=1024; //harcoded for now + switch( get_speaker_mode() ) { + case SPEAKER_MODE_STEREO: { + temp_buffer.resize(1); + } break; + case SPEAKER_SURROUND_51: { + temp_buffer.resize(3); + } break; + case SPEAKER_SURROUND_71: { + temp_buffer.resize(4); + } break; + } + + for(int i=0;i<temp_buffer.size();i++) { + temp_buffer[i].resize(buffer_size); + } + + mix_count=0; set_bus_count(1);; set_bus_name(0,"Master"); + + + if (AudioDriver::get_singleton()) + AudioDriver::get_singleton()->start(); + } void AudioServer::finish() { + for(int i=0;i<buses.size();i++) { + memdelete(buses[i]); + } + buses.clear(); } void AudioServer::update() { @@ -282,18 +722,130 @@ double AudioServer::get_output_delay() const { AudioServer* AudioServer::singleton=NULL; -void AudioServer::_bind_methods() { + +void* AudioServer::audio_data_alloc(uint32_t p_data_len,const uint8_t *p_from_data) { + + void * ad = memalloc( p_data_len ); + ERR_FAIL_COND_V(!ad,NULL); + if (p_from_data) { + copymem(ad,p_from_data,p_data_len); + } + + audio_data_lock->lock(); + audio_data[ad]=p_data_len; + audio_data_total_mem+=p_data_len; + audio_data_max_mem=MAX(audio_data_total_mem,audio_data_max_mem); + audio_data_lock->unlock(); + + return ad; } +void AudioServer::audio_data_free(void* p_data) { + + audio_data_lock->lock(); + if (!audio_data.has(p_data)) { + audio_data_lock->unlock(); + ERR_FAIL(); + } + + audio_data_total_mem-=audio_data[p_data]; + audio_data.erase(p_data); + memfree(p_data); + audio_data_lock->unlock(); + + +} + +size_t AudioServer::audio_data_get_total_memory_usage() const{ + + return audio_data_total_mem; +} +size_t AudioServer::audio_data_get_max_memory_usage() const{ + + return audio_data_max_mem; + +} + +void AudioServer::add_callback(AudioCallback p_callback,void *p_userdata) { + lock(); + CallbackItem ci; + ci.callback=p_callback; + ci.userdata=p_userdata; + callbacks.insert(ci); + unlock(); +} + +void AudioServer::remove_callback(AudioCallback p_callback,void *p_userdata) { + + lock(); + CallbackItem ci; + ci.callback=p_callback; + ci.userdata=p_userdata; + callbacks.erase(ci); + unlock(); + +} + +void AudioServer::_bind_methods() { + + + ClassDB::bind_method(_MD("set_bus_count","amount"),&AudioServer::set_bus_count); + ClassDB::bind_method(_MD("get_bus_count"),&AudioServer::get_bus_count); + + ClassDB::bind_method(_MD("set_bus_name","bus_idx","name"),&AudioServer::set_bus_name); + ClassDB::bind_method(_MD("get_bus_name","bus_idx"),&AudioServer::get_bus_name); + + ClassDB::bind_method(_MD("set_bus_volume_db","bus_idx","volume_db"),&AudioServer::set_bus_volume_db); + ClassDB::bind_method(_MD("get_bus_volume_db","bus_idx"),&AudioServer::get_bus_volume_db); + + ClassDB::bind_method(_MD("set_bus_send","bus_idx","send"),&AudioServer::set_bus_send); + ClassDB::bind_method(_MD("get_bus_send","bus_idx"),&AudioServer::get_bus_send); + + ClassDB::bind_method(_MD("set_bus_solo","bus_idx","enable"),&AudioServer::set_bus_solo); + ClassDB::bind_method(_MD("is_bus_solo","bus_idx"),&AudioServer::is_bus_solo); + + ClassDB::bind_method(_MD("set_bus_mute","bus_idx","enable"),&AudioServer::set_bus_mute); + ClassDB::bind_method(_MD("is_bus_mute","bus_idx"),&AudioServer::is_bus_mute); + + ClassDB::bind_method(_MD("set_bus_bypass_effects","bus_idx","enable"),&AudioServer::set_bus_bypass_effects); + ClassDB::bind_method(_MD("is_bus_bypassing_effects","bus_idx"),&AudioServer::is_bus_bypassing_effects); + + ClassDB::bind_method(_MD("add_bus_effect","bus_idx","effect:AudioEffect"),&AudioServer::add_bus_effect); + ClassDB::bind_method(_MD("remove_bus_effect","bus_idx","effect_idx"),&AudioServer::remove_bus_effect); + + ClassDB::bind_method(_MD("get_bus_effect_count","bus_idx"),&AudioServer::add_bus_effect); + ClassDB::bind_method(_MD("get_bus_effect:AudioEffect","bus_idx","effect_idx"),&AudioServer::get_bus_effect); + ClassDB::bind_method(_MD("swap_bus_effects","bus_idx","effect_idx","by_effect_idx"),&AudioServer::swap_bus_effects); + + ClassDB::bind_method(_MD("set_bus_effect_enabled","bus_idx","effect_idx","enabled"),&AudioServer::set_bus_effect_enabled); + ClassDB::bind_method(_MD("is_bus_effect_enabled","bus_idx","effect_idx"),&AudioServer::is_bus_effect_enabled); + + ClassDB::bind_method(_MD("get_bus_peak_volume_left_db","bus_idx","channel"),&AudioServer::get_bus_peak_volume_left_db); + ClassDB::bind_method(_MD("get_bus_peak_volume_right_db","bus_idx","channel"),&AudioServer::get_bus_peak_volume_right_db); + + ClassDB::bind_method(_MD("lock"),&AudioServer::lock); + ClassDB::bind_method(_MD("unlock"),&AudioServer::unlock); + + ClassDB::bind_method(_MD("get_speaker_mode"),&AudioServer::get_speaker_mode); + ClassDB::bind_method(_MD("get_mix_rate"),&AudioServer::get_mix_rate); + + ADD_SIGNAL(MethodInfo("bus_layout_changed") ); +} AudioServer::AudioServer() { singleton=this; + audio_data_total_mem=0; + audio_data_max_mem=0; + audio_data_lock=Mutex::create(); + mix_frames=0; + to_mix=0; + } AudioServer::~AudioServer() { - + memdelete(audio_data_lock); } |
