#include "audio_player.h" void AudioPlayer::_mix_audio() { if (!stream_playback.is_valid()) { return; } if (!active) { return; } if (setseek>=0.0) { stream_playback->start(setseek); setseek=-1.0; //reset seek } int bus_index = AudioServer::get_singleton()->thread_find_bus_index(bus); //get data AudioFrame *buffer = mix_buffer.ptr(); int buffer_size = mix_buffer.size(); //mix stream_playback->mix(buffer,1.0,buffer_size); //multiply volume interpolating to avoid clicks if this changes float vol = Math::db2linear(mix_volume_db); float vol_inc = (Math::db2linear(volume_db) - vol)/float(buffer_size); for(int i=0;iget_speaker_mode()==AudioServer::SPEAKER_MODE_STEREO) { targets[0] = AudioServer::get_singleton()->thread_get_channel_mix_buffer(bus_index,0); } else { switch(mix_target) { case MIX_TARGET_STEREO: { targets[0]=AudioServer::get_singleton()->thread_get_channel_mix_buffer(bus_index,1); } break; case MIX_TARGET_SURROUND: { targets[0]=AudioServer::get_singleton()->thread_get_channel_mix_buffer(bus_index,1); targets[1]=AudioServer::get_singleton()->thread_get_channel_mix_buffer(bus_index,2); if (AudioServer::get_singleton()->get_speaker_mode()==AudioServer::SPEAKER_SURROUND_71) { targets[2]=AudioServer::get_singleton()->thread_get_channel_mix_buffer(bus_index,3); } } break; case MIX_TARGET_CENTER: { targets[0]=AudioServer::get_singleton()->thread_get_channel_mix_buffer(bus_index,0); } break; } } for(int c=0;c<3;c++) { if (!targets[c]) break; for(int i=0;iadd_callback(_mix_audios,this); if (autoplay && !get_tree()->is_editor_hint()) { play(); } } if (p_what==NOTIFICATION_EXIT_TREE) { AudioServer::get_singleton()->remove_callback(_mix_audios,this); } } void AudioPlayer::set_stream(Ref p_stream) { AudioServer::get_singleton()->lock(); mix_buffer.resize(AudioServer::get_singleton()->thread_get_mix_buffer_size()); if (stream_playback.is_valid()) { stream_playback.unref(); stream.unref(); active=false; setseek=-1; } stream=p_stream; stream_playback=p_stream->instance_playback(); if (stream_playback.is_null()) { stream.unref(); ERR_FAIL_COND(stream_playback.is_null()); } AudioServer::get_singleton()->unlock(); } Ref AudioPlayer::get_stream() const { return stream; } void AudioPlayer::set_volume_db(float p_volume) { volume_db=p_volume; } float AudioPlayer::get_volume_db() const { return volume_db; } void AudioPlayer::play(float p_from_pos) { if (stream_playback.is_valid()) { mix_volume_db=volume_db; //reset volume ramp setseek=p_from_pos; active=true; } } void AudioPlayer::seek(float p_seconds) { if (stream_playback.is_valid()) { setseek=p_seconds; } } void AudioPlayer::stop() { if (stream_playback.is_valid()) { active=false; } } bool AudioPlayer::is_playing() const { if (stream_playback.is_valid()) { return active && stream_playback->is_playing(); } return false; } float AudioPlayer::get_pos() { if (stream_playback.is_valid()) { return stream_playback->get_pos(); } return 0; } void AudioPlayer::set_bus(const StringName& p_bus) { //if audio is active, must lock this AudioServer::get_singleton()->lock(); bus=p_bus; AudioServer::get_singleton()->unlock(); } StringName AudioPlayer::get_bus() const { for(int i=0;iget_bus_count();i++) { if (AudioServer::get_singleton()->get_bus_name(i)==bus) { return bus; } } return "Master"; } void AudioPlayer::set_autoplay(bool p_enable) { autoplay=p_enable; } bool AudioPlayer::is_autoplay_enabled() { return autoplay; } void AudioPlayer::set_mix_target(MixTarget p_target) { mix_target=p_target; } AudioPlayer::MixTarget AudioPlayer::get_mix_target() const{ return mix_target; } void AudioPlayer::_set_playing(bool p_enable) { if (p_enable) play(); else stop(); } bool AudioPlayer::_is_active() const { return active; } void AudioPlayer::_validate_property(PropertyInfo& property) const { if (property.name=="bus") { String options; for(int i=0;iget_bus_count();i++) { if (i>0) options+=","; String name = AudioServer::get_singleton()->get_bus_name(i); options+=name; } property.hint_string=options; } } void AudioPlayer::_bus_layout_changed() { _change_notify(); } void AudioPlayer::_bind_methods() { ClassDB::bind_method(_MD("set_stream","stream:AudioStream"),&AudioPlayer::set_stream); ClassDB::bind_method(_MD("get_stream"),&AudioPlayer::get_stream); ClassDB::bind_method(_MD("set_volume_db","volume_db"),&AudioPlayer::set_volume_db); ClassDB::bind_method(_MD("get_volume_db"),&AudioPlayer::get_volume_db); ClassDB::bind_method(_MD("play","from_pos"),&AudioPlayer::play,DEFVAL(0.0)); ClassDB::bind_method(_MD("seek","to_pos"),&AudioPlayer::seek); ClassDB::bind_method(_MD("stop"),&AudioPlayer::stop); ClassDB::bind_method(_MD("is_playing"),&AudioPlayer::is_playing); ClassDB::bind_method(_MD("get_pos"),&AudioPlayer::get_pos); ClassDB::bind_method(_MD("set_bus","bus"),&AudioPlayer::set_bus); ClassDB::bind_method(_MD("get_bus"),&AudioPlayer::get_bus); ClassDB::bind_method(_MD("set_autoplay","enable"),&AudioPlayer::set_autoplay); ClassDB::bind_method(_MD("is_autoplay_enabled"),&AudioPlayer::is_autoplay_enabled); ClassDB::bind_method(_MD("set_mix_target","mix_target"),&AudioPlayer::set_mix_target); ClassDB::bind_method(_MD("get_mix_target"),&AudioPlayer::get_mix_target); ClassDB::bind_method(_MD("_set_playing","enable"),&AudioPlayer::_set_playing); ClassDB::bind_method(_MD("_is_active"),&AudioPlayer::_is_active); ClassDB::bind_method(_MD("_bus_layout_changed"),&AudioPlayer::_bus_layout_changed); ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"stream",PROPERTY_HINT_RESOURCE_TYPE,"AudioStream"),_SCS("set_stream"),_SCS("get_stream") ); ADD_PROPERTY( PropertyInfo(Variant::REAL,"volume_db",PROPERTY_HINT_RANGE,"-80,24"),_SCS("set_volume_db"),_SCS("get_volume_db") ); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"playing",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_EDITOR),_SCS("_set_playing"),_SCS("_is_active" )); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"autoplay"),_SCS("set_autoplay"),_SCS("is_autoplay_enabled") ); ADD_PROPERTY( PropertyInfo(Variant::INT,"mix_target",PROPERTY_HINT_ENUM,"Stereo,Surround,Center"),_SCS("set_mix_target"),_SCS("get_mix_target")); ADD_PROPERTY( PropertyInfo(Variant::STRING,"bus",PROPERTY_HINT_ENUM,""),_SCS("set_bus"),_SCS("get_bus")); } AudioPlayer::AudioPlayer() { mix_volume_db=0; volume_db=0; autoplay=false; setseek=-1; active=false; mix_target=MIX_TARGET_STEREO; AudioServer::get_singleton()->connect("bus_layout_changed",this,"_bus_layout_changed"); } AudioPlayer::~AudioPlayer() { }