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 //------------------------------------------------------------------------------