/* 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_source.h" #include "sound_engine.h" #include "alincl.h" #include "compiler.h" namespace OrxSound { /** * @brief creates a SoundSource at position sourceNode with the SoundBuffer buffer */ SoundSource::SoundSource(const PNode* sourceNode, const SoundBuffer* buffer) { this->setClassID(CL_SOUND_SOURCE, "SoundSource"); // adding the Source to the SourcesList of the SoundEngine this->buffer = buffer; this->sourceNode = sourceNode; this->resident = false; this->sourceID = 0; this->bPlay = false; } /** * @brief construct a SoundSource out of the another soundSource * @param source the Source to create this source from. * * Copies the buffer from source to this Source. * Acquires a new SourceID if source is Playing. */ SoundSource::SoundSource(const SoundSource& source) { this->setClassID(CL_SOUND_SOURCE, "SoundSource"); // adding the Source to the SourcesList of the SoundEngine this->buffer = source.buffer; this->sourceNode = source.sourceNode; this->resident = source.resident; this->sourceID = 0; if (source.bPlay == true) { this->bPlay = true; SoundEngine::getInstance()->popALSource(this->sourceID); } else this->bPlay = false; } /** * @brief paste a copy of the source into this Source. * @param source the SoundSource to paste into this one. * @returns a Reference to this Source. * */ SoundSource& SoundSource::operator=(const SoundSource& source) { this->buffer = source.buffer; this->sourceNode = sourceNode; this->resident = source.resident; if (source.bPlay) this->play(); else this->stop(); return *this; } /** * @brief compares two Sources with each other. * @param source the Source to compare against this One. * Two Sources are the same, if the PNodes match, and the Sound Played are the same. * The alSource must not match, because no two Sources can have the same alSource. */ bool SoundSource::operator==(const SoundSource& source) { return (this->buffer == source.buffer && this->bPlay == source.bPlay && this->sourceNode == source.sourceNode); } /** * @brief deletes a SoundSource */ SoundSource::~SoundSource() { this->stop(); if (this->sourceID != 0) SoundEngine::getInstance()->pushALSource(this->sourceID); } /** * @brief Plays back a SoundSource */ void SoundSource::play() { if (this->buffer && this->retrieveSource()) { if (this->bPlay) alSourceStop(this->sourceID); alSourcei (this->sourceID, AL_BUFFER, this->buffer->getID()); alSourcei (this->sourceID, AL_LOOPING, AL_FALSE); alSourcef (this->sourceID, AL_GAIN, 1); alSourcePlay(this->sourceID); if (DEBUG_LEVEL >= 3) SoundEngine::checkError("Play Source", __LINE__); this->bPlay = true; } } /** * @brief Plays back buffer on this Source * @param buffer the buffer to play back on this Source */ void SoundSource::play(const SoundBuffer* buffer) { if (!this->retrieveSource()) { PRINTF(3)("No more Free sources (You might consider raising the Source-Count).\n"); return; } alSourceStop(this->sourceID); alSourcei (this->sourceID, AL_BUFFER, buffer->getID()); alSourcei (this->sourceID, AL_LOOPING, AL_FALSE); alSourcef (this->sourceID, AL_GAIN, 1); alSourcePlay(this->sourceID); if (unlikely(this->buffer != NULL)) alSourcei (this->sourceID, AL_BUFFER, this->buffer->getID()); this->bPlay = true; if (DEBUG_LEVEL >= 3) SoundEngine::checkError("Play Source", __LINE__); } /** * @brief Plays back buffer on this Source with gain * @param buffer the buffer to play back on this Source */ void SoundSource::play(const SoundBuffer* buffer, float gain) { if (!this->retrieveSource()) { PRINTF(3)("No more Free sources (You might consider raising the Source-Count).\n"); return; } alSourceStop(this->sourceID); alSourcei (this->sourceID, AL_BUFFER, buffer->getID()); alSourcei (this->sourceID, AL_LOOPING, AL_FALSE); alSourcef (this->sourceID, AL_GAIN, gain); alSourcePlay(this->sourceID); if (unlikely(this->buffer != NULL)) alSourcei (this->sourceID, AL_BUFFER, this->buffer->getID()); this->bPlay = true; if (DEBUG_LEVEL >= 3) SoundEngine::checkError("Play Source", __LINE__); } /** * @brief Plays and loops back a SoundSource */ void SoundSource::loop() { if (this->buffer && this->retrieveSource()) { if (this->bPlay) alSourceStop(this->sourceID); alSourcei (this->sourceID, AL_BUFFER, this->buffer->getID()); alSourcei (this->sourceID, AL_LOOPING, AL_TRUE); alSourcef (this->sourceID, AL_GAIN, 1); alSourcePlay(this->sourceID); if (DEBUG_LEVEL >= 3) SoundEngine::checkError("Play Source", __LINE__); this->bPlay = true; } } /** * @brief Plays and loops buffer on this Source * @param buffer the buffer to play back on this Source */ void SoundSource::loop(const SoundBuffer* buffer) { if (this->buffer && this->retrieveSource()) { if (this->bPlay) alSourceStop(this->sourceID); alSourcei (this->sourceID, AL_BUFFER, this->buffer->getID()); alSourcei (this->sourceID, AL_LOOPING, AL_TRUE); alSourcef (this->sourceID, AL_GAIN, 1); alSourcePlay(this->sourceID); if (DEBUG_LEVEL >= 3) SoundEngine::checkError("Loop Source", __LINE__); this->bPlay = true; } } /** * @brief Plays and loops buffer on this Source with gain control * @param buffer the buffer to play back on this Source */ void SoundSource::loop(const SoundBuffer* buffer, float gain) { if (this->buffer && this->retrieveSource()) { if (this->bPlay) alSourceStop(this->sourceID); alSourcei (this->sourceID, AL_BUFFER, this->buffer->getID()); alSourcei (this->sourceID, AL_LOOPING, AL_TRUE); alSourcef (this->sourceID, AL_GAIN, gain); alSourcePlay(this->sourceID); if (DEBUG_LEVEL >= 3) SoundEngine::checkError("Loop Source", __LINE__); this->bPlay = true; } } /** * @brief Stops playback of a SoundSource */ void SoundSource::stop() { this->bPlay = false; if (this->sourceID != 0) { this->bPlay = false; if (this->sourceID != 0) { alSourceStop(this->sourceID); if (DEBUG_LEVEL >= 3) SoundEngine::checkError("StopSource", __LINE__); alSourcei(this->sourceID, AL_BUFFER, 0); if (!this->resident) SoundEngine::getInstance()->pushALSource(this->sourceID); this->sourceID = 0; } } } /** * @brief Pauses Playback of a SoundSource */ void SoundSource::pause() { alSourcePause(this->sourceID); if (DEBUG_LEVEL >= 3) SoundEngine::checkError("Pause Source", __LINE__); } /** * @brief Rewinds Playback of a SoundSource */ void SoundSource::rewind() { alSourceRewind(this->sourceID); if (DEBUG_LEVEL >= 3) SoundEngine::checkError("Rewind Source", __LINE__); } /** * @brief sets the RolloffFactor of the Sound emitted from the SoundSource * @param rolloffFactor The Factor described * * this tells openAL how fast the Sounds decay outward from the Source */ void SoundSource::setRolloffFactor(ALfloat rolloffFactor) { alSourcef(this->sourceID, AL_ROLLOFF_FACTOR, rolloffFactor); if (DEBUG_LEVEL >= 3) SoundEngine::checkError("Set Source Rolloff-factor", __LINE__); } /** * @brief sets the Positional this Source should be attached to. * @param sourceNode the Source this is attached to. * If sourceNode == NULL then the Source will be centered, and Audio will be played on all channels. */ void SoundSource::setSourceNode(const PNode* sourceNode) { this->sourceNode = sourceNode; } /** * @brief retrieve a Source. */ bool SoundSource::retrieveSource() { if (this->sourceID != 0) return true; else { SoundEngine::getInstance()->popALSource(this->sourceID); if (this->sourceID != 0) { if (unlikely(this->sourceNode == NULL)) resetSource(this->sourceID); return true; } } return false; } /** * @brief reset an alSource to its default Values. */ void SoundSource::resetSource(ALuint sourceID) { alSource3f(sourceID, AL_POSITION, 0.0, 0.0, 0.0); alSource3f(sourceID, AL_VELOCITY, 0.0, 0.0, 0.0); alSource3f(sourceID, AL_DIRECTION, 0.0, 0.0, 0.0); alSourcef (sourceID, AL_ROLLOFF_FACTOR, 0.0 ); //alSourcei (sourceID, AL_SOURCE_RELATIVE, AL_TRUE ); alSourcef (sourceID, AL_GAIN, SoundEngine::getInstance()->getEffectsVolume()); } /** * @brief Fades in a Source over a time period * @param duration time perios to fade in */ void SoundSource::fadein(const SoundBuffer* buffer, ALfloat duration) { //if (this->buffer && this->retrieveSource()) //{ for (ALfloat n = 0.0; n < 1.0; n+=.01) { alSourcef(this->sourceID, AL_GAIN, n); // sleep(1); } // alSourcePlay(this->sourceID); // if (DEBUG_LEVEL >= 3) // SoundEngine::checkError("Loop Source", __LINE__); // this->bPlay = true; //} } }