src/sound.cpp

Go to the documentation of this file.
00001 /* vim: sw=8 noet:
00002  ***************************************************************************
00003  *            sound.cpp
00004  *
00005  *  Fri May 13 19:02:21 2005
00006  *  Copyright  2005  Joe Venzon
00007  *  joe@venzon.net
00008  ****************************************************************************/
00009 
00010 /*
00011  *  This program is free software; you can redistribute it and/or modify
00012  *  it under the terms of the GNU General Public License as published by
00013  *  the Free Software Foundation; either version 2 of the License, or
00014  *  (at your option) any later version.
00015  *
00016  *  This program is distributed in the hope that it will be useful,
00017  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  *  GNU Library General Public License for more details.
00020  *
00021  *  You should have received a copy of the GNU General Public License
00022  *  along with this program; if not, write to the Free Software
00023  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00024  */
00025  
00026 #include "sound.h"
00027 
00028 //#define SOUND_DEBUG
00029 
00030 /*void SOUNDMANAGER::LoadAllSoundFiles()
00031 {
00032         if (disable)
00033                 return;
00034         
00035         //LoadSoundFile(settings.GetDataDir() + "/sounds/engine.wav");
00036         LoadSoundFile(settings.GetFullDataPath("sounds/tire_squeal.wav"));
00037         
00038         string fname = settings.GetFullDataPath("cars/car_list.txt");
00039         ifstream cfile;
00040         cfile.open(fname.c_str());
00041         
00042         if (cfile)
00043         {
00044                 string cftemp = utility.sGetLine(cfile);
00045                 while (!cfile.eof())
00046                 {
00047                         LoadSoundFile(settings.GetFullDataPath("cars/"+cftemp+"/engine.wav"));
00048                         //cout << "Loaded " << cftemp << endl;
00049                         cftemp = utility.sGetLine(cfile);
00050                 }
00051                 cfile.close();
00052         }
00053 }
00054 
00055 void SOUNDMANAGER::SetListenerVel(VERTEX vel)
00056 {
00057         if (disable)
00058                 return;
00059         
00060         vel.Scale(VELOCITY_FACTOR);
00061         alListenerfv(AL_VELOCITY, vel.v3());
00062 }
00063 
00064 void SOUNDMANAGER::SetListenerPos(VERTEX pos)
00065 {
00066         if (disable)
00067                 return;
00068         
00069         pos.Scale(DISTANCE_FACTOR);
00070         alListenerfv(AL_POSITION, pos.v3());
00071 }
00072 
00073 void SOUNDMANAGER::SetListenerOrientation(VERTEX at, VERTEX up)
00074 {
00075         if (disable)
00076                 return;
00077         
00078         float f[6];
00079         f[0] = at.x;
00080         f[1] = at.y;
00081         f[2] = at.z;
00082         f[3] = up.x;
00083         f[4] = up.y;
00084         f[5] = up.z;
00085         
00086         alListenerfv(AL_ORIENTATION, f);
00087 }
00088 
00089 void SOUNDMANAGER::Load()
00090 {
00091         if (disable)
00092                 return;
00093         
00094         alutInit(NULL, 0);
00095         alGetError();
00096         
00097         
00098         // Position of the Listener.
00099         //ALfloat ListenerPos[] = { 0.0, 0.0, 0.0 };
00100         
00101         // Velocity of the Listener.
00102         //ALfloat ListenerVel[] = { 0.0, 0.0, 0.0 };
00103         
00104         // Orientation of the Listener. (first 3 elements are "at", second 3 are "up")
00105         // Also note that these should be units of '1'.
00106         //ALfloat ListenerOri[] = { 0.0, 0.0, -1.0,  0.0, 1.0, 0.0 };
00107 
00108         //set all sources to free
00109         
00110         buffers = new ALuint [MAX_BUFFERS];
00111         buf_fn = new string [MAX_BUFFERS];
00112         
00113         int i;
00114         for (i = 0; i < MAX_SOURCES; i++)
00115         {
00116                 source_free[i] = true;
00117                 
00118                 buf_fn[i] = "";
00119         }
00120         
00121         buf_cur = 0;
00122 
00123         // Do another error check and return.
00124 
00125         //if(alGetError() == AL_NO_ERROR)
00126                 //return AL_TRUE;
00127 
00128         //return AL_FALSE;
00129 
00130         VERTEX p;
00131         SetListenerPos(p);
00132         SetListenerVel(p);
00133         //alListenerfv(AL_POSITION,    ListenerPos);
00134         //alListenerfv(AL_VELOCITY,    ListenerVel);
00135         //alListenerfv(AL_ORIENTATION, ListenerOri);
00136         VERTEX u;
00137         u.y = 1;
00138         p.z = -1;
00139         SetListenerOrientation(p, u);
00140         
00141         //alSourcePlay(sources[0]);
00142         
00143         LoadAllSoundFiles();
00144         
00145         //int sid = NewSource("engine.wav");
00146         //PlaySource(sid);
00147         
00148         alDopplerFactor (0.002);
00149         alDistanceModel (AL_INVERSE_DISTANCE);
00150 }
00151 
00152 void SOUNDMANAGER::PlaySource(int idx)
00153 {
00154         if (disable)
00155                 return;
00156         
00157         //alSourceQueueBuffers(sources[idx], 2, buffers);
00158         alSourcePlay(sources[idx]);
00159 }
00160 
00161 SOUNDMANAGER::SOUNDMANAGER()
00162 {
00163         disable = false;
00164         master_volume = 1.0;
00165 }
00166 
00167 extern bool verbose_output;
00168 SOUNDMANAGER::~SOUNDMANAGER()
00169 {
00170         if (verbose_output)
00171                 cout << "sound deinit" << endl;
00172         
00173         if (!disable)
00174         {
00175                 int i;
00176                 
00177                 for (i = 0; i < buf_cur; i++)
00178                         alDeleteBuffers(1, &buffers[i]);
00179                 
00180                 //alDeleteBuffers(1, &buffers[0]);
00181                 //alDeleteSources(1, &sources[0]);
00182                 
00183                 for (i = 0; i < MAX_SOURCES; i++)
00184                 {
00185                         if (!source_free[i])
00186                         alDeleteSources(1, &sources[i]);        
00187                 }
00188                 
00189                 // Destroy the sound context and device (Gentoo)
00190                 mSoundContext = alcGetCurrentContext();
00191                 mSoundDevice = alcGetContextsDevice( mSoundContext );
00192                 alcDestroyContext( mSoundContext );
00193                 if ( mSoundDevice)
00194                         alcCloseDevice( mSoundDevice );
00195 
00196                 alutExit();
00197                 
00198                 delete [] buffers;
00199                 delete [] buf_fn;
00200         }
00201 }
00202 
00203 ALuint SOUNDMANAGER::NewSource(string buffername)
00204 {
00205         if (disable)
00206                 return 0;
00207         
00208         int i;
00209         for (i = 0; i < MAX_SOURCES; i++)
00210         {
00211                 if (source_free[i])
00212                 {
00213                         source_free[i] = false;
00214 
00215                         //cout << "old source: " << sources[i] << endl;
00216                         
00217                         // Bind the buffer with the source.
00218                         alGenSources(1, &sources[i]);
00219                         
00220                         // Position of the source sound.
00221                         ALfloat SourcePos[] = { 0.0, 0.0, 0.0 };
00222                         // Velocity of the source sound.
00223                         ALfloat SourceVel[] = { 0.0, 0.0, 0.0 };
00224                         
00225                         int idx, m;
00226                         idx = -1;
00227                         for (m = 0; m < MAX_BUFFERS; m++)
00228                         {
00229                                 if (buf_fn[m] == buffername)
00230                                         idx = m;
00231                         }
00232                         
00233                         if (idx == -1)
00234                         {
00235                                 cout << "Cannot find sound file " << buffername << endl;
00236                         }
00237                         else
00238                         {
00239                                 //cout << idx << endl;
00240                                 alSourcei (sources[i], AL_BUFFER,   buffers[idx]   );
00241                                 alSourcef (sources[i], AL_PITCH,    1.0      );
00242                                 alSourcef (sources[i], AL_GAIN,     1.0      );
00243                                 alSourcefv(sources[i], AL_POSITION, SourcePos);
00244                                 alSourcefv(sources[i], AL_VELOCITY, SourceVel);
00245                                 alSourcei (sources[i], AL_LOOPING,  AL_TRUE     );
00246                                 //alSourcei (sources[i], AL_LOOPING,  AL_FALSE     );
00247                                 
00248                                 SetGain(i, 1.0);
00249                         }
00250                         //cout << "new source: " << sources[i] << endl;
00251                         PlaySource(i);
00252                         return i;
00253                 }
00254         }
00255         
00256         cout << "Out of sound sources." << endl;
00257         return 0;
00258 }
00259 
00260 void SOUNDMANAGER::LoadSoundFile(string filename)
00261 {
00262         if (disable)
00263                 return;
00264         
00265         ALenum format;
00266         ALsizei size;
00267         ALvoid* data = 0;
00268 #ifdef OLD_OPENAL
00269         ALsizei freq;
00270         ALboolean loop;
00271 #else
00272         ALfloat freq;
00273 #endif
00274         
00275         // Load wav data into a buffer.
00276         
00277 
00278         //if(alGetError() != AL_NO_ERROR)
00279                 //return AL_FALSE;
00280         
00281         //string sfile = settings.GetDataDir() + "/sounds/engine.wav";
00282         
00283 #ifdef __APPLE__
00284         alutLoadWAVFile((ALbyte*)(filename).c_str(), &format, &data, &size, &freq);
00285 #else
00286 #ifdef OLD_OPENAL
00287         alutLoadWAVFile((ALbyte*)(filename).c_str(), &format, &data, &size, &freq, &loop);
00288 #else
00289         data = alutLoadMemoryFromFile((ALbyte*)(filename).c_str(), &format, &size, &freq);
00290 #endif
00291 #endif
00292         //bool err = LoadWave(filename, &format, &data, &size, &freq, &loop);
00293         //if (filename == settings.GetDataDir() + "/sounds/engine.wav")
00294         {
00295                 //cout << loop << endl;
00296                 //cout << size << ", " << freq << endl;
00297         }
00298         if (data)
00299         {
00300                 alGenBuffers(1, &buffers[buf_cur]);
00301                 //UnloadWave(data);
00302 
00303 #ifdef OLD_OPENAL
00304                 alBufferData(buffers[buf_cur], format, data, size, freq);
00305                 alutUnloadWAV(format, data, size, freq);
00306 #else
00307                 alBufferData(buffers[buf_cur], format, data, size, (int)freq);
00308 #endif
00309 
00310                 buf_fn[buf_cur] = filename;
00311         
00312                 buf_cur++;
00313         }
00314         else
00315         {
00316                 cerr << "Error loading sound file: " << filename << "\n";
00317         }
00318 }
00319 
00320 void SOUNDMANAGER::SetPitch(int sid, float pitch)
00321 {
00322         if (disable)
00323                 return;
00324         
00325         alSourcef (sources[sid], AL_PITCH, pitch);
00326 }
00327 
00328 void SOUNDMANAGER::SetGain(int sid, float gain)
00329 {
00330         if (disable)
00331                 return;
00332 
00333         gain *= master_volume;
00334         
00335         alSourcef (sources[sid], AL_MAX_GAIN, gain);
00336         alSourcef (sources[sid], AL_GAIN, gain);
00337         //alSourcef (sources[sid], AL_MIN_GAIN, gain);
00338 }
00339 
00340 void SOUNDMANAGER::SetPos(int sid, VERTEX pos)
00341 {
00342         if (disable)
00343                 return;
00344         
00345         pos.Scale(DISTANCE_FACTOR);
00346         //cout << sources[sid] << endl;
00347         if (alIsSource(sources[sid]))
00348         {
00349                 alSourcefv(sources[sid], AL_POSITION, pos.v3());
00350         }
00351         else
00352         {
00353         }
00354 }
00355 
00356 void SOUNDMANAGER::SetVel(int sid, VERTEX vel)
00357 {
00358         if (disable)
00359                 return;
00360         
00361         vel.Scale(VELOCITY_FACTOR);
00362         if (alIsSource(sources[sid]))
00363                 alSourcefv(sources[sid], AL_VELOCITY, vel.v3());
00364 }
00365 
00366 void SOUNDMANAGER::MuteAll()
00367 {
00368         if (disable)
00369                 return;
00370         
00371         int i;
00372         for (i = 0; i < MAX_SOURCES; i++)
00373         {
00374                 if (!source_free[i])
00375                 {
00376                         SetGain(i, 0.0f);
00377                 }
00378         }
00379 }
00380 
00381 void SOUNDMANAGER::UnMuteAll()
00382 {
00383         
00384 }
00385 
00386 void SOUNDMANAGER::DisableAllSound()
00387 {
00388         disable = true;
00389 }
00390 
00391 void SOUNDMANAGER::EnableAllSound()
00392 {
00393         disable = false;
00394 }
00395 
00396 void SOUNDMANAGER::StopSource(int sid)
00397 {
00398         alSourceStop(sources[sid]);
00399         alDeleteSources(1, &sources[sid]);
00400         source_free[sid] = true;
00401 }
00402 
00403 void SOUNDMANAGER::SetPosVel(int sid, VERTEX coord, VERTEX tvel)
00404 {
00405         //cout << sid << endl;
00406         //coord.DebugPrint();
00407         SetPos(sid, coord);
00408         SetVel(sid, tvel);
00409 }
00410 
00411 void SOUNDMANAGER::SetListener(VERTEX campos, VERTEX camvel, VERTEX at, VERTEX up)
00412 {
00413         //campos.DebugPrint();
00414         SetListenerPos(campos);
00415         SetListenerVel(camvel);
00416         SetListenerOrientation(at, up);
00417 }*/
00418 
00419 void SOUNDMANAGER::Init()
00420 {
00421         if (disabled)
00422                 return;
00423         
00424         if (!init)
00425         {
00426                 alutInit(NULL, 0);
00427                 alGetError();
00428                 
00429                 alDopplerFactor (0.002);
00430                 alDistanceModel (AL_INVERSE_DISTANCE);
00431                 
00432                 VERTEX p;
00433                 SetListenerPos(p);
00434                 SetListenerVel(p);
00435                 VERTEX u;
00436                 u.y = 1;
00437                 p.z = -1;
00438                 SetListenerOrientation(p, u);
00439                 
00440                 init = true;
00441         }
00442 }
00443 
00444 void SOUNDMANAGER::Deinit()
00445 {
00446         if (disabled)
00447                 return;
00448         
00449         if (init)
00450         {
00451                 Unload();
00452                 
00453                 // Destroy the sound context and device (Gentoo)
00454                 mSoundContext = alcGetCurrentContext();
00455                 mSoundDevice = alcGetContextsDevice( mSoundContext );
00456                 alcDestroyContext( mSoundContext );
00457                 if ( mSoundDevice)
00458                         alcCloseDevice( mSoundDevice );
00459 
00460                 alutExit();
00461                 
00462                 init = false;
00463         }
00464 }
00465 
00466 void SOUNDMANAGER::Load()
00467 {
00468         if (disabled)
00469                 return;
00470         
00471         if (!loaded)
00472         {
00473                 buffers.clear();
00474                 sources.clear();
00475                 
00476                 //string car_name = state.GetCarName(0);
00477                 string car_name;
00478                 settings.Get( "game.selected_car", car_name );
00479                 LoadSoundFile(settings.GetFullDataPath("sounds/tire_squeal.wav"));
00480                 LoadSoundFile(settings.GetFullDataPath("cars/"+car_name+"/engine.wav"));
00481                 
00482                 loaded = true;
00483         }
00484 }
00485 
00486 void SOUNDMANAGER::Unload()
00487 {
00488         if (disabled)
00489                 return;
00490         
00491         if (loaded)
00492         {
00493                 for (map <string, ALuint>::iterator i = buffers.begin(); i != buffers.end(); i++)
00494                 {
00495                         #ifdef SOUND_DEBUG
00496                         cout << "Deleted sound " << i->first << " from buffer " << i->second << endl;
00497                         #endif
00498                         alDeleteBuffers(1, &(i->second));
00499                 }
00500                 
00501                 for (vector <ALuint>::iterator i = sources.begin(); i != sources.end(); i++)
00502                 {
00503                         alDeleteSources(1, &(*(i)));
00504                 }
00505                 
00506                 buffers.clear();
00507                 sources.clear();
00508                 
00509                 loaded = false;
00510         }
00511 }
00512 
00513 void SOUNDMANAGER::Reload()
00514 {
00515         if (disabled)
00516                 return;
00517         
00518         Unload();
00519         Load();
00520 }
00521 
00522 void SOUNDMANAGER::LoadSoundFile(string filename)
00523 {
00524         if (disabled)
00525                 return;
00526         
00527         if (buffers.find(filename) != buffers.end())
00528         {
00529                 cout << "sound file already loaded: " << filename << endl;
00530                 return;
00531         }
00532         
00533         ALenum format;
00534         ALsizei size;
00535         ALvoid* data = 0;
00536         ALsizei freq;
00537         bool error = 0;
00538         
00539 #ifdef __BIG_ENDIAN__    
00540         alutLoadWAVFile((ALbyte*)(filename).c_str(), &format, &data, &size, &freq);      
00541 #else
00542         ALboolean loop;
00543         error= LoadWave(filename.c_str(), &format, &data, &size, &freq, &loop);
00544 #endif
00545 
00546         if (data && !error)
00547         {
00548                 ALuint newbuf;
00549                 alGenBuffers(1, &newbuf);
00550 #ifdef __BIG_ENDIAN__    
00551                 alBufferData(newbuf, format, data, size, freq);  
00552                 alutUnloadWAV(format, data, size, freq);         
00553 #else
00554                 alBufferData(newbuf, format, data, size, (int)freq);
00555                 UnloadWave(data);
00556 #endif
00557                 buffers[filename] = newbuf;
00558                 
00559                 #ifdef SOUND_DEBUG
00560                 cout << "Loaded sound " << filename << " into buffer " << newbuf << endl;
00561                 #endif
00562         }
00563         else
00564         {
00565                 cerr << "Error loading sound file: " << filename << "\n";
00566                 if (!disabled)
00567                 {
00568                         cerr << "Disabling sound." << endl;
00569                         disabled = true;
00570                 }
00571         }
00572 }
00573 
00574 void SOUNDMANAGER::SetPosVel(int sid, VERTEX coord, VERTEX tvel)
00575 {
00576         if (disabled)
00577                 return;
00578         
00579         SetPos(sid, coord);
00580         SetVel(sid, tvel);
00581 }
00582 
00583 void SOUNDMANAGER::SetListener(VERTEX campos, VERTEX camvel, VERTEX at, VERTEX up)
00584 {
00585         if (disabled)
00586                 return;
00587         
00588         SetListenerPos(campos);
00589         SetListenerVel(camvel);
00590         SetListenerOrientation(at, up);
00591 }
00592 
00593 void SOUNDMANAGER::SetPitch(int sid, float pitch)
00594 {
00595         if (disabled)
00596                 return;
00597         
00598         //cout << "asked for source " << sid << "/" << sources.size() << endl;
00599         
00600         alSourcef (sources[sid], AL_PITCH, pitch);
00601 }
00602 
00603 void SOUNDMANAGER::SetGain(int sid, float gain)
00604 {
00605         if (disabled)
00606                 return;
00607         
00608         if (!loaded)
00609         {
00610                 //this happens when the spinning car widget creates a car object which does a NewSource on unloaded buffers
00611                 return;
00612         }
00613 
00614         gain *= master_volume;
00615         
00616         alSourcef (sources[sid], AL_MAX_GAIN, gain);
00617         alSourcef (sources[sid], AL_GAIN, gain);
00618 }
00619 
00620 void SOUNDMANAGER::SetPos(int sid, VERTEX pos)
00621 {
00622         if (disabled)
00623                 return;
00624         
00625         pos.Scale(DISTANCE_FACTOR);
00626 
00627         if (alIsSource(sources[sid]))
00628         {
00629                 alSourcefv(sources[sid], AL_POSITION, pos.v3());
00630         }
00631         else
00632         {
00633         }
00634 }
00635 
00636 void SOUNDMANAGER::SetVel(int sid, VERTEX vel)
00637 {
00638         if (disabled)
00639                 return;
00640         
00641         vel.Scale(VELOCITY_FACTOR);
00642         if (alIsSource(sources[sid]))
00643                 alSourcefv(sources[sid], AL_VELOCITY, vel.v3());
00644 }
00645 
00646 void SOUNDMANAGER::StopSource(int sid)
00647 {
00648         if (disabled || !loaded)
00649                 return;
00650         
00651         alSourceStop(sources[sid]);
00652         alDeleteSources(1, &sources[sid]);
00653         source_free[sid] = true;
00654 }
00655 
00656 void SOUNDMANAGER::PlaySource(int idx)
00657 {
00658         if (disabled || !loaded)
00659                 return;
00660         
00661         alSourcePlay(sources[idx]);
00662 }
00663 
00664 ALuint SOUNDMANAGER::NewSource(string buffername)
00665 {
00666         bool error;
00667         return NewSource(buffername, error);
00668 }
00669 
00670 ALuint SOUNDMANAGER::NewSource(string buffername, bool & error)
00671 {
00672         if (disabled)
00673                 return 0;
00674         
00675         if (!loaded)
00676         {
00677                 //this happens when the spinning car widget creates a car object which does a NewSource on unloaded buffers
00678                 error = true;
00679                 return 0;
00680         }
00681         
00682         if (sources.size() > MAX_SOURCES)
00683         {
00684                 cout << "Out of sound sources, can't create new source for buffer " << buffername << " (" << sources.size() << ")" << endl;
00685                 error = true;
00686                 return 0;
00687         }
00688         
00689         map <string, ALuint>::iterator sbuf = buffers.find(buffername);
00690         if (sbuf == buffers.end())
00691         {
00692                 cout << "Can't find buffer " << buffername << endl;
00693                 error = true;
00694                 return 0;
00695         }
00696         
00697         ALuint newsource;
00698         alGenSources(1, &newsource);
00699         
00700         ALfloat SourcePos[] = { 0.0, 0.0, 0.0 };
00701         ALfloat SourceVel[] = { 0.0, 0.0, 0.0 };
00702         
00703         alSourcei (newsource, AL_BUFFER,   sbuf->second   );
00704         alSourcef (newsource, AL_PITCH,    1.0      );
00705         alSourcef (newsource, AL_GAIN,     1.0      );
00706         alSourcefv(newsource, AL_POSITION, SourcePos);
00707         alSourcefv(newsource, AL_VELOCITY, SourceVel);
00708         alSourcei (newsource, AL_LOOPING,  AL_TRUE     );
00709         //alSourcei (sources[i], AL_LOOPING,  AL_FALSE     );
00710         
00711         int i = sources.size();
00712         sources.push_back(newsource);
00713         
00714         SetGain(i, 1.0);
00715                 
00716         PlaySource(i);
00717         
00718         error = false;
00719         
00720         return i;
00721 }
00722 
00723 void SOUNDMANAGER::SetListenerVel(VERTEX vel)
00724 {
00725         if (disabled)
00726                 return;
00727         
00728         vel.Scale(VELOCITY_FACTOR);
00729         alListenerfv(AL_VELOCITY, vel.v3());
00730 }
00731 
00732 void SOUNDMANAGER::SetListenerPos(VERTEX pos)
00733 {
00734         if (disabled)
00735                 return;
00736         
00737         pos.Scale(DISTANCE_FACTOR);
00738         alListenerfv(AL_POSITION, pos.v3());
00739 }
00740 
00741 void SOUNDMANAGER::SetListenerOrientation(VERTEX at, VERTEX up)
00742 {
00743         if (disabled)
00744                 return;
00745         
00746         float f[6];
00747         f[0] = at.x;
00748         f[1] = at.y;
00749         f[2] = at.z;
00750         f[3] = up.x;
00751         f[4] = up.y;
00752         f[5] = up.z;
00753         
00754         alListenerfv(AL_ORIENTATION, f);
00755 }
00756 
00757 void SOUNDMANAGER::MuteAll()
00758 {
00759         if (disabled)
00760                 return;
00761         
00762         unsigned int i;
00763         for (i = 0; i < sources.size(); i++)
00764         {
00765                 SetGain(i, 0.0f);
00766         }
00767 }
00768 
00769 void SOUNDMANAGER::UnMuteAll()
00770 {
00771         //placeholder, not yet used
00772 }
00773 
00774 bool SOUNDMANAGER::LoadWave(string fname, ALenum *format, ALvoid **data, ALsizei *size,
00775         ALsizei *freq, ALboolean *loop)
00776 {
00777     FILE *fp;
00778         
00779         bool err = false;
00780 
00781     fp = fopen(fname.c_str(),"rb");
00782     if (fp)
00783     {
00784         ALbyte id[4], *sound_buffer; //four bytes to hold 'RIFF'
00785         
00786                 ALint fsize; //32 bit value to hold file size
00787                 
00788         ALshort format_tag; //our 16-bit signed values
00789                 ALushort channels, block_align, bits_per_sample; //our 16-bit unsigned values
00790                 
00791         ALint format_length;//our 32 signed bit values
00792                 ALuint sample_rate, avg_bytes_sec;// data_size;//, i; //our 32 unsigned bit values
00793         ALint data_size;
00794         fsize = 0;
00795         fread(id, sizeof(ALbyte), 4, fp); //read in first four bytes
00796         //if (!strcmp((const char*)id, "RIFF"))
00797                 if (IDMatchesString((char*) id, "RIFF"))
00798         { //we had 'RIFF' let's continue
00799             fread(&fsize, sizeof(ALint), 1, fp); //read in 32bit size value
00800             fread(id, sizeof(ALbyte), 4, fp); //read in 4 byte string now
00801             //if (!strcmp((const char*)id,"WAVE"))
00802                         if (IDMatchesString((char*)id,"WAVE"))
00803             { //this is probably a wave file since it contained "WAVE"
00804                 fread(id, sizeof(ALbyte), 4, fp); //read in 4 bytes "fmt ";
00805                 fread(&format_length, sizeof(ALint),1,fp);
00806                 fread(&format_tag, sizeof(ALshort), 1, fp); //check mmreg.h (i think?) for other 
00807                                                               // possible format tags like ADPCM
00808                 fread(&channels, sizeof(ALshort),1,fp); //1 mono, 2 stereo
00809                 fread(&sample_rate, sizeof(ALint), 1, fp); //like 44100, 22050, etc...
00810                 fread(&avg_bytes_sec, sizeof(ALint), 1, fp); //probably won't need this
00811                 fread(&block_align, sizeof(ALshort), 1, fp); //probably won't need this
00812                 fread(&bits_per_sample, sizeof(ALshort), 1, fp); //8 bit or 16 bit file?
00813                                 
00814                                 //find data chunk
00815                                 bool found_data_chunk = false;
00816                                 long filepos = format_length + 4 + 4 + 4 + 4 + 4;
00817                                 int chunknum = 0;
00818                                 while (!found_data_chunk && chunknum < 10)
00819                                 {
00820                                         #ifdef SOUND_DEBUG
00821                                         cout << "seeking to " << filepos << endl;
00822                                         #endif
00823                                         fseek(fp, filepos, SEEK_SET); //seek to the next chunk
00824                                         fread(id, sizeof(ALbyte), 4, fp); //read in 'data'
00825                                         fread(&data_size, sizeof(ALbyte), 4, fp); //how many bytes of sound data we have
00826                                         if (IDMatchesString((char*)id, "data"))
00827                                         {
00828                                 found_data_chunk = true;
00829                                                 #ifdef SOUND_DEBUG
00830                                                 cout << "Found data chunk at " << filepos << ", chunk " << chunknum << endl;
00831                                                 #endif
00832                                         }
00833                                         else
00834                                         {
00835                                                 #ifdef SOUND_DEBUG
00836                                                 cout << "Chunk isn't data at " << filepos << ", chunk " << chunknum << endl;
00837                                                 #endif
00838                                                 filepos += data_size + 4 + 4;
00839                                         }
00840                                         
00841                                         chunknum++;
00842                                 }
00843                                 
00844                                 if (chunknum >= 10)
00845                                 {
00846                                         cerr << "Error: Wave file contains more than 10 chunks before the data chunk: " << fname << endl;
00847                                         *data = NULL;
00848                                         return false;
00849                                 }
00850                                 
00851                 //sound_buffer = (BYTE *) malloc (sizeof(BYTE) * data_size); //set aside sound buffer space
00852                                 #ifdef SOUND_DEBUG
00853                                 cout << "Loading sound " << fname << ": filesize " << fsize << ", " << data_size << " samples" << endl;
00854                                 #endif
00855                                 sound_buffer = new ALbyte[data_size];
00856                                 fread(sound_buffer, sizeof(ALbyte), data_size, fp); //read in our whole sound data chunk
00857                                 
00858                                 *data = sound_buffer;
00859                                 if (bits_per_sample == 16 && channels == 2)
00860                                                 *format = AL_FORMAT_STEREO16;
00861                                 else if (bits_per_sample == 8 && channels == 2)
00862                                                 *format = AL_FORMAT_STEREO8;
00863                                 else if (bits_per_sample == 16 && channels == 1)
00864                                                 *format = AL_FORMAT_MONO16;
00865                                 else if (bits_per_sample == 8 && channels == 1)
00866                                                 *format = AL_FORMAT_MONO8;
00867                                 else
00868                                 {
00869                                         cerr << "Error: unknown bits per sample and channels in file: " << fname << endl;
00870                                         cerr << channels << " channels" << endl;
00871                                         cerr << bits_per_sample << " bits per sample" << endl;
00872                                 }
00873                                 
00874                                 *size = data_size;
00875                                 *freq = sample_rate;
00876                                 #ifdef SOUND_DEBUG
00877                                 cout << channels << " channels" << endl;
00878                                 cout << bits_per_sample << " bits per sample" << endl;
00879                                 cout << sample_rate << " Hz sample rate" << endl;
00880                                 //cout << << endl;
00881                                 #endif
00882             }
00883             else
00884             {
00885                 cerr << "Error: RIFF file but not a wave file: " << fname << endl;
00886                                 err = true;
00887                                 *data = NULL;
00888             }
00889         }
00890         else
00891         {
00892             cerr << "Error: not a RIFF file: " << fname << endl;
00893                         err = true;
00894                         *data = NULL;
00895         }
00896     }
00897     else
00898     {
00899                 cerr << "Can't find sound file: " << fname << endl;
00900                 err = true;
00901                 *data = NULL;
00902     }
00903         
00904     return err;
00905 }
00906 
00907 void SOUNDMANAGER::UnloadWave(ALvoid* data)
00908 {
00909         delete [] (ALbyte*)data;
00910 }
00911 
00912 bool SOUNDMANAGER::IDMatchesString(const char * id, const char * str)
00913 {
00914         bool match = true;
00915         for (unsigned int i = 0; i < strlen(str); i++)
00916         {
00917                 if (id[i] != str[i])
00918                         match = false;
00919         }
00920         return match;
00921 }

Generated on Thu Oct 19 04:05:54 2006 by  doxygen 1.4.6