Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Namespace Members | Compound Members | File Members

SoundCache.cpp

Go to the documentation of this file.
00001 //------------------------------------------------------------------------------
00002 // Lamp : Open source game middleware
00003 // Copyright (C) 2004  Junpei Ohtani ( Email : junpee@users.sourceforge.jp )
00004 //
00005 // This library is free software; you can redistribute it and/or
00006 // modify it under the terms of the GNU Lesser General Public
00007 // License as published by the Free Software Foundation; either
00008 // version 2.1 of the License, or (at your option) any later version.
00009 //
00010 // This library is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013 // Lesser General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU Lesser General Public
00016 // License along with this library; if not, write to the Free Software
00017 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018 //------------------------------------------------------------------------------
00019 
00020 /** @file
00021  * サウンドキャッシュ実装
00022  * @author Junpee
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 // 静的3Dサウンドのロード
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 // 3Dサウンドの再生
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 // 3Dサウンドの取得
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 } // End of namespace Lamp
00376 //------------------------------------------------------------------------------

Generated on Wed Mar 16 10:29:35 2005 for Lamp by doxygen 1.3.2