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/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
00179
00180
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
00194 description.dwFlags |= DSBCAPS_CTRL3D;
00195
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
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
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
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
00253
00254
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
00264 description.dwFlags |= (DSBCAPS_CTRL3D | DSBCAPS_CTRLPOSITIONNOTIFY);
00265
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
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
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
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
00348
00349
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 }
00441