/* * Copyright (c) 2000 Mark B. Allan. All rights reserved. * * "Chromium B.S.U." is free software; you can redistribute * it and/or use it and/or modify it under the terms of the * "Artistic License" */ #ifdef AUDIO_OPENAL #include "AudioOpenAL.h" #ifdef macintosh #include void *alcCreateContext(int) { alInit(NULL); return (void*)1; } void alcDestroyContext(void*) { alExit(); } #endif //macintosh #include #include #include #include #ifndef _WIN32 #include #include #include #include #include #endif //_WIN32 #include #include #include #include "Config.h" #include "extern.h" #include "define.h" #include "Global.h" #ifdef OLD_OPENAL #ifdef USE_SDL //try to use OpenAL alc[GS]etAudioChannel extensions in linux... #ifdef __linux__ #define CD_VOLUME 1 // #include #include #endif //__linux__ #endif //USE_SDL #else #ifdef USE_SDL //try to use OpenAL alc[GS]etAudioChannel extensions in linux... #ifdef __linux__ #define CD_VOLUME 1 // #include #include #endif //__linux__ #endif //USE_SDL #endif #ifdef __linux__ #define USE_PLAYLIST 1 #endif //==================================================================== AudioOpenAL::AudioOpenAL() : Audio() { Config *config = Config::instance(); int i; context_id = 0; initialized = false; explosionIndex = 0; exploPopIndex = 0; origCDvolume = 0.7; //-- OpenAL extensions alAttenuationScale = 0; alcSetAudioChannel = 0; alcGetAudioChannel = 0; alutLoadMP3 = 0; alutLoadVorbis = 0; soundQueue = new SoundInfo; for(i = 0; i < NumSoundTypes; i++) { buffer[i] = 0; source[i] = 0; gain[i] = 0; sourcePos[i][0] = 0.0; sourcePos[i][1] = 0.0; sourcePos[i][2] = 0.0; numReqThisFrame[i] = 0; } for(i = 0; i < NUM_EXPLO; i++) { sourceExplosion[i] = 0; } for(i = 0; i < NUM_EXPLO_POP; i++) { sourceExploPop[i] = 0; } // NOTE: If we can't create a valid context, config->audioEnabled() will // be set to false. if(config->audioEnabled() == true) config->setAudio(createContext()); if(config->audioEnabled() == true) { initSound(); if(alAttenuationScale) { audioScale[0] = 3.0; audioScale[1] = 1.0; audioScale[2] = 1.0; } else { fprintf(stderr, "alAttenuationScale == 0. Kludge it.\n"); audioScale[0] = 0.5; audioScale[1] = 0.3; audioScale[2] = 0.3; } if(config->swapStereo()) audioScale[0] = -audioScale[0]; if(config->usePlayList() && !cdrom) loadMusicList(); } // fprintf(stderr, "AudioOpenAL::Audio done\n"); } AudioOpenAL::~AudioOpenAL() { if(initialized) { fprintf(stderr, "stopping OpenAL..."); #ifdef CD_VOLUME if(cdrom && alcSetAudioChannel) { alcSetAudioChannel(ALC_CHAN_CD_LOKI, origCDvolume); } #endif //CD_VOLUME if(cdrom) SDL_CDStop(cdrom); checkError("AudioOpenAL::~Audio()"); if(context_id) alcDestroyContext((ALCcontext*)context_id); fprintf(stderr, "done.\n"); } } //---------------------------------------------------------- #ifdef _WIN32 static void warning(const char *msg, ...) { va_list ap; va_start( ap, msg ); vfprintf( stderr, msg, ap ); va_end( ap ); fprintf( stderr, "\n"); } #else static void warning(const char *, ...) { } #endif /** * create OpenAL context. * @returns success */ //---------------------------------------------------------- bool AudioOpenAL::createContext() { #ifdef _WIN32 ALCdevice *dev; dev=alcOpenDevice((unsigned char*)"DirectSound",NULL); context_id=(void*)alcCreateContext(dev,NULL); alcMakeContextCurrent((ALCcontext*)context_id); #else #ifdef OLD_OPENAL context_id = alcCreateContext(NULL); #else ALCdevice *dev; dev = alcOpenDevice( NULL ); context_id = alcCreateContext(dev, NULL); alcMakeContextCurrent((ALCcontext*)context_id); #endif #endif if(!context_id) { fprintf(stderr, "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); fprintf(stderr, "!! ATTENTION !! - one or more errors were encountered during audio check.\n"); fprintf(stderr, "!! Audio will be disabled.\n"); fprintf(stderr, "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); } return (bool)context_id; } /** * Initialize OpenAL. The context should already have been created * in createContext() */ //---------------------------------------------------------- void AudioOpenAL::initSound() { Config *config = Config::instance(); int i; ALfloat pos[] = { 0.0, -5.0, 25.0 }; // fprintf(stderr, "AudioOpenAL::initSound() begin...\n"); fprintf(stderr, "-OpenAL-----------------------------------------------------\n"); fprintf(stderr, "Vendor : %s\n", alGetString( AL_VENDOR ) ); fprintf(stderr, "Renderer : %s\n", alGetString( AL_RENDERER ) ); fprintf(stderr, "Version : %s\n", alGetString( AL_VERSION ) ); // fprintf(stderr, "Extensions : %s\n", alGetString( AL_EXTENSIONS ) ); printExtensions(stderr, (const char*)alGetString( AL_EXTENSIONS )); fprintf(stderr, "------------------------------------------------------------\n"); checkForExtensions(); alListenerfv(AL_POSITION, pos); alGenBuffers(NumSoundTypes, buffer); alGenSources(NumSoundTypes, source); loadSounds(); for(i = 0; i < NumSoundTypes; i++) { switch(i) { case PowerUp: gain[PowerUp] = 0.7; break; case ExploPop: gain[ExploPop] = 0.8; break; case MusicGame: gain[MusicGame] = 0.7; break; case MusicMenu: gain[MusicMenu] = 0.7; break; default: gain[i] = 1.0; break; } } for(i = 0; i < NumSoundTypes; i++) { warning("Audio.cpp - init %s", fileNames[i]); alSourcefv( source[i], AL_POSITION, pos ); alSourcei ( source[i], AL_LOOPING, AL_FALSE); alSourcei ( source[i], AL_BUFFER, buffer[i] ); alSourcef ( source[i], AL_GAIN, gain[i]); checkError(); } //-- We want to have overlapped Explosion alGenSources(NUM_EXPLO-1, sourceExplosion); sourceExplosion[NUM_EXPLO-1] = source[Explosion]; for(i = 0; i < NUM_EXPLO-1; i++) { warning("Audio.cpp - init explosion %d", i); alSourcefv( sourceExplosion[i], AL_POSITION, pos ); alSourcei ( sourceExplosion[i], AL_LOOPING, AL_FALSE); alSourcei ( sourceExplosion[i], AL_BUFFER, buffer[Explosion] ); alSourcef ( sourceExplosion[i], AL_GAIN, gain[Explosion]*(0.7+0.3*FRAND) ); checkError(); } //-- We want to have overlapped ExploPop alGenSources(NUM_EXPLO_POP-1, sourceExploPop); sourceExploPop[NUM_EXPLO_POP-1] = source[ExploPop]; for(i = 0; i < NUM_EXPLO_POP-1; i++) { warning("Audio.cpp - init exploPop %d", i); alSourcefv( sourceExploPop[i], AL_POSITION, pos ); alSourcei ( sourceExploPop[i], AL_LOOPING, AL_FALSE); alSourcei ( sourceExploPop[i], AL_BUFFER, buffer[ExploPop] ); alSourcef ( sourceExploPop[i], AL_GAIN, 0.0*gain[ExploPop]*(0.1+0.9*FRAND) ); checkError(); } setSoundVolume(config->volSound()); setMusicVolume(config->volMusic()); initialized = true; warning("Audio.cpp - initSound complete.", i); } //---------------------------------------------------------- void AudioOpenAL::checkForExtensions() { #ifndef _WIN32 // Win32 doesn't have any useful extensions yet, and // the alGetProcAddress prototype is different (sigh). //-- check AttenuationScale extension alAttenuationScale = (void (*)(ALfloat param)) alGetProcAddress((ALchar *)"alAttenuationScale_LOKI"); if(alAttenuationScale == NULL) fprintf(stderr, "ATTENTION!! Could not load alAttenuationScale\n"); else alAttenuationScale(6.0); //-- check Audio Channel extension alcGetAudioChannel = (float (*)(ALuint channel)) alGetProcAddress((const ALchar *)"alcGetAudioChannel_LOKI"); alcSetAudioChannel = (void (*)(ALuint channel, ALfloat volume)) alGetProcAddress((const ALchar *)"alcSetAudioChannel_LOKI"); #ifdef CD_VOLUME if(alcGetAudioChannel) origCDvolume = alcGetAudioChannel(ALC_CHAN_CD_LOKI); #endif //CD_VOLUME //-- check MP3 extension alutLoadMP3 = (ALboolean (*)(ALuint, ALvoid *, ALint)) alGetProcAddress((const ALchar *)"alutLoadMP3_LOKI"); //-- check Ogg/Vorbis extension alutLoadVorbis = (ALboolean (*)(ALuint, ALvoid *, ALint)) alGetProcAddress((const ALchar *)"alutLoadVorbis_LOKI"); #endif //_WIN32 } /** * Stop OpenAL music. Also calls Audio::stopMusic() */ //---------------------------------------------------------- void AudioOpenAL::stopMusic() { Config *config = Config::instance(); if(config->audioEnabled() == true) { Audio::stopMusic(); alSourceStop(source[MusicMenu]); alSourceStop(source[MusicGame]); } } /** * Pause OpenAL music. Also calls Audio::pauseMusic() */ //---------------------------------------------------------- void AudioOpenAL::pauseGameMusic(bool status) { Config *config = Config::instance(); if(config->audioEnabled() == true) { if(cdrom) { Audio::pauseGameMusic(status); } else { if(status) alSourcePause(source[MusicGame]); else alSourcePlay(source[MusicGame]); } } } //---------------------------------------------------------- void AudioOpenAL::setMusicMode(SoundType mode) { // fprintf(stderr, "AudioOpenAL::setMusicMode(SoundType mode)\n"); Global *game = Global::getInstance(); Config *config = Config::instance(); if(config->audioEnabled() == true) { Audio::setMusicMode(mode); switch(mode) { default: case MusicGame: alSourceStop (source[MusicMenu]); if(!cdrom) { alSourcei (source[MusicGame], AL_LOOPING, AL_TRUE); if(!game->game_pause) alSourcePlay (source[MusicGame]); } break; case MusicMenu: if(!cdrom) { alSourcePause(source[MusicGame]); } alSourcei (source[MusicMenu], AL_LOOPING, AL_TRUE); alSourcePlay (source[MusicMenu]); break; } } } /** * adjust gain of OpenAL sounds */ //---------------------------------------------------------- void AudioOpenAL::setSoundVolume(float vol) { // fprintf(stderr, "AudioOpenAL::setSoundVolume(%f)\n", vol); Config *config = Config::instance(); if(config->audioEnabled() == true) { int i; if(vol > 1.0) vol = 1.0; if(vol < 0.0) vol = 0.0; soundVolume = vol; for(i = 0; i < MusicGame; i++) { alSourcef ( source[i], AL_GAIN, gain[i]*vol); } for(i = 0; i < NUM_EXPLO; i++) { alSourcef ( sourceExplosion[i], AL_GAIN, (0.5+(FRAND*0.5))*gain[Explosion]*soundVolume); } for(i = 0; i < NUM_EXPLO_POP; i++) { alSourcef ( sourceExploPop[i], AL_GAIN, (0.2+(FRAND*0.8))*gain[Explosion]*soundVolume); } } } /** * adjust gain of OpenAL music. Also adjusts CD channel of hardware * mixer if appropriate OpenAL extensions are available. */ //---------------------------------------------------------- void AudioOpenAL::setMusicVolume(float vol) { Config *config = Config::instance(); if(config->audioEnabled() == true) { if(vol > 1.0) vol = 1.0; if(vol < 0.0) vol = 0.0; musicVolume = vol; alSourcef ( source[MusicGame], AL_GAIN, gain[MusicGame]*musicVolume); alSourcef ( source[MusicMenu], AL_GAIN, gain[MusicGame]*musicVolume); #ifdef CD_VOLUME if(cdrom && alcSetAudioChannel) { alcSetAudioChannel(ALC_CHAN_CD_LOKI, musicVolume); } #endif // fprintf(stderr, "Music volume = %f\n", vol); } } /** * load WAV sound effects */ //---------------------------------------------------------- void AudioOpenAL::loadSounds() { int i; ALsizei size, freq, bits; ALenum format; ALvoid *data; ALboolean loop; for(i = 0; i < NumSoundTypes; i++) { if(!fileNames[i]) { fprintf(stderr, "\nERROR! - sound enumerant index %d does not have valid filename!\n", i); } else { #ifndef _WIN32 alutLoadWAVFile((ALbyte*)dataLoc(fileNames[i]), &format, &data, &size, &freq, &loop); alBufferData (buffer[i], format, data, size, freq); free(data); #else //_WIN32 char nameBuffer[256]; sprintf(nameBuffer, "%s", dataLoc(fileNames[i])); fprintf(stderr, "alutLoadWAVFile(\"%s\",...);\n", nameBuffer); alutLoadWAVFile(nameBuffer,&format,&data,&size,&freq); alBufferData(buffer[i],format,data,size,freq); alutUnloadWAV(format,data,size,freq); #endif//_WIN32 } } } //---------------------------------------------------------- void AudioOpenAL::checkError(const char* tag) { ALenum error = alGetError(); if(error != AL_NO_ERROR) { fprintf(stderr, "ERROR!! <%s> alGetError() = %s\n", tag, alGetString(error) ); } // error = alcGetError(); // if(error != ALC_NO_ERROR) // { // fprintf(stderr, "ERROR!! <%s> alcGetError() = %s\n", tag, alcGetString(error) ); // } } /** * This should be called every frame to ensure that delayed sounds are played * and that the numReqThisFrame counter is reset to 0 */ //---------------------------------------------------------- void AudioOpenAL::update() { SoundInfo *sound; SoundInfo *nextSound; SoundInfo *backSound; // play any delayed sounds sound = soundQueue->next; while(sound) { sound->age++; if(sound->age >= 0) { backSound = sound->back; nextSound = sound->next; backSound->next = nextSound; if(nextSound) nextSound->back = backSound; playSound(sound->type, sound->pos); delete sound; sound = backSound; } sound = sound->next; } // reset the number of requests to 0 for(int i = 0; i < NumSoundTypes; i++) { numReqThisFrame[i] = 0; } } /** * play sound of a given type. * @param type type of sound to play * @param pos position of the sound in world coords * @param age If age is negative, playback of the sound will * be delayed |age| frames. */ //---------------------------------------------------------- void AudioOpenAL::playSound(SoundType type, float *pos, int age) { Config *config = Config::instance(); if(config->audioEnabled()) { float p[3]; p[0] = pos[0]*audioScale[0]; p[1] = pos[1]*audioScale[1]; p[2] = pos[2]*audioScale[2]; if(age >= 0) { numReqThisFrame[type]++; // only play one sound of any given type per frame... if(numReqThisFrame[type] < 2) { switch(type) { case Explosion: playSoundExplosion(p); break; case ExploPop: playSoundExploPop(p); break; default: alSourceStop(source[type]); alSourcefv( source[type], AL_POSITION, p ); alSourcePlay(source[type]); // fprintf(stderr, "play %d\n", type); break; } } } else { SoundInfo *first = soundQueue->next; SoundInfo *newSound; newSound = new SoundInfo(type, pos, age); newSound->back = soundQueue; newSound->next = soundQueue->next; soundQueue->next = newSound; if(first) first->back = newSound; } } } //---------------------------------------------------------- void AudioOpenAL::playSoundExplosion(float p[3]) { explosionIndex++; explosionIndex = explosionIndex%NUM_EXPLO; alSourceStop(sourceExplosion[explosionIndex]); alSourcefv (sourceExplosion[explosionIndex], AL_POSITION, p ); alSourcePlay(sourceExplosion[explosionIndex]); } //---------------------------------------------------------- void AudioOpenAL::playSoundExploPop(float p[3]) { p[0] *= 1.5; exploPopIndex++; exploPopIndex = exploPopIndex%NUM_EXPLO_POP; alSourceStop(sourceExploPop[exploPopIndex]); alSourcefv (sourceExploPop[exploPopIndex], AL_POSITION, p ); alSourcePlay(sourceExploPop[exploPopIndex]); } //---------------------------------------------------------- void AudioOpenAL::loadMusicList() { Config *config = Config::instance(); int i; bool ok = false; int lineCount = 0; char buffer[1024]; char configFilename[256]; FILE *file; const char *homeDir = getenv("HOME"); if(!homeDir) homeDir = "./"; musicMax = 0; musicIndex = 0; sprintf(configFilename, "%s/%s", homeDir, CONFIG_MUSIC_FILE); alterPathForPlatform(configFilename); file = fopen(configFilename, "r"); if(file) { while( fgets(buffer, 1024, file) ) { int tmp = strlen(buffer); buffer[tmp-1] = '\0'; //-- get rid of new line ok = false; lineCount++; if(strlen(buffer) > 255) { fprintf(stderr, "ERROR: \"%s\", line %d\n", configFilename, lineCount); fprintf(stderr, " filename too long!\n"); } else if(strlen(buffer) > 4) { switch(extensionFormat(buffer)) { case WAV: strcpy(musicFile[musicMax], buffer); musicMax++; break; case MP3: if(alutLoadMP3) { strcpy(musicFile[musicMax], buffer); musicMax++; } else { fprintf(stderr, "WARNING: \"%s\", line %d\n", configFilename, lineCount); fprintf(stderr, " MP3 support not available.\n"); } break; case OGG: if(alutLoadVorbis) { strcpy(musicFile[musicMax], buffer); musicMax++; } else { fprintf(stderr, "WARNING: \"%s\", line %d\n", configFilename, lineCount); fprintf(stderr, " Ogg/Vorbis support not available.\n"); } break; default: fprintf(stderr, "WARNING: \"%s\", line %d\n", configFilename, lineCount); fprintf(stderr, " file type not recognized: \"%s\"\n", buffer); break; } } if(musicMax+1 >= MAX_MUSIC) // limited music array size. break; } } else config->setUsePlayList(false); if(musicMax < 1) config->setUsePlayList(false); fprintf(stderr, "music playlist:\n"); for(i = 0; i < musicMax; i++) { fprintf(stderr, " %2d : %s\n", i+1, musicFile[i]); } fprintf(stderr, "loaded %s\n", configFilename); } /** * Set music track to index. If CDROM is enabled, calls Audio::setMusicIndex(). * If playList is enabled, set to Nth track. */ //---------------------------------------------------------- void AudioOpenAL::setMusicIndex(int index) { Config *config = Config::instance(); bool wasPlaying = false; if(musicMax) musicIndex = index%musicMax; if(initialized && cdrom) { Audio:: setMusicIndex(index); } else if(initialized && config->usePlayList()) { bool loadSuccess = true; if(config->audioEnabled()) { checkError("AudioOpenAL::setMusicIndex -- begin"); //-- if music is currently playing, we want to // re-start playing after loading new song ALint state = AL_INITIAL; #ifdef OLD_OPENAL alGetSourcei(source[MusicGame], AL_SOURCE_STATE, &state); #else alGetSourceiv(source[MusicGame], AL_SOURCE_STATE, &state); #endif if(state == AL_PLAYING) wasPlaying = true; alSourceStop(source[MusicGame]); checkError("AudioOpenAL::setMusicIndex -- before setting source buffer to 0"); alSourcei(source[MusicGame], AL_BUFFER, 0); // alSourcei(source[MusicGame], AL_BUFFER, AL_NONE); checkError("AudioOpenAL::setMusicIndex -- after setting source buffer to 0"); alDeleteBuffers(1 , &buffer[MusicGame]); alGenBuffers(1, &buffer[MusicGame]); switch(extensionFormat(musicFile[musicIndex])) { case WAV: loadSuccess = loadWAV(musicFile[musicIndex]); break; case MP3: loadSuccess = loadMP3(musicFile[musicIndex]); break; case OGG: loadSuccess = loadVorbis(musicFile[musicIndex]); break; default: loadSuccess = false; break; } if(loadSuccess) { ALfloat pos[] = { 0.0, -5.0, 25.0 }; alSourcei ( source[MusicGame], AL_BUFFER, buffer[MusicGame]); alSourcefv( source[MusicGame], AL_POSITION, pos ); alSourcef ( source[MusicGame], AL_GAIN, gain[MusicGame]*musicVolume); alSourcei ( source[MusicGame], AL_LOOPING, AL_TRUE); if(wasPlaying) alSourcePlay(source[MusicGame]); } else { //-- fall back to default loop loadSuccess = loadWAV(dataLoc(fileNames[MusicGame])); } } checkError("AudioOpenAL::setMusicIndex -- end"); } else if(initialized) { ALint state = AL_INITIAL; #ifdef OLD_OPENAL alGetSourcei(source[MusicGame], AL_SOURCE_STATE, &state); #else alGetSourceiv(source[MusicGame], AL_SOURCE_STATE, &state); #endif if(state == AL_PLAYING) wasPlaying = true; alSourceStop(source[MusicGame]); if(wasPlaying) alSourcePlay(source[MusicGame]); } } #ifndef __linux__ // kludge so things compile on Win32 and Mac int strcasecmp(const char *a, const char *b) { return strcmp(a, b); } #endif //---------------------------------------------------------- AudioOpenAL::AudioFormat AudioOpenAL::extensionFormat(char* filename) { AudioFormat retVal = Unknown; char *walker; walker = strrchr(filename, '.'); if(walker) { if (strcasecmp(walker, ".wav") == 0) retVal = WAV; else if(strcasecmp(walker, ".mp3") == 0) retVal = MP3; else if(strcasecmp(walker, ".ogg") == 0) retVal = OGG; } else retVal = Unknown; return retVal; } //---------------------------------------------------------- bool AudioOpenAL::loadWAV(const char *filename) { #ifndef USE_PLAYLIST fprintf(stderr, "WARNING: %s\n", filename); fprintf(stderr, " PlayList support not compiled into Chromium (AudioOpenAL.cpp)\n"); return false; #else //USE_PLAYLIST bool retVal; ALsizei size, freq, bits; ALenum format; ALvoid *data; retVal = alutLoadWAV(filename, &data, &format, &size, &bits, &freq); if(retVal) { alBufferData (buffer[MusicGame], format, data, size, freq); free(data); } return retVal; #endif//USE_PLAYLIST } //---------------------------------------------------------- bool AudioOpenAL::loadMP3(const char *filename) { #ifndef USE_PLAYLIST fprintf(stderr, "WARNING: %s\n", filename); fprintf(stderr, " PlayList support not compiled into Chromium (AudioOpenAL.cpp)\n"); return false; #else//USE_PLAYLIST FILE *file; struct stat sbuf; int size; void *data; if(stat(filename, &sbuf) == -1) { perror(filename); return false; } size = sbuf.st_size; data = malloc(size); if(!data) { fprintf(stderr, "ERROR: Could not allocate memory in AudioOpenAL::loadMP3\n"); return false; } file = fopen(filename, "rb"); if(!file) { fprintf(stderr, "ERROR: Could not open \"%s\" in AudioOpenAL::loadMP3\n", filename); free(data); return false; } fread(data, 1, size, file); fclose(file); if( !(alutLoadMP3(buffer[MusicGame], data, size)) ) { fprintf(stderr, "ERROR: alutLoadMP3() failed in AudioOpenAL::loadMP3\n"); free(data); return false; } free(data); return true; #endif//USE_PLAYLIST } //---------------------------------------------------------- bool AudioOpenAL::loadVorbis(const char *filename) { #ifndef USE_PLAYLIST fprintf(stderr, "WARNING: %s\n", filename); fprintf(stderr, " PlayList support not compiled into Chromium (AudioOpenAL.cpp)\n"); return false; #else//USE_PLAYLIST if(initialized) { FILE *file; struct stat sbuf; int size; void *data; if(stat(filename, &sbuf) == -1) { perror(filename); return false; } size = sbuf.st_size; data = malloc(size); if(!data) { fprintf(stderr, "ERROR: Could not allocate memory in AudioOpenAL::loadVorbis\n"); return false; } file = fopen(filename, "rb"); if(!file) { fprintf(stderr, "ERROR: Could not open \"%s\" in AudioOpenAL::loadVorbis\n", filename); free(data); return false; } fread(data, 1, size, file); fclose(file); if( !(alutLoadVorbis(buffer[MusicGame], data, size)) ) { fprintf(stderr, "ERROR: alutLoadVorbis() failed in AudioOpenAL::loadVorbis\n"); free(data); return false; } free(data); return true; } else return false; #endif//USE_PLAYLIST } #endif // AUDIO_OPENAL