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

SoundManager.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/System/SoundManager.h"
00027 #include "Sound/System/SoundDefinition.h"
00028 #include "Sound/Reader/WaveReader.h"
00029 #include "Sound/Reader/OggVorbisReader.h"
00030 #include "Sound/Stereo/StaticSound.h"
00031 #include "Sound/Stereo/StreamSound.h"
00032 #include "Sound/3D/StaticSound3D.h"
00033 #include "Sound/3D/StreamSound3D.h"
00034 
00035 namespace Lamp{
00036 
00037 //------------------------------------------------------------------------------
00038 // コンストラクタ
00039 SoundManager::SoundManager(DirectSound* directSound) :
00040     directSound_(directSound), algorithm_(algorithmNormal){
00041 }
00042 //------------------------------------------------------------------------------
00043 // デストラクタ
00044 SoundManager::~SoundManager(){
00045     Assert(sounds_.getCount() == 0);
00046     Assert(updateSounds_.getCount() == 0);
00047 }
00048 //------------------------------------------------------------------------------
00049 // サウンド操作
00050 //------------------------------------------------------------------------------
00051 // サウンドの削除
00052 void SoundManager::destroy(Sound* sound){
00053     sounds_.removeByValue(sound);
00054     delete sound;
00055 }
00056 //------------------------------------------------------------------------------
00057 // 全サウンドの破棄
00058 void SoundManager::destroyAll(){
00059     int soundCount = getCount();
00060     for(int i = 0; i < soundCount; i++){ delete getSound(i); }
00061     sounds_.clear();
00062 }
00063 //------------------------------------------------------------------------------
00064 // 静的サウンド
00065 //------------------------------------------------------------------------------
00066 // 静的サウンドの作成
00067 StaticSound* SoundManager::createStaticSound(
00068     u_int size, int sample, int channel, int bit, Sound::Focus focus){
00069     // ウェーブフォーマットの構築
00070     WAVEFORMATEX waveFormat;
00071     buildWaveFormat(&waveFormat, sample, channel, bit);
00072     // バッファ記述の構築
00073     DSBUFFERDESC description;
00074     buildBufferDescription(&description, &waveFormat, size, focus);
00075     // パン追加
00076     description.dwFlags |= DSBCAPS_CTRLPAN;
00077     // バッファの構築
00078     DirectSoundBuffer* soundBuffer = buildSoundBuffer(&description);
00079     // サウンドの構築
00080     StaticSound* sound = new StaticSound(soundBuffer);
00081     sound->initialize(size, sample, channel, bit, focus);
00082     sounds_.pushBack(sound);
00083     return sound;
00084 }
00085 //------------------------------------------------------------------------------
00086 // 静的サウンドの作成
00087 StaticSound* SoundManager::createStaticSound(
00088     SoundReader* soundReader, const String& name, Sound::Focus focus){
00089     if(soundReader == NULL){ return NULL; }
00090     if(!soundReader->readHeader()){ return NULL; }
00091     // サウンド作成
00092     StaticSound* sound = createStaticSound(
00093         soundReader->getSize(), soundReader->getSample(),
00094         soundReader->getChannel(), soundReader->getBit(), focus);
00095     sound->setName(name);
00096     sound->setComment(soundReader->getComment());
00097     // サウンド読み込み
00098     if(!readSoundBuffer(sound, soundReader)){
00099         destroy(sound);
00100         sound = NULL;
00101     }
00102     return sound;
00103 }
00104 //------------------------------------------------------------------------------
00105 // 静的サウンドの作成
00106 StaticSound* SoundManager::createStaticSound(
00107     const String& fileName, Sound::Focus focus){
00108     FilePath filePath(fileName);
00109     SoundReader* soundReader = createSoundReader(filePath);
00110     StaticSound* sound =
00111         createStaticSound(soundReader, filePath.getFileName(), focus);
00112     SafeDelete(soundReader);
00113     return sound;
00114 }
00115 //------------------------------------------------------------------------------
00116 // 静的サウンドの複製
00117 StaticSound* SoundManager::cloneStaticSound(StaticSound* staticSound){
00118     DirectSoundBuffer* soundBuffer =
00119         duplicateSoundBuffer(staticSound->getSoundBuffer());
00120     // サウンドの構築
00121     StaticSound* sound = new StaticSound(soundBuffer);
00122     sounds_.pushBack(sound);
00123     return sound;
00124 }
00125 //------------------------------------------------------------------------------
00126 // ストリームサウンド
00127 //------------------------------------------------------------------------------
00128 // ストリームサウンドの作成
00129 StreamSound* SoundManager::createStreamSound(
00130     u_int size, int sample, int channel, int bit, Sound::Focus focus){
00131     // ウェーブフォーマットの構築
00132     WAVEFORMATEX waveFormat;
00133     buildWaveFormat(&waveFormat, sample, channel, bit);
00134     // バッファ記述の構築
00135     DSBUFFERDESC description;
00136     buildBufferDescription(&description, &waveFormat, size, focus);
00137     // パン、通知追加
00138     description.dwFlags |= (DSBCAPS_CTRLPAN | DSBCAPS_CTRLPOSITIONNOTIFY);
00139     // バッファの構築
00140     DirectSoundBuffer* soundBuffer = buildSoundBuffer(&description);
00141     // サウンドの構築
00142     StreamSound* sound = new StreamSound(soundBuffer);
00143     sound->initialize(size, sample, channel, bit, focus);
00144     sounds_.pushBack(sound);
00145     return sound;
00146 }
00147 //------------------------------------------------------------------------------
00148 // ストリームサウンドの作成
00149 StreamSound* SoundManager::createStreamSound(
00150     SoundReader* soundReader, const String& name, Sound::Focus focus){
00151     if(soundReader == NULL){ return NULL; }
00152     if(!soundReader->readHeader()){ return NULL; }
00153     // ストリームバッファサイズの算出
00154     u_int size = (u_int)(SoundDefinition::streamBufferLength *
00155         soundReader->getOneSecondBytes());
00156     // サウンド作成
00157     StreamSound* sound = createStreamSound(
00158         size, soundReader->getSample(),
00159         soundReader->getChannel(), soundReader->getBit(), focus);
00160     sound->setName(name);
00161     sound->setComment(soundReader->getComment());
00162     // サウンドリーダの設定
00163     sound->setSoundReader(soundReader);
00164     return sound;
00165 }
00166 //------------------------------------------------------------------------------
00167 // ストリームサウンドの作成
00168 StreamSound* SoundManager::createStreamSound(
00169     const String& fileName, Sound::Focus focus){
00170     FilePath filePath(fileName);
00171     SoundReader* soundReader = createSoundReader(filePath);
00172     StreamSound* sound =
00173         createStreamSound(soundReader, filePath.getFileName(), focus);
00174     // サウンドリーダはストリームサウンドによって削除される
00175     return sound;
00176 }
00177 //------------------------------------------------------------------------------
00178 // 静的3Dサウンド
00179 //------------------------------------------------------------------------------
00180 // 静的3Dサウンドの作成
00181 StaticSound3D* SoundManager::createStaticSound3D(u_int size, int sample,
00182     int channel, int bit, Sound::Focus focus){
00183     if(channel != 1){
00184         ErrorOut("SoundManager::createStaticSound3D() "
00185             "モノラルでないサウンドを3Dサウンドにできません。");
00186     }
00187     // ウェーブフォーマットの構築
00188     WAVEFORMATEX waveFormat;
00189     buildWaveFormat(&waveFormat, sample, channel, bit);
00190     // バッファ記述の構築
00191     DSBUFFERDESC description;
00192     buildBufferDescription(&description, &waveFormat, size, focus);
00193     // 3D
00194     description.dwFlags |= DSBCAPS_CTRL3D;
00195     // 3Dアルゴリズム
00196     if(algorithm_ == algorithmNormal){
00197         description.guid3DAlgorithm = DS3DALG_DEFAULT;
00198     }else if(algorithm_ == algorithmLightHRTF){
00199         description.guid3DAlgorithm = DS3DALG_HRTF_LIGHT;
00200     }else if(algorithm_ == algorithmFullHRTF){
00201         description.guid3DAlgorithm = DS3DALG_HRTF_FULL;
00202     }
00203     // バッファの構築
00204     DirectSoundBuffer* soundBuffer = buildSoundBuffer(&description);
00205     // サウンドの構築
00206     StaticSound3D* sound = new StaticSound3D(soundBuffer);
00207     sound->initialize(size, sample, channel, bit, focus);
00208     sounds_.pushBack(sound);
00209     return sound;
00210 }
00211 //------------------------------------------------------------------------------
00212 // 静的3Dサウンドの作成
00213 StaticSound3D* SoundManager::createStaticSound3D(SoundReader* soundReader,
00214     const String& name, Sound::Focus focus){
00215     if(soundReader == NULL){ return NULL; }
00216     if(!soundReader->readHeader()){ return NULL; }
00217     // サウンド作成
00218     StaticSound3D* sound = createStaticSound3D(soundReader->getSize(),
00219         soundReader->getSample(),soundReader->getChannel(),
00220         soundReader->getBit(), focus);
00221     sound->setName(name);
00222     sound->setComment(soundReader->getComment());
00223     // サウンド読み込み
00224     if(!readSoundBuffer(sound, soundReader)){
00225         destroy(sound);
00226         sound = NULL;
00227     }
00228     return sound;
00229 }
00230 //------------------------------------------------------------------------------
00231 // 静的3Dサウンドの作成
00232 StaticSound3D* SoundManager::createStaticSound3D(
00233     const String& fileName, Sound::Focus focus){
00234     FilePath filePath(fileName);
00235     SoundReader* soundReader = createSoundReader(filePath);
00236     StaticSound3D* sound = createStaticSound3D(
00237         soundReader, filePath.getFileName(), focus);
00238     SafeDelete(soundReader);
00239     return sound;
00240 }
00241 //------------------------------------------------------------------------------
00242 // 静的3Dサウンドの複製
00243 StaticSound3D* SoundManager::cloneStaticSound3D(StaticSound3D* staticSound3D){
00244     DirectSoundBuffer* soundBuffer =
00245         duplicateSoundBuffer(staticSound3D->getSoundBuffer());
00246     // サウンドの構築
00247     StaticSound3D* sound = new StaticSound3D(soundBuffer);
00248     sounds_.pushBack(sound);
00249     return sound;
00250 }
00251 //------------------------------------------------------------------------------
00252 // ストリーム3Dサウンド
00253 //------------------------------------------------------------------------------
00254 // ストリーム3Dサウンドの作成
00255 StreamSound3D* SoundManager::createStreamSound3D(
00256     u_int size, int sample, int channel, int bit, Sound::Focus focus){
00257     // ウェーブフォーマットの構築
00258     WAVEFORMATEX waveFormat;
00259     buildWaveFormat(&waveFormat, sample, channel, bit);
00260     // バッファ記述の構築
00261     DSBUFFERDESC description;
00262     buildBufferDescription(&description, &waveFormat, size, focus);
00263     // 3D、通知追加
00264     description.dwFlags |= (DSBCAPS_CTRL3D | DSBCAPS_CTRLPOSITIONNOTIFY);
00265     // 3Dアルゴリズム
00266     if(algorithm_ == algorithmNormal){
00267         description.guid3DAlgorithm = DS3DALG_DEFAULT;
00268     }else if(algorithm_ == algorithmLightHRTF){
00269         description.guid3DAlgorithm = DS3DALG_HRTF_LIGHT;
00270     }else if(algorithm_ == algorithmFullHRTF){
00271         description.guid3DAlgorithm = DS3DALG_HRTF_FULL;
00272     }
00273     // バッファの構築
00274     DirectSoundBuffer* soundBuffer = buildSoundBuffer(&description);
00275     // サウンドの構築
00276     StreamSound3D* sound = new StreamSound3D(soundBuffer);
00277     sound->initialize(size, sample, channel, bit, focus);
00278     sounds_.pushBack(sound);
00279     return sound;
00280 }
00281 //------------------------------------------------------------------------------
00282 // ストリーム3Dサウンドの作成
00283 StreamSound3D* SoundManager::createStreamSound3D(
00284     SoundReader* soundReader, const String& name, Sound::Focus focus){
00285     if(soundReader == NULL){ return NULL; }
00286     if(!soundReader->readHeader()){ return NULL; }
00287     // ストリームバッファサイズの算出
00288     u_int size = (u_int)(SoundDefinition::streamBufferLength *
00289         soundReader->getOneSecondBytes());
00290     // サウンド作成
00291     StreamSound3D* sound = createStreamSound3D(
00292         size, soundReader->getSample(),
00293         soundReader->getChannel(), soundReader->getBit(), focus);
00294     sound->setName(name);
00295     sound->setComment(soundReader->getComment());
00296     // サウンドリーダの設定
00297     sound->setSoundReader(soundReader);
00298     return sound;
00299 }
00300 //------------------------------------------------------------------------------
00301 // ストリーム3Dサウンドの作成
00302 StreamSound3D* SoundManager::createStreamSound3D(
00303     const String& fileName, Sound::Focus focus){
00304     FilePath filePath(fileName);
00305     SoundReader* soundReader = createSoundReader(filePath);
00306     StreamSound3D* sound =
00307         createStreamSound3D(soundReader, filePath.getFileName(), focus);
00308     // サウンドリーダはストリーム3Dサウンドによって削除される
00309     return sound;
00310 }
00311 //------------------------------------------------------------------------------
00312 // サウンドバッファ
00313 //------------------------------------------------------------------------------
00314 // ウェーブフォーマットの構築
00315 void SoundManager::buildWaveFormat(
00316     WAVEFORMATEX* waveFormat, int sample, int channel, int bit){
00317     Assert((sample >= DSBFREQUENCY_MIN) && (sample <= 100000));
00318     Assert((channel >= 1) && (channel <= 2));
00319     Assert((bit == 16) || (bit == 8));
00320     ::memset(waveFormat, 0, sizeof(WAVEFORMATEX));
00321     waveFormat->wFormatTag = WAVE_FORMAT_PCM;
00322     waveFormat->nSamplesPerSec = sample;
00323     waveFormat->nChannels = channel;
00324     waveFormat->wBitsPerSample = bit;
00325     waveFormat->nBlockAlign =
00326         (waveFormat->nChannels * waveFormat->wBitsPerSample) / 8;
00327     waveFormat->nAvgBytesPerSec =
00328         waveFormat->nSamplesPerSec * waveFormat->nBlockAlign;
00329 }
00330 //------------------------------------------------------------------------------
00331 // バッファ記述の構築
00332 void SoundManager::buildBufferDescription(DSBUFFERDESC* description,
00333     WAVEFORMATEX* waveFormat, int size, Sound::Focus focus){
00334     ::memset(description, 0, sizeof(DSBUFFERDESC));
00335     description->dwSize = sizeof(DSBUFFERDESC);
00336     description->lpwfxFormat = waveFormat;
00337     description->dwBufferBytes = size;
00338     // 動的ボイス管理、ボリューム、周波数、正確な再生カーソル
00339     description->dwFlags = (DSBCAPS_LOCDEFER | DSBCAPS_CTRLVOLUME |
00340         DSBCAPS_CTRLFREQUENCY | DSBCAPS_GETCURRENTPOSITION2);
00341     if(focus == Sound::focusSticky){
00342         description->dwFlags |= DSBCAPS_STICKYFOCUS;
00343     }else if(focus == Sound::focusGlobal){
00344         description->dwFlags |= DSBCAPS_GLOBALFOCUS;
00345     }
00346     // 追加すべきフラグ
00347     // Stereo : DSBCAPS_CTRLPAN
00348     // 3D     : 3Dアルゴリズム
00349     // Stream : DSBCAPS_CTRLPOSITIONNOTIFY
00350 }
00351 //------------------------------------------------------------------------------
00352 // サウンドバッファの構築
00353 DirectSoundBuffer* SoundManager::buildSoundBuffer(DSBUFFERDESC* description){
00354     IDirectSoundBuffer* buffer;
00355     if(DirectXFailed(directSound_->CreateSoundBuffer(
00356         description, &buffer, NULL))){
00357         ErrorOut("SoundManager::buildSoundBuffer() "
00358             "サウンドバッファの構築に失敗しました");
00359     }
00360     DirectSoundBuffer* soundBuffer;
00361     if(DirectXFailed(buffer->QueryInterface(
00362         DirectSoundBufferInterfaceID, (void**)&soundBuffer))){
00363         ErrorOut("SoundManager::buildSoundBuffer() "
00364             "サウンドバッファのインターフェース取得に失敗しました");
00365     }
00366     SafeRelease(buffer);
00367     return soundBuffer;
00368 }
00369 //------------------------------------------------------------------------------
00370 // サウンドリーダの作成
00371 SoundReader* SoundManager::createSoundReader(const FilePath& filePath){
00372     SoundReader* soundReader = NULL;
00373     // リーダの識別
00374     if(WaveReader::isWaveFileName(filePath)){
00375         soundReader = new WaveReader(filePath);
00376     }else if(OggVorbisReader::isOggVorbisFileName(filePath)){
00377         soundReader = new OggVorbisReader(filePath);
00378     }
00379     return soundReader;
00380 }
00381 //------------------------------------------------------------------------------
00382 // サウンドバッファの読み込み
00383 bool SoundManager::readSoundBuffer(
00384     SoundBuffer* soundBuffer, SoundReader* soundReader){
00385     SoundBuffer::Lock lock = soundBuffer->lock();
00386     bool result = lock.isValid();
00387     if(result){
00388         u_int bufferSize = lock.getSize0();
00389         Assert(bufferSize == soundReader->getSize());
00390         int resdSize = soundReader->read(lock.getAddress0(), bufferSize);
00391         result = (resdSize == bufferSize);
00392         soundBuffer->unlock();
00393     }
00394     return result;
00395 }
00396 //------------------------------------------------------------------------------
00397 // サウンドバッファの複製
00398 DirectSoundBuffer* SoundManager::duplicateSoundBuffer(
00399     DirectSoundBuffer* soundBuffer){
00400     IDirectSoundBuffer* buffer;
00401     if(DirectXFailed(directSound_->DuplicateSoundBuffer(
00402         soundBuffer, &buffer))){
00403         ErrorOut("SoundManager::duplicateSoundBuffer() "
00404             "サウンドバッファの複製に失敗しました");
00405     }
00406     DirectSoundBuffer* duplicatedBuffer;
00407     if(DirectXFailed(buffer->QueryInterface(
00408         DirectSoundBufferInterfaceID, (void**)&duplicatedBuffer))){
00409         ErrorOut("SoundManager::duplicateSoundBuffer() "
00410             "サウンドバッファのインターフェース取得に失敗しました");
00411     }
00412     SafeRelease(buffer);
00413     return duplicatedBuffer;
00414 }
00415 //------------------------------------------------------------------------------
00416 // アップデート
00417 //------------------------------------------------------------------------------
00418 // アップデート
00419 void SoundManager::update(){
00420     for(int i = 0; i < updateSounds_.getCount(); i++){
00421         Sound* sound = updateSounds_[i];
00422         if(sound->update()){
00423             updateSounds_.remove(i);
00424             i--;
00425         }
00426     }
00427 }
00428 //------------------------------------------------------------------------------
00429 // アップデートサウンドの追加
00430 void SoundManager::addUpdateSound(Sound* sound){
00431     updateSounds_.pushBack(sound);
00432 }
00433 //------------------------------------------------------------------------------
00434 // アップデートサウンドの削除
00435 void SoundManager::removeUpdateSound(Sound* sound){
00436     int result = updateSounds_.removeByValue(sound);
00437     Assert(result != -1);
00438 }
00439 //------------------------------------------------------------------------------
00440 } // End of namespace Lamp
00441 //------------------------------------------------------------------------------

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