Main Page   Class Hierarchy   Alphabetical List   Data Structures   File List   Data Fields   Globals   Related Pages  

o_sound.cpp

Go to the documentation of this file.
00001 // OMICRON ENGINE HEADER FILE
00002 //
00003 // --------------------------------------------------------------------------
00004 // Copyright (C) 2001-2002 by Bjoern Paetzel <kolrabi@gmx.de>
00005 //
00006 // This file is part of the Omicron Engine.
00007 //
00008 // The Omicron Engine is free software; you can redistribute it and/or modify
00009 // it under the terms of the  GNU General Public License  as published by the
00010 // Free Software Foundation;  either version  2  of the License,  or (at your
00011 // option) any later version.
00012 //
00013 // The Omicron Engine  is distributed in the hope that it will be useful, but
00014 // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
00015 // or  FITNESS FOR A PARTICULAR PURPOSE.  See the  GNU General Public License
00016 // for more details.
00017 //
00018 // You should have  received a copy of the  GNU General Public License  along
00019 // with The Omicron Engine;  if not,  write to the  Free Software Foundation,
00020 // Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
00021 //
00022 // --------------------------------------------------------------------------
00023 // Last modified:       $Date: 2002/12/18 14:35:11 $
00024 // By           :       $Author: kolrabi $
00025 // $Id: o_sound.cpp,v 1.7 2002/12/18 14:35:11 kolrabi Exp $ 
00026 
00027 /*
00028 
00029   $Log: o_sound.cpp,v $
00030   Revision 1.7  2002/12/18 14:35:11  kolrabi
00031   no message
00032 
00033   Revision 1.6  2002/12/14 20:02:33  kolrabi
00034   fixed some memory leaks
00035 
00036   Revision 1.5  2002/12/13 15:59:47  kolrabi
00037   several bug fixes
00038 
00039   Revision 1.4  2002/12/13 12:29:26  kolrabi
00040   fixed some bugs
00041 
00042   Revision 1.3  2002/12/13 10:20:16  kolrabi
00043   no message
00044 
00045   Revision 1.2  2002/12/12 13:13:39  kolrabi
00046   made the fullscreen work under X11
00047 
00048   Revision 1.1  2002/12/12 11:44:04  kolrabi
00049   *** empty log message ***
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 //  alutInit(&gv.init.argc, gv.init.argv);
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[]={ /* at */ 0.0, 0.0, -1.0, /* up */ 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 //    alDeleteSources(CHANNELCOUNT, schannels);
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 /*      case AL_INVALID_ENUM:
00168             return "Invalid OpenAL enumeration used.";*/
00169         case AL_INVALID_VALUE:
00170             return "Invalid value.";
00171 /*      case AL_INVALID_OPERATION:
00172             return "Invalid operation requested.";*/
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     // wave format data
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                     // alSourcePlay(snd->source);
00475                 }
00476             }
00477         }
00478     }
00479 }

Generated on Wed Dec 18 15:48:47 2002 for omicron engine by doxygen1.2.18