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

SoundBuffer.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/SoundBuffer.h"
00027 #include "Sound/System/LampSound.h"
00028 #include "Sound/System/SoundManager.h"
00029 #include "Sound/System/SoundDefinition.h"
00030 
00031 namespace Lamp{
00032 
00033 //------------------------------------------------------------------------------
00034 // 生成、破棄
00035 //------------------------------------------------------------------------------
00036 // コンストラクタ
00037 SoundBuffer::SoundBuffer(DirectSoundBuffer* soundBuffer) :
00038     Sound(), soundBuffer_(soundBuffer){
00039     lock_.clear();
00040     // 初期データの取得
00041     long decibelVolume;
00042     if(DirectXFailed(soundBuffer->GetVolume(&decibelVolume))){
00043         ErrorOut("SoundBuffer::SoundBuffer() ボリュームの取得に失敗しました。");
00044     }
00045     volume_ = decibelToVolume(decibelVolume);
00046     frequency_ = getBufferFrequency();
00047     fadeStartVolume_ = fadeEndVolume_ = 0.f;
00048     isFading_ = false;
00049     setPriority(priorityDefault);
00050     setOwnership(true);
00051     setLoop(false);
00052     isSuspended_ = false;
00053 }
00054 //------------------------------------------------------------------------------
00055 // 初期化
00056 void SoundBuffer::initialize(
00057     u_int size, int sample, int channel, int bit, Focus focus){
00058     size_ = size;
00059     sample_ = sample;
00060     channel_ = channel;
00061     bit_ = bit;
00062     focus_ = focus;
00063 }
00064 //------------------------------------------------------------------------------
00065 // デストラクタ
00066 SoundBuffer::~SoundBuffer(){
00067     // フェード取り消し
00068     stopFade();
00069     stop();
00070     SafeRelease(soundBuffer_);
00071 }
00072 //------------------------------------------------------------------------------
00073 // サウンドバッファデータのコピー
00074 void SoundBuffer::copySoundBufferData(SoundBuffer* destination){
00075     destination->setName(getName());
00076     destination->initialize(
00077         getBufferSize(), getSample(), getChannel(), getBit(), getFocus());
00078     destination->setPriority(getPriority());
00079     destination->setLoop(isLoop());
00080 }
00081 //------------------------------------------------------------------------------
00082 // 再生
00083 //------------------------------------------------------------------------------
00084 // 再生
00085 bool SoundBuffer::play(){
00086     // 再生時にsetCursor(0)するとストリーム先読みとの相性が悪くなる
00087     isSuspended_ = false;
00088     return playBuffer();
00089 }
00090 //------------------------------------------------------------------------------
00091 // 停止
00092 void SoundBuffer::stop(){
00093     isSuspended_ = false;
00094     stopBuffer();
00095     setCursor(0);
00096 }
00097 //------------------------------------------------------------------------------
00098 // 再生の一時停止
00099 void SoundBuffer::suspend(){
00100     State state = getState();
00101     // 停止中なら停止したまま
00102     if(state == stateStop){ return; }
00103     isSuspended_ = true;
00104     stopBuffer();
00105 }
00106 //------------------------------------------------------------------------------
00107 // 再生再開
00108 bool SoundBuffer::resume(){
00109     State state = getState();
00110     // 停止中なら停止したまま
00111     if(state == stateStop){ return true; }
00112     // バッファを再生してから中断フラグをクリアする
00113     bool result = playBuffer();
00114     isSuspended_ = false;
00115     return result;
00116 }
00117 //------------------------------------------------------------------------------
00118 // 状態の取得
00119 SoundBuffer::State SoundBuffer::getState() const{
00120     u_long status;
00121     if(DirectXFailed(soundBuffer_->GetStatus(&status))){
00122         ErrorOut("SoundBuffer::getState() ステータスの取得に失敗しました。");
00123     }
00124     if((status & DSBSTATUS_BUFFERLOST) != 0){
00125         // ロストならリストアして再度ステート取得
00126         if(DirectXFailed(soundBuffer_->Restore())){
00127             ErrorOut("SoundBuffer::getState() バッファのリストアに失敗しました。");
00128         }
00129         if(DirectXFailed(soundBuffer_->GetStatus(&status))){
00130             ErrorOut("SoundBuffer::getState() ステータスの取得に失敗しました。");
00131         }
00132         if((status & DSBSTATUS_BUFFERLOST) != 0){ return stateLost; }
00133     }
00134     if((status & DSBSTATUS_PLAYING) != 0){ return statePlay; }
00135     if(isSuspended_){ return stateSuspend; }
00136     return stateStop;
00137 }
00138 //------------------------------------------------------------------------------
00139 // バッファの再生
00140 bool SoundBuffer::playBuffer(){
00141     u_int priority = (u_int)(getPriority() + 32768);
00142     u_int flag = getPlayFlag();
00143     // 再生を行う
00144     HRESULT result = soundBuffer_->Play(0, priority, flag);
00145     if(DirectXSucceeded(result)){ return true; }
00146     // メモリが足りない、長いサウンドをたくさん同時発音させると起こることがある
00147     if(result == E_OUTOFMEMORY){ Assert(false); return false; }
00148     // バッファロストならリストアしてみる
00149     if(result != DSERR_BUFFERLOST){
00150         ErrorOut("SoundBuffer::playBuffer() バッファの再生に失敗しました。");
00151         return false;
00152     }
00153     result = soundBuffer_->Restore();
00154     if(DirectXFailed(result)){ return false; }
00155     // 再度再生を行う
00156     result = soundBuffer_->Play(0, priority, flag);
00157     if(DirectXSucceeded(result)){ return true; }
00158     return false;
00159 }
00160 //------------------------------------------------------------------------------
00161 // バッファの停止
00162 void SoundBuffer::stopBuffer(){
00163     if(DirectXFailed(soundBuffer_->Stop())){
00164         ErrorOut("SoundBuffer::stopBuffer() サウンドの停止に失敗しました。");
00165     }
00166 }
00167 //------------------------------------------------------------------------------
00168 // 再生位置
00169 //------------------------------------------------------------------------------
00170 // 再生位置設定
00171 void SoundBuffer::setCursor(u_int cursor){
00172     Assert((cursor >= 0) && (cursor < getSize()));
00173     if(DirectXFailed(soundBuffer_->SetCurrentPosition(cursor))){
00174         ErrorOut("SoundBuffer::setCursor() 再生位置の設定に失敗しました。");
00175     }
00176 }
00177 //------------------------------------------------------------------------------
00178 // 再生位置取得
00179 u_int SoundBuffer::getCursor() const{
00180     u_long result;
00181     if(DirectXFailed(soundBuffer_->GetCurrentPosition(&result, NULL))){
00182         ErrorOut("SoundBuffer::getCursor() 再生位置の取得に失敗しました。");
00183     }
00184     return result;
00185 }
00186 //------------------------------------------------------------------------------
00187 // ボリューム
00188 //------------------------------------------------------------------------------
00189 // ボリュームの設定
00190 void SoundBuffer::setVolume(float volume){
00191     if(volume_ == volume){ return; }
00192     int db = volumeToDecibel(volume);
00193     if(DirectXFailed(soundBuffer_->SetVolume(db))){
00194         ErrorOut("SoundBuffer::setVolume() ボリュームの設定に失敗しました。");
00195     }
00196     volume_ = volume;
00197 }
00198 //------------------------------------------------------------------------------
00199 // 周波数
00200 //------------------------------------------------------------------------------
00201 // 周波数の設定
00202 void SoundBuffer::setFrequency(int frequency){
00203     if(frequency_ == frequency){ return; }
00204     Assert(frequency >= DSBFREQUENCY_MIN);
00205     Assert(frequency <= 100000);
00206     if(DirectXFailed(soundBuffer_->SetFrequency(frequency))){
00207         ErrorOut("SoundBuffer::setFrequency() 周波数の設定に失敗しました。");
00208     }
00209     frequency_ = frequency;
00210 }
00211 //------------------------------------------------------------------------------
00212 // オリジナル周波数の設定
00213 void SoundBuffer::setOriginalFrequency(){
00214     if(DirectXFailed(soundBuffer_->SetFrequency(DSBFREQUENCY_ORIGINAL))){
00215         ErrorOut("SoundBuffer::resetFrequency() 周波数の設定に失敗しました。");
00216     }
00217     frequency_ = getBufferFrequency();
00218 }
00219 //------------------------------------------------------------------------------
00220 // バッファ周波数の取得
00221 int SoundBuffer::getBufferFrequency() const{
00222     u_long frequency;
00223     if(DirectXFailed(soundBuffer_->GetFrequency(&frequency))){
00224         ErrorOut("SoundBuffer::getBufferFrequency() "
00225             "バッファ周波数の取得に失敗しました。");
00226     }
00227     Assert(frequency >= DSBFREQUENCY_MIN);
00228     Assert(frequency <= 100000);
00229     return frequency;
00230 }
00231 //------------------------------------------------------------------------------
00232 // フェード
00233 //------------------------------------------------------------------------------
00234 // フェード
00235 void SoundBuffer::fade(float millisecond, float startVolume, float endVolume){
00236     Assert(millisecond >= 0.f);
00237     if(isFading_){
00238         LampSound::getSoundManager()->removeUpdateSound(this);
00239         isFading_ = false;
00240     }
00241     if(millisecond <= Math::epsilon){ return; }
00242     fadeStartTime_ = Timer::getTick();
00243     fadePeriod_ = millisecond;
00244     fadeStartVolume_ = startVolume;
00245     fadeEndVolume_ = endVolume;
00246     isFading_ = true;
00247     setVolume(fadeStartVolume_);
00248     play();
00249     LampSound::getSoundManager()->addUpdateSound(this);
00250 }
00251 //------------------------------------------------------------------------------
00252 // アップデート
00253 bool SoundBuffer::update(){
00254     Assert(isFading());
00255     float rate = Timer::getInterval(fadeStartTime_) / fadePeriod_;
00256     // フェード終了
00257     if(rate >= 1.f){
00258         setVolume(fadeEndVolume_);
00259         if(fadeEndVolume_ <= Math::epsilon){ stop(); }
00260         isFading_ = false;
00261         return true;
00262     }
00263     float volume =
00264         (fadeEndVolume_ - fadeStartVolume_) * rate + fadeStartVolume_;
00265     setVolume(volume);
00266     return false;
00267 }
00268 //------------------------------------------------------------------------------
00269 // ロック
00270 //------------------------------------------------------------------------------
00271 // ロック
00272 SoundBuffer::Lock& SoundBuffer::lock(){
00273     Assert(!lock_.isValid());
00274     HRESULT result = soundBuffer_->Lock(0, 0,
00275         &lock_.address0_, &lock_.size0_, NULL, NULL, DSBLOCK_ENTIREBUFFER);
00276     if(DirectXSucceeded(result)){ return lock_; }
00277     // バッファロストならリストアしてみる
00278     lock_.clear();
00279     if(result != DSERR_BUFFERLOST){
00280         ErrorOut("SoundBuffer::lock() バッファのロックに失敗しました。");
00281         return lock_;
00282     }
00283     result = soundBuffer_->Restore();
00284     if(DirectXFailed(result)){ return lock_; }
00285     // 再度ロックを行う
00286     result = soundBuffer_->Lock(0, 0,
00287         &lock_.address0_, &lock_.size0_, NULL, NULL, DSBLOCK_ENTIREBUFFER);
00288     if(DirectXFailed(result)){ lock_.clear(); }
00289     return lock_;
00290 }
00291 //------------------------------------------------------------------------------
00292 // ロック
00293 SoundBuffer::Lock& SoundBuffer::lock(u_int offset, u_int bytes){
00294     Assert(!lock_.isValid());
00295     HRESULT result = soundBuffer_->Lock(offset, bytes,
00296         &lock_.address0_, &lock_.size0_, &lock_.address1_, &lock_.size1_, 0);
00297     if(DirectXSucceeded(result)){ return lock_; }
00298     // バッファロストならリストアしてみる
00299     lock_.clear();
00300     if(result != DSERR_BUFFERLOST){
00301         ErrorOut("SoundBuffer::lock() バッファのロックに失敗しました。");
00302         return lock_;
00303     }
00304     result = soundBuffer_->Restore();
00305     if(DirectXFailed(result)){ return lock_; }
00306     // 再度ロックを行う
00307     result = soundBuffer_->Lock(0, 0,
00308         &lock_.address0_, &lock_.size0_, &lock_.address1_, &lock_.size1_, 0);
00309     if(DirectXFailed(result)){ lock_.clear(); }
00310     return lock_;
00311 }
00312 //------------------------------------------------------------------------------
00313 // アンロック
00314 void SoundBuffer::unlock(){
00315     // 有効なロックが行われていなければ何もしない
00316     if(!lock_.isValid()){ return; }
00317     if(DirectXFailed(soundBuffer_->Unlock(
00318         lock_.address0_, lock_.size0_, lock_.address1_, lock_.size1_))){
00319         ErrorOut("SoundBuffer::unlock() バッファのアンロックに失敗しました。");
00320     }
00321     lock_.clear();
00322 }
00323 //------------------------------------------------------------------------------
00324 } // End of namespace Lamp
00325 //------------------------------------------------------------------------------

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