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

StreamPlayer.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/Utility/StreamPlayer.h"
00027 #include "Sound/System/SoundBuffer.h"
00028 #include "Sound/Reader/SoundReader.h"
00029 #include "Core/Thread/SynchronizedBlock.h"
00030 
00031 namespace Lamp{
00032 
00033 //------------------------------------------------------------------------------
00034 // コンストラクタ
00035 StreamPlayer::StreamPlayer() :
00036     directSoundNotify_(NULL), soundBuffer_(NULL), soundReader_(NULL),
00037     cursor_(0), loopCursor_(0), initialized_(false){
00038     for(int i = 0; i < eventCount_; i++){ event_[i] = NULL; }
00039 }
00040 //------------------------------------------------------------------------------
00041 // デストラクタ
00042 StreamPlayer::~StreamPlayer(){
00043     soundBuffer_->stop();
00044     // スレッド停止を待つ、SetEventは再生せずに削除する場合に必要
00045     requestStop();
00046     ::SetEvent(event_[2]);
00047     join();
00048     for(int i = 0; i < eventCount_; i++){
00049         if(event_[i] != NULL){ CloseHandle(event_[i]); }
00050     }
00051     SafeRelease(directSoundNotify_);
00052 }
00053 //------------------------------------------------------------------------------
00054 // 初期化
00055 bool StreamPlayer::initialize(
00056     SoundBuffer* soundBuffer, SoundReader* soundReader){
00057     if(initialized_){ Assert(false); return true; }
00058     soundBuffer_ = soundBuffer;
00059     soundReader_ = soundReader;
00060     Assert((soundBuffer_ != NULL) && (soundReader_ != NULL));
00061     // 通知インターフェース初期化
00062     if(DirectXFailed(soundBuffer_->getSoundBuffer()->QueryInterface(
00063         DirectSoundNotifyInterfaceID, (void**)&directSoundNotify_))){
00064         ErrorOut("StreamPlayer::initialize() "
00065             "通知インターフェースの取得に失敗しました。");
00066         return false;
00067     }
00068     // イベント初期化
00069     for(int i = 0; i < eventCount_; i++){
00070         event_[i] = ::CreateEvent(NULL, false, false, NULL);
00071     }
00072     DSBPOSITIONNOTIFY cursorNotify[eventCount_];
00073     cursorNotify[0].dwOffset = 0;
00074     cursorNotify[0].hEventNotify = event_[0];
00075     cursorNotify[1].dwOffset = soundBuffer_->getBufferSize() / 2;
00076     cursorNotify[1].hEventNotify = event_[1];
00077     cursorNotify[2].dwOffset = DSBPN_OFFSETSTOP;
00078     cursorNotify[2].hEventNotify = event_[2];
00079     if(DirectXFailed(directSoundNotify_->SetNotificationPositions(
00080         eventCount_, cursorNotify))){
00081         ErrorOut("StreamPlayer::initialize() "
00082             "通知イベントの設定に失敗しました。");
00083     }
00084     // ロード前に再生されるとまずいので最初にバッファを半分読み込む
00085     reset();
00086     initialized_ = true;
00087     // 実行
00088     start();
00089     return true;
00090 }
00091 //------------------------------------------------------------------------------
00092 // リセット
00093 void StreamPlayer::reset(){
00094     bool result = writeStream(0);
00095     Assert(result);
00096 }
00097 //------------------------------------------------------------------------------
00098 // 実行
00099 void StreamPlayer::run(Thread* thread){
00100     Assert(initialized_);
00101     while(!isStopRequested()){
00102         u_long flag = ::WaitForMultipleObjects(
00103             eventCount_, event_, false, INFINITE);
00104         switch(flag){
00105             case WAIT_OBJECT_0 + 0:
00106                 // 停止命令が無い状態で書き込みが成功するまでループ
00107                 while((!isStopRequested()) && (!writeStream(1))){ yield(); }
00108                 break;
00109             case WAIT_OBJECT_0 + 1:
00110                 // 停止命令が無い状態で書き込みが成功するまでループ
00111                 while((!isStopRequested()) && (!writeStream(0))){ yield(); }
00112                 break;
00113             case WAIT_OBJECT_0 + 2:
00114                 break;
00115         }
00116     }
00117 }
00118 //------------------------------------------------------------------------------
00119 // ストリーム書き込み
00120 bool StreamPlayer::writeStream(int offset){
00121     u_int size = soundBuffer_->getSize();
00122     bool isLoop = soundBuffer_->isLoop();
00123     u_int writeSize = soundBuffer_->getBufferSize() / 2;
00124     u_int writeOffset = writeSize * (offset & 1);
00125     // 最後に書き込んだバッファが再生されてから停止する
00126     if((!isLoop) && (cursor_ == size)){
00127         soundBuffer_->stop();
00128         return true;
00129     }
00130     // ロック
00131     SoundBuffer::Lock& lock = soundBuffer_->lock(writeOffset, writeSize);
00132     if(!lock.isValid()){ return false; }
00133     // バッファ後半にはロックがかからないはず
00134     Assert((lock.getAddress0() != NULL) && (lock.getSize0() == writeSize));
00135     Assert((lock.getAddress1() == NULL) && (lock.getSize1() == 0));
00136     // パラメータの確保
00137     u_int cursor, loopCursor;
00138     {
00139         SynchronizedBlock synchronizedBlock(this);
00140         cursor = cursor_;
00141         loopCursor = loopCursor_;
00142         cursor_ += writeSize;
00143         // ループ処理
00144         if(cursor_ > size){
00145             if(isLoop){ cursor_ = loopCursor + (cursor_ - size); }
00146             else{ cursor_ = size; }
00147         }
00148     }
00149     Assert(soundReader_->getCursor() == cursor);
00150     // ストリーム前半書き込み
00151     int preWriteSize = writeSize;
00152     int postWriteSize = (cursor + writeSize) - size;
00153     if(postWriteSize > 0){ preWriteSize -= postWriteSize; }
00154     int result = soundReader_->read(lock.getAddress0(), preWriteSize);
00155     Assert(result == preWriteSize);
00156     // ストリーム後半書き込み
00157     char* postWriteAddress = (((char*)lock.getAddress0()) + preWriteSize);
00158     if(postWriteSize > 0){
00159         if(isLoop){
00160             // ループ位置に戻る
00161             soundReader_->setCursor(loopCursor);
00162             result = soundReader_->read(postWriteAddress, postWriteSize);
00163             Assert(result == postWriteSize);
00164         }else{
00165             // 残りを0(16bit)か128(8bit)で埋める
00166             u_char value = 0;
00167             if(soundBuffer_->getBit() == 8){ value = 128; }
00168             ::memset(postWriteAddress, 0, postWriteSize);
00169         }
00170     }
00171     soundBuffer_->unlock();
00172     return true;
00173 }
00174 //------------------------------------------------------------------------------
00175 // 再生位置
00176 //------------------------------------------------------------------------------
00177 // 再生位置設定
00178 void StreamPlayer::setCursor(u_int cursor){
00179     Assert(cursor <= soundBuffer_->getSize());
00180     // 1サンプル以下のバイト数は切り捨てる
00181     u_int fixedCursor =
00182         cursor - (cursor % soundBuffer_->getOneSampleBytes());
00183     {
00184         SynchronizedBlock synchronizedBlock(this);
00185         cursor_ = fixedCursor;
00186         soundReader_->setCursor(cursor_);
00187     }
00188 }
00189 //------------------------------------------------------------------------------
00190 // ループ
00191 //------------------------------------------------------------------------------
00192 // ループ位置の設定
00193 void StreamPlayer::setLoopCursor(u_int loopCursor){
00194     Assert(loopCursor <= soundBuffer_->getSize());
00195     // 1サンプル以下のバイト数は切り捨てる
00196     u_int fixedLoopCursor =
00197         loopCursor - (loopCursor % soundBuffer_->getOneSampleBytes());
00198     {
00199         SynchronizedBlock synchronizedBlock(this);
00200         loopCursor_ = fixedLoopCursor;
00201     }
00202 }
00203 //------------------------------------------------------------------------------
00204 } // End of namespace Lamp
00205 //------------------------------------------------------------------------------

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