00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "LampBasic.h"
00026 #include "Sound/Utility/SoundCache.h"
00027 #include "Sound/System/LampSound.h"
00028 #include "Sound/System/SoundManager.h"
00029 #include "Sound/Stereo/StaticSound.h"
00030 #include "Sound/3D/StaticSound3D.h"
00031 #include "Sound/Utility/SoundList.h"
00032
00033 namespace Lamp{
00034
00035
00036
00037
00038
00039 SoundCache::SoundCache(const String& basePath, const String& extension,
00040 Sound::Focus focus, int defaultMaxMixingCount) :
00041 basePath_(basePath), extension_(extension),
00042 focus_(focus), defaultMaxMixingCount_(defaultMaxMixingCount){
00043 Assert(defaultMaxMixingCount_ > 0);
00044 }
00045
00046
00047 SoundCache::~SoundCache(){
00048 unloadAll();
00049 }
00050
00051
00052
00053
00054 bool SoundCache::loadStaticSound(
00055 const String& name, bool loop, int priority, int maxMixingCount){
00056
00057 if(cache_.get(name) != NULL){ Assert(false); return false; }
00058
00059 StaticSound* sound = LampSound::getSoundManager()->createStaticSound(
00060 basePath_ + name + extension_, focus_);
00061 if(sound == NULL){ Assert(false); return false; }
00062 sound->setLoop(loop);
00063 sound->setPriority(priority);
00064
00065 int soundCount = maxMixingCount;
00066 if(soundCount == 0){ soundCount = defaultMaxMixingCount_; }
00067 createCache(name, sound, soundCount);
00068 return true;
00069 }
00070
00071
00072 bool SoundCache::loadStaticSound3D(const String& name, bool loop, int priority,
00073 float minimumDistance, float maximumDistance, int maxMixingCount){
00074
00075 if(cache_.get(name) != NULL){ Assert(false); return false; }
00076
00077 StaticSound3D* sound = LampSound::getSoundManager()->createStaticSound3D(
00078 basePath_ + name + extension_, focus_);
00079 if(sound == NULL){ Assert(false); return false; }
00080 sound->setLoop(loop);
00081 sound->setPriority(priority);
00082 sound->setDistance(minimumDistance, maximumDistance);
00083
00084 int mixingCount = maxMixingCount;
00085 if(mixingCount == 0){ mixingCount = defaultMaxMixingCount_; }
00086 createCache(name, sound, mixingCount);
00087 return true;
00088 }
00089
00090
00091 void SoundCache::createCache(
00092 const String& name, Sound* sound, int maxMixingCount){
00093 SoundArray* soundArray = new SoundArray(sound, maxMixingCount);
00094 cache_.put(name, soundArray);
00095 list_.add(soundArray);
00096 }
00097
00098
00099 bool SoundCache::unloadSound(const String& name){
00100 SoundArray* soundArray = cache_.remove(name);
00101 if(soundArray == NULL){ return false; }
00102 list_.removeByValue(soundArray);
00103 delete soundArray;
00104 return true;
00105 }
00106
00107
00108 void SoundCache::unloadAll(){
00109 int count = list_.getCount();
00110 for(int i = count - 1; i >= 0; i--){ delete list_[i]; }
00111 list_.clear();
00112 cache_.clear();
00113 }
00114
00115
00116
00117
00118 bool SoundCache::loadSoundList(const String& filePath){
00119 return SoundList::load(this, basePath_ + filePath);
00120 }
00121
00122
00123 bool SoundCache::loadSoundList(TextReader* textReader){
00124 return SoundList::load(this, textReader);
00125 }
00126
00127
00128
00129
00130 Sound* SoundCache::playSound(const String& name, float volume, int frequency){
00131
00132 SoundArray* array = cache_.get(name);
00133 if(array == NULL){ return NULL; }
00134 Sound* sound = array->getFreeSound();
00135 if(sound == NULL){ return NULL; }
00136
00137 sound->reset(Sound::resetRuntime);
00138 sound->setVolume(volume);
00139 if(frequency != 0){ sound->setFrequency(frequency); }
00140 sound->play();
00141 return sound;
00142 }
00143
00144
00145 StereoSound* SoundCache::playStereoSound(
00146 const String& name, float volume, int frequency, float pan){
00147
00148 SoundArray* array = cache_.get(name);
00149 if(array == NULL){ return NULL; }
00150 Sound* sound = array->getFreeSound();
00151 if(sound == NULL){ return NULL; }
00152 StereoSound* stereoSound = sound->castStereoSound();
00153 if(stereoSound == NULL){ return NULL; }
00154
00155 stereoSound->reset(Sound::resetRuntime);
00156 stereoSound->setVolume(volume);
00157 if(frequency != 0){ stereoSound->setFrequency(frequency); }
00158 stereoSound->setPan(pan);
00159 stereoSound->play();
00160 return stereoSound;
00161 }
00162
00163
00164 Sound3D* SoundCache::playSound3D(
00165 const String& name, float volume, int frequency, const Vector3& position){
00166
00167 SoundArray* array = cache_.get(name);
00168 if(array == NULL){ return NULL; }
00169 Sound* sound = array->getFreeSound();
00170 if(sound == NULL){ return NULL; }
00171 Sound3D* sound3D = sound->castSound3D();
00172 if(sound3D == NULL){ return NULL; }
00173
00174 sound3D->reset(Sound::resetRuntime);
00175 sound3D->setVolume(volume);
00176 if(frequency != 0){ sound3D->setFrequency(frequency); }
00177 sound3D->setPosition(position);
00178 sound3D->play();
00179 return sound3D;
00180 }
00181
00182
00183
00184
00185 Sound* SoundCache::getSound(const String& name, Sound::Reset resetFlag){
00186
00187 SoundArray* array = cache_.get(name);
00188 if(array == NULL){ Assert(false); return NULL; }
00189 Sound* sound = array->getFreeSound();
00190 if(sound == NULL){ Assert(false); return NULL; }
00191
00192 Assert(sound->hasOwnership());
00193 sound->setOwnership(false);
00194 sound->reset(resetFlag);
00195 return sound;
00196 }
00197
00198
00199 StereoSound* SoundCache::getStereoSound(
00200 const String& name, Sound::Reset resetFlag){
00201 Sound* sound = getSound(name, resetFlag);
00202 if(sound == NULL){ return NULL; }
00203 StereoSound* stereoSound = sound->castStereoSound();
00204 if(stereoSound == NULL){
00205 releaseSound(sound);
00206 return NULL;
00207 }
00208 return stereoSound;
00209 }
00210
00211
00212 Sound3D* SoundCache::getSound3D(const String& name, Sound::Reset resetFlag){
00213 Sound* sound = getSound(name, resetFlag);
00214 if(sound == NULL){ return NULL; }
00215 Sound3D* sound3D = sound->castSound3D();
00216 if(sound3D == NULL){
00217 releaseSound(sound);
00218 return NULL;
00219 }
00220 return sound3D;
00221 }
00222
00223
00224 void SoundCache::releaseSound(Sound* sound){
00225 Assert(sound != NULL);
00226
00227 Assert(!sound->hasOwnership());
00228 sound->setOwnership(true);
00229 }
00230
00231
00232
00233
00234 void SoundCache::suspendAll(){
00235 int listCount = list_.getCount();
00236 for(int i = 0; i < listCount; i++){
00237 SoundArray* soundArray = list_[i];
00238 int soundCount = soundArray->getSoundCount();
00239 for(int j = 0; j < soundCount; j++){
00240 soundArray->getSound(j)->suspend();
00241 }
00242 }
00243 }
00244
00245
00246 void SoundCache::resumeAll(){
00247 int listCount = list_.getCount();
00248 for(int i = 0; i < listCount; i++){
00249 SoundArray* soundArray = list_[i];
00250 int soundCount = soundArray->getSoundCount();
00251 for(int j = 0; j < soundCount; j++){
00252 soundArray->getSound(j)->resume();
00253 }
00254 }
00255 }
00256
00257
00258 String SoundCache::toString() const{
00259 String result;
00260 int listCount = list_.getCount();
00261 int cacheCount = 0;
00262 for(int i = 0; i < listCount; i++){
00263 cacheCount += list_[i]->getSoundCount();
00264 }
00265 result.format("Cache/List (%d/%d) ", cacheCount, listCount);
00266 if(focus_ == Sound::focusNormal){
00267 result += "Normal\n";
00268 }else if(focus_ == Sound::focusSticky){
00269 result += "Sticky\n";
00270 }else if(focus_ == Sound::focusGlobal){
00271 result += "Global\n";
00272 }
00273 result += "Path " + basePath_ + " Extension " + extension_ + "\n";
00274 for(int i = 0; i < listCount; i++){
00275 result += list_[i]->toString();
00276 }
00277 return result;
00278 }
00279
00280
00281
00282
00283 SoundCache::SoundArray::SoundArray(Sound* sound, int maxMixingCount) :
00284 sounds_(maxMixingCount), maxMixingCount_(maxMixingCount){
00285 Assert(sound != NULL);
00286 sounds_.add(sound);
00287 }
00288
00289
00290 SoundCache::SoundArray::~SoundArray(){
00291
00292 int count = sounds_.getCount();
00293 SoundManager* manager = LampSound::getSoundManager();
00294 for(int i = count - 1; i >= 0; i--){ manager->destroy(sounds_[i]); }
00295 sounds_.clear();
00296 }
00297
00298
00299 Sound* SoundCache::SoundArray::getFreeSound(){
00300 Assert(!sounds_.isEmpty());
00301 Sound* topSound = sounds_[0];
00302
00303 int count = sounds_.getCount();
00304 for(int i = 0; i < count; i++){
00305 Sound* sound = sounds_[i];
00306
00307 if(!sound->hasOwnership()){ continue; }
00308 Sound::State state = sound->getState();
00309
00310
00311 if((state == Sound::statePlay) ||
00312 (state == Sound::stateSuspend)){ continue; }
00313 return sound;
00314 }
00315
00316
00317 int soundCount = sounds_.getCount();
00318 if(soundCount == maxMixingCount_){
00319 u_int maxCursor = 0, maxIndex = -1;
00320 for(int i = 0; i < soundCount; i++){
00321 Sound* sound = sounds_[i];
00322
00323 if(!sound->hasOwnership()){ continue; }
00324 u_int cursor = sound->getCursor();
00325 if(cursor > maxCursor){
00326 maxCursor = cursor;
00327 maxIndex = i;
00328 }
00329 }
00330 if(maxIndex == -1){ return NULL; }
00331 return sounds_[maxIndex];
00332 }
00333
00334
00335 Sound* clone = topSound->clone();
00336 if(clone != NULL){
00337 sounds_.add(clone);
00338 return clone;
00339 }
00340 return NULL;
00341 }
00342
00343
00344 String SoundCache::SoundArray::toString() const{
00345 String result, temp;
00346 Sound* sound = sounds_[0];
00347 result.format(" %2d/%2d ", sounds_.getCount(), maxMixingCount_);
00348 if(sound->isStereoSound()){
00349 result += "Stereo ";
00350 }else{
00351 result += "3D ";
00352 }
00353 if(sound->isLoop()){
00354 result += "Loop ";
00355 }else{
00356 result += "Once ";
00357 }
00358 temp.format("Pri%4d ", sound->getPriority());
00359 result += temp;
00360
00361
00362 FilePath path(sound->getName());
00363 result += path.getName();
00364
00365 Sound3D* sound3D = sound->castSound3D();
00366 if(sound3D != NULL){
00367 temp.format(" Dist %.1f-%.1f ",
00368 sound3D->getMinimumDistance(), sound3D->getMaximumDistance());
00369 result += temp;
00370 }
00371 result += "\n";
00372 return result;
00373 }
00374
00375 }
00376