00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00061 #include "omicron/internal.h"
00062 #include "omicron/array.h"
00063 #include "omicron/sound.h"
00064 #include "omicron/file.h"
00065
00066 sound_manager_c::sound_manager_c()
00067 {
00068 sounds = NULL;
00069 sounddevice = NULL;
00070 soundcontext = NULL;
00071
00072 if (gv.init.nosound)
00073 return;
00074
00075 SafeDelete(gv.soundman);
00076
00077 gv.soundman = this;
00078
00079 #if !defined(NOSOUND)
00080
00081
00082 _log_printf(0, "initializing sound...");
00083
00084 _log_printf(0, "opening device...");
00085
00086 if (NULL == (sounddevice = alcOpenDevice(NULL)))
00087 {
00088 _log_printf(0, "could not open device: %s",
00089 sound_alerror(alGetError()));
00090 gv.init.nosound = true;
00091 return;
00092 }
00093
00094 _log_printf(0, "creating context...");
00095
00096 int attr[] = { ALC_REFRESH, 100, ALC_SYNC, 0 };
00097
00098 if (NULL == (soundcontext = alcCreateContext(sounddevice, attr)))
00099 {
00100 _log_printf(0, "could not create context: %s",
00101 sound_alerror(alGetError()));
00102
00103 gv.init.nosound = true;
00104 alcCloseDevice(sounddevice);
00105 return;
00106 }
00107
00108 _log_printf(0, "making context current...");
00109
00110 alcMakeContextCurrent(soundcontext);
00111 int err = alGetError();
00112
00113 if (AL_NO_ERROR != err)
00114 {
00115 _log_printf(0, "could not make context current: %s",
00116 sound_alerror(err));
00117
00118 gv.init.nosound = true;
00119 alcDestroyContext(soundcontext);
00120 alcCloseDevice(sounddevice);
00121 return;
00122 }
00123
00124 ALfloat listenerOri[]={ 0.0, 0.0, -1.0, 0.0, 1.0, 0.0};
00125
00126 alListener3f(AL_POSITION, 0, 0, 0);
00127 alListener3f(AL_VELOCITY, 0, 0, 0);
00128 alListenerfv(AL_ORIENTATION, listenerOri);
00129
00130 sounds = new array_c<sound_t>;
00131
00132 #endif
00133 }
00134
00135 sound_manager_c::~sound_manager_c()
00136 {
00137 AssertThis;
00138 if (gv.init.nosound)
00139 return;
00140
00141 #if !defined(NOSOUND)
00142
00143 for (sshort i=0; i<sounds->get_count(); i++)
00144 unload(i);
00145
00146 SafeDelete(sounds);
00147
00148
00149
00150 alcMakeContextCurrent(NULL);
00151 alcDestroyContext(soundcontext);
00152 alcCloseDevice(sounddevice);
00153 #endif
00154 }
00155
00156 const char *
00157 sound_manager_c::sound_alerror(
00158 ALenum e
00159 )
00160 {
00161 switch(e)
00162 {
00163 case AL_NO_ERROR:
00164 return "No error occured.";
00165 case AL_INVALID_NAME:
00166 return "Invalid OpenAL name used.";
00167
00168
00169 case AL_INVALID_VALUE:
00170 return "Invalid value.";
00171
00172
00173 case AL_OUT_OF_MEMORY:
00174 return "Out of memory.";
00175 }
00176
00177 return "Unknown error.";
00178 }
00179
00180 void
00181 sound_manager_c::unload(
00182 sshort num
00183 )
00184 {
00185 AssertThis;
00186
00187 if (gv.init.nosound)
00188 return;
00189
00190 #if !defined(NOSOUND)
00191
00192 sound_t *snd = sounds->get(num);
00193
00194 if (snd)
00195 {
00196 alSourceStop(snd->source);
00197 alDeleteSources(1, &snd->source);
00198
00199 if (!snd->iscopy)
00200 alDeleteBuffers(1, &snd->buffer);
00201
00202 sounds->remove(num);
00203 SafeDelete(snd);
00204 }
00205
00206 #endif
00207 }
00208
00209 sshort
00210 sound_manager_c::load_wav(
00211 const char *fname
00212 )
00213 {
00214 if (gv.init.nosound)
00215 return 0;
00216
00217 AssertThisValue(-1);
00218
00219 #if !defined(NOSOUND)
00220
00221 _log_printf(MSG_DEBUG, "Loading wave...");
00222 file_t *f = gv.fileman->load(fname, false);
00223
00224 if (!f)
00225 return 0;
00226
00227 ALenum format = AL_FORMAT_MONO8;
00228 char *data = NULL;
00229 ALuint sndbuf = 0;
00230 ALuint sndsrc = 0;
00231
00232 char chunkid[5] = " ";
00233 ulong chunksize = 0;
00234
00235 _log_printf(MSG_DEBUG, "seeking fmt chunk...");
00236 gv.fileman->seek(f, 12, SEEK_SET);
00237
00238 while(strcmp(chunkid, "fmt ") && !gv.fileman->eof(f))
00239 {
00240 gv.fileman->seek(f, chunksize, SEEK_CUR);
00241 gv.fileman->read(chunkid, 4, 1, f);
00242 gv.fileman->read(&chunksize, 4, 1, f);
00243 }
00244
00245 if (gv.fileman->eof(f))
00246 {
00247 gv.fileman->close(f);
00248 return -1;
00249 }
00250
00251 _log_printf(MSG_DEBUG, "found...");
00252
00253
00254 sshort wv_formattag = 0;
00255 ushort wv_channels = 0;
00256 ulong wv_avgsrate = 0;
00257 ulong wv_avgbrate = 0;
00258 ushort wv_blockalign = 0;
00259 ushort wv_bits = 0;
00260
00261 bool invalidformat = false;
00262
00263 gv.fileman->read(&wv_formattag, sizeof(sshort), 1, f);
00264 gv.fileman->read(&wv_channels, sizeof(ushort), 1, f);
00265 gv.fileman->read(&wv_avgsrate, sizeof(ulong), 1, f);
00266 gv.fileman->read(&wv_avgbrate, sizeof(ulong), 1, f);
00267 gv.fileman->read(&wv_blockalign, sizeof(ushort), 1, f);
00268 gv.fileman->read(&wv_bits, sizeof(ushort), 1, f);
00269
00270 if (wv_channels == 1)
00271 {
00272 if (wv_bits == 8)
00273 format = AL_FORMAT_MONO8;
00274 else if (wv_bits == 16)
00275 format = AL_FORMAT_MONO16;
00276 else
00277 invalidformat = true;
00278 }
00279 else if (wv_channels == 2)
00280 {
00281 if (wv_bits == 8)
00282 format = AL_FORMAT_STEREO8;
00283 else if (wv_bits == 16)
00284 format = AL_FORMAT_STEREO16;
00285 else
00286 invalidformat = true;
00287 }
00288
00289 _log_printf(MSG_DEBUG, "%u hz %u channels %u bits... format: %04x", wv_avgsrate, wv_channels, wv_bits, format);
00290
00291 if (invalidformat)
00292 {
00293 gv.fileman->close(f);
00294 return -1;
00295 }
00296
00297 _log_printf(MSG_DEBUG, "seeking data chunk...");
00298 gv.fileman->seek(f, 12, SEEK_SET);
00299
00300 chunksize = 0;
00301
00302 while(strcmp(chunkid, "data") && !gv.fileman->eof(f))
00303 {
00304 gv.fileman->seek(f, chunksize, SEEK_CUR);
00305 gv.fileman->read(chunkid, 4, 1, f);
00306 gv.fileman->read(&chunksize, 4, 1, f);
00307 }
00308
00309 if (gv.fileman->eof(f))
00310 {
00311 gv.fileman->close(f);
00312 return -1;
00313 }
00314
00315 _log_printf(MSG_DEBUG, "found... reading %u bytes of sound...", chunksize);
00316 data = new char[chunksize*2+1024];
00317
00318 gv.fileman->read(data, 1, chunksize, f);
00319
00320 _log_printf(MSG_DEBUG, "creating openal buffer...");
00321 alGenBuffers(1, &sndbuf);
00322 _log_printf(MSG_DEBUG2, "%s", sound_alerror(alGetError()));
00323 _log_printf(MSG_DEBUG, "filling buffer...");
00324 alBufferData(sndbuf, format, data, chunksize, wv_avgsrate);
00325 _log_printf(MSG_DEBUG3, "%s", sound_alerror(alGetError()));
00326
00327 SafeArrayDelete(data);
00328
00329 gv.fileman->close(f);
00330
00331 _log_printf(MSG_DEBUG, "creating openal source...");
00332 alGenSources(1, &sndsrc);
00333 _log_printf(MSG_DEBUG3, "%s", sound_alerror(alGetError()));
00334
00335 _log_printf(MSG_DEBUG, "attaching buffer to source...");
00336 alSourcei(sndsrc, AL_BUFFER, sndbuf);
00337 _log_printf(MSG_DEBUG3, "%s", sound_alerror(alGetError()));
00338
00339 _log_printf(MSG_DEBUG, "setting source parameters...");
00340 alSource3f(sndsrc, AL_POSITION, 0,0,0);
00341 alSource3f(sndsrc, AL_VELOCITY, 0,0,0);
00342 alSource3f(sndsrc, AL_DIRECTION, 0,0,1);
00343
00344 _log_printf(MSG_DEBUG2, "new sound_t");
00345 sound_t *snd = new sound_t;
00346
00347 snd->buffer = sndbuf;
00348 snd->source = sndsrc;
00349
00350 _log_printf(MSG_DEBUG2, "adding sound_t to list");
00351 return sounds->add(snd);
00352 #endif
00353
00354 return INVALID_INDEX;
00355 }
00356
00357 sshort
00358 sound_manager_c::duplicate(
00359 sshort num
00360 )
00361 {
00362 if (gv.init.nosound)
00363 return INVALID_INDEX;
00364
00365 AssertThisValue(INVALID_INDEX);
00366
00367 sound_t *snd, *snd2;
00368
00369 snd = sounds->get(num);
00370 if (snd)
00371 {
00372 snd2 = new sound_t;
00373 snd2->buffer = snd->buffer;
00374 alGenSources(1, &snd2->source);
00375
00376 alSourcei(snd2->source, AL_BUFFER, snd2->buffer);
00377 alSource3f(snd2->source, AL_POSITION, 0,0,0);
00378 alSource3f(snd2->source, AL_VELOCITY, 0,0,0);
00379 alSource3f(snd2->source, AL_DIRECTION, 0,0,1);
00380
00381 snd2->iscopy = true;
00382
00383 return sounds->add(snd2);
00384 }
00385 return INVALID_INDEX;
00386 }
00387
00388 void
00389 sound_manager_c::play(
00390 sshort num
00391 )
00392 {
00393 if (gv.init.nosound)
00394 return;
00395
00396 AssertThis;
00397
00398 #if !defined(NOSOUND)
00399 sound_t *snd = sounds->get(num);
00400
00401 if (snd)
00402 {
00403 ALint state;
00404
00405 alGetSourcei(snd->source, AL_SOURCE_STATE, &state);
00406
00407 if (state != AL_PLAYING)
00408 alSourcePlay(snd->source);
00409 }
00410 #endif
00411 }
00412
00413 void
00414 sound_manager_c::play_copy(
00415 sshort num
00416 )
00417 {
00418 if (gv.init.nosound)
00419 return;
00420
00421 AssertThis;
00422
00423 sshort num2 = duplicate(num);
00424 sound_t *snd = sounds->get(num2);
00425
00426 if (snd)
00427 {
00428 snd->temporary = true;
00429 play(num2);
00430 }
00431 }
00432
00433 void
00434 sound_manager_c::stop(
00435 sshort num
00436 )
00437 {
00438 if (gv.init.nosound)
00439 return;
00440
00441 AssertThis;
00442
00443 #if !defined(NOSOUND)
00444 sound_t *snd = sounds->get(num);
00445
00446 if (snd)
00447 alSourceStop(snd->source);
00448 #endif
00449 }
00450
00451 void
00452 sound_manager_c::update()
00453 {
00454 if (gv.init.nosound)
00455 return;
00456
00457 AssertThis;
00458
00459 for (sshort i=0; i<sounds->get_count(); i++)
00460 {
00461 sound_t *snd = sounds->get(i);
00462
00463 if (snd)
00464 {
00465 if (snd->iscopy && snd->temporary)
00466 {
00467 ALint state;
00468
00469 alGetSourcei(snd->source, AL_SOURCE_STATE, &state);
00470
00471 if (state != AL_PLAYING)
00472 {
00473 unload(i);
00474
00475 }
00476 }
00477 }
00478 }
00479 }