src/engine/sound/sdl_mixer/eChannelSDLMixer.cpp

Go to the documentation of this file.
00001 
00002 #include "eChannelSDLMixer.h"
00003 
00004 // I don't know how many of these includes are actually necessary
00005 #include "rSDL.h"
00006 #include "rScreen.h"
00007 #include "defs.h"
00008 // #include "eGrid.h"
00009 #include "tString.h"
00010 #include "tLinkedList.h"
00011 #include "tDirectories.h"
00012 #include "tConfiguration.h"
00013 #include "tConsole.h"
00014 #include "tError.h"
00015 #include "eGameObject.h"
00016 #include "eCoord.h"
00017 
00018 #include "eSoundMixer.h"
00019 
00020 // Possibly temporary?
00021 #include <math.h>
00022 
00023 // sound quality
00024 #define SOUND_OFF 0
00025 #define SOUND_LOW 1
00026 #define SOUND_MED 2
00027 #define SOUND_HIGH 3
00028 
00029 // Playlist options
00030 #define PLAYLIST_INTERNAL 0
00031 #define PLAYLIST_CUSTOM 1
00032 /*******************************************************************************
00033  *
00034  * eWavData
00035  *
00036  *******************************************************************************/
00037 
00038 eWavData::eWavData() :
00039         m_Volume(64), m_Playable(false)
00040 {
00041 #ifdef HAVE_LIBSDL_MIXER
00042     // Do nothing constructor
00043     m_WavData = NULL;
00044 #endif // DEDICATED
00045 }
00046 
00047 eWavData::~eWavData() {
00048 #ifdef HAVE_LIBSDL_MIXER
00049     if(m_WavData != NULL) {
00050         Mix_FreeChunk(m_WavData);
00051     }
00052 #endif // DEDICATED
00053 }
00054 
00055 eWavData::eWavData(const char* filename) {
00056 #ifdef HAVE_LIBSDL_MIXER
00057     // Construct a new wavdata by loading a file
00058 #endif // DEDICATED
00059 }
00060 
00061 void eWavData::LoadWavFile(const char* filename) {
00062 #ifdef HAVE_LIBSDL_MIXER
00063 #ifdef MACOSX
00064     // BUG: This call is very very slow on my system. Disable it until I figure out what is wrong. -- Dan
00065     return;
00066 #endif
00067 
00068     m_WavData = Mix_LoadWAV(filename);
00069 
00070     if(!m_WavData) {
00071         tERR_WARN("Couldn't load wav file\n");
00072     } else {
00073         //std::cout << "Successfully loaded sound effect: " << filename << "\n";
00074     }
00075 #endif // DEDICATED
00076 }
00077 
00078 /*******************************************************************************
00079  *
00080  * eChannel
00081  *
00082  *******************************************************************************/
00083 
00084 int eChannel::numChannels = 0;
00085 
00086 eChannel::eChannel() : m_Delayed(false) {
00087 #ifdef HAVE_LIBSDL_MIXER
00088     m_ChannelID = numChannels;
00089     numChannels++;
00090     m_Volume = 50;
00091     m_isDirty = false;
00092     m_isPlaying = false;
00093     m_continuous = false;
00094 #endif // DEDICATED
00095 }
00096 
00097 void eChannel::PlaySound(eWavData& sound) {
00098 #ifdef HAVE_LIBSDL_MIXER
00099     if(m_isPlaying) {
00100         Mix_HaltChannel(m_ChannelID);
00101         //std::cerr << "Channel occupied, halting: " << m_ChannelID << "\n";
00102     }
00103     int theChannel;
00104     Mix_Volume(m_ChannelID, sound.GetVolume());
00105     theChannel = Mix_PlayChannel(m_ChannelID, sound.GetWavData(), 0);
00106 
00107     if(theChannel != m_ChannelID) {
00108         // do nothing, but there's an error
00109         //std::cerr << "Couldn't play a sound: " << m_ChannelID << "\n";
00110     } else {
00111         m_isPlaying = true;
00112         m_StartTime = SDL_GetTicks();
00113     }
00114 #endif // DEDICATED
00115 }
00116 
00117 void eChannel::Set3d(eCoord home, eCoord soundPos, eCoord homeDirection) {
00118 #ifdef HAVE_LIBSDL_MIXER
00119     // the sound position relative to the microphone
00120     eCoord soundPosRelative = (soundPos - home).Turn( homeDirection.Conj() );
00121 
00122     // the distance to the microphone
00123     REAL distance = soundPosRelative.Norm();
00124 
00125     // the bearing in radians (taken from the inverse of the direction to put the discontinuous jump in the right spot)
00126     double bearing = atan2( -soundPosRelative.x, -soundPosRelative.y );
00127 
00128     // We get it in radians and need to convert to degrees because SDL_mixer is lame.
00129     // atan2's return value is specified to be between -PI and PI,
00130     // so we need to linearily transform the result.
00131     int bearingInt = 180 + (int) (bearing * 180.0/M_PI);
00132 
00133     // and the distance needs to be an integer, too. The conversion
00134     // could use some tweaking/customization.
00135     const REAL microphoneSize = 3;
00136     int distanceInt = 255 - int( 255 * microphoneSize / ( sqrt(distance) + microphoneSize ) );
00137     // clamp. Distance == 0 seems to be dangerous :(
00138     distanceInt = distanceInt > 255 ? 255 : distanceInt;
00139     distanceInt = distanceInt < 1 ? 1 : distanceInt;
00140 
00141     // override bearing for close sounds, the value of atan2 is undefined then
00142     if ( distance < EPS * microphoneSize )
00143         bearingInt = 0;
00144 
00145     // Remove the old effect, if present
00146     Mix_SetPosition(m_ChannelID, 0, 0);
00147     // Add the new effect
00148     Mix_SetPosition(m_ChannelID, bearingInt, distanceInt );
00149 #endif // DEDICATED
00150 }
00151 
00152 void eChannel::Update() {
00153 #ifdef HAVE_LIBSDL_MIXER
00154     if(m_isDirty && !m_isPlaying) {
00155         Mix_UnregisterAllEffects(m_ChannelID);
00156         m_isDirty = false;
00157     }
00158 
00159     if(m_continuous) {
00160         if(m_Delayed) {
00161             if(m_StartNow) {
00162                 m_StartNow = false;
00163                 m_Delayed = false;
00164                 LoopSound(m_Sound);
00165                 Set3d(m_Home->Position(), m_Owner->Position(), m_Home->Direction());
00166                 std::cout << "Starting delayed effect\n";
00167             }
00168         } else {
00169             if(!m_Home || !m_Owner) {
00170                 StopSound();
00171                 return;
00172             }
00173             Set3d(m_Home->Position(), m_Owner->Position(), m_Home->Direction());
00174         }
00175     }
00176 #endif // DEDICATED
00177 }
00178 
00179 void eChannel::UnplaySound() {
00180 #ifdef HAVE_LIBSDL_MIXER
00181     m_isDirty = true;
00182     m_isPlaying = false;
00183 #endif // DEDICATED
00184 }
00185 
00186 void eChannel::SetOwner(eGameObject* owner) {
00187 #ifdef HAVE_LIBSDL_MIXER
00188     m_Owner = owner;
00189 #endif
00190 }
00191 
00192 void eChannel::LoopSound(eWavData& sound) {
00193 #ifdef HAVE_LIBSDL_MIXER
00194     //std::cout << "Looping sound\n";
00195     if(m_isPlaying) {
00196         Mix_HaltChannel(m_ChannelID);
00197         //std::cerr << "Channel occupied, halting: " << m_ChannelID << "\n";
00198     }
00199     m_continuous = true;
00200     m_Sound = sound;
00201 
00202     if(m_Delayed) {
00203         return;
00204     }
00205     int theChannel;
00206     Mix_Volume(m_ChannelID, sound.GetVolume());
00207     theChannel = Mix_PlayChannel(m_ChannelID, m_Sound.GetWavData(), -1);
00208 
00209     //std::cout << "Looping sound\n";
00210     if(theChannel < 0) {
00211         // do nothing, but there's an error
00212         //std::cerr << "Couldn't play a sound on channel: " << m_ChannelID << "\n";
00213     } else {
00214         m_isPlaying = true;
00215     }
00216 #endif
00217 }
00218 

Generated on Sat Mar 15 22:55:48 2008 for Armagetron Advanced by  doxygen 1.5.4