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