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