|
From: julien r. <jul...@us...> - 2004-10-10 21:16:38
|
Update of /cvsroot/epfl/tgengine-0.1 In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv20643 Added Files: soundmanager.cc soundmanager.h Log Message: --- NEW FILE: soundmanager.cc --- // Sebastien "Whistle Master or Seb" Samyn: sebastien.samyn *at* epfl.ch #include <map> #include <vector> #include <string> #include <iostream> #ifdef TGOSX #include <OpenAL/al.h> #include <OpenAL/alut.h> #include <OpenAL/alc.h> #include <OpenAL/altypes.h> #else #include <AL/al.h> #include <AL/alut.h> #include <AL/alc.h> #include <AL/altypes.h> #endif #include <vorbis/vorbisfile.h> #include "soundmanager.h" #include "engine.h" using std::string; using std::map; using std::vector; using namespace std; // Constructor SoundManager::SoundManager() { #ifdef DEBUG cout << "OpenAL:: Starting SoundManager" << endl; #endif init(); } // Constructor SoundManager::SoundManager(bool little) { if(little == true) { endian = 0; #ifdef DEBUG cout << "OpenAL:: Starting SoundManager" << endl; cout << "OpenAL:: Little Endian detected..." << endl; #endif } else { endian = 1; #ifdef DEBUG cout << "OpenAL:: Starting SoundManager" << endl; cout << "OpenAL:: Big Endian detected..." << endl; #endif } init(); } // Destructor SoundManager::~SoundManager() { #ifdef DEBUG cout << "OpenAL:: Ending SoundManager" << endl; #endif KillALData(); alutExit(); } // Intialisation void SoundManager::init() { #ifdef DEBUG cout << "OpenAL:: Initializing SoundManager" << endl; #endif alutInit(NULL, 0); const ALubyte *alversion, *alrenderer, *alvendor, *alext; alversion = alGetString( AL_VERSION ); alrenderer = alGetString( AL_RENDERER ); alvendor = alGetString( AL_VENDOR ); alext = alGetString( AL_EXTENSIONS ); #ifdef DEBUG cout << "OpenAL:: Loading Lib: Vers = " << alversion << " | Renderer = " << alrenderer << " | Vendor = " << alvendor << endl; #endif } // Listener Position (player or camera) void SoundManager::SetListenerPosition(float x, float y, float z) { #ifdef DEBUG cout << "OpenAL:: SetListenerPosition (" << x << "," << y << "," << z << ")" << endl; #endif //set the position using 3 seperate floats alListener3f(AL_POSITION, x/100,y/100,z/100); } // Listener Orientation void SoundManager::SetListenerOrientation(float fx, float fy, float fz, float ux, float uy, float uz) { #ifdef DEBUG cout << "OpenAL:: SetListenerOrientation" << endl; #endif //set the orientation using an array of floats float vec[6]; vec[0] = fx; vec[1] = fy; vec[2] = fz; vec[3] = ux; vec[4] = uy; vec[5] = uz; alListenerfv(AL_ORIENTATION, vec); } // Creat a new buffer for a sound ALuint SoundManager::LoadWavALBuffer(char path[40]) { // Variables to store data which defines the buffer. ALenum format; ALsizei size; ALvoid* data; ALsizei freq; // Buffer id and error checking variable. ALuint buffer; ALenum result; #ifdef DEBUG cout << "OpenAL:: LoadWavALBuffer: " << path << endl; #endif // Generate a buffer. Check that it was created successfully. alGenBuffers(1, &buffer); if ((result = alGetError()) != AL_NO_ERROR) throw GetALErrorString(result); // Read in the wav data from file. Check that it loaded correctly. #ifdef TGOSX alutLoadWAVFile(path, &format, &data, &size, &freq); #endif #ifdef TGWIN32 alutLoadWAVFile(path, &format, &data, &size, &freq, AL_FALSE); #endif #ifdef TGLINUX alutLoadWAVFile((ALbyte *) path, &format, &data, &size,&freq, AL_FALSE); #endif if ((result = alGetError()) != AL_NO_ERROR) throw GetALErrorString(result); // Send the wav data into the buffer. Check that it was received properly. alBufferData(buffer, format, data, size, freq); if ((result = alGetError()) != AL_NO_ERROR) throw GetALErrorString(result); // Get rid of the temporary data. alutUnloadWAV(format, data, size, freq); if ((result = alGetError()) != AL_NO_ERROR) throw GetALErrorString(result); // Return the buffer id. return buffer; } // Check if a buffer already exist. If no, creat a new one ALuint SoundManager::GetLoadedWavALBuffer(char path[40]) { int count = 0; // 'count' will be an index to the buffer list. ALuint buffer; // Buffer id for the loaded buffer. #ifdef DEBUG cout << "OpenAL:: GetLoadedWavALBuffer: " << path << endl; #endif // Iterate through each file path in the list. for(vector<string>::iterator iter = LoadedFiles.begin(); iter != LoadedFiles.end(); ++iter, count++) { // If this file path matches one we have loaded already, return the buffer id for it. if(*iter == path) return Buffers[count]; } // If we have made it this far then this file is new and we will create a buffer for it. buffer = LoadWavALBuffer(path); // Add this new buffer to the list, and register that this file has been loaded already. Buffers.push_back(buffer); LoadedFiles.push_back(path); return buffer; } // Creat a buffer and a source for a new sound ALuint SoundManager::LoadWavALSample(string name, bool loop) { ALuint source; ALuint buffer; ALenum result; // All new sound are in postion (0,0,0) ALfloat SourcePos[] = {0.0, 0.0, 0.0}; ALfloat SourceVel[]= {0.0, 0.0, 0.0}; char *path = (char*) name.c_str(); #ifdef DEBUG cout << "OpenAL:: LoadWavALSample: " << name << endl; #endif // Get the files buffer id (load it if necessary). buffer = GetLoadedWavALBuffer(path); // Generate a source. alGenSources(1, &source); if ((result = alGetError()) != AL_NO_ERROR) throw GetALErrorString(result); // Setup the source properties. alSourcei (source, AL_BUFFER, buffer ); alSourcef (source, AL_PITCH, 1.0f ); alSourcef (source, AL_GAIN, 1.0f ); alSourcefv(source, AL_POSITION, SourcePos); alSourcefv(source, AL_VELOCITY, SourceVel); alSourcei (source, AL_LOOPING, loop ); // Save the source id. Sources.push_back(source); // Return the source id. return source; } // Add a Wav sound to the sounds list void SoundManager::AddWAV(string name, bool relative,bool looping) { try { #ifdef DEBUG cout << "OpenAL:: AddWAV: " << name << endl; #endif SoundList[name] = LoadWavALSample("data/sounds/"+name+".wav", looping); if(relative) alSourcei(SoundList[name],AL_SOURCE_RELATIVE,AL_TRUE); } catch(string err) { cout << "OpenAL error: " << err.c_str() << endl; } LoadedFiles.clear(); } // Sound properties (position and velocity) void SoundManager::SetSoundProperties(string name, float x, float y, float z, float vx, float vy, float vz) { #ifdef DEBUG cout << "OpenAL:: SetSoundProperties: " << name << "(" << x << "," << y << "," << z << ")" << endl; #endif //set the sounds position and velocity alSource3f(SoundList[name],AL_POSITION,x/100,y/100,z/100); alSource3f(SoundList[name],AL_VELOCITY,vx,vy,vz); } // Sound volume void SoundManager::SetSoundVolume(string name, float x) { #ifdef DEBUG cout << "OpenAL:: SetSoundVolume: " << name << "(" << x << ")" << endl; #endif //set the sounds volume alSourcef (SoundList[name], AL_GAIN,x); } // Play a sound void SoundManager::PlaySound(string name) { #ifdef DEBUG cout << "OpenAL:: PlaySound: " << name << endl; #endif alSourcePlay(SoundList[name]); } // Stop a sound void SoundManager::StopSound(string name) { #ifdef DEBUG cout << "OpenAL:: StopSound: " << name << endl; #endif alSourceStop(SoundList[name]); } // Get Status int SoundManager::SoundStatus(string name) { ALint state; #ifdef DEBUG cout << "OpenAL:: SoundStatus: " << name << endl; #endif alGetSourcei(SoundList[name], AL_SOURCE_STATE, &state); if (state == AL_PLAYING) return 1; else if (state == AL_PAUSED) return 0; else if (state == AL_STOPPED) return -1; return -2; } // Kill all buffers and sources void SoundManager::KillALData() { // Release all buffer data. for (vector<ALuint>::iterator iter = Buffers.begin(); iter != Buffers.end(); ++iter) alDeleteBuffers(1, (ALuint*)(*iter)); // Release all source data. for (vector<ALuint>::iterator iter = Sources.begin(); iter != Sources.end(); ++iter) alDeleteBuffers(1, (ALuint*)(*iter)); #ifdef DEBUG cout << "OpenAL:: KillALData" << endl; #endif // Destroy the lists. Buffers.clear(); Sources.clear(); SoundList.clear(); } // Creat a new buffer for a sound ALuint SoundManager::LoadOggALBuffer(char path[40]) { // Variables to store data which defines the buffer. ALenum format; ALsizei freq; vector<char> bufferData; // Buffer id and error checking variable. ALuint buffer; ALenum result; #ifdef DEBUG cout << "OpenAL:: LoadOggALBuffer: " << path << endl; #endif // Generate a buffer. Check that it was created successfully. alGenBuffers(1, &buffer); if ((result = alGetError()) != AL_NO_ERROR) throw GetALErrorString(result); // Read in the wav data from file. Check that it loaded correctly. LoadOGG(path, bufferData, format, freq); if ((result = alGetError()) != AL_NO_ERROR) throw GetALErrorString(result); // Send the wav data into the buffer. Check that it was received properly. alBufferData(buffer, format, &bufferData[0], static_cast<ALsizei>(bufferData.size()), freq); if ((result = alGetError()) != AL_NO_ERROR) throw GetALErrorString(result); // Return the buffer id. return buffer; } // Check if a buffer already exist. If no, creat a new one ALuint SoundManager::GetLoadedOggALBuffer(char path[40]) { int count = 0; // 'count' will be an index to the buffer list. ALuint buffer; // Buffer id for the loaded buffer. #ifdef DEBUG cout << "OpenAL:: GetLoadedOggALBuffer: " << path << endl; #endif // Iterate through each file path in the list. for(vector<string>::iterator iter = LoadedFiles.begin(); iter != LoadedFiles.end(); ++iter, count++) { // If this file path matches one we have loaded already, return the buffer id for it. if(*iter == path) return Buffers[count]; } // If we have made it this far then this file is new and we will create a buffer for it. buffer = LoadOggALBuffer(path); // Add this new buffer to the list, and register that this file has been loaded already. Buffers.push_back(buffer); LoadedFiles.push_back(path); return buffer; } // Creat a buffer and a source for a new sound ALuint SoundManager::LoadOggALSample(string name, bool loop) { ALuint source; ALuint buffer; ALenum result; // All new sound are in postion (0,0,0) ALfloat SourcePos[] = {0.0, 0.0, 0.0}; ALfloat SourceVel[]= {0.0, 0.0, 0.0}; char *path = (char*) name.c_str(); #ifdef DEBUG cout << "OpenAL:: LoadOggALSample: " << name << endl; #endif // Get the files buffer id (load it if necessary). buffer = GetLoadedOggALBuffer(path); // Generate a source. alGenSources(1, &source); if ((result = alGetError()) != AL_NO_ERROR) throw GetALErrorString(result); // Setup the source properties. alSourcei (source, AL_BUFFER, buffer ); alSourcef (source, AL_PITCH, 1.0f ); alSourcef (source, AL_GAIN, 1.0f ); alSourcefv(source, AL_POSITION, SourcePos); alSourcefv(source, AL_VELOCITY, SourceVel); alSourcei (source, AL_LOOPING, loop ); // Save the source id. Sources.push_back(source); // Return the source id. return source; } // Add a Wav sound to the sounds list void SoundManager::AddOGG(string name, bool relative,bool looping) { try { #ifdef DEBUG cout << "OpenAL:: AddOGG: " << name << endl; #endif SoundList[name] = LoadOggALSample("data/sounds/"+name+".ogg", looping); if(relative) alSourcei(SoundList[name],AL_SOURCE_RELATIVE,AL_TRUE); } catch(string err) { cout << "OpenAL:: Error: " << err.c_str() << endl; } LoadedFiles.clear(); } // This function loads a .ogg file into a memory buffer and returns the format and frequency. void SoundManager::LoadOGG(char *fileName, vector<char> &buffer, ALenum &format, ALsizei &freq) { int bitStream; long bytes; char array[BUFFER_SIZE]; // Local fixed size array FILE *f; // Open for binary reading f = fopen(fileName, "rb"); if (f == NULL) { cerr << "OpenAL:: Cannot open " << fileName << " for reading..." << endl; exit(-1); } // end if vorbis_info *pInfo; OggVorbis_File oggFile; // Try opening the given file if (ov_open(f, &oggFile, NULL, 0) != 0) { cerr << "OpenAL:: Error opening " << fileName << " for decoding..." << endl; exit(-1); } // end if // Get some information about the OGG file pInfo = ov_info(&oggFile, -1); // Check the number of channels... always use 16-bit samples if (pInfo->channels == 1) format = AL_FORMAT_MONO16; else format = AL_FORMAT_STEREO16; // end if // The frequency of the sampling rate freq = pInfo->rate; // Keep reading until all is read do { // Read up to a buffer's worth of decoded sound data bytes = ov_read(&oggFile, array, BUFFER_SIZE, endian, 2, 1, &bitStream); if (bytes < 0) { ov_clear(&oggFile); cerr << "OpenAL:: Error decoding " << fileName << "..." << endl; exit(-1); } // end if // Append to end of buffer buffer.insert(buffer.end(), array, array + bytes); } while (bytes > 0); // Clean up! ov_clear(&oggFile); } // Handling Errors string SoundManager::GetALErrorString(ALenum err) { switch(err) { case AL_NO_ERROR: return string("AL_NO_ERROR"); break; case AL_INVALID_NAME: return string("AL_INVALID_NAME"); break; case AL_INVALID_ENUM: return string("AL_INVALID_ENUM"); break; case AL_INVALID_VALUE: return string("AL_INVALID_VALUE"); break; case AL_INVALID_OPERATION: return string("AL_INVALID_OPERATION"); break; case AL_OUT_OF_MEMORY: return string("AL_OUT_OF_MEMORY"); break; }; return 0; } // Handling Errors string SoundManager::GetALCErrorString(ALenum err) { switch(err) { case ALC_NO_ERROR: return string("AL_NO_ERROR"); break; case ALC_INVALID_DEVICE: return string("ALC_INVALID_DEVICE"); break; case ALC_INVALID_CONTEXT: return string("ALC_INVALID_CONTEXT"); break; case ALC_INVALID_ENUM: return string("ALC_INVALID_ENUM"); break; case ALC_INVALID_VALUE: return string("ALC_INVALID_VALUE"); break; case ALC_OUT_OF_MEMORY: return string("ALC_OUT_OF_MEMORY"); break; }; return 0; } --- NEW FILE: soundmanager.h --- // Sebastien "Whistle Master or Seb" Samyn: sebastien.samyn *chez* epfl.ch #include <map> #include <vector> #include <string> #ifdef TGOSX #include <OpenAL/al.h> #include <OpenAL/alut.h> #include <OpenAL/alc.h> #include <OpenAL/altypes.h> #else #include <AL/al.h> #include <AL/alut.h> #include <AL/alc.h> #include <AL/altypes.h> #endif #include <vorbis/vorbisfile.h> #define BUFFER_SIZE 32768 // 32 KB buffers using std::string; using std::map; using std::vector; //SoundManager class SoundManager { public: ~SoundManager(); SoundManager(); SoundManager(bool little); void AddWAV(string name, bool relative,bool looping); void AddOGG(string name, bool relative,bool looping); void PlaySound(string name); void StopSound(string name); int SoundStatus(string name); void SetSoundVolume(string name, float x); void SetSoundProperties(string name, float x, float y, float z, float vx, float vy, float vz); void SetListenerPosition(float x, float y, float z); void SetListenerOrientation(float fx, float fy, float fz, float ux, float uy, float uz); void KillALData(); protected: int endian; // 0 for Little-Endian, 1 for Big-Endian void init(); string GetALErrorString(ALenum err); string GetALCErrorString(ALenum err); ALuint LoadWavALBuffer(char path[40]); ALuint GetLoadedWavALBuffer(char path[40]); ALuint LoadWavALSample(string name, bool loop); ALuint LoadOggALBuffer(char path[40]); ALuint GetLoadedOggALBuffer(char path[40]); ALuint LoadOggALSample(string name, bool loop); void LoadOGG(char *fileName, vector<char> &buffer, ALenum &format, ALsizei &freq); vector<string> LoadedFiles; // Holds loaded file paths temporarily. vector<ALuint> Buffers; // Holds all loaded buffers. vector<ALuint> Sources; // Holds all validated sources. map<string, ALuint> SoundList; // Hold all sounds. }; |