Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Ignore:
Timestamp:
Oct 6, 2009, 11:12:01 PM (15 years ago)
Author:
rgrieder
Message:

Added some basic sound classes: WorldSound (to be used for 3D sound, is a WorldEntity) and AmbientSound (BaseObject, just add it somewhere and it will play with playOnLoad=true).
Also moved the sound listener device updating to the HumanController. We might want to modify this again so that the listener is at the camera position again, not at the space ship.

File:
1 copied

Legend:

Unmodified
Added
Removed
  • code/branches/core5/src/orxonox/sound/AmbientSound.cc

    r5891 r5896  
    2121 *
    2222 *   Author:
    23  *       Erwin 'vaiursch' Herrsche
     23 *      Reto Grieder
    2424 *   Co-authors:
    2525 *      ...
     
    2727 */
    2828
    29 #include "SoundBase.h"
     29#include "AmbientSound.h"
    3030
    31 #include <string>
    32 #include <vector>
    33 #include <AL/alut.h>
    34 #include <vorbis/vorbisfile.h>
    35 
    36 #include "util/Math.h"
    37 #include "core/Resource.h"
    38 #include "worldentities/WorldEntity.h"
    39 #include "SoundManager.h"
     31#include "core/EventIncludes.h"
     32#include "core/XMLPort.h"
    4033
    4134namespace orxonox
    4235{
    43     SoundBase::SoundBase(WorldEntity* entity)
     36    CreateFactory(AmbientSound);
     37
     38    AmbientSound::AmbientSound(BaseObject* creator)
     39        : BaseObject(creator)
    4440    {
    45         this->source_ = 0;
    46         this->buffer_ = 0;
    47         this->entity_ = entity;
    48 
    49         SoundManager::getInstance().addSound(this);
     41        RegisterObject(AmbientSound);
    5042    }
    5143
    52     SoundBase::~SoundBase()
     44    AmbientSound::~AmbientSound()
    5345    {
    54         alSourcei(this->source_, AL_BUFFER, 0);
    55         alDeleteSources(1, &this->source_);
    56         alDeleteBuffers(1, &this->buffer_);
    5746    }
    5847
    59     void SoundBase::attachToEntity(WorldEntity* entity)
     48    void AmbientSound::XMLPort(Element& xmlelement, XMLPort::Mode mode)
    6049    {
    61         this->entity_ = entity;
    62         this->update();
     50        SUPER(AmbientSound, XMLPort, xmlelement, mode);
     51        XMLPortParamExtern(AmbientSound, BaseSound, this, "soundFile", setSoundFile, getSoundFile, xmlelement, mode);
     52        XMLPortParamExtern(AmbientSound, BaseSound, this, "loop", setLoop, getLoop, xmlelement, mode);
     53        XMLPortParamExtern(AmbientSound, BaseSound, this, "playOnLoad", setPlayOnLoad, getPlayOnLoad, xmlelement, mode);
    6354    }
    6455
    65     void SoundBase::update() {
    66         if(this->entity_ != NULL && alIsSource(this->source_)) {
    67             const Vector3& pos = this->entity_->getPosition();
    68             alSource3f(this->source_, AL_POSITION, pos.x, pos.y, pos.z);
    69             ALenum error = alGetError();
    70             if(error == AL_INVALID_VALUE)
    71                 COUT(2) << "Sound: OpenAL: Invalid sound position" << std::endl;
    72 
    73             const Vector3& vel = this->entity_->getVelocity();
    74             alSource3f(this->source_, AL_VELOCITY, vel.x, vel.y, vel.z);
    75             error = alGetError();
    76             if(error == AL_INVALID_VALUE)
    77                 COUT(2) << "Sound: OpenAL: Invalid sound velocity" << std::endl;
    78 
    79             const Quaternion& orient = this->entity_->getOrientation();
    80             Vector3 at = orient.zAxis();
    81             alSource3f(this->source_, AL_DIRECTION, at.x, at.y, at.z);
    82             error = alGetError();
    83             if(error == AL_INVALID_VALUE)
    84                 COUT(2) << "Sound: OpenAL: Invalid sound direction" << std::endl;
    85         }
     56    void AmbientSound::XMLEventPort(Element& xmlelement, XMLPort::Mode mode)
     57    {
     58        SUPER(AmbientSound, XMLEventPort, xmlelement, mode);
     59        XMLPortEventState(AmbientSound, BaseObject, "play", play, xmlelement, mode);
    8660    }
    87 
    88     void SoundBase::play(bool loop) {
    89         if(alIsSource(this->source_)) {
    90             if(loop)
    91                 alSourcei(this->source_, AL_LOOPING, AL_TRUE);
    92             else
    93                 alSourcei(this->source_, AL_LOOPING, AL_FALSE);
    94             alSourcePlay(this->source_);
    95 
    96             if(alGetError() != AL_NO_ERROR)
    97             {
    98                  COUT(2) << "Sound: OpenAL: Error playin sound " << this->source_ << std::endl;
    99             }
    100         }
    101     }
    102 
    103     void SoundBase::stop() {
    104         if(alIsSource(this->source_)) {
    105             alSourceStop(this->source_);
    106         }
    107     }
    108 
    109     void SoundBase::pause() {
    110         if(alIsSource(this->source_)) {
    111             alSourcePause(this->source_);
    112         }
    113     }
    114 
    115     bool SoundBase::isPlaying() {
    116         if(alIsSource(this->source_)) {
    117             return getSourceState() == AL_PLAYING;
    118         }
    119         return false;
    120     }
    121 
    122     bool SoundBase::isPaused() {
    123         if(alIsSource(this->source_)) {
    124             return getSourceState() == AL_PAUSED;
    125         }
    126         return true;
    127     }
    128 
    129     bool SoundBase::isStopped() {
    130         if(alIsSource(this->source_)) {
    131             return getSourceState() == AL_INITIAL || getSourceState() == AL_STOPPED;
    132         }
    133         return true;
    134     }
    135 
    136     bool SoundBase::loadFile(const std::string& filename) {
    137         if(!SoundManager::getInstance().isSoundAvailable())
    138         {
    139             COUT(3) << "Sound: not available, skipping " << filename << std::endl;
    140             return false;
    141         }
    142 
    143         COUT(3) << "Sound: OpenAL ALUT: loading file " << filename << std::endl;
    144         // Get DataStream from the resources
    145         shared_ptr<ResourceInfo> fileInfo = Resource::getInfo(filename);
    146         if (fileInfo == NULL) {
    147             COUT(2) << "Warning: Sound file '" << filename << "' not found" << std::endl;
    148             return false;
    149         }
    150         DataStreamPtr stream = Resource::open(filename);
    151         // Read everything into a temporary buffer
    152         char* buffer = new char[fileInfo->size];
    153         stream->read(buffer, fileInfo->size);
    154 
    155         this->buffer_ = alutCreateBufferFromFileImage(buffer, fileInfo->size);
    156         delete[] buffer;
    157 
    158         if(this->buffer_ == AL_NONE) {
    159             COUT(2) << "Sound: OpenAL ALUT: " << alutGetErrorString(alutGetError()) << std::endl;
    160             if(filename.find("ogg", 0) != std::string::npos)
    161             {
    162                 COUT(2) << "Sound: Trying fallback ogg loader" << std::endl;
    163                 this->buffer_ = loadOggFile(filename);
    164             }
    165 
    166             if(this->buffer_ == AL_NONE)
    167             {
    168                 COUT(2) << "Sound: fallback ogg loader failed: " << alutGetErrorString(alutGetError()) << std::endl;
    169                 return false;
    170             }
    171         }
    172 
    173         alGenSources(1, &this->source_);
    174         alSourcei(this->source_, AL_BUFFER, this->buffer_);
    175         if(alGetError() != AL_NO_ERROR) {
    176             COUT(2) << "Sound: OpenAL: Error loading sample file: " << filename << std::endl;
    177             return false;
    178         }
    179         return true;
    180     }
    181 
    182     ALint SoundBase::getSourceState() {
    183         ALint state;
    184         alGetSourcei(this->source_, AL_SOURCE_STATE, &state);
    185         return state;
    186     }
    187 
    188     ALuint SoundBase::loadOggFile(const std::string& filename)
    189     {
    190         char inbuffer[4096];
    191         std::vector<char> outbuffer;
    192         OggVorbis_File vf;
    193         vorbis_info* vorbisInfo;
    194         int eof = false;
    195         int current_section;
    196         ALuint buffer;
    197         ALenum format;
    198 
    199         FILE* f = fopen(filename.c_str(), "rb");
    200 
    201         if(ov_open(f, &vf, NULL, 0) < 0)
    202         {
    203             COUT(2) << "Sound: libvorbisfile: File does not seem to be an Ogg Vorbis bitstream" << std::endl;
    204             ov_clear(&vf);
    205             return AL_NONE;
    206         }
    207 
    208         while(!eof)
    209         {
    210             long ret = ov_read(&vf, inbuffer, sizeof(inbuffer), 0, 2, 1, &current_section);
    211             if (ret == 0)
    212             {
    213                 eof = true;
    214             }
    215             else if (ret < 0)
    216             {
    217                 COUT(2) << "Sound: libvorbisfile: error reading the file" << std::endl;
    218                 ov_clear(&vf);
    219                 return AL_NONE;
    220             }
    221             else
    222             {
    223                 outbuffer.insert(outbuffer.end(), inbuffer, inbuffer + sizeof(inbuffer));
    224             }
    225         }
    226 
    227         vorbisInfo = ov_info(&vf, -1);
    228         if(vorbisInfo->channels == 1)
    229             format = AL_FORMAT_MONO16;
    230         else
    231             format = AL_FORMAT_STEREO16;
    232 
    233         alGenBuffers(1, &buffer);
    234         alBufferData(buffer, format, &outbuffer[0], outbuffer.size(), vorbisInfo->rate);
    235         ov_clear(&vf);
    236 
    237         return buffer;
    238     }
    239 } // namespace: orxonox
     61}
Note: See TracChangeset for help on using the changeset viewer.