00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include <limits>
00018 #include <math.h>
00019
00020 #include "audio/sound_manager.hpp"
00021 #include "audio/sound_source.hpp"
00022 #include "object/ambient_sound.hpp"
00023 #include "object/camera.hpp"
00024 #include "scripting/squirrel_util.hpp"
00025 #include "supertux/object_factory.hpp"
00026 #include "supertux/sector.hpp"
00027 #include "util/reader.hpp"
00028
00029 AmbientSound::AmbientSound(const Reader& lisp) :
00030 name(),
00031 position(),
00032 dimension(),
00033 sample(),
00034 sound_source(),
00035 latency(),
00036 distance_factor(),
00037 distance_bias(),
00038 silence_distance(),
00039 maximumvolume(),
00040 targetvolume(),
00041 currentvolume(),
00042 volume_ptr()
00043 {
00044 name="";
00045 position.x = 0;
00046 position.y = 0;
00047
00048 dimension.x = 0;
00049 dimension.y = 0;
00050
00051 distance_factor = 0;
00052 distance_bias = 0;
00053 maximumvolume = 1;
00054 sample = "";
00055 currentvolume = 0;
00056
00057 if (!(lisp.get("x", position.x)&&lisp.get("y", position.y))) {
00058 log_warning << "No Position in ambient_sound" << std::endl;
00059 }
00060
00061 lisp.get("name" , name);
00062 lisp.get("width" , dimension.x);
00063 lisp.get("height", dimension.y);
00064
00065 lisp.get("distance_factor",distance_factor);
00066 lisp.get("distance_bias" ,distance_bias );
00067 lisp.get("sample" ,sample );
00068 lisp.get("volume" ,maximumvolume );
00069
00070
00071
00072 if ((dimension.x <= 64) || (dimension.y <= 64)) {
00073 dimension.x = 0;
00074 dimension.y = 0;
00075 }
00076
00077
00078
00079 distance_bias*=distance_bias;
00080 distance_factor*=distance_factor;
00081
00082
00083
00084 if (distance_factor == 0)
00085 silence_distance = std::numeric_limits<float>::max();
00086 else
00087 silence_distance = 1/distance_factor;
00088
00089 lisp.get("silence_distance",silence_distance);
00090
00091 sound_source = 0;
00092 sound_manager->preload(sample);
00093 latency=0;
00094 }
00095
00096 AmbientSound::AmbientSound(Vector pos, float factor, float bias, float vol, std::string file) :
00097 name(),
00098 position(),
00099 dimension(),
00100 sample(),
00101 sound_source(),
00102 latency(),
00103 distance_factor(),
00104 distance_bias(),
00105 silence_distance(),
00106 maximumvolume(),
00107 targetvolume(),
00108 currentvolume(),
00109 volume_ptr()
00110 {
00111 position.x=pos.x;
00112 position.y=pos.y;
00113
00114 dimension.x=0;
00115 dimension.y=0;
00116
00117 distance_factor=factor*factor;
00118 distance_bias=bias*bias;
00119 maximumvolume=vol;
00120 sample=file;
00121
00122
00123
00124 if (distance_factor == 0)
00125 silence_distance = std::numeric_limits<float>::max();
00126 else
00127 silence_distance = 1/distance_factor;
00128
00129 sound_source = 0;
00130 sound_manager->preload(sample);
00131 latency=0;
00132 }
00133
00134 AmbientSound::~AmbientSound()
00135 {
00136 stop_playing();
00137 }
00138
00139 void
00140 AmbientSound::hit(Player& )
00141 {
00142 }
00143
00144 void
00145 AmbientSound::stop_playing()
00146 {
00147 delete sound_source;
00148 sound_source = 0;
00149 }
00150
00151 void
00152 AmbientSound::start_playing()
00153 {
00154 try {
00155 sound_source = sound_manager->create_sound_source(sample);
00156 if(!sound_source)
00157 throw std::runtime_error("file not found");
00158
00159 sound_source->set_gain(0);
00160 sound_source->set_looping(true);
00161 currentvolume=targetvolume=1e-20f;
00162 sound_source->play();
00163 } catch(std::exception& e) {
00164 log_warning << "Couldn't play '" << sample << "': " << e.what() << "" << std::endl;
00165 delete sound_source;
00166 sound_source = 0;
00167 remove_me();
00168 }
00169 }
00170
00171 void
00172 AmbientSound::update(float deltat)
00173 {
00174 if (latency-- <= 0) {
00175 float px,py;
00176 float rx,ry;
00177
00178 if (!Sector::current() || !Sector::current()->camera) return;
00179
00180 px=Sector::current()->camera->get_center().x;
00181 py=Sector::current()->camera->get_center().y;
00182
00183
00184 rx=px<position.x?position.x:
00185 (px<position.x+dimension.x?px:position.x+dimension.x);
00186 ry=py<position.y?position.y:
00187 (py<position.y+dimension.y?py:position.y+dimension.y);
00188
00189
00190 float sqrdistance=(px-rx)*(px-rx)+(py-ry)*(py-ry);
00191 sqrdistance-=distance_bias;
00192
00193
00194 if (sqrdistance<0)
00195 sqrdistance=0;
00196
00197
00198 targetvolume=1/(1+sqrdistance*distance_factor);
00199 float rise=targetvolume/currentvolume;
00200
00201
00202 currentvolume*=pow(rise,deltat*10);
00203 currentvolume += 1e-6f;
00204
00205 if (sound_source != 0) {
00206
00207
00208 sound_source->set_gain(currentvolume*maximumvolume);
00209
00210 if (sqrdistance>=silence_distance && currentvolume<1e-3)
00211 stop_playing();
00212 latency=0;
00213 } else {
00214 if (sqrdistance<silence_distance) {
00215 start_playing();
00216 latency=0;
00217 }
00218 else
00219 latency=(int)(0.001/distance_factor);
00220
00221 }
00222 }
00223
00224
00225
00226
00227
00228 }
00229
00230 void
00231 AmbientSound::draw(DrawingContext &)
00232 {
00233 }
00234
00235 void
00236 AmbientSound::expose(HSQUIRRELVM vm, SQInteger table_idx)
00237 {
00238 scripting::AmbientSound* _this = static_cast<scripting::AmbientSound*> (this);
00239 expose_object(vm, table_idx, _this, name, false);
00240 }
00241
00242 void
00243 AmbientSound::unexpose(HSQUIRRELVM vm, SQInteger table_idx)
00244 {
00245 scripting::unexpose_object(vm, table_idx, name);
00246 }
00247
00248 void
00249 AmbientSound::set_pos(float x, float y)
00250 {
00251 position.x = x;
00252 position.y = y;
00253 }
00254
00255 float
00256 AmbientSound::get_pos_x() const
00257 {
00258 return position.x;
00259 }
00260
00261 float
00262 AmbientSound::get_pos_y() const
00263 {
00264 return position.y;
00265 }
00266
00267