/* orxonox - the future of 3D-vertical-scrollers Copyright (C) 2004 orx This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. ### File Specific: main-programmer: Benjamin Grauer co-programmer: ... */ #define DEBUG_SPECIAL_MODULE DEBUG_MODULE_SOUND #include "sound_buffer_data.h" #include "sound_engine.h" #include "sdlincl.h" #include #include "debug.h" #include "sys/stat.h" #include "helper_functions.h" /*#ifdef HAVE_SDL_SDL_H #include // #include #else #include //#include #endif*/ namespace OrxSound { ObjectListDefinition(SoundBufferData); ////////////////// /* SOUND-BUFFER */ ////////////////// /** * @brief Creates a SoundbufferData out of an inputfile * @param fileName The name of the File */ SoundBufferData::SoundBufferData() { this->registerObject(this, SoundBufferData::_objectList); this->bufferID = 0; this->size = 0; this->loop = AL_FALSE; this->bLoaded = false; } SoundBufferData::~SoundBufferData() { // SoundEngine::getInstance()->removeBuffer(this); alDeleteBuffers(1, &this->bufferID); SoundEngine::checkError("SoundBuffer: Delete Buffer", __LINE__); } /** * @brief check the File-extension and loads either Wav of Ogg * @param fileName the Name of the File to load. * @returns true on success (file found, and loaded.) */ bool SoundBufferData::load(const std::string& fileName) { // generate a Buffer alGenBuffers(1, &this->bufferID); SoundEngine::checkError("Generate Buffer", __LINE__); if (!nocaseCmp(fileName.substr(fileName.size() - 3), "WAV")) { return this->loadWAV(fileName); } else if (!nocaseCmp(fileName.substr(fileName.size() - 3), "OGG")) return this->loadOGG(fileName); else return false; } /** * @brief loads a Waveform from the local fileSystem into this Source. * @param fileName the Name of the File to Load. * @returns true on success. */ bool SoundBufferData::loadWAV(const std::string& fileName) { SDL_AudioSpec wavSpec; Uint32 wavLength; Uint8 *wavBuffer; /* Load the WAV */ if( SDL_LoadWAV(fileName.c_str(), &wavSpec, &wavBuffer, &wavLength) == NULL) { PRINTF(2)("Could not open %s: %s\n", fileName.c_str(), SDL_GetError()); return false; } #if SDL_BYTEORDER == SDL_BIG_ENDIAN if ( !( wavSpec.format == AUDIO_U8 || wavSpec.format == AUDIO_S8 ) ) { int cnt = wavLength/2; Uint16* wavBufferAsShorts = ( Uint16* )wavBuffer; for ( int i = 0; i < cnt; ++i, ++wavBufferAsShorts ) *wavBufferAsShorts = SDL_Swap16( *wavBufferAsShorts ); } #endif alBufferData(this->bufferID, SoundBufferData::sdlAudioSpecToAlFormat(&wavSpec), wavBuffer, wavLength, wavSpec.freq); SDL_FreeWAV(wavBuffer); if (SoundEngine::checkError("Could not load Wave file", __LINE__)) { this->bLoaded = true; return true; } else return false; } #ifndef AL_FORMAT_VORBIS_EXT #define AL_FORMAT_VORBIS_EXT 0x100030 #endif /** * @brief loads an OGG-file into a SOundBuffer * @param fileName the Name of the File to load. * @returns true on success (file exists and is fully loaded), false otherwise. */ bool SoundBufferData::loadOGG(const std::string& fileName) { void* ovdata; FILE* fh; fh = fopen( fileName.c_str() , "rb") ; if( fh != NULL ) { struct stat sbuf ; if(stat( fileName.c_str(), &sbuf ) != -1) { ovdata = malloc(sbuf.st_size); if(ovdata != NULL) { fread( ovdata, 1, sbuf.st_size, fh); alBufferData( this->bufferID, AL_FORMAT_VORBIS_EXT, ovdata, sbuf.st_size, 1) ; SoundEngine::checkError("Could not load OGG file", __LINE__); free(ovdata); } fclose(fh); } else return false; } else return false; this->bLoaded = true; return true ; } /** * @brief converts an SDL_AudioSpec into a valid OpenAL AUDIO_FORMAT enumerator * @param audiospec the AudioSpec to convert. * @returns the AL_FORMAT */ ALenum SoundBufferData::sdlAudioSpecToAlFormat(const SDL_AudioSpec* audiospec) { assert (audiospec != NULL); bool stereo = true; bool is16Bit = true; if (audiospec->format == AUDIO_U8 || audiospec->format == AUDIO_S8) is16Bit = false; if (audiospec->channels == 1) stereo = false; if (!stereo && !is16Bit) return AL_FORMAT_MONO8; else if (!stereo && is16Bit) return AL_FORMAT_MONO16; else if (stereo && !is16Bit) return AL_FORMAT_STEREO8; else /* if (stereo && is16Bit) */ return AL_FORMAT_STEREO16; } }