00001 #include "SoundManager.h"
00002 #include "DebugUtil.h"
00003
00004 #include "SDL.h"
00005
00006 #include "TimeUtility.h"
00007
00008 #include "ISound.h"
00009 #include "Song.h"
00010
00011 #include "InputEvents.h"
00012 #include "EventManager.h"
00013
00014 #include "GameConfig.h"
00015 #include "GameException.h"
00016
00017 #define MAX_WAVE_DIFF 20000
00018
00019 template<> SoundManager* TSingleton<SoundManager>::m_pInstance = NULL;
00020
00021 SoundManager::SoundManager()
00022 : m_lastUpdate(0), m_volume(SOUND_MAX_VOLUME), m_pAudioSpec(0)
00023 {
00024
00025 }
00026
00027 SoundManager::~SoundManager()
00028 {
00029 }
00030
00031 void SoundManager::Initialise(int freq , Uint16 samples , Uint8 channels )
00032 {
00033 m_pAudioSpec = new SDL_AudioSpec();
00034 SDL_AudioSpec* pDesiredSpec = new SDL_AudioSpec();
00035
00036 pDesiredSpec->freq = freq;
00037 pDesiredSpec->format = AUDIO_S16;
00038 pDesiredSpec->samples = samples;
00039 pDesiredSpec->channels = channels;
00040 pDesiredSpec->callback = SoundManager::SDLAudioCallback;
00041 pDesiredSpec->userdata = 0;
00042
00043 if(SDL_OpenAudio(pDesiredSpec, m_pAudioSpec) == -1)
00044 {
00045 throw GameException(eMajorError, "SoundManager: SDL_OpenAudio failed!");
00046 return;
00047 }
00048
00049 SDL_PauseAudio(false);
00050
00051 EventManager::getSingleton()->AddEventListener(ButtonInputEvent::cEventName, this);
00052 }
00053
00054 void SoundManager::Shutdown()
00055 {
00056 SDL_CloseAudio();
00057 delete m_pAudioSpec;
00058
00059 for(size_t i = 0; i < m_vSounds.size(); i++)
00060 {
00061 if(m_vSounds[i])
00062 delete m_vSounds[i];
00063 }
00064
00065 m_vSounds.clear();
00066 }
00067
00068 void SoundManager::Output()
00069 {
00070 for(size_t i = 0; i < m_vSounds.size(); i++)
00071 {
00072 if(m_vSounds[i])
00073 m_vSounds[i]->Output();
00074 }
00075 }
00076
00077 SoundID SoundManager::CreateSoundSong(const bool &bPreCreate, const UInt &bpm, const UInt &numUniqueSections, const UInt &lengthInSections, const UInt &timePerSection)
00078 {
00079 Song* pSong = new Song();
00080
00081 pSong->Initialise(bPreCreate, bpm, numUniqueSections, lengthInSections, timePerSection);
00082
00083 m_vSounds.push_back((ISound*)pSong);
00084
00085 return m_vSounds.size() - 1;
00086 }
00087
00088 SoundInstanceID SoundManager::PlaySoundID(const SoundID &sid, bool loop)
00089 {
00090 if(!m_vSounds[sid])
00091 {
00092 throw GameException(eMinorError, "SoundManager: PlaySoundID failed on Sound ID: %d", (int)sid);
00093 return 0;
00094 }
00095
00096 SoundInstance* pInstance = new SoundInstance();
00097
00098 pInstance->pSound = m_vSounds[sid];
00099 pInstance->isPaused = false;
00100 pInstance->isLooping = loop;
00101 pInstance->position = 0;
00102
00103 m_vInstances.push_back(pInstance);
00104
00105 return m_vInstances.size() - 1;
00106 }
00107
00108 bool SoundManager::PauseSound(const SoundInstanceID &siid)
00109 {
00110 if(m_vInstances[siid])
00111 {
00112 m_vInstances[siid]->isPaused = !m_vInstances[siid]->isPaused;
00113
00114 return true;
00115 }
00116
00117 return false;
00118 }
00119
00120 bool SoundManager::StopSound(const SoundInstanceID &siid)
00121 {
00122 if(m_vInstances[siid])
00123 {
00124 delete m_vInstances[siid];
00125 m_vInstances[siid] = 0;
00126
00127 return true;
00128 }
00129
00130 return false;
00131 }
00132
00133 void SoundManager::Update()
00134 {
00135
00136
00137
00138
00139
00140
00141
00142
00143 }
00144
00145 void SoundManager::MixBuffers(Sint16 *pBuf1, Sint16 *pBuf2, size_t sz)
00146 {
00147 for(size_t i = 0; i < sz; i++)
00148 {
00149 long int val = pBuf1[i] + pBuf2[i];
00150 if(val > 32767)
00151 val = 32767;
00152 if(val < -32768)
00153 val = -32768;
00154
00155 pBuf1[i] = (Sint16)val;
00156 }
00157 }
00158
00159 void SoundManager::HandleAudioBuffer(void* userdata, Uint8* stream, int len)
00160 {
00161 unsigned long dt = TimeUtility::getTime() - m_lastUpdate;
00162
00163 memset(stream, 0, len * sizeof(Uint8));
00164 Sint16* pRealStream = (Sint16*)stream;
00165
00166 int rlen = len / sizeof(Sint16);
00167 Sint16* pTmpStream = new Sint16[rlen];
00168
00169 double secsPerSampleset = (double)m_pAudioSpec->samples / (double)m_pAudioSpec->freq;
00170
00171 for(size_t i = 0; i < m_vInstances.size(); i++)
00172 {
00173 if(m_vInstances[i])
00174 {
00175 SoundInstance* pInst = m_vInstances[i];
00176 if(pInst->isPaused == false)
00177 {
00178 m_vInstances[i]->position += dt;
00179 Sint16* pBuffer = pInst->pSound->GetBuffer(pInst->position, rlen, pInst->isLooping);
00180 if(pBuffer)
00181 MixBuffers(pRealStream, pBuffer, rlen);
00182
00183 else
00184 {
00185 delete pInst;
00186 pInst = 0;
00187 }
00188 }
00189 }
00190 }
00191
00192 ApplyVolumeToStream(pRealStream, rlen);
00193 m_lastUpdate = TimeUtility::getTime();
00194
00195
00196 }
00197
00198 void SoundManager::IncreaseVolume()
00199 {
00200 m_volume += SOUND_VOLUME_STEP;
00201 if(m_volume > SOUND_MAX_VOLUME)
00202 m_volume = SOUND_MAX_VOLUME;
00203 }
00204
00205 void SoundManager::DecreaseVolume()
00206 {
00207 m_volume -= SOUND_VOLUME_STEP;
00208 if(m_volume < 0)
00209 m_volume = 0;
00210 }
00211
00212 bool SoundManager::HandleEvent(IEvent* pEvent)
00213 {
00214 if(pEvent->GetEventType() == ButtonInputEvent::cEventName)
00215 {
00216 ButtonInputEvent* pButtonEvent = (ButtonInputEvent*)pEvent;
00217 int key = pButtonEvent->GetKey();
00218
00219 if(key == eKeyButtonVolumeUp && pButtonEvent->IsKeyDown())
00220 {
00221 DebugUtil::outputDebugText("Volume Up Received!\n");
00222 IncreaseVolume();
00223 return true;
00224 }
00225
00226 if(key == eKeyButtonVolumeDown && pButtonEvent->IsKeyDown())
00227 {
00228 DebugUtil::outputDebugText("Volume Down Received!\n");
00229 DecreaseVolume();
00230 return true;
00231 }
00232 }
00233
00234 return false;
00235 }
00236
00237 void SoundManager::SDLAudioCallback(void *userdata, Uint8 *stream, int len)
00238 {
00239 SoundManager::getSingleton()->HandleAudioBuffer(userdata, stream, len);
00240 }
00241
00242 void SoundManager::ApplyVolumeToStream(Sint16 *pStream, size_t sz)
00243 {
00244 for(size_t i = 0; i < sz; i++)
00245 {
00246 pStream[i] = (pStream[i] * m_volume) / SOUND_MAX_VOLUME;
00247 }
00248 }